Skip to content

Instantly share code, notes, and snippets.

@nitredd
Created July 25, 2021 12:53
Show Gist options
  • Save nitredd/03042b9ed9240b8765cd588569612a5a to your computer and use it in GitHub Desktop.
Save nitredd/03042b9ed9240b8765cd588569612a5a to your computer and use it in GitHub Desktop.
Parsing the Wire Protocol in C. I also wrote a Ruby version earlier, WireProto.
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
void processMessage(int);
struct wire_proto_message {
unsigned int msgLen;
unsigned int requestId;
unsigned int responseTo;
unsigned int opCode;
};
struct opquery_message {
unsigned int flags;
char* collection_name;
unsigned int skip;
unsigned int returned;
};
int main() {
const int sizeof_sockaddr_in = sizeof(struct sockaddr_in);
struct sockaddr_in server, client;
int srvsockfd, clientsockfd;
int retval;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(27000);
srvsockfd = socket(AF_INET, SOCK_STREAM, 0);
if (srvsockfd == -1) {
perror("Could not create a socket");
// printf("Could not create a socket");
// exit(-1);
}
retval = setsockopt(srvsockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int));
if (retval < 0) {
perror("Could not set socket option");
}
retval = bind(srvsockfd, (struct sockaddr *) &server, sizeof_sockaddr_in);
if (retval < 0) {
perror("Could not create a server socket");
// printf("Could not create a server socket");
// exit(-2);
}
listen(srvsockfd, 0);
clientsockfd = accept(srvsockfd, (struct sockaddr *) &client, (socklen_t *) &sizeof_sockaddr_in);
if (clientsockfd < 0) {
perror("Could not accept connection");
}
while(1) {
processMessage(clientsockfd);
}
puts("Received data");
return 0;
}
void processMessage(int clientsockfd) {
const unsigned int OP_QUERY = 2004;
struct wire_proto_message msgMeta1;
const int bufsize=4096;
int retval;
char databuf[bufsize];
retval = recv(clientsockfd, databuf, bufsize, 0);
if (retval < 0) {
perror("Could not receive data");
}
// unsigned int * msgLenPtr = (unsigned int *) databuf;
// unsigned int msgLenPtrDeref = * msgLenPtr;
msgMeta1.msgLen = *((unsigned int *) (databuf));
int bufPos = 0;
bufPos += 4;
msgMeta1.requestId = *((unsigned int *) (((char*)databuf) + bufPos));
bufPos += 4;
msgMeta1.responseTo = *((unsigned int *) (((char*)databuf) + bufPos));
bufPos += 4;
msgMeta1.opCode = *((unsigned int *) (((char*)databuf) + bufPos));
bufPos += 4;
if (msgMeta1.opCode == OP_QUERY) {
struct opquery_message opqueryMeta;
opqueryMeta.flags= *((unsigned int *) (((char*)databuf) + bufPos));
bufPos += 4;
int collnameLen = strlen(((char*)databuf) + bufPos);
opqueryMeta.collection_name = ((char*)databuf) + bufPos;
bufPos += collnameLen + 1;
opqueryMeta.skip= *((unsigned int *) (((char*)databuf) + bufPos));
bufPos += 4;
opqueryMeta.returned= *((unsigned int *) (((char*)databuf) + bufPos));
bufPos += 4;
// msgMeta1.msgLen - bufPos;
unsigned int bsonDocSize = *((unsigned int *) (((char*)databuf) + bufPos));
bufPos += 4;
//Set the debugger breakpoint here to examine the data within the 2 structs
puts("-");
}
puts(".");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment