793 lines
20 KiB
C
793 lines
20 KiB
C
#include "include/conf.h"
|
|
/* This is just a testing program for now. Please don't take this for granted.
|
|
* As a final thing. This is nothing but a test while developing.
|
|
*
|
|
* Later on, this will become `vessel` CLI program.
|
|
*/
|
|
|
|
#define _POSIX_C_SOURCE 199309L
|
|
|
|
#include <time.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include <vessel-web/httpbody.h>
|
|
#include <vessel-web/srv.h>
|
|
#include <vessel-web/web.h>
|
|
#include <vessel/mem.h>
|
|
#include <vessel/def.h>
|
|
#include <vessel/log.h>
|
|
#include <vessel-web/http.h>
|
|
#include <vessel/server.h>
|
|
#include <vessel/main.h>
|
|
#include <vessel/hmap.h>
|
|
#include <vessel/stream.h>
|
|
#include <vessel/hashing.h>
|
|
#include <vessel-web/request.h>
|
|
#include <vessel-web/form.h>
|
|
#include <vessel-web/path-builtin.h>
|
|
#include <vessel/vessel.h>
|
|
#include <vessel/thread.h>
|
|
/* #include "include/response.h" */
|
|
|
|
volatile uint64_t n = 0;
|
|
|
|
static bool gbye(vs_SockServer *s) {
|
|
/* Sock_drop(*(int*)s->arg); */
|
|
(void)s;
|
|
return true;
|
|
}
|
|
|
|
static bool before(vs_SockWorker *w) {
|
|
vw_Proxy *p = (vw_Proxy *)w->arg;
|
|
|
|
/* HTTPResponse_begin(&p->req, HTTP_OLDEST_SUPPORTED, 666); */
|
|
vw_HTTPRequest_res_header(&p->req, "x-rizz", "this is a test");
|
|
vw_HTTPRequest_res_header(&p->req, "x-ip-addr", p->ip);
|
|
/* HTTPResponse_content_and_length(&p->req, */
|
|
/* "You have been blocked." HTTP_CRLF); */
|
|
return true;
|
|
}
|
|
|
|
static bool gactg(vw_Proxy *p) {
|
|
static const char *nucleotides = "ACTG";
|
|
|
|
vw_HTTPRequest_res_begin(&p->req, 200);
|
|
|
|
char sequence[1000];
|
|
|
|
srand((unsigned)time(NULL));
|
|
|
|
while (true) {
|
|
for (uint32_t idx = 0; idx < 1000; ++idx)
|
|
sequence[idx] = nucleotides[rand() % 4];
|
|
|
|
if (vs_Stream_ignore_err(vw_HTTPRequest_write_chunk(&p->req, sequence, 1000)) == 0)
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool gindex(vw_Proxy *p) {
|
|
if (vw_HTTPRequest_res_begin(&p->req, 200) == VS_STREAM_ERROR) {
|
|
puts("HERE 0");
|
|
fflush(stdout);
|
|
}
|
|
|
|
/* vs_HMap_print_as_str(&p->req.headers); */
|
|
|
|
if (vw_HTTPRequest_res_header(&p->req, "content-type", "text/html") == VS_STREAM_ERROR) {
|
|
puts("HERE 1");
|
|
fflush(stdout);
|
|
}
|
|
|
|
/* clang-format off */
|
|
if (vs_Stream_ignore_err(vw_HTTPRequest_writef(&p->req,
|
|
"<!DOCTYPE html>"
|
|
"<html lang=\"en\">"
|
|
" <head>"
|
|
" <meta charset=\"UTF-8\">"
|
|
" <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"
|
|
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
|
" <title>Home Page</title>"
|
|
" </head>"
|
|
""
|
|
" <body>"
|
|
" <h1>Hello!</h1>"
|
|
" <p>This is a sample website. Your request number: %ju. Submit form here:</p>"
|
|
" <form enctype=\"multipart/form-data\" action=\"/save\" method=\"POST\"> <input name=test id=test type=\"text\" /> <input name=file id=file type=\"file\" /> <input name=file1 id=file1 type=\"file\" /> <input type=\"submit\" value=\"Submit\" /> </form>"
|
|
" </body>"
|
|
"</html>",
|
|
++n
|
|
)) == 0) {
|
|
puts("HERE 2"); fflush(stdout);
|
|
}
|
|
/* clang-format on */
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool gmeow(vw_Proxy *p) {
|
|
vw_HTTPRequest_res_begin(&p->req, 200);
|
|
vw_HTTPRequest_res_header(&p->req, "content-type", "text/plain");
|
|
|
|
uintmax_t num = 0;
|
|
|
|
const vs_HMapEntry *bucket = vs_HMap_find(&p->params, "number");
|
|
if (bucket) {
|
|
const vw_PathMatch *match = bucket->value;
|
|
num = *(uintmax_t *)match->conv;
|
|
}
|
|
|
|
/* clang-format off */
|
|
vw_HTTPRequest_writef(&p->req, "meow, number : %ju", num);
|
|
/* clang-format on */
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool ga(vw_Proxy *p) {
|
|
vw_HTTPRequest_res_begin(&p->req, 200);
|
|
vw_HTTPRequest_res_header(&p->req, "content-type", "text/plain");
|
|
|
|
/* clang-format off */
|
|
vw_HTTPRequest_write(&p->req, "a\n", 2);
|
|
/* clang-format on */
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool gb(vw_Proxy *p) {
|
|
vw_HTTPRequest_res_begin(&p->req, 200);
|
|
vw_HTTPRequest_res_header(&p->req, "content-type", "text/plain");
|
|
|
|
/* clang-format off */
|
|
vw_HTTPRequest_write(&p->req, "b\n", 2);
|
|
/* clang-format on */
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool notfound(vw_Proxy *p) {
|
|
vw_HTTPRequest_res_begin(&p->req, 404);
|
|
vw_HTTPRequest_res_header(&p->req, "content-type", "text/html");
|
|
|
|
/* clang-format off */
|
|
vw_HTTPRequest_writef(&p->req,
|
|
"<!DOCTYPE html>"
|
|
"<html lang=\"en\">"
|
|
" <head>"
|
|
" <meta charset=\"UTF-8\">"
|
|
" <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"
|
|
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
|
|
" <title>404 Not Found</title>"
|
|
" </head>"
|
|
""
|
|
" <body>"
|
|
" <h1>HTTP/404: Not Found</h1>"
|
|
" <p>Requested resource was not found on the server. Your request number: %ju.</p>"
|
|
" </body>"
|
|
"</html>",
|
|
(uint64_t)0
|
|
);
|
|
/* clang-format on */
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool gindex_html(vw_Proxy *p) {
|
|
vw_srv_redirect(&p->req, 307, "/");
|
|
return true;
|
|
}
|
|
|
|
static bool psave(vw_Proxy *p) {
|
|
vs_HMap h = { 0 };
|
|
|
|
if (!vs_HMap_init(&h))
|
|
return false;
|
|
|
|
if (!vw_Form_read(&p->req, &h)) {
|
|
puts("Oh no!");
|
|
vs_HMap_print_as_ptr(&h);
|
|
vw_Form_destroy(&h);
|
|
return false;
|
|
}
|
|
|
|
vw_Form_print(&h);
|
|
|
|
vs_HMapEntry *test = vs_HMap_find(&h, "test");
|
|
|
|
if (test) {
|
|
vw_FormField *tf = test->value;
|
|
const char *v = tf->value;
|
|
|
|
puts("---BEGIN FIELD TEST---");
|
|
|
|
while (*v) {
|
|
switch (*v) {
|
|
case '\r':
|
|
fputs("\\r", stdout);
|
|
break;
|
|
case '\n':
|
|
fputs("\\n\n", stdout);
|
|
break;
|
|
default:
|
|
putchar(*v);
|
|
break;
|
|
}
|
|
|
|
++v;
|
|
}
|
|
|
|
puts("\n---END FIELD TEST---");
|
|
}
|
|
|
|
/* vs_HMap_print_as_ptr(&h); */
|
|
|
|
vs_HMapEntry *b = vs_HMap_find(&h, "file");
|
|
|
|
if (b) {
|
|
vw_FormField *ff = b->value;
|
|
vw_FormFile *f = ff->value;
|
|
|
|
printf("%zu - %d %d // %ls => %s\n",
|
|
sizeof(*f->filename),
|
|
((char *)f->filename)[0],
|
|
((char *)f->filename)[1],
|
|
f->filename,
|
|
f->path);
|
|
fflush(stdout);
|
|
vs_HMap_print_as_str(&ff->headers);
|
|
fflush(stdout);
|
|
|
|
vw_FormFile_open(f);
|
|
vs_FileStat s = { 0 };
|
|
vs_File_stat(&f->file, &s);
|
|
printf("%zu\n", s.size);
|
|
|
|
vw_HTTPRequest_res_begin(&p->req, 200);
|
|
vw_HTTPRequest_res_headerf(&p->req, "content-length", "%zu", s.size);
|
|
if (vs_HMap_find(&ff->headers, "content-type"))
|
|
vw_HTTPRequest_res_header(
|
|
&p->req, "content-type", vs_HMap_find(&ff->headers, "content-type")->value);
|
|
vw_HTTPRequest_res_headers_end(&p->req);
|
|
|
|
char a[1024 * 256] = { 0 };
|
|
uint64_t total = 0;
|
|
|
|
while (total < s.size) {
|
|
const size_t now = vw_FormFile_read(f, a, 1024 * 256);
|
|
if (now <= 0)
|
|
break;
|
|
vw_HTTPBody_write(&p->req.body, a, now);
|
|
total += now;
|
|
}
|
|
} else {
|
|
vw_HTTPRequest_res_begin(&p->req, 200);
|
|
vw_HTTPRequest_res_header(&p->req, "content-type", "text/plain");
|
|
vw_HTTPRequest_writef(&p->req, "Your response has been registered without a file.");
|
|
}
|
|
|
|
vw_Form_destroy(&h);
|
|
|
|
return true;
|
|
}
|
|
|
|
#if 0
|
|
|
|
static bool hello(vw_Proxy *p) {
|
|
HTTPResponse_begin(&p->req, p->req.version, 200, "close");
|
|
HTTPResponse_content_and_length(&p->req, "hello");
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool save(vw_Proxy *p) {
|
|
vs_HMap h = {0};
|
|
|
|
if (!vs_HMap_init(&h))
|
|
return false;
|
|
|
|
if (!Form_read(&p->req, &h)) {
|
|
puts("Oh no!");
|
|
vs_HMap_print_as_ptr(&h);
|
|
Form_destroy(&h);
|
|
return false;
|
|
}
|
|
|
|
vs_HMapEntry *test = vs_HMap_find(&h, "test");
|
|
|
|
if (test) {
|
|
FormField *tf = test->value;
|
|
const char *v = tf->value;
|
|
|
|
puts("---BEGIN FIELD TEST---");
|
|
|
|
while (*v) {
|
|
switch (*v) {
|
|
case '\r': fputs("\\r", stdout); break;
|
|
case '\n': fputs("\\n\n", stdout); break;
|
|
default: putchar(*v); break;
|
|
}
|
|
|
|
++v;
|
|
}
|
|
|
|
puts("\n---END FIELD TEST---");
|
|
}
|
|
|
|
/* vs_HMap_print_as_ptr(&h); */
|
|
|
|
vs_HMapEntry *b = vs_HMap_find(&h, "file");
|
|
|
|
if (b) {
|
|
FormField *ff = b->value;
|
|
FormFile *f = ff->value;
|
|
|
|
printf("%ju - %d %d // %ls => %s\n", sizeof(*f->filename),
|
|
((char *)f->filename)[0], ((char *)f->filename)[1], f->filename,
|
|
f->path);
|
|
fflush(stdout);
|
|
vs_HMap_print_as_str(&ff->headers);
|
|
fflush(stdout);
|
|
|
|
FormFile_open(f);
|
|
FileStat s = {0};
|
|
File_stat(&f->f, &s);
|
|
printf("%ju\n", s.size);
|
|
|
|
HTTPResponse_begin(&p->req, p->req.version, 200, "close");
|
|
HTTPRequest_res_headerf(&p->req, "content-length", "%ju", s.size);
|
|
if (vs_HMap_find(&ff->headers, "content-type"))
|
|
HTTPRequest_res_header(&p->req, "content-type",
|
|
vs_HMap_find(&ff->headers, "content-type")->value);
|
|
HTTPRequest_res_headers_end(&p->req);
|
|
|
|
char a[1024 * 256] = {0};
|
|
uint64_t total = 0;
|
|
|
|
while (total < s.size) {
|
|
const uint64_t now = FormFile_read(f, a, 1024 * 256);
|
|
if (now <= 0)
|
|
break;
|
|
Stream_write(p->req.fp, a, now);
|
|
total += now;
|
|
}
|
|
} else {
|
|
HTTPResponse_begin(&p->req, p->req.version, 200, "close");
|
|
HTTPResponse_content_and_length(
|
|
&p->req, "Your response has been registered without a file.");
|
|
}
|
|
|
|
Form_destroy(&h);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool gerror(vw_Proxy *p) {
|
|
(void)p;
|
|
return true;
|
|
/* return srv_redirect(&p->req, p->req.version, 301, "/"); */
|
|
}
|
|
#endif
|
|
|
|
int main(void) {
|
|
#if 0
|
|
const Logger plg = LOG_ALL;
|
|
|
|
vs_HMap path = {0};
|
|
vs_HMap_init(&path);
|
|
|
|
const char *pattern = "/hello/<int:hello?=123><path:meow?=>";
|
|
const char *matchee = "/hello/111/meow/test";
|
|
|
|
PathPattern *pat = PathPattern_compile(&plg, pattern);
|
|
|
|
if (!pat)
|
|
return 1;
|
|
PathPattern_print(pat, true);
|
|
|
|
uint32_t matched =
|
|
PathPattern_matchn(pat, &path, matchee, (uint32_t)strlen(matchee));
|
|
|
|
if (matched == 0)
|
|
return 1;
|
|
|
|
vs_HMap_print_as_ptr(&path);
|
|
printf("m=%u l=%zu\n", matched, strlen(matchee));
|
|
|
|
for (VS_HMAP_TYPE a = 0; a < path.size; ++a) {
|
|
vs_HMapEntry *b = &path.buckets[path.order_table[a]];
|
|
PathMatch *pm = (PathMatch *)b->value;
|
|
|
|
printf("X: %s %ld\n", pm->str, pm->conv ? (*(intmax_t *)pm->conv) : 69);
|
|
}
|
|
|
|
vs_HMap_destroy(&path);
|
|
PathPattern_destroy(pat);
|
|
|
|
return 0;
|
|
#endif
|
|
|
|
#if 0
|
|
/* clang-format off */
|
|
/* const char *i = "/<int(2..4/2):hello?=2>"; */
|
|
/* const char *i = */
|
|
/* "/<int!(..):hi?=11><str( 11 " */
|
|
/* ")>/j/hi<str(10)>\\\\h/<float(0..10):test?= 1 ><double:hi?=0.1>"; */
|
|
/* const char *i = "< str ! ( 1..69 ) : h ? =>"; */
|
|
/* const char *i = "<bool( hello world test/h 124 hi ):hello?= hELlo " */
|
|
/* ">/<uuid(4):hi?=ffc636fc-db2f-4a16-aa67-c9e6baec9afb>/<hex:h?=0>"; */
|
|
const char *i = "?/hello/wor?ld<Date:hi?=2024-09-01>";
|
|
/* clang-format on */
|
|
const Logger alg = LOG_ALL;
|
|
PathPattern *p = PathPattern_compile(&alg, i);
|
|
if (!p)
|
|
return 1;
|
|
if (!PathPattern_print(p, true)) {
|
|
PathPattern_destroy(p);
|
|
return 1;
|
|
}
|
|
if (!PathPattern_destroy(p))
|
|
return 1;
|
|
return 0;
|
|
#endif
|
|
|
|
#if 0
|
|
const char *passing_tests[] = {
|
|
"",
|
|
"0..10",
|
|
"-5..5",
|
|
"-10..-1",
|
|
"5..5",
|
|
"5",
|
|
"0..10/2",
|
|
"-10..10/5",
|
|
"1..20/3",
|
|
"-30..-10/10",
|
|
"..",
|
|
"5..",
|
|
"..5",
|
|
"../2",
|
|
"/3",
|
|
"5../2",
|
|
"..10/3",
|
|
"-10../4",
|
|
"..-42/2",
|
|
"1..10",
|
|
"1..10",
|
|
"1..10",
|
|
"1..10/2",
|
|
"1..10/2",
|
|
"0..0",
|
|
"-0..0",
|
|
"0..-0",
|
|
"0..0/1",
|
|
"42",
|
|
"-42",
|
|
"0",
|
|
"42../1",
|
|
"0",
|
|
"1000000..2000000",
|
|
"-2000000..-1000000",
|
|
"1..1000000/1000",
|
|
"2147483647..2147483647",
|
|
"-2147483648..-2147483648",
|
|
"-5..5/1",
|
|
"10..20/5",
|
|
"2..10/4",
|
|
};
|
|
|
|
const char *failing_tests[] = {
|
|
"a..b", "1..b", "a..2", "1..2/c", "abc", "$100",
|
|
"#1..10", "1..@10", "*1..10", "1&..&10", "1..2.3", "1,2",
|
|
"1-10", "1+10", "1:10", "1..10%2", "1+2", "1,..10",
|
|
"../", "//", "...", ".5", "5.", "5/..",
|
|
"5../ ..10", "1..2/", "1/2/3", "1....10", "//5", "1..2//",
|
|
"1../2..", "1..2/-1", "1..10/-5", "1.1..2", "1..2.2", "1..2/3.3",
|
|
".1..2", "1.1.2", "-", "+", "/", "!/2",
|
|
"1<..>10",
|
|
};
|
|
|
|
puts("Passing...");
|
|
|
|
for (uint64_t idx = 0;
|
|
idx < sizeof(passing_tests) / sizeof(passing_tests[0]); ++idx) {
|
|
IntRange r = {0};
|
|
printf("%s => ", passing_tests[idx]);
|
|
if (!IntRange_parse(&r, passing_tests[idx],
|
|
strlen(passing_tests[idx]))) {
|
|
fputs("(failed) ", stdout);
|
|
IntRange_print(&r);
|
|
return 1;
|
|
}
|
|
IntRange_print(&r);
|
|
}
|
|
|
|
puts("Failing...");
|
|
|
|
for (uint64_t idx = 0;
|
|
idx < sizeof(failing_tests) / sizeof(failing_tests[0]); ++idx) {
|
|
IntRange r = {0};
|
|
printf("%s => ", failing_tests[idx]);
|
|
if (IntRange_parse(&r, failing_tests[idx],
|
|
strlen(failing_tests[idx]))) {
|
|
fputs("(passed) ", stdout);
|
|
IntRange_print(&r);
|
|
return 1;
|
|
}
|
|
puts("(failed)");
|
|
}
|
|
|
|
return 0;
|
|
#endif
|
|
|
|
#if 0
|
|
Atom_u64 a = ATOM_INIT_VAR(0);
|
|
printf("%ju\n", ATOM_LOAD(&a));
|
|
ATOM_STORE(&a, 1);
|
|
printf("%ju\n", ATOM_LOAD(&a));
|
|
ATOM_STORE(&a, 2);
|
|
printf("%ju\n", ATOM_LOAD(&a));
|
|
return 0;
|
|
#endif
|
|
|
|
#if 0
|
|
vs_HMap h = {0};
|
|
vs_HMap_init(&h);
|
|
VS_HMAP_ID_TYPE ha = vs_HMap_insert(&h, "Hello", "World");
|
|
VS_HMAP_ID_TYPE hb = vs_HMap_insert(&h, "Test", "World");
|
|
VS_HMAP_ID_TYPE hc = vs_HMap_insert(&h, "Test", "World");
|
|
printf("%lu %lu %lu\n", ha, hb, hc);
|
|
vs_HMap_print_as_str(&h);
|
|
vs_HMapEntry *hab = vs_HMap_get(&h, ha);
|
|
vs_HMapEntry *hbb = vs_HMap_get(&h, hb);
|
|
vs_HMapEntry *hcb = vs_HMap_get(&h, hc);
|
|
VS_HMAP_ID_TYPE id = vs_HMap_find_id(&h, "Test");
|
|
printf("%d\n", hc == id);
|
|
if (hab)
|
|
puts(hab->key);
|
|
if (hbb)
|
|
puts(hbb->key);
|
|
if (hcb)
|
|
puts(hcb->key);
|
|
vs_HMap_rehash(&h, true);
|
|
hab = vs_HMap_get(&h, ha);
|
|
hbb = vs_HMap_get(&h, hb);
|
|
hcb = vs_HMap_get(&h, hc);
|
|
if (hab)
|
|
puts(hab->key);
|
|
if (hbb)
|
|
puts(hbb->key);
|
|
if (hcb)
|
|
puts(hcb->key);
|
|
vs_HMap_print_as_str(&h);
|
|
vs_HMap_insert(&h, "Testing...", "Meow!");
|
|
vs_HMap_rehash(&h, true);
|
|
puts("Deleting test");
|
|
vs_HMap_delete(&h, "Test");
|
|
hab = vs_HMap_get(&h, ha);
|
|
hbb = vs_HMap_get(&h, hb);
|
|
hcb = vs_HMap_get(&h, hc);
|
|
if (hab)
|
|
puts(hab->key);
|
|
if (hbb)
|
|
puts(hbb->key);
|
|
if (hcb)
|
|
puts(hcb->key);
|
|
vs_HMap_print_as_str(&h);
|
|
hab = vs_HMap_get(&h, ha);
|
|
hbb = vs_HMap_get(&h, hb);
|
|
hcb = vs_HMap_get(&h, hc);
|
|
if (hab)
|
|
puts(hab->key);
|
|
if (hbb)
|
|
puts(hbb->key);
|
|
if (hcb)
|
|
puts(hcb->key);
|
|
vs_HMap_destroy(&h);
|
|
|
|
return 0;
|
|
#endif
|
|
#if 0
|
|
Logger lo = LOG_ALL;
|
|
PathPattern *pat = PathPattern_compile("", &lo);
|
|
|
|
if (!pat) {
|
|
puts("compilation failed");
|
|
}
|
|
|
|
return 0;
|
|
#endif
|
|
|
|
#if 0
|
|
Stream hello_s = {0};
|
|
File bye_s = {0};
|
|
|
|
if (!File_init(&bye_s, NULL))
|
|
return 1;
|
|
|
|
if (!File_open(&bye_s, "chunked.test", FILEF_RD, FILEM_NONE))
|
|
return 1;
|
|
|
|
if (!Stream_init(&hello_s, STREAM_RD))
|
|
return 1;
|
|
|
|
if (!Stream_use(&hello_s, &bye_s))
|
|
return 1;
|
|
|
|
/* bool meow; */
|
|
char a[64] = {0};
|
|
uint64_t b = Stream_readb(&hello_s, NULL, 5, "END", 3, NULL, true);
|
|
printf("%ju\n", b);
|
|
b = Stream_readb(&hello_s, a, 64, "END", 3, NULL, true);
|
|
puts(a);
|
|
printf("%ju\n", b);
|
|
|
|
return 0;
|
|
#endif
|
|
|
|
#if 0
|
|
Stream hello_s = {0};
|
|
HTTPBody hsmeow = {0};
|
|
File bye_s = {0};
|
|
|
|
if (!File_init(&bye_s, NULL))
|
|
return 1;
|
|
|
|
if (!File_open(&bye_s, "chunked.test", FILEF_RD, FILEM_NONE))
|
|
return 1;
|
|
|
|
if (!Stream_init(&hello_s, STREAM_RD))
|
|
return 1;
|
|
|
|
if (!Stream_use(&hello_s, &bye_s))
|
|
return 1;
|
|
|
|
if (!HTTPBody_init(&hsmeow, &hello_s, 50, false))
|
|
return 1;
|
|
|
|
/* bool meow; */
|
|
char a[64] = {0};
|
|
|
|
printf("%ju\n", HTTPBody_read(&hsmeow, NULL, 5));
|
|
|
|
if (!HTTPBody_read1(&hsmeow, a))
|
|
return 1;
|
|
putchar(*a);
|
|
*a = '\0';
|
|
if (!HTTPBody_read1(&hsmeow, a))
|
|
return 1;
|
|
putchar(*a);
|
|
*a = '\0';
|
|
if (!HTTPBody_read1(&hsmeow, a))
|
|
return 1;
|
|
putchar(*a);
|
|
*a = '\0';
|
|
|
|
putchar('\n');
|
|
|
|
HTTPBody_readbf(&hsmeow, a, 64, NULL, true, "H%sE", "W");
|
|
printf("^%s$\n", a);
|
|
|
|
return 0;
|
|
#endif
|
|
|
|
#if 0
|
|
vessel_init(VESSEL_HEADER_VERSION);
|
|
|
|
Temple t;
|
|
|
|
if (!Temple_init(&t))
|
|
return 1;
|
|
|
|
if (!Temple_open(&t, "example.tmpl.test"))
|
|
return 1;
|
|
|
|
printf("version %x flags %x magic %c digest %d\n", t.version, t.flags, t.magic[0], t.digest[0]);
|
|
|
|
TempleState state;
|
|
|
|
if (!TempleState_init(&state, &t))
|
|
return 1;
|
|
|
|
if (!TempleState_destroy(&state, &t))
|
|
return 1;
|
|
|
|
if (!Temple_destroy(&t))
|
|
return 1;
|
|
|
|
return 0;
|
|
#endif
|
|
vs_Logger lg = VS_LOG_ALL;
|
|
|
|
vs_vessel_init(VS_VESSEL_HEADER_VERSION);
|
|
|
|
vs_SockServer s = { 0 };
|
|
vs_SockWorkerHook hooks[] = VS_HOOKS(VW_WEBSERVER_HOOKS);
|
|
|
|
s.host = "127.0.0.1";
|
|
s.port = 8080;
|
|
s.logger = ≶
|
|
s.threads = 128;
|
|
|
|
if (!vs_SockServer_create_generic(&s)) {
|
|
vs_log_error(&lg, "Failed to create a generic TCP server.");
|
|
return 1;
|
|
}
|
|
|
|
if (!vs_SockServer_init(&s, VS_SEC2TO(30))) {
|
|
vs_log_error(&lg, "Failed to create a generic TCP server.");
|
|
vs_SockServer_destroy(&s);
|
|
return 1;
|
|
}
|
|
|
|
if (!vs_SockServer_setup_signals(&s)) {
|
|
vs_log_error(&lg, "Failed to handle signals for the server.");
|
|
vs_SockServer_destroy(&s);
|
|
return 1;
|
|
}
|
|
|
|
vw_Route routes[] = VW_ROUTES(VW_NEW_ROUTE(ANY, "/<int:u?>", normal, gindex),
|
|
VW_NEW_ROUTE(ANY, "/<int:number?>-?meow", normal, gmeow),
|
|
VW_NEW_ROUTE(ANY, "/a", normal, ga),
|
|
VW_NEW_ROUTE(ANY, "/b", normal, gb),
|
|
VW_NEW_ROUTE(ANY, "/index.html", normal, gindex_html),
|
|
VW_NEW_ROUTE(POST, "/save", normal, psave),
|
|
VW_NEW_ROUTE(GET, "/actg", normal, gactg),
|
|
VW_NEW_ROUTE(ANY, "<path>", not_found, notfound));
|
|
#if 0
|
|
{
|
|
NULL,
|
|
"%p",
|
|
RouteType_error,
|
|
gerror,
|
|
},
|
|
{
|
|
"GET",
|
|
"/logo.png",
|
|
RouteType_normal,
|
|
logo,
|
|
},
|
|
{
|
|
NULL,
|
|
"/hello",
|
|
RouteType_normal,
|
|
hello,
|
|
}
|
|
,{
|
|
"POST",
|
|
"/save",
|
|
RouteType_normal,
|
|
save,
|
|
}
|
|
#endif
|
|
|
|
const vw_RouteHook rhooks[] = VS_HOOKS({ vw_RouteHookType_pre_read, before });
|
|
|
|
vw_Router router = { 0 };
|
|
|
|
router.routes = routes;
|
|
router.hooks = rhooks;
|
|
|
|
const vs_SockServerHook oofhooks[] = VS_HOOKS({ vs_SockServerHookType_pre_worker, &gbye });
|
|
|
|
if (!vw_WebServer_init(&s, &router)) {
|
|
vs_log_error(s.logger, "Failed to init the web server.");
|
|
vs_SockServer_destroy(&s);
|
|
return 1;
|
|
}
|
|
|
|
if (!vs_SockServer_start(&s, hooks, oofhooks)) {
|
|
vs_log_error(s.logger, "Failed to start the server.");
|
|
vs_SockServer_destroy(&s);
|
|
return 1;
|
|
}
|
|
|
|
vw_WebServer_destroy(&router);
|
|
vs_SockServer_destroy(&s);
|
|
|
|
return 0;
|
|
}
|