#include #include #include #include "tinyparser.h" #include "streecmp/streecmp.h" extern char *methods; extern char *headers; static struct nod *method_tree = NULL; static struct nod *header_tree = NULL; static void debug_stats(struct httpars *pars) { fprintf(stderr, "\tstats:\n" "\t\tmethod\t: %d\n" "\t\turi\t: %.*s\n" "\t\tver\t: %.*s\n", pars->titl.method, pars->titl.uri.len, pars->titl.uri.er, pars->titl.ver.len, pars->titl.ver.er ); fprintf(stdout, "\theaders:\n"); for (int i = 0; i < header_count; i++) { struct point *pnt = &pars->hentries[i]; if (!pnt->er) { continue; } fprintf(stdout, "\t\t%d\t: %.*s\n", i, pnt->len, pnt->er); } } int initres(void) { int ret = 0; header_tree = allocnod(); if (!header_tree) { return -1; } method_tree = allocnod(); if (!method_tree) { return -1; } ret = gentree(header_tree, headers, NULL); if (ret < 0) { return -1; } ret = gentree(method_tree, methods, NULL); if (ret < 0) { return -1; } return 0; } void fretres(void) { free(method_tree); free(header_tree); } int readlin(char **buff, char **buff_lim) { int diff = 0; if ((*buff) >= (*buff_lim)) { return diff; } int ret = 0; char *match = strstr(*buff, "\r\n"); if (match) { ret = match-(*buff); *buff += 2; } else { ret = (*buff_lim)-(*buff); } *buff += ret; return ret; } int parshfield(char *offset, int len, struct point *hentries) { int key = 0; int ret = 0; int diff = 0; char *cursor = offset; char *cursor_lim = offset+len; // header title char *htitle_lim = strchr(cursor, ':'); if (!htitle_lim) { return -1; } if (htitle_lim > cursor_lim) { return -1; } diff = htitle_lim-cursor; ret = streencmp(header_tree, cursor, diff); if (!ret) { return -1; } key = ret; cursor += diff; // white space and seperators _loop: if (cursor > cursor_lim) { return -1; } if (*cursor == ':') { cursor++; goto _loop; } if (*cursor == ' ') { cursor++; goto _loop; } // header value diff = cursor_lim-cursor; hentries[key].er = cursor; hentries[key].len = diff; return 0; } int parstitle(char *offset, int len, struct httitle *titl) { int ret = 0; int diff = 0; char *cursor = offset; char *cursor_lim = cursor+len; // method char *method_lim = strchr(offset, ' '); if (!method_lim) { return -1; } if (method_lim > cursor_lim) { return -1; } diff = method_lim-cursor; ret = streencmp(method_tree, cursor, diff); if (ret == 0) { return -1; } titl->method = ret; cursor += diff; // white space _loop1: if (cursor > cursor_lim) { return -1; } if (*cursor == ' ') { cursor++; goto _loop1; } // uri char *uri_lim = strchr(cursor, ' '); if (!uri_lim) { return -1; } if (uri_lim > cursor_lim) { return -1; } diff = uri_lim-cursor; titl->uri.er = cursor; titl->uri.len = diff; cursor += diff; // white space _loop2: if (cursor > cursor_lim) { return -1; } if (*cursor == ' ') { cursor++; goto _loop2; } // ver diff = cursor_lim-cursor; titl->ver.er = cursor; titl->ver.len = diff; cursor += diff; return 0; } int parsme(char *buff, struct httpars *pars) { int ret; char *buff_lim = buff+strlen(buff); char *title_offset = buff; int title_len = readlin(&buff, &buff_lim); if ((ret = parstitle(title_offset, title_len, &pars->titl)) < 0) { fprintf(stderr, "Failed parsing title\n"); return -1; } for (int bound = 0; bound < MAX_BOUND; bound++) { char *header_offset = buff; int header_len = readlin(&buff, &buff_lim); char *header_limit = header_offset+header_len; // IF END OF MESSAGE if (!header_len) { break; } if ((ret = parshfield(header_offset, header_len, pars->hentries)) < 0) { fprintf(stderr, "Failed parsing header\n"); return -1; } } return 0; }