Mercurial
changeset 152:7387eec8e7f8
[Postdog] Updated to use Seobeo_Client instead of CURL. Updated to handle websocket connection.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Sun, 11 Jan 2026 07:47:05 -0800 |
| parents | c37490913530 |
| children | 790930d9bb90 |
| files | playground/main.c postdog/BUILD postdog/main.c seobeo/BUILD |
| diffstat | 4 files changed, 119 insertions(+), 126 deletions(-) [+] |
line wrap: on
line diff
--- a/playground/main.c Sat Jan 10 13:30:28 2026 -0800 +++ b/playground/main.c Sun Jan 11 07:47:05 2026 -0800 @@ -3,18 +3,7 @@ void Test_Echo() { printf("\n=== Test: Multiple Messages ===\n"); - - // Seobeo_Client_Request *foo = Seobeo_Client_Request_Create("http://mrjunejune.com/echo"); - // Seobeo_Client_Request_Add_Header_Array(foo, "Upgrade: websocket"); - // Seobeo_Client_Request_Add_Header_Array(foo, "Connection: Upgrade"); - // Seobeo_Client_Request_Add_Header_Array(foo, "Sec-WebSocket-Key: asbc3e12bA"); - // Seobeo_Client_Request_Add_Header_Array(foo, "Sec-WebSocket-Version: 13"); - // Seobeo_Client_Response *foo2 = Seobeo_Client_Request_Execute(foo); - // printf("June: %s\n", foo2->body); - - - Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("ws://mrjunejune.com/echo"); - // Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("ws://localhost:6969/echo"); + Seobeo_WebSocket *p_ws = Seobeo_WebSocket_Connect("wss://mrjunejune.com/echo"); if (!p_ws) { printf("Failed to connect\n");
--- a/postdog/BUILD Sat Jan 10 13:30:28 2026 -0800 +++ b/postdog/BUILD Sun Jan 11 07:47:05 2026 -0800 @@ -21,6 +21,7 @@ deps = [ "//third_party/raylib:raylib", "//dowa:dowa", + "//seobeo:seobeo_client", ], data = [":all_static_assets",], linkopts_macos = [ @@ -29,7 +30,6 @@ "-framework Cocoa", "-framework GLUT", "-framework OpenGL", - "-lcurl", ], linkopts_linux = [ "-lGL", @@ -38,7 +38,6 @@ "-ldl", "-lrt", "-lX11", - "-lcurl", ], static = True )
--- a/postdog/main.c Sat Jan 10 13:30:28 2026 -0800 +++ b/postdog/main.c Sun Jan 11 07:47:05 2026 -0800 @@ -3,13 +3,28 @@ #include <string.h> #include <time.h> #include <sys/stat.h> -#include "dowa/dowa.h" +#include <pthread.h> -#include <curl/curl.h> +#ifdef _WIN32 + #include <direct.h> + #include <io.h> + #define mkdir(path, mode) _mkdir(path) + #define access _access + #define F_OK 0 +#else + #include <sys/stat.h> + #include <dirent.h> + #include <unistd.h> +#endif + + #include "third_party/raylib/include/raylib.h" #define RAYGUI_IMPLEMENTATION #include "third_party/raylib/include/raygui.h" +#include "dowa/dowa.h" +#include "seobeo/seobeo.h" + #ifndef POSTDOG_PATHS #define POSTDOG_PATHS "/Users/mrjunejune/zenbu/postdog/history" #endif @@ -24,19 +39,6 @@ #define BODY_BUFFER_LENGTH 1024 * 1024 * 5 #define RESULT_BUFFER_LENGTH 1024 * 1024 * 5 - -#ifdef _WIN32 - #include <direct.h> - #include <io.h> - #define mkdir(path, mode) _mkdir(path) - #define access _access - #define F_OK 0 -#else - #include <sys/stat.h> - #include <dirent.h> - #include <unistd.h> -#endif - typedef Dowa_KV(char*, char*) INPUT_HASHMAP; typedef struct { @@ -62,7 +64,7 @@ TAB_HEADER = 0, TAB_BODY, TAB_GET_PARAMS, - TAB_BAR, + TAB_WEBSOCKET, TAB_LENGTH } PostDog_Tab_Enum; @@ -75,6 +77,8 @@ char *url_result_text = NULL; char **url_body_map = NULL; int active_method_dropdown = 0; +int active_input_tab = 0; +Seobeo_WebSocket *ws = NULL; int CompareHistoryItemsByDate(const void *a, const void *b) { HistoryItem *itemA = (HistoryItem *)a; @@ -246,7 +250,7 @@ url_body_map[TAB_HEADER], url_body_map[TAB_BODY], url_body_map[TAB_GET_PARAMS], - url_body_map[TAB_BAR], + url_body_map[TAB_WEBSOCKET], url_result_text ); char *filename = Dowa_Arena_Allocate(arena, 1024); @@ -276,118 +280,108 @@ Dowa_Arena_Free(arena); } -static size_t Postdog_Curl_Callback(void *contents, size_t size, size_t nmemb, void *userp) +int PostDog_Websocket_Send(void) { - size_t real_size = size * nmemb; - ResponseBuffer *buf = (ResponseBuffer *)userp; + if (!ws) + ws = Seobeo_WebSocket_Connect(url_input_text); - char *ptr = realloc(buf->data, buf->size + real_size + 1); - if (ptr == NULL) + printf("URL %s\n", url_input_text); + if (Seobeo_WebSocket_Send_Text(ws, url_body_map[active_input_tab]) < 0) + printf("Failed to send message\n"); + + printf("Receiving responses...\n"); + + int received = 0; + while (TRUE) { - printf("Not enough memory for response\n"); - return 0; + Seobeo_WebSocket_Message *p_msg = Seobeo_WebSocket_Receive(ws); + if (p_msg) + { + if (p_msg->opcode == SEOBEO_WS_OPCODE_TEXT) + { + printf("Response %d: %.*s\n", received + 1, (int)p_msg->length, (char*)p_msg->data); + snprintf(url_result_text, RESULT_BUFFER_LENGTH, "%s", p_msg->data); + received++; + } + Seobeo_WebSocket_Message_Destroy(p_msg); + } + usleep(10000); } + printf("Received %d/%d messages\n", received, 3); +} - buf->data = ptr; - memcpy(&(buf->data[buf->size]), contents, real_size); - buf->size += real_size; - buf->data[buf->size] = 0; +void* PostDog_Websocket_Thread(void* arg) +{ + PostDog_Websocket_Send(); + printf("Websocket request finished.\n"); + return NULL; +} - return real_size; +void Trigger_Async_Send() +{ + pthread_t thread_id; + + if (pthread_create(&thread_id, NULL, PostDog_Websocket_Thread, NULL) != 0) + { + perror("Failed to create thread"); + return; + } + pthread_detach(thread_id); } int PostDog_Http_Request(void) { - const char *method = PostDog_Enum_To_String(active_method_dropdown); - CURL *curl; - CURLcode res; - ResponseBuffer buffer = { .data = malloc(1), .size = 0 }; - - url_result_text[0] = '\n'; - - if (buffer.data == NULL) + Seobeo_Client_Request *req = Seobeo_Client_Request_Create(url_input_text); + Seobeo_Client_Response *res; + switch (active_method_dropdown) { - snprintf(url_result_text, RESULT_BUFFER_LENGTH, "Error: Failed to allocate memory"); - return -1; + case 0: + { + Seobeo_Client_Request_Set_Method(req, "GET"); + break; + } + case 1: + { + Seobeo_Client_Request_Set_Method(req, "POST"); + break; + } + case 2: + { + Seobeo_Client_Request_Set_Method(req, "PUT"); + break; + } + case 3: + { + Seobeo_Client_Request_Set_Method(req, "DELETE"); + break; + } } - buffer.data[0] = '\0'; - - curl_global_init(CURL_GLOBAL_DEFAULT); - curl = curl_easy_init(); - - if (curl) - { - struct curl_slist *headerList = NULL; - // Set URL - curl_easy_setopt(curl, CURLOPT_URL, url_input_text); - - // Set HTTP method - if (strcmp(method, "POST") == 0) - { - curl_easy_setopt(curl, CURLOPT_POST, 1L); - if (url_body_map[TAB_BODY] && strlen(url_body_map[TAB_BODY]) > 0) - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, url_body_map[TAB_BODY]); - } - else if (strcmp(method, "PUT") == 0) - { - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); - if (url_body_map[TAB_BODY] && strlen(url_body_map[TAB_BODY]) > 0) - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, url_body_map[TAB_BODY]); - } - else if (strcmp(method, "DELETE") == 0) - { - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); - } - // Default is GET - - // Parse and add headers + { if (url_body_map[TAB_HEADER] && strlen(url_body_map[TAB_HEADER]) > 0) { char *headersCopy = strdup(url_body_map[TAB_HEADER]); char *line = strtok(headersCopy, "\n"); - while (line != NULL) { + while (line != NULL) + { while (*line == ' ' || *line == '\t') line++; if (strlen(line) > 0) - headerList = curl_slist_append(headerList, line); + Seobeo_Client_Request_Add_Header_Array(req, line); line = strtok(NULL, "\n"); } - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList); - free(headersCopy); - } - - // Set write callback - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Postdog_Curl_Callback); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buffer); - // Follow redirects - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); - res = curl_easy_perform(curl); + } + Seobeo_Client_Request_Set_Follow_Redirects(req, TRUE, 5); // TODO: remove magic number; + res = Seobeo_Client_Request_Execute(req); - if (res != CURLE_OK) - snprintf(url_result_text, RESULT_BUFFER_LENGTH, "Error: %s\n", curl_easy_strerror(res)); + if (res == NULL) + snprintf(url_result_text, RESULT_BUFFER_LENGTH, "Error: Failed to send the request\n"); else - { - long response_code; - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); - - if (buffer.size > RESULT_BUFFER_LENGTH) - printf("TODO: Realloc\n"); - - snprintf(url_result_text, RESULT_BUFFER_LENGTH, "HTTP Status: %ld\n\n%s", - response_code, buffer.data ? buffer.data : ""); - } - - if (headerList) curl_slist_free_all(headerList); - curl_easy_cleanup(curl); + snprintf(url_result_text, RESULT_BUFFER_LENGTH, "HTTP Status: %d\n\n%s", + res->status_code, res->body ? res->body : ""); } - else - snprintf(url_result_text, RESULT_BUFFER_LENGTH, "Error: Failed to initialize curl"); - - free(buffer.data); - curl_global_cleanup(); - + Seobeo_Client_Request_Destroy(req); + Seobeo_Client_Response_Destroy(res); PostDog_Request_SaveFile(); return 0; } @@ -492,7 +486,7 @@ case 3: // Headers (TAB_HEADER) case 4: // Body (TAB_BODY) case 5: // Get Params (TAB_GET_PARAMS) - case 6: // Bar (TAB_BAR) + case 6: // Bar (TAB_WEBSOCKET) { int map_index = i - 3; // 3->0, 4->1, 5->2, 6->3 snprintf(url_body_map[map_index], strlen(values[i]) + 1, "%s", values[i]); @@ -633,7 +627,7 @@ // Initialize global UI state url_input_text = (char *)malloc(sizeof(char) * URL_TEXT_BUFFER_LENGTH); - snprintf(url_input_text, URL_TEXT_BUFFER_LENGTH, "https://httpbin.org/get"); + snprintf(url_input_text, URL_TEXT_BUFFER_LENGTH, "wss://mrjunejune.com/echo"); Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * HEADER_BUFFER_LENGTH)); Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * BODY_BUFFER_LENGTH)); @@ -662,7 +656,6 @@ // General styling. float padding = 10; // TODO make it % based? - int active_input_tab = 0; int prev_input_tab = 0; // Scroll offsets @@ -785,7 +778,8 @@ float mouse_wheel = GetMouseWheelMove(); // Reset input body scroll when tab changes - if (prev_input_tab != active_input_tab) { + if (prev_input_tab != active_input_tab) + { input_body_scroll_offset = 0; prev_input_tab = active_input_tab; } @@ -905,8 +899,18 @@ Rectangle scrolled_input = AddPadding(input_body, padding * 2); scrolled_input.y += input_body_scroll_offset; scrolled_input.height = MAX_SCROLL_HEIGHT; - if (JUNE_GuiTextBox(scrolled_input, url_body_map[active_input_tab], DEFAULT_TEXT_BUFFER_LENGTH, input_body_bool)) - input_body_bool = !input_body_bool; + if (active_input_tab != TAB_WEBSOCKET) + { + if (JUNE_GuiTextBox(scrolled_input, url_body_map[active_input_tab], DEFAULT_TEXT_BUFFER_LENGTH, input_body_bool)) + input_body_bool = !input_body_bool; + } + else + { + boolean temp = true; + if (GuiTextInputBox(input_body, "send message", "connected", + "send", url_body_map[active_input_tab], BODY_BUFFER_LENGTH, &temp) == 1) + Trigger_Async_Send(); + } EndScissorMode(); if (input_body_scroll_offset < 0) { @@ -937,7 +941,8 @@ GuiTextBoxMulti(scrolled_result, url_result_text, RESULT_BUFFER_LENGTH, false); EndScissorMode(); - if (result_body_scroll_offset < 0) { + if (result_body_scroll_offset < 0) + { float scrollbar_height = 10; float scrollbar_y = result_body.y - (result_body_scroll_offset / MAX_SCROLL_HEIGHT) * (result_body.height - scrollbar_height); Rectangle scrollbar = {