]> Git repositories of Nishi - tewi.git/commitdiff
can parse http now
authorNishi <nishi@nishi.boats>
Fri, 13 Sep 2024 15:09:52 +0000 (15:09 +0000)
committerNishi <nishi@nishi.boats>
Fri, 13 Sep 2024 15:09:52 +0000 (15:09 +0000)
git-svn-id: file:///raid/svn-personal/tewi/trunk@16 8739d7e6-ffea-ec47-b151-bdff447c6205

Common/cm_string.h
Common/string.c
Server/Makefile
Server/config.c
Server/http.c [new file with mode: 0644]
Server/main.c
Server/server.c
Server/ssl.c
Server/tw_http.h [new file with mode: 0644]
Server/tw_server.h
Server/version.c

index 01f7f18e0cdfcd105ed3ff2ef0a580726cce34fa..476e297c2c4e17b336b2ef7e49dcfabd6476a517 100644 (file)
@@ -6,6 +6,7 @@
 #include <stdbool.h>
 
 char* cm_strcat(const char* a, const char* b);
+char* cm_strcat3(const char* a, const char* b, const char* c);
 char* cm_strdup(const char* str);
 char* cm_trimstart(const char* str);
 char* cm_trimend(const char* str);
index bd344584da5b59157a5207058e85546e1476e105..f858d7704076a034ab08d56c8710862e73d169a6 100644 (file)
@@ -13,6 +13,13 @@ char* cm_strcat(const char* a, const char* b) {
        return str;
 }
 
+char* cm_strcat3(const char* a, const char* b, const char* c) {
+       char* tmp = cm_strcat(a, b);
+       char* str = cm_strcat(tmp, c);
+       free(tmp);
+       return str;
+}
+
 char* cm_strdup(const char* str) { return cm_strcat(str, ""); }
 
 char* cm_trimstart(const char* str) {
index a2ef9e8c0138ad6406d799f5c8853b49ddf2e6ef..0053402eee8e70430a87f9ba4b75757558778157 100644 (file)
@@ -5,7 +5,7 @@ include $(PWD)/Platform/$(PLATFORM).mk
 .PHONY: all clean
 .SUFFIXES: .c .o
 
-OBJS = version.o main.o config.o server.o ssl.o
+OBJS = version.o main.o config.o server.o ssl.o http.o
 
 all: tewi$(EXEC)
 
index 1104a03a0c4efa96a99ec2c980c8eeefad2dc776..1920627ac9e7143e9accc2b344f3c118a9da24f2 100644 (file)
@@ -1,5 +1,7 @@
 /* $Id$ */
 
+#define SOURCE
+
 #include "tw_config.h"
 
 #include <stdio.h>
diff --git a/Server/http.c b/Server/http.c
new file mode 100644 (file)
index 0000000..0462d3d
--- /dev/null
@@ -0,0 +1,243 @@
+/* $Id$ */
+
+#define SOURCE
+
+#include "tw_http.h"
+
+#include "tw_server.h"
+
+#include <cm_log.h>
+#include <cm_string.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+
+void tw_free_request(struct tw_http_request* req) {
+       if(req->method != NULL) free(req->method);
+       if(req->path != NULL) free(req->path);
+       if(req->headers != NULL) {
+               int i;
+               for(i = 0; req->headers[i] != NULL; i++) free(req->headers[i]);
+               free(req->headers);
+       }
+       if(req->body != NULL) free(req->body);
+       if(req->version != NULL) free(req->version);
+}
+
+int tw_http_parse(SSL* ssl, int sock, struct tw_http_request* req) {
+       char buffer[512];
+       char cbuf[2];
+       int phase = 0;
+       fd_set fds;
+
+       bool bad = false;
+
+       cbuf[1] = 0;
+
+       req->method = NULL;
+       req->path = NULL;
+       req->headers = NULL;
+       req->body = NULL;
+       req->version = NULL;
+
+       char* header = malloc(1);
+       header[0] = 0;
+       int nl = 0;
+
+       while(1) {
+               FD_ZERO(&fds);
+               FD_SET(sock, &fds);
+               struct timeval tv;
+               tv.tv_sec = 5;
+               tv.tv_usec = 0;
+               int n = select(FD_SETSIZE, &fds, NULL, NULL, &tv);
+               if(n == 0) break;
+               int len = tw_read(ssl, sock, buffer, 512);
+               if(len <= 0) break;
+               int i;
+               for(i = 0; i < len; i++) {
+                       char c = buffer[i];
+                       if(phase == 0) {
+                               if(c == ' ') {
+                                       if(req->method == NULL) {
+                                               tw_free_request(req);
+                                               bad = true;
+                                               goto getout;
+                                       } else {
+                                               phase++;
+                                       }
+                               } else {
+                                       if(req->method == NULL) {
+                                               req->method = malloc(1);
+                                               req->method[0] = 0;
+                                       }
+                                       cbuf[0] = c;
+                                       char* tmp = req->method;
+                                       req->method = cm_strcat(tmp, cbuf);
+                                       free(tmp);
+                               }
+                       } else if(phase == 1) {
+                               if(c == ' ') {
+                                       if(req->path == NULL) {
+                                               tw_free_request(req);
+                                               bad = true;
+                                               goto getout;
+                                       } else {
+                                               phase++;
+                                       }
+                               } else {
+                                       if(req->path == NULL) {
+                                               req->path = malloc(1);
+                                               req->path[0] = 0;
+                                       }
+                                       cbuf[0] = c;
+                                       char* tmp = req->path;
+                                       req->path = cm_strcat(tmp, cbuf);
+                                       free(tmp);
+                               }
+                       } else if(phase == 2) {
+                               if(c == '\n') {
+                                       if(req->version == NULL) {
+                                               tw_free_request(req);
+                                               bad = true;
+                                               goto getout;
+                                       } else {
+                                               /* We have Method, Path, Version now */
+
+                                               if(strcmp(req->version, "HTTP/1.1") != 0 && strcmp(req->version, "HTTP/1.0") != 0) {
+                                                       cm_log("HTTP", "Bad HTTP Version");
+                                                       bad = true;
+                                                       goto getout;
+                                               }
+
+                                               int j;
+                                               char* p = malloc(1);
+                                               p[0] = 0;
+                                               for(j = 0; req->path[j] != 0; j++) {
+                                                       if(req->path[j] == '/') {
+                                                               cbuf[0] = '/';
+                                                               for(; req->path[j] != 0 && req->path[j] == '/'; j++)
+                                                                       ;
+                                                               j--;
+                                                       } else {
+                                                               cbuf[0] = req->path[j];
+                                                       }
+                                                       char* tmp = p;
+                                                       p = cm_strcat(tmp, cbuf);
+                                                       free(tmp);
+                                               }
+                                               free(req->path);
+                                               req->path = p;
+
+                                               int incr = 0;
+                                               p = malloc(1);
+                                               p[0] = 0;
+                                               for(j = 0;; j++) {
+                                                       if(req->path[j] == '/' || req->path[j] == 0) {
+                                                               char oldc = req->path[j];
+                                                               cbuf[0] = oldc;
+                                                               req->path[j] = 0;
+
+                                                               char* pth = req->path + incr;
+
+                                                               if(strcmp(pth, "..") == 0) {
+                                                                       int k;
+                                                                       if(p[strlen(p) - 1] == '/') p[strlen(p) - 1] = 0;
+                                                                       for(k = strlen(p) - 1; k >= 0; k--) {
+                                                                               if(p[k] == '/') {
+                                                                                       p[k + 1] = 0;
+                                                                                       break;
+                                                                               }
+                                                                       }
+                                                                       if(strlen(p) == 0) {
+                                                                               free(p);
+                                                                               p = cm_strdup("/");
+                                                                       }
+                                                               } else if(strcmp(pth, ".") == 0) {
+                                                               } else {
+                                                                       char* tmp = p;
+                                                                       p = cm_strcat3(tmp, pth, cbuf);
+                                                                       free(tmp);
+                                                               }
+
+                                                               incr = j + 1;
+                                                               if(oldc == 0) break;
+                                                       }
+                                               }
+                                               free(req->path);
+                                               req->path = p;
+
+                                               cm_log("HTTP", "Request: %s %s %s", req->method, req->path, req->version);
+
+                                               phase++;
+                                       }
+                               } else if(c != '\r') {
+                                       if(req->version == NULL) {
+                                               req->version = malloc(1);
+                                               req->version[0] = 0;
+                                       }
+                                       cbuf[0] = c;
+                                       char* tmp = req->version;
+                                       req->version = cm_strcat(tmp, cbuf);
+                                       free(tmp);
+                               }
+                       } else if(phase == 3) {
+                               if(c == '\n') {
+                                       nl++;
+                                       if(nl == 2) {
+                                               phase++;
+                                               goto getout;
+                                       } else {
+                                               if(req->headers == NULL) {
+                                                       req->headers = malloc(sizeof(*req->headers));
+                                                       req->headers[0] = NULL;
+                                               }
+                                               int j;
+                                               for(j = 0; header[j] != 0; j++) {
+                                                       if(header[j] == ':') {
+                                                               header[j] = 0;
+                                                               j++;
+                                                               for(; header[j] != 0 && (header[j] == ' ' || header[j] == '\t'); j++)
+                                                                       ;
+                                                               char* kv = header;
+                                                               char* vv = header + j;
+
+                                                               char** old = req->headers;
+                                                               int k;
+                                                               for(k = 0; old[k] != NULL; k++)
+                                                                       ;
+                                                               req->headers = malloc(sizeof(*req->headers) * (k + 3));
+                                                               for(k = 0; old[k] != NULL; k++) req->headers[k] = old[k];
+                                                               req->headers[k] = cm_strdup(kv);
+                                                               req->headers[k + 1] = cm_strdup(vv);
+                                                               req->headers[k + 2] = NULL;
+                                                               free(old);
+
+                                                               cm_log("HTTP", "Header: %s: %s", kv, vv);
+
+                                                               break;
+                                                       }
+                                               }
+                                               free(header);
+                                               header = malloc(1);
+                                               header[0] = 0;
+                                       }
+                               } else if(c != '\r') {
+                                       nl = 0;
+                                       cbuf[0] = c;
+                                       char* tmp = header;
+                                       header = cm_strcat(tmp, cbuf);
+                                       free(tmp);
+                               }
+                       }
+               }
+       }
+getout:
+       free(header);
+       if(bad) {
+               tw_free_request(req);
+               return 1;
+       }
+       return 0;
+}
index eb13a489580af579fffbb17de8111e5be28a96d6..e0cccb2c924d32ca18704513fec7bd878bf44e2d 100644 (file)
@@ -1,8 +1,11 @@
 /* $Id$ */
 
+#define SOURCE
+
 #include <stdio.h>
 #include <stdbool.h>
 #include <string.h>
+#include <signal.h>
 
 #include <openssl/opensslv.h>
 
@@ -49,5 +52,8 @@ int main(int argc, char** argv) {
                return 1;
        }
        cm_log("Daemon", "Ready");
+#ifndef __MINGW32__
+       signal(SIGCHLD, SIG_IGN);
+#endif
        tw_server_loop();
 }
