aboutsummaryrefslogtreecommitdiff
path: root/libs/libnet/http.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libnet/http.c')
-rw-r--r--libs/libnet/http.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/libs/libnet/http.c b/libs/libnet/http.c
new file mode 100644
index 0000000..808d4c2
--- /dev/null
+++ b/libs/libnet/http.c
@@ -0,0 +1,134 @@
+// MIT License, Copyright (c) 2020 Marvin Borner
+
+#include <assert.h>
+#include <conv.h>
+#include <def.h>
+#include <libnet/http.h>
+#include <libnet/net.h>
+#include <libnet/socket.h>
+#include <mem.h>
+#include <print.h>
+#include <str.h>
+
+char *http_data(char *r)
+{
+ char *h = NULL;
+ for (u32 i = 0; i < strlen(r); ++i) {
+ if (r[i] == '\r' && r[i + 1] == '\n' && r[i + 2] == '\r' && r[i + 3] == '\n') {
+ h = &r[i + 4];
+ break;
+ }
+ }
+ return h;
+}
+
+char *http_header_key(char *r, const char *key)
+{
+ char *res = NULL;
+ for (char *p = r; *p; p++) {
+ /* printf("'%c%c%c' vs '%c%c%c'\n", p[0], p[1], p[2], key[0], key[1], key[2]); */
+ if (strlen(p) >= strlen(key) && !memcmp(p, key, strlen(key))) {
+ char *start = p + strlen(key) + 2;
+ char *end = start;
+ for (; *end != '\n'; end++)
+ ;
+ res = malloc(end - start);
+ memcpy(res, start, end - start - 1);
+ res[end - start] = '\0';
+ break;
+ }
+ }
+ return res;
+}
+
+u32 http_content_length(char *r)
+{
+ char *value = http_header_key(r, "Content-Length");
+ int length = value ? atoi(value) : 0;
+ free(value);
+ return length;
+}
+
+char *http_code(char *r)
+{
+ char *code = malloc(4);
+ char tmp = r[12];
+ r[12] = '\0';
+ memcpy(code, r + 9, 3);
+ code[3] = '\0';
+ r[12] = tmp;
+ return code;
+}
+
+u32 http_response(const char *http_code, u32 content_length, const char *data, char *resp)
+{
+ char buf[16] = { 0 };
+
+ resp[0] = '\0';
+ strcat(resp, "HTTP/1.1 ");
+ strcat(resp, buf);
+ strcat(resp, http_code);
+ strcat(resp, "\r\n");
+ strcat(resp, "Content-Length: ");
+ strcat(resp, conv_base(content_length, buf, 10, 0));
+ strcat(resp, "\r\n");
+ strcat(resp, "Server: Melvix\r\n");
+ strcat(resp, "Content-Type: text/html\r\n");
+ strcat(resp, "Connection: close\r\n\r\n");
+ u32 len = strlen(resp);
+ memcpy(&resp[len], data, content_length);
+
+ return len + content_length;
+}
+
+char *http_query_get(const char *url, const char *path)
+{
+ char *query = malloc(27 + strlen(url)); // TODO: Dynamic http length etc
+ query[0] = '\0';
+ strcat(query, "GET ");
+ if (path[0] != '/')
+ strcat(query, "/");
+ strcat(query, path);
+ strcat(query, " HTTP/1.1\r\nHost: ");
+ strcat(query, url);
+ strcat(query, "\r\n\r\n");
+ return query;
+}
+
+char *http_query_path(const char *query, char *path)
+{
+ u8 b = 0;
+ u32 s = 0;
+ u32 e = 0;
+
+ while (1) {
+ if (!b && query[e] == ' ' && query[++e]) {
+ s = e;
+ b = 1;
+ } else if (b && query[e] == ' ') {
+ strncat(path, &query[s], e - s);
+ break;
+ } else if (query[e] == '\0') {
+ return NULL;
+ }
+ e++;
+ }
+
+ return path;
+}
+
+char *http_receive(struct socket *socket)
+{
+ char buf[4096] = { 0 };
+ if (!net_receive(socket, buf, 4096, NET_TIMEOUT))
+ return NULL;
+
+ u32 length = http_content_length(buf);
+ char *data = malloc(strlen(buf) + length);
+ memcpy(data, buf, strlen(buf));
+ while (strlen(http_data(data)) != length) {
+ if (!net_receive(socket, data, length, NET_TIMEOUT))
+ break;
+ }
+ return data;
+}