diff seobeo/s_websocket.c @ 173:827c6ac504cd hg-web

Merged in default here.
author MrJuneJune <me@mrjunejune.com>
date Mon, 19 Jan 2026 18:59:10 -0800
parents 0face9898d04
children
line wrap: on
line diff
--- a/seobeo/s_websocket.c	Sat Jan 10 13:35:09 2026 -0800
+++ b/seobeo/s_websocket.c	Mon Jan 19 18:59:10 2026 -0800
@@ -88,7 +88,7 @@
   key_out[out_idx] = '\0';
 }
 
-Seobeo_WebSocket *Seobeo_WebSocket_Connect(const char *url)
+Seobeo_WebSocket *Seobeo_WebSocket_Connect_With_Headers(const char *url, const char *headers)
 {
   Seobeo_WebSocket *p_ws = malloc(sizeof(Seobeo_WebSocket));
   if (!p_ws)
@@ -123,17 +123,52 @@
   char ws_key[32];
   Seobeo_WebSocket_Generate_Key(ws_key, sizeof(ws_key));
 
-  char handshake[2048];
+  // Build handshake with optional custom headers
+  char handshake[4096];
   int handshake_len = snprintf(handshake, sizeof(handshake),
     "GET %s HTTP/1.1\r\n"
     "Host: %s\r\n"
     "Upgrade: websocket\r\n"
     "Connection: Upgrade\r\n"
     "Sec-WebSocket-Key: %s\r\n"
-    "Sec-WebSocket-Version: 13\r\n"
-    "\r\n",
+    "Sec-WebSocket-Version: 13\r\n",
     p_ws->path, p_ws->host, ws_key);
 
+  if (headers && strlen(headers) > 0)
+  {
+    const char *line_start = headers;
+    while (*line_start)
+    {
+      while (*line_start == ' ' || *line_start == '\t') line_start++;
+      if (*line_start == '\0') break;
+
+      const char *line_end = line_start;
+      while (*line_end && *line_end != '\n') line_end++;
+
+      size_t line_len = line_end - line_start;
+      if (line_len > 0 && memchr(line_start, ':', line_len) != NULL)
+      {
+        while (line_len > 0 && (line_start[line_len-1] == '\r' ||
+               line_start[line_len-1] == ' ' || line_start[line_len-1] == '\t'))
+          line_len--;
+
+        if (line_len > 0 && handshake_len + line_len + 4 < sizeof(handshake))
+        {
+          memcpy(handshake + handshake_len, line_start, line_len);
+          handshake_len += line_len;
+          handshake[handshake_len++] = '\r';
+          handshake[handshake_len++] = '\n';
+        }
+      }
+
+      line_start = (*line_end == '\n') ? line_end + 1 : line_end;
+    }
+  }
+
+  handshake[handshake_len++] = '\r';
+  handshake[handshake_len++] = '\n';
+  handshake[handshake_len] = '\0';
+
   Seobeo_Handle_Queue(p_ws->p_handle, (uint8*)handshake, (uint32)handshake_len);
   if (Seobeo_Handle_Flush(p_ws->p_handle) < 0)
   {
@@ -190,7 +225,10 @@
   return p_ws;
 }
 
-// Seobeo_WebSocket_Mask_Data moved to s_websocket_common.c
+Seobeo_WebSocket *Seobeo_WebSocket_Connect(const char *url)
+{
+  return Seobeo_WebSocket_Connect_With_Headers(url, NULL);
+}
 
 static int32 Seobeo_WebSocket_Send_Frame(Seobeo_WebSocket *p_ws, Seobeo_WebSocket_Opcode opcode,
     const uint8 *payload, size_t payload_length, boolean fin)
@@ -480,8 +518,6 @@
   return p_msg;
 }
 
-// Seobeo_WebSocket_Message_Destroy moved to s_websocket_common.c
-
 int32 Seobeo_WebSocket_Close(Seobeo_WebSocket *p_ws, uint16 code, const char *reason)
 {
   if (!p_ws || p_ws->state == SEOBEO_WS_STATE_CLOSED)