diff options
| author | ame <[email protected]> | 2026-04-24 05:06:15 -0500 |
|---|---|---|
| committer | ame <[email protected]> | 2026-04-24 05:06:15 -0500 |
| commit | fe168cff249a672aced9cda1439ac7aea343c9af (patch) | |
| tree | 5539a21ed89c63c2b80af2cf47bd6d69e57bfe4c | |
| parent | 91738e3cee334ecc122ce11687c7e434c6bb581a (diff) | |
http body parsing & request reading
| -rw-r--r-- | src/lua.c | 38 | ||||
| -rw-r--r-- | src/lua.h | 1 | ||||
| -rw-r--r-- | src/net.c | 21 | ||||
| -rw-r--r-- | src/net/lua.c | 2 | ||||
| -rw-r--r-- | src/net/luai.c | 72 | ||||
| -rw-r--r-- | src/net/luai.h | 2 | ||||
| -rw-r--r-- | src/types/parray.c | 15 | ||||
| -rw-r--r-- | src/types/parray.h | 1 | ||||
| -rw-r--r-- | src/util.c | 22 | ||||
| -rw-r--r-- | src/util.h | 1 |
10 files changed, 88 insertions, 87 deletions
@@ -25,18 +25,23 @@ void __free_(void* p){ return (free)(p);
}
+int luaI_iserror(lua_State* L){
+ if(lua_gettop(L) < 3) return 0;
+ return lua_type(L, -3) == LUA_TNIL &&
+ lua_type(L, -2) == LUA_TSTRING &&
+ lua_type(L, -1) == LUA_TNUMBER;
+}
+
int _stream_read(lua_State* L){
uint64_t len = 0;
if(lua_gettop(L) > 1){
len = lua_tointeger(L, 2);
}
- lua_pushstring(L, "_read");
- lua_gettable(L, 1);
+ lua_getfield(L, 1, "_read");
stream_read_function rf = lua_touserdata(L, -1);
- lua_pushstring(L, "_state");
- lua_gettable(L, 1);
+ lua_getfield(L, 1, "_state");
void* state = lua_touserdata(L, -1);
str* cont = str_init("");
@@ -55,6 +60,15 @@ int _stream_read(lua_State* L){ return 1;
}
+int _stream_load(lua_State* L){
+ _stream_read(L);
+ if(luaI_iserror(L)) return 3;
+ int idx = lua_gettop(L);
+ luaI_tsetv(L, 1, "txt", idx);
+
+ return 0;
+}
+
int _stream_file(lua_State* L){
const int CHUNK_SIZE = 4096;
uint64_t maxlen = 0;
@@ -68,12 +82,10 @@ int _stream_file(lua_State* L){ mode = lua_tostring(L, 4);
}
- lua_pushstring(L, "_read");
- lua_gettable(L, 1);
+ lua_getfield(L, 1, "_read");
stream_read_function rf = lua_touserdata(L, -1);
- lua_pushstring(L, "_state");
- lua_gettable(L, 1);
+ lua_getfield(L, 1, "_state");
void* state = lua_touserdata(L, -1);
const char* filename = lua_tostring(L, 2);
@@ -90,6 +102,7 @@ int _stream_file(lua_State* L){ if(ret < 0){
fclose(f);
+ str_free(cont);
luaI_error(L, ret, "read error");
}
@@ -102,18 +115,17 @@ int _stream_file(lua_State* L){ break;
}
}
+ str_free(cont);
fclose(f);
return 0;
}
int _stream_free(lua_State* L){
- lua_pushstring(L, "_free");
- lua_gettable(L, 1);
+ lua_getfield(L, 1, "_free");
void* rf = lua_touserdata(L, -1);
- lua_pushstring(L, "_state");
- lua_gettable(L, 1);
+ lua_getfield(L, 1, "_state");
void* state = lua_touserdata(L, -1);
if(rf != NULL){
@@ -130,9 +142,11 @@ void luaI_newstream(lua_State* L, stream_read_function readf, stream_free_functi luaI_tsetlud(L, tidx, "_free", freef);
luaI_tsetlud(L, tidx, "_state", state);
luaI_tsetcf(L, tidx, "read", _stream_read);
+ luaI_tsetcf(L, tidx, "load", _stream_load);
luaI_tsetcf(L, tidx, "close", _stream_free);
luaI_tsetb(L, tidx, "more", 1);
luaI_tsetcf(L, tidx, "file", _stream_file);
+ luaI_tsets(L, tidx, "txt", "")
lua_newtable(L);
int midx = lua_gettop(L);
@@ -36,6 +36,7 @@ void luaI_copyvars(lua_State* src, lua_State* dest); void lua_upvalue_key_table(lua_State* L, int fidx);
int lua_assign_upvalues(lua_State* L, int fidx);
+int lua_iserror(lua_State* L);
typedef int (*stream_read_function)(uint64_t, str**, void**);
typedef int (*stream_free_function)(void**);
@@ -245,7 +245,9 @@ int i_ws_close(lua_State* L){ return 0;
}
-#define BUFFER_LEN 4096
+//2^14, max ssl frame size or whatever
+#warning "make this a compile time option"
+#define BUFFER_LEN 16384
int l_wss(lua_State* L){
uint64_t len = 0;
@@ -373,8 +375,7 @@ int _srequest_read(uint64_t reqlen, str** _output, void** _state){ state->buffer = NULL;
}
- char buffer[BUFFER_LEN];
- memset(buffer, 0, BUFFER_LEN);
+ char *buffer = calloc(BUFFER_LEN, sizeof * buffer);
uint64_t len;
for(; (len = _request_read(state, buffer, BUFFER_LEN)) > 0;){
if(state->state != NULL){
@@ -384,6 +385,7 @@ int _srequest_read(uint64_t reqlen, str** _output, void** _state){ }
memset(buffer, 0, BUFFER_LEN);
}
+ free(buffer);
if(state->state != NULL){
str_pushl(output, state->state->content->c, state->state->content->len);
@@ -412,7 +414,10 @@ int l_request(lua_State* L){ ssize_t _request_read(struct request_state* state, void* buffer, size_t count){
if(state->secure){
- return SSL_read(state->ssl, buffer, count);
+ uint64_t len;
+ if(SSL_read_ex(state->ssl, buffer, count, &len) == 0)
+ return 0;
+ return len;
} else {
return read(state->sock, buffer, count);
}
@@ -420,7 +425,10 @@ ssize_t _request_read(struct request_state* state, void* buffer, size_t count){ ssize_t _request_write(struct request_state* state, const void* buffer, size_t count){
if(state->secure){
- return SSL_write(state->ssl, buffer, count);
+ uint64_t len;
+ if(SSL_write_ex(state->ssl, buffer, count, &len) == 0)
+ return 0;
+ return len;
} else {
return write(state->sock, buffer, count);
}
@@ -699,7 +707,7 @@ void* handle_client(void *_arg){ v = route_match(args->paths, aa->c, ¶ms);
if(sT != NULL)
- rolling_file_parse(L, &files_idx, &body_idx, header + 4, sT, bite - header_eof - 4, file_cont);
+ http_body_parse(L, &files_idx, &body_idx, header + 4, sT, bite - header_eof - 4, file_cont);
}
str_free(decoded_path);
@@ -718,6 +726,7 @@ void* handle_client(void *_arg){ parray_t* cookie = parray_init();
gen_parse(sC->c, sC->len, &cookie);
for(int i = 0; i != cookie->len; i++){
+ if(cookie->P[i].value == NULL) continue;
luaI_tsetsl(L, lcookie, cookie->P[i].key->c, ((str*)cookie->P[i].value)->c, ((str*)cookie->P[i].value)->len);
}
luaI_tsetv(L, req_idx, "cookies", lcookie);
diff --git a/src/net/lua.c b/src/net/lua.c index 6e8c955..50d050a 100644 --- a/src/net/lua.c +++ b/src/net/lua.c @@ -184,7 +184,7 @@ int l_roll(lua_State* L){ lua_gettable(L, 1); int files_idx = lua_gettop(L); //time_start(parse) - rolling_file_parse(L, &files_idx, &body_idx, buffer, NULL, r, data); + http_body_parse(L, &files_idx, &body_idx, buffer, NULL, r, data); //time_end("parse", parse) luaI_tsetv(L, 1, "body", body_idx); luaI_tsetv(L, 1, "files", files_idx); diff --git a/src/net/luai.c b/src/net/luai.c index dc39720..9c320a0 100644 --- a/src/net/luai.c +++ b/src/net/luai.c @@ -40,68 +40,31 @@ void i_write_header(lua_State* L, int header_top, str** _resp, char* content, si * @param {str*} response header Content-Type value * @return {int} lua index of table */ -int rolling_file_parse(lua_State* L, int* files_idx, int* body_idx, char* buffer, str* content_type, size_t blen, struct file_parse* _content){ +int http_body_parse(lua_State* L, int* files_idx, int* body_idx, char* buffer, str* content_type, size_t blen, struct file_parse* _content){ struct file_parse content = *_content; - /*enum file_status* status = (enum file_status*)parray_get(content, "_status"); - str* current = (str*)parray_get(content, "_current"); - str* old = (str*)parray_get(content, "_old"); - str* boundary = (str*)parray_get(content, "_boundary"); - str* boundary_id = (str*)parray_get(content, "_boundary_id"); - int* dash_count = (int*)parray_get(content, "_dash_count"); - int* table_idx = (int*)parray_get(content, "_table_idx");*/ - - //time_start(start) + if(content.status == _ignore){ - content.boundary = str_init(""); //usually add + 2 to the length when using - int state = 0; - for(int i = 0; content_type->c[i] != '\0'; i++){ - if(state == 2 && content_type->c[i] != '-') str_pushl(content.boundary, content_type->c + i, 1); - if(content_type->c[i] == ';') state = 1; - if(content_type->c[i] == '=' && state == 1) state = 2; - } - if(state == 2){ - str_pushl(content.boundary, "\r\n\r\n", 4); - } - content.status = state==2?BARRIER_READ:NORMAL;//malloc(sizeof * status); content.status = state==2?BARRIER_READ:NORMAL; - content.dash_count = 0;//malloc(sizeof * dash_count); *dash_count = 0; + parray_t* par = parray_init(); + gen_parse(content_type->c, content_type->len, &par); + content.boundary = parray_pop(par, "boundary"); + content.status = content.boundary == NULL?BARRIER_READ:NORMAL; + content.dash_count = 0; content.current = str_init(""); - - content.table_idx = lua_gettop(L);//malloc(sizeof * table_idx); *table_idx = lua_gettop(L); - //parray_set(content, "_table_idx", (void*)(table_idx)); - //parray_set(content, "_status", (void*)(status)); - //parray_set(content, "_dash_count", (void*)(dash_count)); - //parray_set(content, "_current", (void*)(current)); - + content.table_idx = lua_gettop(L); content.boundary_id = str_init(""); - - //quick fix? - //str_popb(content.boundary, 4); - if(content.boundary->len >= 4) str_popb(content.boundary, 4); - - //parray_set(content, "_boundary", (void*)boundary); - //parray_set(content, "_boundary_id", (void*)boundary_id); + parray_clear(par, STR); } - //time_end("start", start) - //printf("hi\n"); if(content.status == NORMAL){ - //strnstr(buffer, ) - //if(override) str_clear(current); - //str_pushl(current, buffer, blen); - //printf("%s\n",current->c); lua_pushvalue(L, *body_idx); lua_pushlstring(L, buffer, blen); lua_concat(L, 2); *body_idx = lua_gettop(L); } else { file_start:; - //time_start(barrier_read) if(content.status == BARRIER_READ){ - //printf("read %llu\n", blen); for(int i = 0; i != blen; i++){ - //printf("%c",buffer[i]); - //printf("\n"); if(*buffer == '\r'){ content.status = FILE_HEADER; buffer += 2; @@ -117,14 +80,11 @@ file_start:; buffer++; } } - //time_end("barrier_read", barrier_read) lua_pushvalue(L, *files_idx); lua_pushinteger(L, content.table_idx); lua_gettable(L, -2); int rfiles_idx = lua_gettop(L); - //time_start(file_header) if(content.status == FILE_HEADER){ - //printf("header\n"); for(int i = 0; i < blen; i++){ if(buffer[i] == ':'){ @@ -142,8 +102,7 @@ file_start:; content.current = str_init(""); break; } - //printf("%i '%s' : '%s'\n",*table_idx, old->c, current->c); - +#warning "error here" luaI_tsets(L, rfiles_idx, content.old->c, content.current->c); str_free(content.old); @@ -152,8 +111,7 @@ file_start:; } else if(buffer[i] != '\r' && !(buffer[i] == ' ' && content.current->len == 0)) str_pushl(content.current, buffer + i, 1); } } - //time_end("file_header", file_header) - //time_start(file_body) + if(content.status == FILE_BODY){ char* barrier_end = memmem(buffer, blen, content.boundary->c, content.boundary->len); if(barrier_end == NULL){ @@ -178,18 +136,10 @@ file_start:; buffer = end; content.status = BARRIER_READ; goto file_start; - //printf("%s\n",content.current->c); } } - //time_end("file_body", file_body) } - /*parray_set(content, "_dash_count", dash_count); - parray_set(content, "_boundary_id", boundary_id); - parray_set(content, "_boundary", boundary); - parray_set(content, "_status", status); - parray_set(content, "_current", current); - parray_set(content, "_old", old);*/ *_content = content; diff --git a/src/net/luai.h b/src/net/luai.h index 7e5fb07..77da0b8 100644 --- a/src/net/luai.h +++ b/src/net/luai.h @@ -10,5 +10,5 @@ void i_write_header(lua_State* L, int header_top, str** _resp, char* content, si * @param {str*} response header Content-Type value * @return {int} lua index of table */ -int rolling_file_parse(lua_State* L, int* files_idx, int* body_idx, char* buffer, str* content_type, size_t blen, struct file_parse* _content); +int http_body_parse(lua_State* L, int* files_idx, int* body_idx, char* buffer, str* content_type, size_t blen, struct file_parse* _content); diff --git a/src/types/parray.c b/src/types/parray.c index 22f6be9..ba89ffc 100644 --- a/src/types/parray.c +++ b/src/types/parray.c @@ -75,6 +75,21 @@ void* parray_get(parray_t* p, char* key){ return NULL;
}
+//removes key/value pair and returns the value
+void* parray_pop(parray_t* p, char* key){
+ int ind = parray_geti(p, key);
+ if(ind == -1) return NULL;
+
+ str_free(p->P[ind].key);
+ void* v = p->P[ind].value;
+
+ for(int i = ind; i < p->len - 1; i++) p->P[i] = p->P[i+1];
+ p->len--;
+ p->P = realloc(p->P, sizeof * p->P * (p->len + 1));
+
+ return v;
+}
+
/**
* @brief gets index with a key
*
diff --git a/src/types/parray.h b/src/types/parray.h index 374a073..7a8c5da 100644 --- a/src/types/parray.h +++ b/src/types/parray.h @@ -24,6 +24,7 @@ parray_t* parray_initl(int len); void parray_set(parray_t*, char*, void*);
void parray_push(parray_t*, char*, void*);
void* parray_get(parray_t* , char*);
+void* parray_pop(parray_t* p, char* key);
int parray_geti(parray_t* , char*);
void parray_remove(parray_t* p, char* key, enum free_type free);
void parray_clear(parray_t*, enum free_type);
@@ -5,6 +5,14 @@ #include "lua.h"
#include "net.h"
+/*
+ simple function to parse key=value; strings which are common in http headers
+ values may be null, because these strings can often just be a key such as
+ content-type: multipart/form-data; boundary=awa
+ will set the table to
+ multipart/form-data = (null)
+ boundary = awa
+*/
int gen_parse(char* inp, int len, parray_t** _table){
str* current = str_init(""), *last = NULL;
int state = 0;
@@ -13,17 +21,18 @@ int gen_parse(char* inp, int len, parray_t** _table){ for(int i = 0; i < len; i++){
if(state != 1 && inp[i] == ';'){
- if(last != NULL){
- parray_set(table, last->c, (void*)current);
- str_free(last);
- }
+ //if(last != NULL){
+ if(last == NULL) swap(str*, current, last);
+ parray_set(table, last->c, (void*)current);
+ str_free(last);
+ //}
last = NULL;
current = str_init("");
state = 0;
} else if(state != 1 && inp[i] == '='){
last = current;
current = str_init("");
- if(inp[i+1] == '"'){
+ if(i + 1 < len && inp[i+1] == '"'){
state = 1;
i++;
}
@@ -32,7 +41,8 @@ int gen_parse(char* inp, int len, parray_t** _table){ } else if(current->c[0] != '\0' || inp[i] != ' ') str_pushl(current, inp + i, 1);
}
- if(last != NULL){
+ if(current->len > 0){
+ if(last == NULL) swap(str*, current, last);
parray_set(table, last->c, (void*)current);
str_free(last);
}
@@ -23,6 +23,7 @@ #define color_reset "\e[0m" #define i_swap(A,B) double temp = A; A = B; B = temp; +#define swap(T,A,B) {T temp = A; A = B; B = temp;} #define lesser(A,B) ((A)>(B)?(B):(A)) #define inter(V,I) (I * ceil((double)V / I)) #define time_start(name)\ |
