summaryrefslogtreecommitdiff
path: root/mcproto/handshake.ha
diff options
context:
space:
mode:
Diffstat (limited to 'mcproto/handshake.ha')
-rw-r--r--mcproto/handshake.ha46
1 files changed, 46 insertions, 0 deletions
diff --git a/mcproto/handshake.ha b/mcproto/handshake.ha
new file mode 100644
index 0000000..8df5254
--- /dev/null
+++ b/mcproto/handshake.ha
@@ -0,0 +1,46 @@
+use trace;
+
+export def SB_HANDSHAKE: i32 = 0x00;
+
+export type Handshake = struct {
+ proto_ver: i32,
+ server_addr: str,
+ server_port: u16,
+ next_state: NextState,
+};
+
+export type NextState = enum i32 {
+ STATUS = 1,
+ LOGIN = 2,
+};
+
+export fn encode_handshake(out: *[]u8, pkt: *Handshake) void = {
+ encode_varint(out, pkt.proto_ver);
+ encode_string(out, pkt.server_addr);
+ encode_short(out, pkt.server_port);
+ encode_varint(out, pkt.next_state);
+};
+
+export fn decode_handshake(ctx: *Context) (Handshake | trace::failed) = {
+ const ctx_ = context(ctx, "protocol version");
+ const proto_ver = decode_varint(&ctx_)?;
+ const ctx_ = context(ctx, "server address");
+ const server_addr = decode_string(&ctx_, 255)?;
+ const ctx_ = context(ctx, "server port");
+ const server_port = decode_short(&ctx_)?;
+ const ctx_ = context(ctx, "next state");
+ const next_state = decode_varint(&ctx_)?: NextState;
+ if (next_state != NextState::STATUS
+ && next_state != NextState::LOGIN) {
+ return error(&ctx_, "Invalid next state 0x{:02x}",
+ next_state: i32);
+ };
+ expect_end(ctx)?;
+
+ return Handshake {
+ proto_ver = proto_ver,
+ server_addr = server_addr,
+ server_port = server_port,
+ next_state = next_state,
+ };
+};