comparison mrjunejune/main.c @ 173:827c6ac504cd hg-web

Merged in default here.
author MrJuneJune <me@mrjunejune.com>
date Mon, 19 Jan 2026 18:59:10 -0800
parents 295ac2e5ec00
children 90dfcef375fb
comparison
equal deleted inserted replaced
151:c033667da5f9 173:827c6ac504cd
1 // Debug mode is now controlled by build target: use //seobeo:seobeo_tcp_server_ws_debug
2 #include "seobeo/seobeo.h" 1 #include "seobeo/seobeo.h"
2 #include "markdown_converter/markdown_to_html.h"
3 #include <time.h> 3 #include <time.h>
4 4
5 // UUID + /tmp/ + format (max 4) 5 // UUID + /tmp/ + format (max 4)
6 #define TMP_FILE_LENGTH 47 6 #define TMP_FILE_LENGTH 47
7 #define UUID_LEN 37 7 #define UUID_LEN 37
13 { 13 {
14 printf("Failed\n"); 14 printf("Failed\n");
15 stop_server = 1; 15 stop_server = 1;
16 } 16 }
17 17
18 void Seobeo_ServerSideRender( 18 void Seobeo_Render_Html(
19 char *final_body, 19 char *final_body,
20 char *path, 20 char *template,
21 Dowa_Arena *arena 21 Dowa_Arena *arena
22 ) { 22 )
23 Seobeo_Log(SEOBEO_DEBUG, "[Curr] %s\n", path); 23 {
24 size_t html_size = 0;
25 char *template = Seobeo_Web_LoadFile(path, &html_size);
26 if (!template) return;
27 Seobeo_Log(SEOBEO_DEBUG, "[Curr] ??\n");
28
29 size_t current_offset = 0; 24 size_t current_offset = 0;
30 char *cursor = template; 25 char *cursor = template;
31 26
32 int32 token_len = 2; 27 int32 token_len = 2;
33 28
59 } 54 }
60 55
61 cursor = end_tag + 2; 56 cursor = end_tag + 2;
62 } 57 }
63 strcpy(final_body + current_offset, cursor); 58 strcpy(final_body + current_offset, cursor);
64 free(template); 59 }
60
61
62 void Seobeo_Render_Html_FilePath(
63 char *final_body,
64 char *path,
65 Dowa_Arena *arena
66 ) {
67 Seobeo_Log(SEOBEO_DEBUG, "[Curr] %s\n", path);
68 size_t html_size = 0;
69 char *template = Seobeo_Web_LoadFile(path, &html_size);
70 if (!template) return;
71 Seobeo_Render_Html(final_body, template, arena);
65 } 72 }
66 73
67 Seobeo_Request_Entry* GetHomePage(Seobeo_Request_Entry *req, Dowa_Arena *arena) 74 Seobeo_Request_Entry* GetHomePage(Seobeo_Request_Entry *req, Dowa_Arena *arena)
68 { 75 {
69 Seobeo_Request_Entry *resp = NULL; 76 Seobeo_Request_Entry *resp = NULL;
70 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024); 77 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
71 Seobeo_ServerSideRender(final_body, "/index.html", arena); 78 Seobeo_Render_Html_FilePath(final_body, "/index.html", arena);
72 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); 79 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
73 return resp; 80 return resp;
74 } 81 }
75 82
76 Seobeo_Request_Entry* GetResume(Seobeo_Request_Entry *req, Dowa_Arena *arena) 83 Seobeo_Request_Entry* GetResume(Seobeo_Request_Entry *req, Dowa_Arena *arena)
77 { 84 {
78 Seobeo_Request_Entry *resp = NULL; 85 Seobeo_Request_Entry *resp = NULL;
79 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024); 86 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
80 Seobeo_ServerSideRender(final_body, "/resume/index.html", arena); 87 Seobeo_Render_Html_FilePath(final_body, "/resume/index.html", arena);
81 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); 88 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
82 return resp; 89 return resp;
83 } 90 }
84 91
85 Seobeo_Request_Entry* GetTools(Seobeo_Request_Entry *req, Dowa_Arena *arena) 92 Seobeo_Request_Entry* GetTools(Seobeo_Request_Entry *req, Dowa_Arena *arena)
86 { 93 {
87 Seobeo_Request_Entry *resp = NULL; 94 Seobeo_Request_Entry *resp = NULL;
88 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024); 95 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
89 Seobeo_ServerSideRender(final_body, "/tools/index.html", arena); 96 Seobeo_Render_Html_FilePath(final_body, "/tools/index.html", arena);
90 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); 97 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
91 return resp; 98 return resp;
92 } 99 }
93 100
94 101
95 Seobeo_Request_Entry* GetMDToHTML(Seobeo_Request_Entry *req, Dowa_Arena *arena) 102 Seobeo_Request_Entry* GetMDToHTML(Seobeo_Request_Entry *req, Dowa_Arena *arena)
96 { 103 {
97 Seobeo_Request_Entry *resp = NULL; 104 Seobeo_Request_Entry *resp = NULL;
98 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024); 105 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
99 Seobeo_ServerSideRender(final_body, "/tools/markdown_to_html/index.html", arena); 106 Seobeo_Render_Html_FilePath(final_body, "/tools/markdown_to_html/index.html", arena);
100 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); 107 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
101 return resp; 108 return resp;
102 } 109 }
103 110
104 Seobeo_Request_Entry* GetFileConverter(Seobeo_Request_Entry *req, Dowa_Arena *arena) 111 Seobeo_Request_Entry* GetFileConverter(Seobeo_Request_Entry *req, Dowa_Arena *arena)
105 { 112 {
106 Seobeo_Request_Entry *resp = NULL; 113 Seobeo_Request_Entry *resp = NULL;
107 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024); 114 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
108 Seobeo_ServerSideRender(final_body, "/tools/file_converter/index.html", arena); 115 Seobeo_Render_Html_FilePath(final_body, "/tools/file_converter/index.html", arena);
109 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); 116 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
110 return resp; 117 return resp;
111 } 118 }
112 119
113 Seobeo_Request_Entry *ConvertImageToWebP(Seobeo_Request_Entry *req, Dowa_Arena *arena) 120 Seobeo_Request_Entry *ConvertImageToWebP(Seobeo_Request_Entry *req, Dowa_Arena *arena)
158 const char *content_length_str = ((Seobeo_Request_Entry*)cl_kv)->value; 165 const char *content_length_str = ((Seobeo_Request_Entry*)cl_kv)->value;
159 size_t file_size = atoi(content_length_str); 166 size_t file_size = atoi(content_length_str);
160 167
161 printf("DEBUG: Converting image, file_size=%zu bytes\n", file_size); 168 printf("DEBUG: Converting image, file_size=%zu bytes\n", file_size);
162 169
163
164 int open_flags = O_RDWR | O_CREAT | O_EXCL; 170 int open_flags = O_RDWR | O_CREAT | O_EXCL;
165 171
166 char *uuid4 = (char *)Dowa_Arena_Allocate(arena, UUID_LEN); 172 char *uuid4 = (char *)Dowa_Arena_Allocate(arena, UUID_LEN);
167 uint32 seed = (uint32)time(NULL) ^ (uint32)pthread_self() ^ counter++; 173 uint32 seed = (uint32)time(NULL) ^ (uint32)pthread_self() ^ counter++;
168 Dowa_String_UUID(seed, uuid4); 174 Dowa_String_UUID(seed, uuid4);
277 const char *content_length_str = ((Seobeo_Request_Entry*)cl_kv)->value; 283 const char *content_length_str = ((Seobeo_Request_Entry*)cl_kv)->value;
278 size_t file_size = atoi(content_length_str); 284 size_t file_size = atoi(content_length_str);
279 285
280 printf("DEBUG: Converting video, file_size=%zu bytes\n", file_size); 286 printf("DEBUG: Converting video, file_size=%zu bytes\n", file_size);
281 287
288 int open_flags = O_RDWR | O_CREAT | O_EXCL;
289
282 char *uuid4 = (char *)Dowa_Arena_Allocate(arena, UUID_LEN); 290 char *uuid4 = (char *)Dowa_Arena_Allocate(arena, UUID_LEN);
283 Dowa_String_UUID((uint32)time(NULL), uuid4); 291 uint32 seed = (uint32)time(NULL) ^ (uint32)pthread_self() ^ counter++;
292 Dowa_String_UUID(seed, uuid4);
284 char *input_path = Dowa_Arena_Allocate(arena, TMP_FILE_LENGTH); 293 char *input_path = Dowa_Arena_Allocate(arena, TMP_FILE_LENGTH);
285 snprintf(input_path, TMP_FILE_LENGTH, "/tmp/%s", uuid4); 294 snprintf(input_path, TMP_FILE_LENGTH, "/tmp/%s", uuid4);
286 int input_fd = mkstemp(input_path); 295 Seobeo_Log(SEOBEO_DEBUG, "Input path: %s\n", input_path);
296
297 int input_fd = open(input_path, open_flags, 0600);
287 if (input_fd == -1) 298 if (input_fd == -1)
288 { 299 {
300 Seobeo_Log(SEOBEO_DEBUG, "errno: %d (%s)\n", errno, strerror(errno));
289 char *error_msg = "Failed to create temporary file"; 301 char *error_msg = "Failed to create temporary file";
290 Dowa_HashMap_Push_Arena(resp, "status", "500", arena); 302 Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
291 Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena); 303 Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
292 Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena); 304 Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
293 return resp; 305 return resp;
294 } 306 }
295 307
296 write(input_fd, file_data, file_size); 308 write(input_fd, file_data, file_size);
297 close(input_fd); 309 close(input_fd);
298 310
299 int open_flags = O_RDWR | O_CREAT | O_EXCL; 311 seed = (uint32)time(NULL) ^ (uint32)pthread_self() ^ counter++;
300
301 uint32 seed = (uint32)time(NULL) ^ (uint32)pthread_self() ^ counter++;;
302 Dowa_String_UUID(seed, uuid4); 312 Dowa_String_UUID(seed, uuid4);
303 char *output_path = (char *)Dowa_Arena_Allocate(arena, TMP_FILE_LENGTH);; 313 char *output_path = (char *)Dowa_Arena_Allocate(arena, TMP_FILE_LENGTH);;
304 snprintf(output_path, TMP_FILE_LENGTH, "/tmp/%s.mp4", uuid4); 314 snprintf(output_path, TMP_FILE_LENGTH, "/tmp/%s.mp4", uuid4);
305 int output_fd = open(output_path, open_flags, 0600); 315 int output_fd = open(output_path, open_flags, 0600);
306 if (output_fd == -1) 316 if (output_fd == -1)
425 435
426 unlink(filepath); 436 unlink(filepath);
427 437
428 printf("DEBUG: Served and deleted file: %s (%zu bytes)\n", filename, file_size); 438 printf("DEBUG: Served and deleted file: %s (%zu bytes)\n", filename, file_size);
429 439
430 // Set proper Content-Length for binary data
431 char *content_length = Dowa_Arena_Allocate(arena, 32); 440 char *content_length = Dowa_Arena_Allocate(arena, 32);
432 snprintf(content_length, 32, "%zu", file_size); 441 snprintf(content_length, 32, "%zu", file_size);
433 442
434 Dowa_HashMap_Push_Arena(resp, "status", "200", arena); 443 Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
435 Dowa_HashMap_Push_Arena(resp, "content-type", content_type, arena); 444 Dowa_HashMap_Push_Arena(resp, "content-type", content_type, arena);
441 450
442 Seobeo_Request_Entry *RenderBlogList(Seobeo_Request_Entry *req, Dowa_Arena *arena) 451 Seobeo_Request_Entry *RenderBlogList(Seobeo_Request_Entry *req, Dowa_Arena *arena)
443 { 452 {
444 Seobeo_Request_Entry *resp = NULL; 453 Seobeo_Request_Entry *resp = NULL;
445 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024); 454 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
446 Seobeo_ServerSideRender(final_body, "/blog/index.html", arena); 455 Seobeo_Render_Html_FilePath(final_body, "/blog/index.html", arena);
447 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); 456 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
448 return resp; 457 return resp;
449 } 458 }
450 459
451 460
452 Seobeo_Request_Entry *RenderBlog(Seobeo_Request_Entry *req, Dowa_Arena *arena) 461 Seobeo_Request_Entry *RenderBlog(Seobeo_Request_Entry *req, Dowa_Arena *arena)
453 { 462 {
454 Seobeo_Log(SEOBEO_DEBUG, "[CURR], Hello\n"); 463 Seobeo_Request_Entry *resp = NULL;
455 Seobeo_Request_Entry *resp = NULL; 464
456 465 char *file_path = Dowa_Arena_Allocate(arena, 1024);
457 void *blog_id_kv = Dowa_HashMap_Get_Ptr(req, ":blog_id"); 466 void *blog_id_kv = Dowa_HashMap_Get_Ptr(req, ":blog_id");
458 if (!blog_id_kv) 467 char *blog_id = ((Seobeo_Request_Entry*)blog_id_kv)->value;
459 { 468 snprintf(file_path, 1024, "/blog/%s/index.html", blog_id);
460 char *error_msg = "No Blog Id"; 469
461 Dowa_HashMap_Push_Arena(resp, "status", "404", arena); 470 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
462 Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena); 471 Seobeo_Render_Html_FilePath(final_body, file_path, arena);
463 Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
464 return resp;
465 }
466
467 const char *blog_id = ((Seobeo_Request_Entry *)blog_id_kv)->value;
468 char *html_path = Dowa_Arena_Allocate(arena, 512);
469 sprintf(html_path, "/blog/%s/index.html", blog_id);
470
471 char *final_body = Dowa_Arena_Allocate(arena, 100 * 1024); // TODO: Think about the sizes
472 Seobeo_ServerSideRender(final_body, html_path, arena);
473 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); 472 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
474 return resp; 473 return resp;
475 } 474 }
476 475
477 void Chat_Handler(Seobeo_WebSocket_Server_Connection *p_conn, Seobeo_WebSocket_Message *p_msg, void *p_user_data) 476 void Chat_Handler(Seobeo_WebSocket_Server_Connection *p_conn, Seobeo_WebSocket_Message *p_msg, void *p_user_data)
490 489
491 Seobeo_Request_Entry *GetTalk(Seobeo_Request_Entry *req, Dowa_Arena *arena) 490 Seobeo_Request_Entry *GetTalk(Seobeo_Request_Entry *req, Dowa_Arena *arena)
492 { 491 {
493 Seobeo_Request_Entry *resp = NULL; 492 Seobeo_Request_Entry *resp = NULL;
494 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024); 493 char *final_body = Dowa_Arena_Allocate(arena, 50 * 1024);
495 Seobeo_ServerSideRender(final_body, "/talk/index.html", arena); 494 Seobeo_Render_Html_FilePath(final_body, "/talk/index.html", arena);
496 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena); 495 Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
497 return resp; 496 return resp;
498 } 497 }
499 498
500 CREATE_REDIRECT_HANDLER(HomePage, "/") 499 CREATE_REDIRECT_HANDLER(HomePage, "/")
532 Seobeo_Router_Register("GET", "/blog", RenderBlogList); 531 Seobeo_Router_Register("GET", "/blog", RenderBlogList);
533 Seobeo_Router_Register("GET", "/blog/:blog_id", RenderBlog); 532 Seobeo_Router_Register("GET", "/blog/:blog_id", RenderBlog);
534 533
535 // -- Talk --/ 534 // -- Talk --/
536 Seobeo_Router_Register("GET", "/talk", GetTalk); 535 Seobeo_Router_Register("GET", "/talk", GetTalk);
537 // TODO: Bug where I can't est redriect huh...
538 Seobeo_Router_Register("GET", "/talk/index.html", GetRedirectTalk); 536 Seobeo_Router_Register("GET", "/talk/index.html", GetRedirectTalk);
539
540 printf("Registered Websockets\n");
541 537
542 Seobeo_WebSocket_Server_Init(); 538 Seobeo_WebSocket_Server_Init();
543 Seobeo_WebSocket_Server_Register("/chat", Chat_Handler, NULL); 539 Seobeo_WebSocket_Server_Register("/chat", Chat_Handler, NULL);
544 540
545 Seobeo_Web_Server_Start("mrjunejune/src", "6969", SEOBEO_MODE_EDGE, 3); 541 Seobeo_Web_Server_Start("mrjunejune/src", "6969", SEOBEO_MODE_EDGE, 3);