summaryrefslogtreecommitdiff
path: root/mcproto/handshake.ha
blob: 8df52540cdb27a6b0e93781a3c8d38e5fef32463 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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,
	};
};