index 120e5a1b26763e4167a1ddb172346127d9b785b8..3f4d45d9875d41ec68919963de96691966d668dd 100644 (file)
@@ -1,9 +1,12 @@
 /* $Id$ */
 
+#define SOURCE
+
 #include "tw_server.h"
 
 #include "tw_ssl.h"
 #include "tw_config.h"
+#include "tw_http.h"
 
 #include <unistd.h>
 #include <string.h>
@@ -112,6 +115,22 @@ int tw_server_init(void) {
        return 0;
 }
 
+size_t tw_read(SSL* ssl, int s, void* data, size_t len) {
+       if(ssl == NULL) {
+               return recv(s, data, len, 0);
+       } else {
+               return SSL_read(ssl, data, len);
+       }
+}
+
+size_t tw_write(SSL* ssl, int s, void* data, size_t len) {
+       if(ssl == NULL) {
+               return send(s, data, len, 0);
+       } else {
+               return SSL_write(ssl, data, len);
+       }
+}
+
 #ifdef __MINGW32__
 struct pass_entry {
        int sock;
@@ -139,8 +158,10 @@ void tw_server_pass(int sock, bool ssl, int port) {
                if(SSL_accept(s) <= 0) goto cleanup;
                sslworks = true;
        }
+       struct tw_http_request req;
+       int ret = tw_http_parse(s, sock, &req);
 cleanup:
-       if(sslworks){
+       if(sslworks) {
                SSL_shutdown(s);
        }
        SSL_free(s);
index e5bb8d3481e1e0b6655b1af3d78d472617111cf6..db4e0019f6844d5f4e2bc410a1488fb43393b693 100644 (file)
@@ -1,5 +1,7 @@
 /* $Id$ */
 
+#define SOURCE
+
 #include "tw_ssl.h"
 
 #include "tw_config.h"
diff --git a/Server/tw_http.h b/Server/tw_http.h
new file mode 100644 (file)
index 0000000..2818c65
--- /dev/null
@@ -0,0 +1,25 @@
+/* $Id$ */
+
+#ifndef __TW_HTTP_H__
+#define __TW_HTTP_H__
+
+struct tw_http_request {
+       char* method;
+       char* path;
+       char* version;
+       char** headers;
+       char* body;
+};
+
+struct tw_http_response {
+       char** headers;
+};
+
+struct tw_http_tool {};
+
+#ifdef SOURCE
+#include <openssl/ssl.h>
+int tw_http_parse(SSL* ssl, int sock, struct tw_http_request* req);
+#endif
+
+#endif
index 3ab54d6db0a7a49c82b7dce6c0e1afba5a850fe2..eecb72c23a5d9c1a2653115686eb9e6f7dbc2665 100644 (file)
@@ -3,7 +3,11 @@
 #ifndef __TW_SERVER_H__
 #define __TW_SERVER_H__
 
+#include <openssl/ssl.h>
+
 int tw_server_init(void);
 void tw_server_loop(void);
+size_t tw_read(SSL* ssl, int s, void* data, size_t len);
+size_t tw_write(SSL* ssl, int s, void* data, size_t len);
 
 #endif
index ef33fab11033b3d0ad634313ac6d568d52b8e503..480577016a1d64e7d6eb4256f702aca276d106af 100644 (file)
@@ -1,5 +1,7 @@
 /* $Id$ */
 
+#define SOURCE
+
 #include "tw_version.h"
 
 const char* tw_version = "0.00";