comparison 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
comparison
equal deleted inserted replaced
151:c033667da5f9 173:827c6ac504cd
86 } 86 }
87 87
88 key_out[out_idx] = '\0'; 88 key_out[out_idx] = '\0';
89 } 89 }
90 90
91 Seobeo_WebSocket *Seobeo_WebSocket_Connect(const char *url) 91 Seobeo_WebSocket *Seobeo_WebSocket_Connect_With_Headers(const char *url, const char *headers)
92 { 92 {
93 Seobeo_WebSocket *p_ws = malloc(sizeof(Seobeo_WebSocket)); 93 Seobeo_WebSocket *p_ws = malloc(sizeof(Seobeo_WebSocket));
94 if (!p_ws) 94 if (!p_ws)
95 return NULL; 95 return NULL;
96 96
121 } 121 }
122 122
123 char ws_key[32]; 123 char ws_key[32];
124 Seobeo_WebSocket_Generate_Key(ws_key, sizeof(ws_key)); 124 Seobeo_WebSocket_Generate_Key(ws_key, sizeof(ws_key));
125 125
126 char handshake[2048]; 126 // Build handshake with optional custom headers
127 char handshake[4096];
127 int handshake_len = snprintf(handshake, sizeof(handshake), 128 int handshake_len = snprintf(handshake, sizeof(handshake),
128 "GET %s HTTP/1.1\r\n" 129 "GET %s HTTP/1.1\r\n"
129 "Host: %s\r\n" 130 "Host: %s\r\n"
130 "Upgrade: websocket\r\n" 131 "Upgrade: websocket\r\n"
131 "Connection: Upgrade\r\n" 132 "Connection: Upgrade\r\n"
132 "Sec-WebSocket-Key: %s\r\n" 133 "Sec-WebSocket-Key: %s\r\n"
133 "Sec-WebSocket-Version: 13\r\n" 134 "Sec-WebSocket-Version: 13\r\n",
134 "\r\n",
135 p_ws->path, p_ws->host, ws_key); 135 p_ws->path, p_ws->host, ws_key);
136
137 if (headers && strlen(headers) > 0)
138 {
139 const char *line_start = headers;
140 while (*line_start)
141 {
142 while (*line_start == ' ' || *line_start == '\t') line_start++;
143 if (*line_start == '\0') break;
144
145 const char *line_end = line_start;
146 while (*line_end && *line_end != '\n') line_end++;
147
148 size_t line_len = line_end - line_start;
149 if (line_len > 0 && memchr(line_start, ':', line_len) != NULL)
150 {
151 while (line_len > 0 && (line_start[line_len-1] == '\r' ||
152 line_start[line_len-1] == ' ' || line_start[line_len-1] == '\t'))
153 line_len--;
154
155 if (line_len > 0 && handshake_len + line_len + 4 < sizeof(handshake))
156 {
157 memcpy(handshake + handshake_len, line_start, line_len);
158 handshake_len += line_len;
159 handshake[handshake_len++] = '\r';
160 handshake[handshake_len++] = '\n';
161 }
162 }
163
164 line_start = (*line_end == '\n') ? line_end + 1 : line_end;
165 }
166 }
167
168 handshake[handshake_len++] = '\r';
169 handshake[handshake_len++] = '\n';
170 handshake[handshake_len] = '\0';
136 171
137 Seobeo_Handle_Queue(p_ws->p_handle, (uint8*)handshake, (uint32)handshake_len); 172 Seobeo_Handle_Queue(p_ws->p_handle, (uint8*)handshake, (uint32)handshake_len);
138 if (Seobeo_Handle_Flush(p_ws->p_handle) < 0) 173 if (Seobeo_Handle_Flush(p_ws->p_handle) < 0)
139 { 174 {
140 Seobeo_Log(SEOBEO_ERROR, "Failed to send WebSocket handshake\n"); 175 Seobeo_Log(SEOBEO_ERROR, "Failed to send WebSocket handshake\n");
188 Seobeo_Log(SEOBEO_INFO, "WebSocket connected to %s\n", url); 223 Seobeo_Log(SEOBEO_INFO, "WebSocket connected to %s\n", url);
189 224
190 return p_ws; 225 return p_ws;
191 } 226 }
192 227
193 // Seobeo_WebSocket_Mask_Data moved to s_websocket_common.c 228 Seobeo_WebSocket *Seobeo_WebSocket_Connect(const char *url)
229 {
230 return Seobeo_WebSocket_Connect_With_Headers(url, NULL);
231 }
194 232
195 static int32 Seobeo_WebSocket_Send_Frame(Seobeo_WebSocket *p_ws, Seobeo_WebSocket_Opcode opcode, 233 static int32 Seobeo_WebSocket_Send_Frame(Seobeo_WebSocket *p_ws, Seobeo_WebSocket_Opcode opcode,
196 const uint8 *payload, size_t payload_length, boolean fin) 234 const uint8 *payload, size_t payload_length, boolean fin)
197 { 235 {
198 if (!p_ws || p_ws->state != SEOBEO_WS_STATE_OPEN) 236 if (!p_ws || p_ws->state != SEOBEO_WS_STATE_OPEN)
478 p_msg->is_final = fin; 516 p_msg->is_final = fin;
479 517
480 return p_msg; 518 return p_msg;
481 } 519 }
482 520
483 // Seobeo_WebSocket_Message_Destroy moved to s_websocket_common.c
484
485 int32 Seobeo_WebSocket_Close(Seobeo_WebSocket *p_ws, uint16 code, const char *reason) 521 int32 Seobeo_WebSocket_Close(Seobeo_WebSocket *p_ws, uint16 code, const char *reason)
486 { 522 {
487 if (!p_ws || p_ws->state == SEOBEO_WS_STATE_CLOSED) 523 if (!p_ws || p_ws->state == SEOBEO_WS_STATE_CLOSED)
488 return -1; 524 return -1;
489 525