use fmt; use net; use net::tcp; use net::ip; use io; use os; use unix::poll; use bufio; def PORT: u16 = 41460; type conn = net::socket; type packet = []u8; def PCKSZ: size = 4; type packet_reader = struct { buf: [256]u8, good: []u8, }; fn packet_reader_new() packet_reader = { let pr = packet_reader { buf = [0...], ... }; pr.good = pr.buf[0..0]; return pr; }; // call when input is ready. could block otherwise fn packet_reader_read(pr: *packet_reader, sock: net::socket) (void | io::error | io::EOF) = { const remaining_amt = len(pr.good); const read_pos = if (remaining_amt > 0) { // still some unconsumed content in the buffer // move unconsumed stuff to start of buffer fmt::printfln("moving {} remaining bytes",remaining_amt)!; pr.buf[0..remaining_amt] = pr.good; yield remaining_amt; } else 0z; const nread = match(io::read(sock, pr.buf[read_pos..])?) { case io::EOF => return io::EOF; case let n: size => yield n; }; fmt::printfln("read {} bytes",nread)!; const total_amt = read_pos + nread; pr.good = pr.buf[0..total_amt]; fmt::printfln("now {} bytes in buffer",total_amt)!; }; fn packet_reader_next(pr: *packet_reader) (packet | done) = { // either parse a full packet out of the front of good, // move good along that many bytes, // and return the packet, // or, ascertain there is no full packet, and return done if (len(pr.good) < PCKSZ) return done; const packet_bytes = pr.good[..PCKSZ]; pr.good = pr.good[PCKSZ..]; return packet_bytes; }; export fn main() void = { const listener = tcp::listen(ip::ANY_V4, PORT)!; const conn = tcp::accept(listener)!; const pr = packet_reader_new(); for :mainloop (true) { if (packet_reader_read(&pr, conn)! is io::EOF) fmt::fatal("disconnected"); let i = 0; for (const packet => packet_reader_next(&pr)) { fmt::printf("#{} got {}:",i,len(packet))!; i+=1; for (let byte .. packet) fmt::printf(" {:x}",byte)!; fmt::println("")!; }; }; }; // fn loop(listener: net::socket) void = { // const buf: [256]u8 = [0...]; // let pollfds: []poll::pollfd = alloc([ poll::pollfd { // fd = listener, events = poll::event::POLLIN, revents = 0 // }]); // for (true) { // poll::poll(pollfds, poll::INDEF)!; // if (0 != pollfds[0].revents & poll::event::POLLIN) { // fmt::println("new conn")!; // append(pollfds, poll::pollfd { // fd = tcp::accept(pollfds[0].fd)!, // events = poll::event::POLLIN, revents = 0 // }); // }; // for (let i = 1z; i < len(pollfds); i += 1) { // if (0 != pollfds[i].revents & poll::event::POLLIN) { // match (io::read(pollfds[i].fd, buf)!) { // case io::EOF => // fmt::println("disconnect", i)!; // delete(pollfds[i]); // i -= 1; // case let n: size => // io::write(os::stdout_file, buf[..n])!; // for (let j = 1z; j < len(pollfds); j += 1) { // if (i != j) { // io::writeall(pollfds[j].fd, buf[..n])!; // }; // }; // }; // }; // }; // }; // };