#include #include #include #include "parslib.h" #include "streecmp/streecmp.h" extern char *methods; extern char *headers; static struct nod *method_tree = NULL; static struct nod *header_tree = NULL; static int stoin(char *str, int len, int *out) { int ret = 0; int place = 1; for (char *chr = str+len; chr >= str; chr--) { if (chr == str) { if (*ch == '+') { goto _proceed; } if (*ch == '-') { goto _proceed; } } if (*chr >= '0' && *ch <= '9') { goto _proceed; } return -1; _proceed: if (*chr == '-') { ret = -ret; continue; } if (*chr == '+') { continue; } int number = *chr-'0'; ret += number * place; place *= 10; } *out = ret; } void printfpars(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 parestitl(char *offset, int len, struct httitleres *titl) { int ret = 0; int diff = 0; char *cursor = offset; char *cursor_lim = cursor+len; // ver char *ver_lim = strchr(cursor, ' '); if (!ver_lim) { return -1; } if (ver_lim > cursor_lim) { return -1; } diff = ver_lim-cursor; titl->ver.er = cursor; titl->ver.len = diff; cursor += diff; // white space _loop1: if (cursor > cursor_lim) { return -1; } if (*cursor == ' ') { cursor++; goto _loop1; } // code char *code_lim = strchr(cursor, ' '); if (!code_lim) { return -1; } if (code_lim > cursor_lim) { return -1; } diff = code_lim-cursor; int code; ret = stoin(cursor, diff, &code); if (ret < 0) { return -1; } titl->code = code; cursor += diff; // white space _loop2: if (cursor > cursor_lim) { return -1; } if (*cursor == ' ') { cursor++; goto _loop2; } // status text diff = cursor_lim-cursor; titl->stxt.er = cursor; titl->stxt.len = diff; cursor += diff; return 0; } int pareqtitl(char *offset, int len, struct httitlereq *titl) { int ret = 0; int diff = 0; char *cursor = offset; char *cursor_lim = cursor+len; // method char *method_lim = strchr(cursor, ' '); 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; }