aboutsummaryrefslogtreecommitdiff
path: root/src/net/util.c
diff options
context:
space:
mode:
authoramelia squires <[email protected]>2024-08-26 12:41:30 -0500
committeramelia squires <[email protected]>2024-08-26 12:42:47 -0500
commit064376146afad7af0b496014c59ba4b4f78d4c78 (patch)
tree408852199d1e7cd5cfc628319671622ab8f51558 /src/net/util.c
parentb093eebff0f8c6dedc49c62747049fe7e464c8f3 (diff)
sort networking code
Diffstat (limited to 'src/net/util.c')
-rw-r--r--src/net/util.c241
1 files changed, 241 insertions, 0 deletions
diff --git a/src/net/util.c b/src/net/util.c
new file mode 100644
index 0000000..213be9f
--- /dev/null
+++ b/src/net/util.c
@@ -0,0 +1,241 @@
+#include "common.h"
+#include "util.h"
+
+/**
+ * @brief calls recv into buffer until everything is read
+ *
+*/
+int64_t recv_full_buffer(int client_fd, char** _buffer, int* header_eof, int* state){
+ char* header, *buffer = malloc(BUFFER_SIZE * sizeof * buffer);
+ memset(buffer, 0, BUFFER_SIZE);
+ int64_t len = 0;
+ *header_eof = -1;
+ int n, content_len = -1;
+ //printf("&_\n");
+ for(;;){
+ n = recv(client_fd, buffer + len, BUFFER_SIZE, 0);
+ if(n < 0){
+ *_buffer = buffer;
+ printf("%s %i\n",strerror(errno),errno);
+ if(*header_eof == -1) return -2; //dont even try w/ request, no header to read
+ return -1; //well the header is fine atleast
+
+ };
+ if(*header_eof == -1 && (header = strstr(buffer, "\r\n\r\n")) != NULL){
+ *header_eof = header - buffer;
+ char* cont_len_raw = strstr(buffer, "Content-Length: ");
+
+ if(cont_len_raw == NULL) {
+ len += n;
+ *_buffer = buffer;
+ return len;
+ }
+
+ str* cont_len_str = str_init("");
+ if(cont_len_raw == NULL) abort();
+ //i is length of 'Content-Length: '
+ for(int i = 16; cont_len_raw[i] != '\r'; i++) str_pushl(cont_len_str, cont_len_raw + i, 1);
+ content_len = strtol(cont_len_str->c, NULL, 10);
+ str_free(cont_len_str);
+ if(content_len > max_content_length) {
+ *_buffer = buffer;
+ *state = (len + n != content_len + *header_eof + 4);
+ return len + n;
+ }
+ buffer = realloc(buffer, content_len + *header_eof + 4 + BUFFER_SIZE);
+ if(buffer == NULL) p_fatal("unable to allocate");
+ }
+
+ len += n;
+ if(*header_eof == -1){
+ buffer = realloc(buffer, len + BUFFER_SIZE + 1);
+ memset(buffer + len, 0, n + 1);
+ }
+
+
+ if(content_len != -1 && len - *header_eof - 4 >= content_len) break;
+ }
+ *_buffer = buffer;
+ return len;
+}
+
+/**
+ * @brief converts the request buffer into a parray_t
+ *
+*/
+int parse_header(char* buffer, int header_eof, parray_t** _table){
+ if(header_eof == -1) return -1;
+ char add[] = {0,0};
+ int lines = 3;
+ for(int i = 0; i != header_eof; i++) lines += buffer[i] == '\n';
+ parray_t* table = parray_init();
+ str* current = str_init("");
+ int oi = 0;
+ int item = 0;
+ for(; oi != header_eof; oi++){
+ if(buffer[oi] == ' ' || buffer[oi] == '\n'){
+ if(buffer[oi] == '\n') current->c[current->len - 1] = 0;
+ parray_set(table, item == 0 ? "Request" :
+ item == 1 ? "Path" : "Version", (void*)str_init(current->c));
+ str_clear(current);
+ item++;
+ if(buffer[oi] == '\n') break;
+ } else str_pushl(current, buffer + oi, 1);
+ }
+
+ int key = 1;
+ str* sw = NULL;
+ for(int i = oi + 1; i != header_eof; i++){
+ if(buffer[i] == ' ' && strcmp(current->c, "") == 0) continue;
+ if(key && buffer[i] == ':' || !key && buffer[i] == '\n'){
+ if(key){
+ sw = current;
+ current = str_init("");
+ key = 0;
+ } else {
+ if(buffer[oi] == '\n') current->c[current->len - 1] = 0;
+ parray_set(table, sw->c, (void*)str_init(current->c));
+ str_clear(current);
+ str_free(sw);
+ sw = NULL;
+ key = 1;
+ }
+ continue;
+ } else str_pushl(current, buffer + i, 1);
+ }
+ parray_set(table, sw->c, (void*)str_init(current->c));
+
+ str_free(current);
+ if(sw != NULL) str_free(sw);
+ *_table = table;
+ return 0;
+}
+
+/**
+ * @brief contructs an http request
+ *
+*/
+void http_build(str** _dest, int code, char* code_det, char* header_vs, char* content, size_t len){
+ char* dest = malloc(HTTP_BUFFER_SIZE);
+ memset(dest, 0, HTTP_BUFFER_SIZE);
+
+ sprintf(dest,
+ "HTTP/1.1 %i %s\r\n"
+ "%s"
+ "\r\n"
+ , code, code_det, header_vs);
+ *_dest = str_init(dest);
+ str_pushl(*_dest, content, len);
+
+ free(dest);
+}
+
+/**
+ * @brief gets a string representation of a http code
+ *
+*/
+void http_code(int code, char* code_det){
+ //this was done with a script btw
+ switch(code){
+ case 100: sprintf(code_det,"Continue"); break;
+ case 101: sprintf(code_det,"Switching Protocols"); break;
+ case 102: sprintf(code_det,"Processing"); break;
+ case 103: sprintf(code_det,"Early Hints"); break;
+ case 200: sprintf(code_det,"OK"); break;
+ case 201: sprintf(code_det,"Created"); break;
+ case 202: sprintf(code_det,"Accepted"); break;
+ case 203: sprintf(code_det,"Non-Authoritative Information"); break;
+ case 204: sprintf(code_det,"No Content"); break;
+ case 205: sprintf(code_det,"Reset Content"); break;
+ case 206: sprintf(code_det,"Partial Content"); break;
+ case 207: sprintf(code_det,"Multi-Status"); break;
+ case 208: sprintf(code_det,"Already Reported"); break;
+ case 226: sprintf(code_det,"IM Used"); break;
+ case 300: sprintf(code_det,"Multiple Choices"); break;
+ case 301: sprintf(code_det,"Moved Permanently"); break;
+ case 302: sprintf(code_det,"Found"); break;
+ case 303: sprintf(code_det,"See Other"); break;
+ case 304: sprintf(code_det,"Not Modified"); break;
+ case 307: sprintf(code_det,"Temporary Redirect"); break;
+ case 308: sprintf(code_det,"Permanent Redirect"); break;
+ case 400: sprintf(code_det,"Bad Request"); break;
+ case 401: sprintf(code_det,"Unauthorized"); break;
+ case 402: sprintf(code_det,"Payment Required"); break;
+ case 403: sprintf(code_det,"Forbidden"); break;
+ case 404: sprintf(code_det,"Not Found"); break;
+ case 405: sprintf(code_det,"Method Not Allowed"); break;
+ case 406: sprintf(code_det,"Not Acceptable"); break;
+ case 407: sprintf(code_det,"Proxy Authentication Required"); break;
+ case 408: sprintf(code_det,"Request Timeout"); break;
+ case 409: sprintf(code_det,"Conflict"); break;
+ case 410: sprintf(code_det,"Gone"); break;
+ case 411: sprintf(code_det,"Length Required"); break;
+ case 412: sprintf(code_det,"Precondition Failed"); break;
+ case 413: sprintf(code_det,"Content Too Large"); break;
+ case 414: sprintf(code_det,"URI Too Long"); break;
+ case 415: sprintf(code_det,"Unsupported Media Type"); break;
+ case 416: sprintf(code_det,"Range Not Satisfiable"); break;
+ case 417: sprintf(code_det,"Expectation Failed"); break;
+ case 418: sprintf(code_det,"I'm a teapot"); break;
+ case 421: sprintf(code_det,"Misdirected Request"); break;
+ case 422: sprintf(code_det,"Unprocessable Content"); break;
+ case 423: sprintf(code_det,"Locked"); break;
+ case 424: sprintf(code_det,"Failed Dependency"); break;
+ case 425: sprintf(code_det,"Too Early"); break;
+ case 426: sprintf(code_det,"Upgrade Required"); break;
+ case 428: sprintf(code_det,"Precondition Required"); break;
+ case 429: sprintf(code_det,"Too Many Requests"); break;
+ case 431: sprintf(code_det,"Request Header Fields Too Large"); break;
+ case 451: sprintf(code_det,"Unavailable For Legal Reasons"); break;
+ case 500: sprintf(code_det,"Internal Server Error"); break;
+ case 501: sprintf(code_det,"Not Implemented"); break;
+ case 502: sprintf(code_det,"Bad Gateway"); break;
+ case 503: sprintf(code_det,"Service Unavailable"); break;
+ case 504: sprintf(code_det,"Gateway Timeout"); break;
+ case 505: sprintf(code_det,"HTTP Version Not Supported"); break;
+ case 506: sprintf(code_det,"Variant Also Negotiates"); break;
+ case 507: sprintf(code_det,"Insufficient Storage"); break;
+ case 508: sprintf(code_det,"Loop Detected"); break;
+ case 510: sprintf(code_det,"Not Extended"); break;
+ case 511: sprintf(code_det,"Network Authentication Required"); break;
+ default: sprintf(code_det,"unknown");
+ }
+}
+
+void client_fd_errors(int client_fd){
+ if(client_fd>=0) return;
+
+ switch(client_fd){
+ case -1:
+ p_fatal("client fd already closed\n");
+ case -2:
+ p_fatal("request was partial\n");
+ default:
+ p_fatal("unknown negative client_fd value");
+ }
+}
+
+int content_disposition(str* src, parray_t** _dest){
+
+ char* end = strnstr(src->c, ";", src->len);
+ parray_t* dest = parray_init();
+ if(end == NULL){
+ parray_set(dest, "form-data", (void*)str_init(src->c));
+ return 0;
+ }
+ str* temp = str_init("");
+ str_pushl(temp, src->c, end - src->c);
+ parray_set(dest, "form-data", (void*)temp);
+
+ int len = end - src->c;
+ char* buffer = end + 1;
+
+ gen_parse(buffer, src->len - len, &dest);
+ //printf("\n**\n");
+ //for(int i = 0; i != dest->len; i++){
+ // printf("'%s : %s'\n",((str*)dest->P[i].key)->c,((str*)dest->P[i].value)->c);
+ //}
+ *_dest = dest;
+
+ return 1;
+}