summaryrefslogtreecommitdiff
path: root/packet_reader
diff options
context:
space:
mode:
Diffstat (limited to 'packet_reader')
-rw-r--r--packet_reader/packet_reader.ha66
1 files changed, 57 insertions, 9 deletions
diff --git a/packet_reader/packet_reader.ha b/packet_reader/packet_reader.ha
index 43b85d1..9cae444 100644
--- a/packet_reader/packet_reader.ha
+++ b/packet_reader/packet_reader.ha
@@ -1,24 +1,33 @@
use io;
use fmt;
+use endian;
+use drawing;
-export type packet = []u8;
-def PCKSZ: size = 8;
+export type error = !str;
export type packet_reader = struct {
- buf: [256]u8,
+ buf: []u8,
good: []u8,
};
export fn new() packet_reader = {
let pr = packet_reader {
- buf = [0...],
+ buf = alloc([0...],512*512*4*2), // ehhh
...
};
pr.good = pr.buf[0..0];
return pr;
+};
+export type packet_type = enum u8 {
+ DRAW_OP,
+ SEND_CHUNK,
};
+export type packet_drawop = drawing::op;
+export type packet_sendchunk = []u32;
+export type packet = (packet_drawop | packet_sendchunk);
+
// call when input is ready. could block otherwise
export fn read(pr: *packet_reader, sock: io::handle) (void | io::error | io::EOF) = {
const remaining_amt = len(pr.good);
@@ -39,14 +48,53 @@ export fn read(pr: *packet_reader, sock: io::handle) (void | io::error | io::EOF
fmt::printfln("now {} bytes in buffer",total_amt)!;
};
+// packet format:
+// u32 size
+// u32 type
+// [size-8]u8 data...
+// size includes size of header (size and type fields)
-export fn next(pr: *packet_reader) (packet | done) = {
+export fn next(pr: *packet_reader) (packet | done | error) = {
// 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;
+ if (len(pr.good) < size(u32)) return done;
+ const packet_len = endian::legetu32(pr.good[0..4]);
+ if (packet_len < 8) return "packet size field too small": error;
+ if (len(pr.good) < packet_len) return done;
+
+ const packet_bytes = pr.good[..packet_len];
+ pr.good = pr.good[packet_len..];
+
+ const ty = endian::legetu32(packet_bytes[4..8]): packet_type;
+ switch (ty) {
+ case packet_type::DRAW_OP =>
+ const op = drawing::deser_op(packet_bytes[8..]);
+ return op: packet_drawop;
+ case packet_type::SEND_CHUNK =>
+ // in an ideal world we would need no copies
+ const totally_necessary_copy = alloc(packet_bytes[8..]...);
+ return totally_necessary_copy: packet_sendchunk;
+ };
+};
+
+export fn send_raw(sock: io::file, ty: packet_type, data: []u8) (void | io::error) = {
+ // ehh
+ const header: [8]u8 = [0...];
+ endian::leputu32(header[0..4], 8u32 + len(data):u32);
+ endian::leputu32(header[4..8], ty);
+ io::writeall(sock, header)?;
+ io::writeall(sock, data)?;
+};
+
+export fn send(sock: io::file, packet: packet) (void | io::error) = {
+ match (packet) {
+ case let op: packet_drawop =>
+ const ser_op = drawing::ser_op(op);
+ defer free(ser_op);
+ send_raw(sock, packet_type::DRAW_OP, ser_op)?;
+ case let chunkdata: packet_sendchunk =>
+ abort("not implemented sendchunk yet");
+ };
};