Skip to content

Instantly share code, notes, and snippets.

@ldmsys
Last active March 7, 2024 00:40
Show Gist options
  • Save ldmsys/db228996c9696c7ad59a579abb6e7afd to your computer and use it in GitHub Desktop.
Save ldmsys/db228996c9696c7ad59a579abb6e7afd to your computer and use it in GitHub Desktop.
FakeMCServer Minimal Edition (requires 3 syscall: read(), write(), close())
#define MC_MTU 1500
#define MC_COLOR_PREFIX "\xc2\247"
#define MC_MOTD MC_COLOR_PREFIX "b" MC_COLOR_PREFIX "l" "FakeMCServer Test"
#define MC_KICK_MESSAGE "You are not white-listed on this server!"
typedef int type_debug_func (const char*, ...);
size_t mc_varintSize(unsigned char* varint) {
int i;
for(i=0;i<4;i++) if((varint[i] & 0x80) == 0) break;
return i+1;
}
int mc_varintToint(unsigned char* varint) {
int value = 0;
char currentByte;
for(int i=0;i<4;i++) {
currentByte = varint[i];
value |= (currentByte & 0x7f) << i*7;
if ((currentByte & 0x80) == 0) break;
}
return value;
}
size_t mc_intTovarint(int data, unsigned char* varint) {
int i;
for (i=0; i<4; i++) {
if ((data & ~0x7f) == 0) {
varint[i] = data;
break;
}
varint[i] = (data & 0x7f) | 0x80;
data >>= 7;
}
return i+1;
}
size_t mc_appendLengthvarint(char* string, size_t length, char* mcstring) {
unsigned char len[4];
int i;
size_t headerlen;
headerlen = mc_intTovarint(length, len);
for (i=0; i<headerlen; i++) mcstring[i] = len[i];
for (i=0; i<length; i++) mcstring[i+headerlen] = string[i];
return headerlen+length;
}
size_t mc_strlen(char* string) {
size_t cnt;
for(cnt=0;(cnt<MC_MTU && string[cnt] != '\0'); cnt++) {}
return cnt;
}
void mc_handle_session(int fd, type_debug_func debug_func) {
int i, n, dn, expected_packet_size, mode, yebiopt, protocol;
unsigned char buf[MC_MTU], returnbuf[MC_MTU], yebibuf[MC_MTU], packedJSON[MC_MTU], packetID, payloadsize_varint[4];
char *json, *motd_json, *kick_json;
size_t payloadsize, lengthsize, final_size, sz_i;
motd_json = "{\"version\": {\"name\": \"ldmsys 1.12.2\", \"protocol\":340},\"players\":{\"max\":99999,\"online\": 0,\"sample\":[]},\"description\":{\"text\": \"" MC_MOTD "\"}}";
kick_json = "{\"text\": \"" MC_KICK_MESSAGE "\"}";
i = n = expected_packet_size = mode = yebiopt = protocol = 0;
(!!debug_func) && debug_func("One connected!\n");
while (1) {
if (yebiopt) {
(!!debug_func) && debug_func("Restoring from yebi! %d\n", yebiopt);
n = yebiopt;
for (i=0; i<yebiopt; i++) buf[i] = yebibuf[i];
yebiopt = 0;
} else {
(!!debug_func) && debug_func("Reading... %d\n", mode);
dn = read(fd, buf+n, 1500-n);
if (dn <= 0) {
close(fd);
break;
}
n += dn;
(!!debug_func) && debug_func("Read! +%d=%d\n", dn,n);
}
if(expected_packet_size == 0) {
expected_packet_size = mc_varintToint(buf);
(!!debug_func) && debug_func("Expected packet size: %d\n", expected_packet_size);
}
if(expected_packet_size == 0) continue;
if(n < expected_packet_size + mc_varintSize(buf)) {
(!!debug_func) && debug_func("Johnbeo! %d < %d\n", n, expected_packet_size + mc_varintSize(buf));
continue;
} else if(n > expected_packet_size + mc_varintSize(buf)) {
(!!debug_func) && debug_func("Moving! %d > %d\n", n, expected_packet_size + mc_varintSize(buf));
for (i=0; i<n-expected_packet_size; i++)
yebibuf[i] = *(buf+expected_packet_size+mc_varintSize(buf)+i);
yebiopt = n-expected_packet_size-mc_varintSize(buf);
n = expected_packet_size + mc_varintSize(buf);
}
// Complete Packet Received
packetID = buf[mc_varintSize(buf)];
(!!debug_func) && debug_func("Packet done! %x %x %x %x %x (%d)\n", buf[0], buf[1], buf[2], buf[3], buf[4], mc_varintSize(buf));
if(mode == 0) { // pre-handshaking
protocol = mc_varintToint(buf+mc_varintSize(buf)+1);
mode = buf[expected_packet_size]; // new mode
(!!debug_func) && debug_func("Handshaking! %d\n", mode);
if(packetID != 0 || mode > 2 || mode <= 0) {
// Undefined behavior
(!!debug_func) && debug_func("Undefined behavior! %d %d\n", packetID, mode);
close(fd); break;
}
} else if(mode == 1 || mode == 2) {
(!!debug_func) && debug_func("Respond Mode! %d\n", packetID);
if (packetID == 0) { // MOTD Request
// json should vary on mode == 1 or mode == 2, ping and kick respectively.
json = (mode - 1) ? kick_json : motd_json;
payloadsize = mc_appendLengthvarint(json, mc_strlen(json), (void*)packedJSON);
lengthsize = mc_intTovarint(payloadsize+1, payloadsize_varint);
for (sz_i=0; sz_i<lengthsize; sz_i++) returnbuf[sz_i] = payloadsize_varint[sz_i];
returnbuf[lengthsize] = 0x00;
for (sz_i=0; sz_i<payloadsize; sz_i++) returnbuf[lengthsize+1+sz_i] = packedJSON[sz_i];
(!!debug_func) && debug_func("Sent JSON! 1 %d %d %d\n", payloadsize, lengthsize, 1 + payloadsize + lengthsize);
write(fd, returnbuf, 1 + payloadsize + lengthsize);
} else if(packetID == 1) { // Ping Request
if (mode == 1)
write(fd, buf, expected_packet_size+mc_varintSize(buf)); // Send back the full packet
else {
close(fd); // Undefined behavior
break;
}
}
}
n = expected_packet_size = 0;
for (i=0; i<MC_MTU; i++) buf[i] = 0;
}
(!!debug_func) && debug_func("Got out of loop!\n");
close(fd);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment