Created
May 24, 2012 14:35
-
-
Save deoxxa/2781929 to your computer and use it in GitHub Desktop.
Silly zero-copy minecraft protocol parser idea!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CFLAGS += -std=c99 -Wall -Werror -Wextra -pedantic -O0 -g | |
all: test | |
parser.o: parser.c | |
$(CC) $(CFLAGS) $(LDFLAGS) -c -o parser.o parser.c | |
test.o: test.c | |
$(CC) $(CFLAGS) $(LDFLAGS) -c -o test.o test.c | |
test: parser.o test.o | |
$(CC) $(CFLAGS) $(LDFLAGS) -o test test.o parser.o | |
clean: | |
rm -f *.o test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PARSER_PACKETS_H | |
#define PARSER_PACKETS_H | |
#include <stdint.h> | |
#define PACKET_LENGTH 1 | |
typedef struct protocol_packet_s { | |
uint8_t type; | |
} protocol_packet_t; | |
#define PACKET_LENGTH_00 5 | |
typedef struct protocol_packet_00_s { | |
uint8_t type; | |
int32_t id; | |
} protocol_packet_00_t; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <sys/types.h> | |
#define __USE_BSD | |
#include <endian.h> | |
#include "parser.h" | |
#include "packets.h" | |
#define UNUSED(x) (void)(x) | |
#define PARSER_CASE(x) case 0x##x: { if (data_len < PACKET_LENGTH_##x) { return 0; } else { return protocol_parser_parse_##x(parser, settings, data, data_len); } } | |
size_t protocol_parser_execute(protocol_parser_t* parser, protocol_parser_settings_t* settings, char* data, size_t data_len) { | |
if (data_len < 1) { | |
return 0; | |
} | |
switch (data[0]) { | |
PARSER_CASE(00); | |
default: { | |
if (settings->on_error != NULL) { | |
settings->on_error(parser, -1); | |
} | |
return 0; | |
} | |
} | |
return 0; | |
} | |
size_t protocol_parser_parse_00(protocol_parser_t* parser, protocol_parser_settings_t* settings, char* data, size_t data_len) { | |
protocol_packet_00_t packet; | |
UNUSED(data_len); | |
packet.type = data[0]; | |
packet.id = htobe32(*((int32_t*)(data + 1))); | |
if (settings->on_packet != NULL) { | |
settings->on_packet(parser, (protocol_packet_t*)&packet); | |
} | |
return 5; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PARSER_H | |
#define PARSER_H | |
#include "packets.h" | |
typedef struct protocol_parser_s { | |
void* data; | |
} protocol_parser_t; | |
typedef void (*packet_cb)(protocol_parser_t* parser, protocol_packet_t* packet); | |
typedef void (*error_cb)(protocol_parser_t* parser, int err); | |
typedef struct protocol_parser_settings_s { | |
packet_cb on_packet; | |
error_cb on_error; | |
} protocol_parser_settings_t; | |
size_t protocol_parser_execute(protocol_parser_t* parser, protocol_parser_settings_t* settings, char* data, size_t data_len); | |
size_t protocol_parser_parse_00(protocol_parser_t* parser, protocol_parser_settings_t* settings, char* data, size_t data_len); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include "parser.h" | |
#include "packets.h" | |
void on_packet(protocol_parser_t* parser, protocol_packet_t* packet) { | |
printf("[%p] packet type: %02x\n", parser->data, packet->type); | |
if (packet->type == 0x00) { | |
protocol_packet_00_t* packet_00 = (protocol_packet_00_t*)packet; | |
printf("-> id: %d\n", packet_00->id); | |
} | |
} | |
void on_error(protocol_parser_t* parser, int err) { | |
printf("[%p] error %d\n", parser->data, err); | |
} | |
int main() { | |
protocol_parser_t parser = { .data = NULL }; | |
protocol_parser_settings_t settings = { .on_packet = on_packet, .on_error = on_error }; | |
char data[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02 }; | |
size_t nparsed = 0, offset = 0; | |
while ((nparsed = protocol_parser_execute(&parser, &settings, data + offset, 10 - offset)) != 0) { | |
printf("parsed %d bytes\n", nparsed); | |
offset += nparsed; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment