Created
July 25, 2021 12:53
-
-
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.
This file contains hidden or 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 <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