can parse http now

git-svn-id: file:///raid/svn-personal/tewi/trunk@16 8739d7e6-ffea-ec47-b151-bdff447c6205
This commit is contained in:
Nishi 2024-09-13 15:09:52 +00:00
parent 44d467e9f0
commit ddcd7e3817
11 changed files with 315 additions and 2 deletions

View File

@ -6,6 +6,7 @@
#include <stdbool.h> #include <stdbool.h>
char* cm_strcat(const char* a, const char* b); 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_strdup(const char* str);
char* cm_trimstart(const char* str); char* cm_trimstart(const char* str);
char* cm_trimend(const char* str); char* cm_trimend(const char* str);

View File

@ -13,6 +13,13 @@ char* cm_strcat(const char* a, const char* b) {
return str; 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_strdup(const char* str) { return cm_strcat(str, ""); }
char* cm_trimstart(const char* str) { char* cm_trimstart(const char* str) {

View File

@ -5,7 +5,7 @@ include $(PWD)/Platform/$(PLATFORM).mk
.PHONY: all clean .PHONY: all clean
.SUFFIXES: .c .o .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) all: tewi$(EXEC)

View File

@ -1,5 +1,7 @@
/* $Id$ */ /* $Id$ */
#define SOURCE
#include "tw_config.h" #include "tw_config.h"
#include <stdio.h> #include <stdio.h>

243
Server/http.c Normal file
View File

@ -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;
}

View File

@ -1,8 +1,11 @@
/* $Id$ */ /* $Id$ */
#define SOURCE
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <signal.h>
#include <openssl/opensslv.h> #include <openssl/opensslv.h>
@ -49,5 +52,8 @@ int main(int argc, char** argv) {
return 1; return 1;
} }
cm_log("Daemon", "Ready"); cm_log("Daemon", "Ready");
#ifndef __MINGW32__
signal(SIGCHLD, SIG_IGN);
#endif
tw_server_loop(); tw_server_loop();
} }

View File

@ -1,9 +1,12 @@
/* $Id$ */ /* $Id$ */
#define SOURCE
#include "tw_server.h" #include "tw_server.h"
#include "tw_ssl.h" #include "tw_ssl.h"
#include "tw_config.h" #include "tw_config.h"
#include "tw_http.h"
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@ -112,6 +115,22 @@ int tw_server_init(void) {
return 0; 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__ #ifdef __MINGW32__
struct pass_entry { struct pass_entry {
int sock; int sock;
@ -139,8 +158,10 @@ void tw_server_pass(int sock, bool ssl, int port) {
if(SSL_accept(s) <= 0) goto cleanup; if(SSL_accept(s) <= 0) goto cleanup;
sslworks = true; sslworks = true;
} }
struct tw_http_request req;
int ret = tw_http_parse(s, sock, &req);
cleanup: cleanup:
if(sslworks){ if(sslworks) {
SSL_shutdown(s); SSL_shutdown(s);
} }
SSL_free(s); SSL_free(s);

View File

@ -1,5 +1,7 @@
/* $Id$ */ /* $Id$ */
#define SOURCE
#include "tw_ssl.h" #include "tw_ssl.h"
#include "tw_config.h" #include "tw_config.h"

25
Server/tw_http.h Normal file
View File

@ -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

View File

@ -3,7 +3,11 @@
#ifndef __TW_SERVER_H__ #ifndef __TW_SERVER_H__
#define __TW_SERVER_H__ #define __TW_SERVER_H__
#include <openssl/ssl.h>
int tw_server_init(void); int tw_server_init(void);
void tw_server_loop(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 #endif

View File

@ -1,5 +1,7 @@
/* $Id$ */ /* $Id$ */
#define SOURCE
#include "tw_version.h" #include "tw_version.h"
const char* tw_version = "0.00"; const char* tw_version = "0.00";