Repository navigation
Expand file tree
/
Copy pathminecraft.c
More file actions
126 lines (99 loc) · 2.79 KB
/
Copy pathminecraft.c
File metadata and controls
126 lines (99 loc) · 2.79 KB
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "minecraft.h"
#include <string.h>
#include <stdlib.h>
int read_VarInt(unsigned char *buf, size_t len, int *used) {
int numRead = 0;
int result = 0;
unsigned char read;
do {
if(numRead == len) {
*used = -1;
return 0;
}
read = buf[numRead];
int value = (read & 0b01111111);
result |= (value << (7 * numRead));
numRead++;
if (numRead > 5) {
*used = -2;
return 0;
}
} while ((read & 0b10000000) != 0);
*used = numRead;
return result;
}
struct mcpacket_handshake parse_handshake(unsigned char *buf, size_t len, char *status) {
struct mcpacket_handshake packet;
int head = 0;
int used = 0;
packet.protocol_version = read_VarInt(buf + head, len - head, &used);
if(used < 0) { *status = -1; return packet; }
head += used;
//packet.server_address_len = read_VarInt(buf + head, len - head, &used);
int addr_len = read_VarInt(buf + head, len - head, &used);
if(used < 0) { *status = -1; return packet; }
head += used;
if(addr_len > 255*4+3) { *status = -1; return packet; }
if(head + addr_len > len) { *status = -1; return packet; }
packet.server_address = malloc(addr_len + 1);
if(packet.server_address == NULL) { *status = -1; return packet; }
memcpy(packet.server_address, buf + head, addr_len);
packet.server_address[addr_len] = '\0';
head += addr_len;
// server port - unsigned short, ignoring it
if(head + 2 > len) {
free(packet.server_address);
*status = -1;
return packet;
}
head += 2;
packet.next_state = read_VarInt(buf + head, len - head, &used);
if(used < 0) {
free(packet.server_address);
*status = -1;
return packet;
}
*status = 0;
return packet;
}
struct mcpacket_hdr parse_hdr(unsigned char *buf, size_t len, int *bytes_used) {
struct mcpacket_hdr packet;
int head = 0;
int used = 0;
// packet length, as in minectaft protocol - len of packetid + data
int plen = read_VarInt(buf + head, len - head, &used);
if(used == -1) { // more data needed
*bytes_used = 0;
return packet;
}
if(used == -2) { // error reading plen
*bytes_used = -1;
return packet;
}
head += used;
packet.packetid = read_VarInt(buf + head, len - head, &used);
if(used == -1) { // more data needed
*bytes_used = 0;
return packet;
}
if(used == -2) { // error reading packetid
*bytes_used = -1;
return packet;
}
head += used;
if(plen-used < 0) {
*bytes_used = -1;
return packet;
}
// payload = minecraft protocol "data"
packet.payloadlen = plen-used;
//printf("payloadlen=%d, head=%d, plen=%d, used=%d, len=%ld\n", packet.payloadlen, head, plen, used, len);
if(head + packet.payloadlen > len) {
*bytes_used = 0; // need more data
return packet;
}
*bytes_used = head + packet.payloadlen;
packet.payload = malloc(packet.payloadlen); // TODO error checking
memcpy(packet.payload, buf + head, packet.payloadlen);
return packet;
}