Mercurial
annotate seobeo/tests/seobeo_http_framing_test.c @ 279:b3b547563ec7
Add Google connector service and agent wiki
Implement the C/Seobeo Google Drive and Gmail connector with encrypted OAuth storage, Zenbu authentication, browser testing, AI tool discovery, chunked HTTP decoding, and Bazel coverage. Consolidate repository guidance into progressive wiki documentation and enforce arena-first allocation for new first-party C code.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: 84c338fd-0939-4bb3-b7f3-1062eb213e5d
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 22:22:36 -0700 |
| parents | ce7f4400c2de |
| children |
| rev | line source |
|---|---|
|
221
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1 #include "seobeo/seobeo.h" |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
2 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
3 #include <arpa/inet.h> |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
4 #include <pthread.h> |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
5 #include <stdio.h> |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
6 #include <string.h> |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
7 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
8 typedef struct { |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
9 int listener; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
10 } Framing_Server; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
11 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
12 static void *serve_close_delimited_response(void *argument) |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
13 { |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
14 Framing_Server *server = argument; |
|
279
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
15 for (int response_index = 0; response_index < 2; response_index++) { |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
16 int client = accept(server->listener, NULL, NULL); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
17 if (client < 0) |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
18 continue; |
|
221
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
19 char request[1024]; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
20 (void)read(client, request, sizeof(request)); |
|
279
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
21 if (response_index == 0) { |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
22 const char response[] = |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
23 "HTTP/1.1 200 OK\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
24 "Content-Type: text/plain\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
25 "Connection: close\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
26 "\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
27 "buffered-body"; |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
28 (void)write(client, response, sizeof(response) - 1); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
29 } else { |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
30 const char response[] = |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
31 "HTTP/1.1 200 OK\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
32 "Content-Type: application/json\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
33 "Transfer-Encoding: chunked\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
34 "Connection: close\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
35 "\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
36 "7;sample=yes\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
37 "{\"ok\":t\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
38 "4\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
39 "rue}\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
40 "0\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
41 "X-Trailer: ignored\r\n" |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
42 "\r\n"; |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
43 (void)write(client, response, sizeof(response) - 1); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
44 } |
|
221
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
45 close(client); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
46 } |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
47 return NULL; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
48 } |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
49 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
50 int main(void) |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
51 { |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
52 int listener = socket(AF_INET, SOCK_STREAM, 0); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
53 if (listener < 0) |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
54 return 1; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
55 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
56 struct sockaddr_in address = { |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
57 .sin_family = AF_INET, |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
58 .sin_addr.s_addr = htonl(INADDR_LOOPBACK), |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
59 .sin_port = 0, |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
60 }; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
61 if (bind(listener, (struct sockaddr *)&address, sizeof(address)) != 0 || |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
62 listen(listener, 1) != 0) { |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
63 close(listener); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
64 return 1; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
65 } |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
66 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
67 socklen_t address_length = sizeof(address); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
68 if (getsockname(listener, (struct sockaddr *)&address, &address_length) != 0) { |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
69 close(listener); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
70 return 1; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
71 } |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
72 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
73 Framing_Server server = {.listener = listener}; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
74 pthread_t thread; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
75 if (pthread_create(&thread, NULL, serve_close_delimited_response, &server) != 0) { |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
76 close(listener); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
77 return 1; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
78 } |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
79 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
80 char url[128]; |
|
279
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
81 snprintf( |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
82 url, sizeof(url), "http://127.0.0.1:%u/close", |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
83 ntohs(address.sin_port)); |
|
221
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
84 Seobeo_Client_Request *request = Seobeo_Client_Request_Create(url); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
85 Seobeo_Client_Request_Set_Timeout_Milliseconds(request, 1000); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
86 Seobeo_Client_Response *response = Seobeo_Client_Request_Execute(request); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
87 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
88 int failed = !response || |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
89 response->status_code != 200 || |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
90 response->body_length != strlen("buffered-body") || |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
91 memcmp(response->body, "buffered-body", strlen("buffered-body")) != 0; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
92 if (failed) |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
93 fprintf(stderr, "Close-delimited response body was not preserved\n"); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
94 |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
95 Seobeo_Client_Response_Destroy(response); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
96 Seobeo_Client_Request_Destroy(request); |
|
279
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
97 |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
98 snprintf( |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
99 url, sizeof(url), "http://127.0.0.1:%u/chunked", |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
100 ntohs(address.sin_port)); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
101 request = Seobeo_Client_Request_Create(url); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
102 Seobeo_Client_Request_Set_Timeout_Milliseconds(request, 1000); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
103 response = Seobeo_Client_Request_Execute(request); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
104 int chunked_failed = !response || |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
105 response->status_code != 200 || |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
106 response->body_length != strlen("{\"ok\":true}") || |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
107 memcmp(response->body, "{\"ok\":true}", strlen("{\"ok\":true}")) != 0; |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
108 if (chunked_failed) |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
109 fprintf(stderr, "Chunked response body was not decoded\n"); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
110 failed = failed || chunked_failed; |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
111 |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
112 Seobeo_Client_Response_Destroy(response); |
|
b3b547563ec7
Add Google connector service and agent wiki
MrJuneJune <me@mrjunejune.com>
parents:
221
diff
changeset
|
113 Seobeo_Client_Request_Destroy(request); |
|
221
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
114 pthread_join(thread, NULL); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
115 close(listener); |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
116 return failed; |
|
ce7f4400c2de
[hg-web] Harden forge and add changeset UI
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
117 } |