]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/examples/websocket_client/websocket_client.c
bump version to 12.2.12-pve1
[ceph.git] / ceph / src / civetweb / examples / websocket_client / websocket_client.c
1 /*
2 * Copyright (c) 2014-2015 the Civetweb developers
3 * Copyright (c) 2014 Jordan Shelley
4 * https://github.com/jshelley
5 * License http://opensource.org/licenses/mit-license.php MIT License
6 */
7
8 /* This example is superseeded by other examples, and no longer
9 * actively maintained.
10 * See examples/embedded_c for an up to date example.
11 */
12
13 // Simple example program on how to use websocket client embedded C interface.
14 #ifdef _WIN32
15 #include <Windows.h>
16 #define sleep(x) Sleep(1000 * (x))
17 #else
18 #include <unistd.h>
19 #endif
20
21 #include <assert.h>
22 #include <string.h>
23 #include "civetweb.h"
24
25 #define DOCUMENT_ROOT "."
26 #define PORT "8888"
27 #define SSL_CERT "./ssl/server.pem"
28
29 const char *websocket_welcome_msg = "websocket welcome\n";
30 const size_t websocket_welcome_msg_len = 18 /* strlen(websocket_welcome_msg) */;
31 const char *websocket_acknowledge_msg = "websocket msg ok\n";
32 const size_t websocket_acknowledge_msg_len =
33 17 /* strlen(websocket_acknowledge_msg) */;
34 const char *websocket_goodbye_msg = "websocket bye\n";
35 const size_t websocket_goodbye_msg_len = 14 /* strlen(websocket_goodbye_msg) */;
36
37
38 /*************************************************************************************/
39 /* WEBSOCKET SERVER */
40 /*************************************************************************************/
41 #if defined(MG_LEGACY_INTERFACE)
42 int
43 websock_server_connect(const struct mg_connection *conn)
44 #else
45 int
46 websocket_server_connect(const struct mg_connection *conn, void *_ignored)
47 #endif
48 {
49 printf("Server: Websocket connected\n");
50 return 0; /* return 0 to accept every connection */
51 }
52
53
54 #if defined(MG_LEGACY_INTERFACE)
55 void
56 websocket_server_ready(struct mg_connection *conn)
57 #else
58 void
59 websocket_server_ready(struct mg_connection *conn, void *_ignored)
60 #endif
61 {
62 printf("Server: Websocket ready\n");
63
64 /* Send websocket welcome message */
65 mg_lock_connection(conn);
66 mg_websocket_write(conn,
67 WEBSOCKET_OPCODE_TEXT,
68 websocket_welcome_msg,
69 websocket_welcome_msg_len);
70 mg_unlock_connection(conn);
71 }
72
73
74 #if defined(MG_LEGACY_INTERFACE)
75 int
76 websocket_server_data(struct mg_connection *conn,
77 int bits,
78 char *data,
79 size_t data_len)
80 #else
81 int
82 websocket_server_data(struct mg_connection *conn,
83 int bits,
84 char *data,
85 size_t data_len,
86 void *_ignored)
87 #endif
88 {
89 printf("Server: Got %lu bytes from the client\n", (unsigned long)data_len);
90 printf("Server received data from client: ");
91 fwrite(data, 1, data_len, stdout);
92 printf("\n");
93
94 if (data_len < 3 || 0 != memcmp(data, "bye", 3)) {
95 /* Send websocket acknowledge message */
96 mg_lock_connection(conn);
97 mg_websocket_write(conn,
98 WEBSOCKET_OPCODE_TEXT,
99 websocket_acknowledge_msg,
100 websocket_acknowledge_msg_len);
101 mg_unlock_connection(conn);
102 } else {
103 /* Send websocket acknowledge message */
104 mg_lock_connection(conn);
105 mg_websocket_write(conn,
106 WEBSOCKET_OPCODE_TEXT,
107 websocket_goodbye_msg,
108 websocket_goodbye_msg_len);
109 mg_unlock_connection(conn);
110 }
111
112 return 1; /* return 1 to keep the connetion open */
113 }
114
115
116 #if defined(MG_LEGACY_INTERFACE)
117 void
118 websocket_server_connection_close(const struct mg_connection *conn)
119 #else
120 void
121 websocket_server_connection_close(const struct mg_connection *conn,
122 void *_ignored)
123 #endif
124 {
125 printf("Server: Close connection\n");
126
127 /* Can not send a websocket goodbye message here - the connection is already
128 * closed */
129 }
130
131
132 struct mg_context *
133 start_websocket_server()
134 {
135 const char *options[] = {"document_root",
136 DOCUMENT_ROOT,
137 "ssl_certificate",
138 SSL_CERT,
139 "listening_ports",
140 PORT,
141 "request_timeout_ms",
142 "5000",
143 0};
144 struct mg_callbacks callbacks;
145 struct mg_context *ctx;
146
147 memset(&callbacks, 0, sizeof(callbacks));
148
149 #if defined(MG_LEGACY_INTERFACE)
150 /* Obsolete: */
151 callbacks.websocket_connect = websock_server_connect;
152 callbacks.websocket_ready = websocket_server_ready;
153 callbacks.websocket_data = websocket_server_data;
154 callbacks.connection_close = websocket_server_connection_close;
155
156 ctx = mg_start(&callbacks, 0, options);
157 #else
158 /* New interface: */
159 ctx = mg_start(&callbacks, 0, options);
160
161 mg_set_websocket_handler(ctx,
162 "/websocket",
163 websocket_server_connect,
164 websocket_server_ready,
165 websocket_server_data,
166 websocket_server_connection_close,
167 NULL);
168 #endif
169
170 return ctx;
171 }
172
173
174 /*************************************************************************************/
175 /* WEBSOCKET CLIENT */
176 /*************************************************************************************/
177 struct tclient_data {
178 void *data;
179 size_t len;
180 int closed;
181 };
182
183 static int
184 websocket_client_data_handler(struct mg_connection *conn,
185 int flags,
186 char *data,
187 size_t data_len,
188 void *user_data)
189 {
190 struct mg_context *ctx = mg_get_context(conn);
191 struct tclient_data *pclient_data =
192 (struct tclient_data *)mg_get_user_data(ctx);
193
194 printf("Client received data from server: ");
195 fwrite(data, 1, data_len, stdout);
196 printf("\n");
197
198 pclient_data->data = malloc(data_len);
199 assert(pclient_data->data != NULL);
200 memcpy(pclient_data->data, data, data_len);
201 pclient_data->len = data_len;
202
203 return 1;
204 }
205
206 static void
207 websocket_client_close_handler(const struct mg_connection *conn,
208 void *user_data)
209 {
210 struct mg_context *ctx = mg_get_context(conn);
211 struct tclient_data *pclient_data =
212 (struct tclient_data *)mg_get_user_data(ctx);
213
214 printf("Client: Close handler\n");
215 pclient_data->closed++;
216 }
217
218
219 int
220 main(int argc, char *argv[])
221 {
222 struct mg_context *ctx = NULL;
223 struct tclient_data client1_data = {NULL, 0, 0};
224 struct tclient_data client2_data = {NULL, 0, 0};
225 struct tclient_data client3_data = {NULL, 0, 0};
226 struct mg_connection *newconn1 = NULL;
227 struct mg_connection *newconn2 = NULL;
228 struct mg_connection *newconn3 = NULL;
229 char ebuf[100] = {0};
230
231 assert(websocket_welcome_msg_len == strlen(websocket_welcome_msg));
232
233 /* First set up a websocket server */
234 ctx = start_websocket_server();
235 assert(ctx != NULL);
236 printf("Server init\n\n");
237
238 /* Then connect a first client */
239 newconn1 = mg_connect_websocket_client("localhost",
240 atoi(PORT),
241 0,
242 ebuf,
243 sizeof(ebuf),
244 "/websocket",
245 NULL,
246 websocket_client_data_handler,
247 websocket_client_close_handler,
248 &client1_data);
249
250 if (newconn1 == NULL) {
251 printf("Error: %s", ebuf);
252 return 1;
253 }
254
255 sleep(1); /* Should get the websocket welcome message */
256 assert(client1_data.closed == 0);
257 assert(client2_data.closed == 0);
258 assert(client2_data.data == NULL);
259 assert(client2_data.len == 0);
260 assert(client1_data.data != NULL);
261 assert(client1_data.len == websocket_welcome_msg_len);
262 assert(!memcmp(client1_data.data,
263 websocket_welcome_msg,
264 websocket_welcome_msg_len));
265 free(client1_data.data);
266 client1_data.data = NULL;
267 client1_data.len = 0;
268
269 mg_websocket_client_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data1", 5);
270
271 sleep(1); /* Should get the acknowledge message */
272 assert(client1_data.closed == 0);
273 assert(client2_data.closed == 0);
274 assert(client2_data.data == NULL);
275 assert(client2_data.len == 0);
276 assert(client1_data.data != NULL);
277 assert(client1_data.len == websocket_acknowledge_msg_len);
278 assert(!memcmp(client1_data.data,
279 websocket_acknowledge_msg,
280 websocket_acknowledge_msg_len));
281 free(client1_data.data);
282 client1_data.data = NULL;
283 client1_data.len = 0;
284
285 /* Now connect a second client */
286 newconn2 = mg_connect_websocket_client("localhost",
287 atoi(PORT),
288 0,
289 ebuf,
290 sizeof(ebuf),
291 "/websocket",
292 NULL,
293 websocket_client_data_handler,
294 websocket_client_close_handler,
295 &client2_data);
296
297 if (newconn2 == NULL) {
298 printf("Error: %s", ebuf);
299 return 1;
300 }
301
302 sleep(1); /* Client 2 should get the websocket welcome message */
303 assert(client1_data.closed == 0);
304 assert(client2_data.closed == 0);
305 assert(client1_data.data == NULL);
306 assert(client1_data.len == 0);
307 assert(client2_data.data != NULL);
308 assert(client2_data.len == websocket_welcome_msg_len);
309 assert(!memcmp(client2_data.data,
310 websocket_welcome_msg,
311 websocket_welcome_msg_len));
312 free(client2_data.data);
313 client2_data.data = NULL;
314 client2_data.len = 0;
315
316 mg_websocket_client_write(newconn1, WEBSOCKET_OPCODE_TEXT, "data2", 5);
317
318 sleep(1); /* Should get the acknowledge message */
319 assert(client1_data.closed == 0);
320 assert(client2_data.closed == 0);
321 assert(client2_data.data == NULL);
322 assert(client2_data.len == 0);
323 assert(client1_data.data != NULL);
324 assert(client1_data.len == websocket_acknowledge_msg_len);
325 assert(!memcmp(client1_data.data,
326 websocket_acknowledge_msg,
327 websocket_acknowledge_msg_len));
328 free(client1_data.data);
329 client1_data.data = NULL;
330 client1_data.len = 0;
331
332 mg_websocket_client_write(newconn1, WEBSOCKET_OPCODE_TEXT, "bye", 3);
333
334 sleep(1); /* Should get the goodbye message */
335 assert(client1_data.closed == 0);
336 assert(client2_data.closed == 0);
337 assert(client2_data.data == NULL);
338 assert(client2_data.len == 0);
339 assert(client1_data.data != NULL);
340 assert(client1_data.len == websocket_goodbye_msg_len);
341 assert(!memcmp(client1_data.data,
342 websocket_goodbye_msg,
343 websocket_goodbye_msg_len));
344 free(client1_data.data);
345 client1_data.data = NULL;
346 client1_data.len = 0;
347
348 mg_close_connection(newconn1);
349
350 sleep(1); /* Won't get any message */
351 assert(client1_data.closed == 1);
352 assert(client2_data.closed == 0);
353 assert(client1_data.data == NULL);
354 assert(client1_data.len == 0);
355 assert(client2_data.data == NULL);
356 assert(client2_data.len == 0);
357
358 mg_websocket_client_write(newconn2, WEBSOCKET_OPCODE_TEXT, "bye", 3);
359
360 sleep(1); /* Should get the goodbye message */
361 assert(client1_data.closed == 1);
362 assert(client2_data.closed == 0);
363 assert(client1_data.data == NULL);
364 assert(client1_data.len == 0);
365 assert(client2_data.data != NULL);
366 assert(client2_data.len == websocket_goodbye_msg_len);
367 assert(!memcmp(client2_data.data,
368 websocket_goodbye_msg,
369 websocket_goodbye_msg_len));
370 free(client2_data.data);
371 client2_data.data = NULL;
372 client2_data.len = 0;
373
374 mg_close_connection(newconn2);
375
376 sleep(1); /* Won't get any message */
377 assert(client1_data.closed == 1);
378 assert(client2_data.closed == 1);
379 assert(client1_data.data == NULL);
380 assert(client1_data.len == 0);
381 assert(client2_data.data == NULL);
382 assert(client2_data.len == 0);
383
384 /* Connect client 3 */
385 newconn3 = mg_connect_websocket_client("localhost",
386 atoi(PORT),
387 0,
388 ebuf,
389 sizeof(ebuf),
390 "/websocket",
391 NULL,
392 websocket_client_data_handler,
393 websocket_client_close_handler,
394 &client3_data);
395
396 sleep(1); /* Client 3 should get the websocket welcome message */
397 assert(client1_data.closed == 1);
398 assert(client2_data.closed == 1);
399 assert(client3_data.closed == 0);
400 assert(client1_data.data == NULL);
401 assert(client1_data.len == 0);
402 assert(client2_data.data == NULL);
403 assert(client2_data.len == 0);
404 assert(client3_data.data != NULL);
405 assert(client3_data.len == websocket_welcome_msg_len);
406 assert(!memcmp(client3_data.data,
407 websocket_welcome_msg,
408 websocket_welcome_msg_len));
409 free(client3_data.data);
410 client3_data.data = NULL;
411 client3_data.len = 0;
412
413 mg_stop(ctx);
414 printf("Server shutdown\n");
415
416 sleep(10);
417
418 assert(client3_data.closed == 1);
419
420 return 0;
421 }