porttest.zig 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const std = @import("std");
  2. const mem = std.mem;
  3. const fmt = std.fmt;
  4. const debug = std.debug;
  5. // read n bytes or return err
  6. fn readExactly(reader: anytype, buffer: []u8) !void{
  7. var have: usize = 0;
  8. while(have < buffer.len){
  9. const amt = try reader.read(buffer[have..]);
  10. if(amt == 0){ return error.EndOfStream; }
  11. have += amt;
  12. }
  13. }
  14. pub fn main() !void{
  15. const stdin = std.io.getStdIn().reader();
  16. const stdout = std.io.getStdOut().writer();
  17. var buffer: [64]u8 = [_]u8{0} ** 64;
  18. var len_bytes_buf: [2]u8 = [_]u8{0} ** 2;
  19. var reply_buffer: [64]u8 = [_]u8{0} ** 64;
  20. while(true){
  21. // read msg length (2 bytes, big-endian)
  22. readExactly(stdin, &len_bytes_buf) catch |err|{
  23. if(err == error.EndOfStream){ break; }
  24. return err;
  25. };
  26. const msg_len = @as(u16, len_bytes_buf[0]) << 8 | len_bytes_buf[1]; // convert to u16, big-endian
  27. //std.debug.print("Full buffer: ", .{});
  28. //for(buffer[0..msg_len]) |b|{
  29. // std.debug.print("{c}", .{b});
  30. //}
  31. //std.debug.print("\n", .{});
  32. if(msg_len == 0 or msg_len > buffer.len){
  33. try stdout.writeAll(&[2]u8{ 0, 0 });
  34. continue;
  35. }
  36. readExactly(stdin, buffer[0..msg_len]) catch |err|{ // read msg
  37. if(err == error.EndOfStream){ break; }
  38. return err;
  39. };
  40. //debug.print("RECV: '{s}'\n", .{buffer[0..msg_len]});
  41. var fbs = std.io.fixedBufferStream(&reply_buffer);
  42. var writer = fbs.writer();
  43. if(mem.eql(u8, buffer[0..msg_len], "hello")){
  44. try writer.writeAll("Hello world!");
  45. }else if(mem.startsWith(u8, buffer[0..msg_len], "factorial ")){
  46. const prefix_len = "factorial ".len;
  47. const n_str = buffer[prefix_len..msg_len];
  48. //std.debug.print("n_str = '{s}' ({} chars)\n", .{ n_str, n_str.len });
  49. const n = fmt.parseInt(isize, n_str, 10) catch {
  50. //std.debug.print("error:PARSE ERROR for '{s}'\n", .{n_str});
  51. try writer.writeAll("error:badarg");
  52. //try writer.writeAll("0");
  53. try sendResponse(stdout, fbs.getWritten());
  54. continue;
  55. };
  56. if(n < 0){
  57. //try writer.writeAll("error:badarg");
  58. //std.debug.print("n < 0 -> badarg\n", .{});
  59. //try writer.writeAll("0");
  60. try writer.writeAll("error:badarg: n < 0");
  61. }else if(n > 34){
  62. //std.debug.print("n > 34 -> too large\n", .{});
  63. //try writer.writeAll("0");
  64. try writer.writeAll("error:input too large, max is 34");
  65. }else{
  66. var result: u128 = 1;
  67. var i = @as(u128, @intCast(n));
  68. while (i > 1) : (i -= 1) result *= i;
  69. //std.debug.print("factorial({d}) = {d}\n", .{n, result});
  70. try fmt.formatInt(result, 10, .lower, .{}, writer);
  71. }
  72. }else{
  73. try writer.writeAll("error:unknown command");
  74. }
  75. try sendResponse(stdout, fbs.getWritten());
  76. }
  77. }
  78. fn sendResponse(writer: anytype, response: []const u8) !void{
  79. const len: u16 = @intCast(response.len);
  80. //std.debug.print("SEND: len={d} (0x{X:0>4}) data='{s}'\n", .{ len, len, response });
  81. try writer.writeByte(@intCast((len >> 8) & 0xFF)); // high byte
  82. try writer.writeByte(@intCast(len & 0xFF)); // low byte
  83. try writer.writeAll(response);
  84. }