aboutsummaryrefslogtreecommitdiff
path: root/packet_reader
diff options
context:
space:
mode:
Diffstat (limited to 'packet_reader')
-rw-r--r--packet_reader/packet_reader.ha94
1 files changed, 66 insertions, 28 deletions
diff --git a/packet_reader/packet_reader.ha b/packet_reader/packet_reader.ha
index d541a11..ae38be7 100644
--- a/packet_reader/packet_reader.ha
+++ b/packet_reader/packet_reader.ha
@@ -4,7 +4,7 @@ use endian;
use drawing;
use drawing::{pos,CHUNKSIZE};
-export def VERSION: u8 = 2;
+export def VERSION: u8 = 3;
export type error = !str;
@@ -13,12 +13,14 @@ export type packet_reader = struct {
good: []u8,
wbuf: []u8,
wgood: []u8,
+ sock: io::file,
};
-export fn new() packet_reader = {
+export fn new(sock: io::file) packet_reader = {
let pr = packet_reader {
buf = alloc([0...],512*512*4*2), // ehhh
wbuf = alloc([0...], 512*512*4*2), // ehhhh
+ sock = sock,
...
};
pr.good = pr.buf[0..0];
@@ -26,6 +28,11 @@ export fn new() packet_reader = {
return pr;
};
+export fn finish(pr: *packet_reader) void = {
+ free(pr.buf);
+ free(pr.wbuf);
+};
+
fn cast_u32s_to_u8s(in: []u32) []u8 =
(in: *[*]u32: *[*]u8)[..len(in)*4];
fn cast_u8s_to_u32s(in: []u8) []u32 =
@@ -52,24 +59,51 @@ export type packet = (
| packet_position
| packet_reqchunk);
-// 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);
- 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;
+// call when input ready, so it doesn't block
+export fn service(
+ pr: *packet_reader,
+ should_read: bool,
+ should_write: bool,
+) (void | io::error | io::EOF) = {
+ const sock = pr.sock;
+
+ if (should_read) {
+ // reading
+ 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)!;
+ };
+
+
+ if (should_write) {
+ // writing
+ const amt_to_write = len(pr.wgood);
+ if (amt_to_write == 0) return;
+ const nwritten = io::write(sock, pr.wgood)?;
+ // fmt::printfln("written {} of {} bytes", nwritten, amt_to_write)!;
+ if (nwritten < amt_to_write) {
+ // fmt::println("moving buffer back")!;
+ const remaining_len = amt_to_write - nwritten;
+ pr.wbuf[0..remaining_len] = pr.wgood[nwritten..];
+ pr.wgood = pr.wbuf[0..remaining_len];
+ } else {
+ pr.wgood = pr.wbuf[0..0];
+ };
+ // fmt::printfln(" {} to write next time", len(pr.wgood))!;
};
- // 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)!;
};
// packet format:
@@ -78,7 +112,7 @@ export fn read(pr: *packet_reader, sock: io::handle) (void | io::error | io::EOF
// [size-8]u8 data...
// size includes size of header (size and type fields)
-export fn next(pr: *packet_reader) (packet | done | error) = {
+export fn read_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,
@@ -136,24 +170,28 @@ export fn next(pr: *packet_reader) (packet | done | error) = {
};
};
-export fn send_raw(sock: io::file, ty: packet_type, datas: []u8...) (void | io::error) = {
+fn append_wbuf(pr: *packet_reader, ty: packet_type, datas: []u8...) (void | error) = {
// ehh
const header: [8]u8 = [0...];
let total_len = 8u32;
for (const data .. datas) total_len += len(data): u32;
+
+ const remaining_space = len(pr.wbuf) - len(pr.wgood);
+ if (remaining_space < total_len) return "wbuff full": error;
+
endian::leputu32(header[0..4], total_len);
endian::leputu32(header[4..8], ty);
- io::writeall(sock, header)?;
+ static append(pr.wgood, header...);
for (const data .. datas)
- io::writeall(sock, data)?;
+ static append(pr.wgood, data...);
};
-export fn send(sock: io::file, packet: packet) (void | io::error) = {
+export fn write(pr: *packet_reader, packet: packet) (void | 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)?;
+ append_wbuf(pr, packet_type::DRAW_OP, ser_op)?;
case let packet: packet_sendchunk =>
const pos_buf: [8]u8 = [0...];
endian::leputu32(pos_buf[0..4],packet.world_pos.0: u32);
@@ -161,16 +199,16 @@ export fn send(sock: io::file, packet: packet) (void | io::error) = {
const chunk_data_compressed = rle_encode(packet.chunk_data);
defer free(chunk_data_compressed);
const compressed_data_bytes = cast_u32s_to_u8s(chunk_data_compressed);
- send_raw(sock, packet_type::SEND_CHUNK, pos_buf, compressed_data_bytes)?;
+ append_wbuf(pr, packet_type::SEND_CHUNK, pos_buf, compressed_data_bytes)?;
case let pos: packet_position =>
const pos_buf: [8]u8 = [0...];
endian::leputu32(pos_buf[0..4], pos.0: u32);
endian::leputu32(pos_buf[4..8], pos.1: u32);
- send_raw(sock, packet_type::POSITION, pos_buf)?;
+ append_wbuf(pr, packet_type::POSITION, pos_buf)?;
case let world_pos: packet_reqchunk =>
const pos_buf: [8]u8 = [0...];
endian::leputu32(pos_buf[0..4], world_pos.0: u32);
endian::leputu32(pos_buf[4..8], world_pos.1: u32);
- send_raw(sock, packet_type::REQ_CHUNK, pos_buf)?;
+ append_wbuf(pr, packet_type::REQ_CHUNK, pos_buf)?;
};
};