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
8 /* This example is superseeded by other examples, and no longer
10 * See examples/embedded_c for an up to date example.
13 // Simple example program on how to use websocket client embedded C interface.
16 #define sleep(x) Sleep(1000 * (x))
25 #define DOCUMENT_ROOT "."
27 #define SSL_CERT "./ssl/server.pem"
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) */;
38 /*************************************************************************************/
39 /* WEBSOCKET SERVER */
40 /*************************************************************************************/
41 #if defined(MG_LEGACY_INTERFACE)
43 websock_server_connect(const struct mg_connection
*conn
)
46 websocket_server_connect(const struct mg_connection
*conn
, void *_ignored
)
49 printf("Server: Websocket connected\n");
50 return 0; /* return 0 to accept every connection */
54 #if defined(MG_LEGACY_INTERFACE)
56 websocket_server_ready(struct mg_connection
*conn
)
59 websocket_server_ready(struct mg_connection
*conn
, void *_ignored
)
62 printf("Server: Websocket ready\n");
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
);
74 #if defined(MG_LEGACY_INTERFACE)
76 websocket_server_data(struct mg_connection
*conn
,
82 websocket_server_data(struct mg_connection
*conn
,
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
);
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
);
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
);
112 return 1; /* return 1 to keep the connetion open */
116 #if defined(MG_LEGACY_INTERFACE)
118 websocket_server_connection_close(const struct mg_connection
*conn
)
121 websocket_server_connection_close(const struct mg_connection
*conn
,
125 printf("Server: Close connection\n");
127 /* Can not send a websocket goodbye message here - the connection is already
133 start_websocket_server()
135 const char *options
[] = {"document_root",
141 "request_timeout_ms",
144 struct mg_callbacks callbacks
;
145 struct mg_context
*ctx
;
147 memset(&callbacks
, 0, sizeof(callbacks
));
149 #if defined(MG_LEGACY_INTERFACE)
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
;
156 ctx
= mg_start(&callbacks
, 0, options
);
159 ctx
= mg_start(&callbacks
, 0, options
);
161 mg_set_websocket_handler(ctx
,
163 websocket_server_connect
,
164 websocket_server_ready
,
165 websocket_server_data
,
166 websocket_server_connection_close
,
174 /*************************************************************************************/
175 /* WEBSOCKET CLIENT */
176 /*************************************************************************************/
177 struct tclient_data
{
184 websocket_client_data_handler(struct mg_connection
*conn
,
190 struct mg_context
*ctx
= mg_get_context(conn
);
191 struct tclient_data
*pclient_data
=
192 (struct tclient_data
*)mg_get_user_data(ctx
);
194 printf("Client received data from server: ");
195 fwrite(data
, 1, data_len
, stdout
);
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
;
207 websocket_client_close_handler(const struct mg_connection
*conn
,
210 struct mg_context
*ctx
= mg_get_context(conn
);
211 struct tclient_data
*pclient_data
=
212 (struct tclient_data
*)mg_get_user_data(ctx
);
214 printf("Client: Close handler\n");
215 pclient_data
->closed
++;
220 main(int argc
, char *argv
[])
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};
231 assert(websocket_welcome_msg_len
== strlen(websocket_welcome_msg
));
233 /* First set up a websocket server */
234 ctx
= start_websocket_server();
236 printf("Server init\n\n");
238 /* Then connect a first client */
239 newconn1
= mg_connect_websocket_client("localhost",
246 websocket_client_data_handler
,
247 websocket_client_close_handler
,
250 if (newconn1
== NULL
) {
251 printf("Error: %s", ebuf
);
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;
269 mg_websocket_client_write(newconn1
, WEBSOCKET_OPCODE_TEXT
, "data1", 5);
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;
285 /* Now connect a second client */
286 newconn2
= mg_connect_websocket_client("localhost",
293 websocket_client_data_handler
,
294 websocket_client_close_handler
,
297 if (newconn2
== NULL
) {
298 printf("Error: %s", ebuf
);
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;
316 mg_websocket_client_write(newconn1
, WEBSOCKET_OPCODE_TEXT
, "data2", 5);
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;
332 mg_websocket_client_write(newconn1
, WEBSOCKET_OPCODE_TEXT
, "bye", 3);
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;
348 mg_close_connection(newconn1
);
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);
358 mg_websocket_client_write(newconn2
, WEBSOCKET_OPCODE_TEXT
, "bye", 3);
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;
374 mg_close_connection(newconn2
);
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);
384 /* Connect client 3 */
385 newconn3
= mg_connect_websocket_client("localhost",
392 websocket_client_data_handler
,
393 websocket_client_close_handler
,
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;
414 printf("Server shutdown\n");
418 assert(client3_data
.closed
== 1);