WebSockCallbacks.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /* This example uses deprecated interfaces: global websocket callbacks.
  2. They have been superseeded by URI specific callbacks.
  3. See examples/embedded_c for an up to date example.
  4. */
  5. #include <assert.h>
  6. #include <stdlib.h>
  7. #include <time.h>
  8. #include <string.h>
  9. #include "WebSockCallbacks.h"
  10. #ifdef _WIN32
  11. #include <Windows.h>
  12. #define mg_sleep(x) Sleep(x)
  13. #else
  14. #include <unistd.h>
  15. #include <pthread.h>
  16. #define mg_sleep(x) usleep((x)*1000)
  17. #endif
  18. static void
  19. send_to_all_websockets(struct mg_context *ctx, const char *data, int data_len)
  20. {
  21. int i;
  22. tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
  23. mg_lock_context(ctx);
  24. for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) {
  25. if (ws_ctx->socketList[i]
  26. && (ws_ctx->socketList[i]->webSockState == 2)) {
  27. mg_websocket_write(ws_ctx->socketList[i]->conn,
  28. WEBSOCKET_OPCODE_TEXT,
  29. data,
  30. data_len);
  31. }
  32. }
  33. mg_unlock_context(ctx);
  34. }
  35. void
  36. websocket_ready_handler(struct mg_connection *conn, void *_ignored)
  37. {
  38. int i;
  39. const struct mg_request_info *rq = mg_get_request_info(conn);
  40. struct mg_context *ctx = mg_get_context(conn);
  41. tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
  42. tWebSockInfo *wsock = malloc(sizeof(tWebSockInfo));
  43. assert(wsock);
  44. wsock->webSockState = 0;
  45. mg_set_user_connection_data(conn, wsock);
  46. mg_lock_context(ctx);
  47. for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) {
  48. if (0 == ws_ctx->socketList[i]) {
  49. ws_ctx->socketList[i] = wsock;
  50. wsock->conn = conn;
  51. wsock->webSockState = 1;
  52. break;
  53. }
  54. }
  55. printf("\nNew websocket attached: %s:%u\n",
  56. rq->remote_addr,
  57. rq->remote_port);
  58. mg_unlock_context(ctx);
  59. }
  60. static void
  61. websocket_done(tWebSockContext *ws_ctx, tWebSockInfo *wsock)
  62. {
  63. int i;
  64. if (wsock) {
  65. wsock->webSockState = 99;
  66. for (i = 0; i < MAX_NUM_OF_WEBSOCKS; i++) {
  67. if (wsock == ws_ctx->socketList[i]) {
  68. ws_ctx->socketList[i] = 0;
  69. break;
  70. }
  71. }
  72. printf("\nClose websocket attached: %s:%u\n",
  73. mg_get_request_info(wsock->conn)->remote_addr,
  74. mg_get_request_info(wsock->conn)->remote_port);
  75. free(wsock);
  76. }
  77. }
  78. int
  79. websocket_data_handler(struct mg_connection *conn,
  80. int flags,
  81. char *data,
  82. size_t data_len,
  83. void *_ignored)
  84. {
  85. const struct mg_request_info *rq = mg_get_request_info(conn);
  86. tWebSockInfo *wsock = (tWebSockInfo *)rq->conn_data;
  87. struct mg_context *ctx = mg_get_context(conn);
  88. tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
  89. char msg[128];
  90. mg_lock_context(ctx);
  91. if (flags == 136) {
  92. // close websock
  93. websocket_done(ws_ctx, wsock);
  94. mg_set_user_connection_data(conn, NULL);
  95. mg_unlock_context(ctx);
  96. return 1;
  97. }
  98. if (((data_len >= 5) && (data_len < 100) && (flags == 129))
  99. || (flags == 130)) {
  100. // init command
  101. if ((wsock->webSockState == 1) && (!memcmp(data, "init ", 5))) {
  102. char *chk;
  103. unsigned long gid;
  104. memcpy(msg, data + 5, data_len - 5);
  105. msg[data_len - 5] = 0;
  106. gid = strtoul(msg, &chk, 10);
  107. wsock->initId = gid;
  108. if (gid > 0 && chk != NULL && *chk == 0) {
  109. wsock->webSockState = 2;
  110. }
  111. mg_unlock_context(ctx);
  112. return 1;
  113. }
  114. // chat message
  115. if ((wsock->webSockState == 2) && (!memcmp(data, "msg ", 4))) {
  116. send_to_all_websockets(ctx, data, data_len);
  117. mg_unlock_context(ctx);
  118. return 1;
  119. }
  120. }
  121. // keep alive
  122. if ((data_len == 4) && !memcmp(data, "ping", 4)) {
  123. mg_unlock_context(ctx);
  124. return 1;
  125. }
  126. mg_unlock_context(ctx);
  127. return 0;
  128. }
  129. void
  130. connection_close_handler(const struct mg_connection *conn, void *_ignored)
  131. {
  132. const struct mg_request_info *rq = mg_get_request_info(conn);
  133. tWebSockInfo *wsock = (tWebSockInfo *)rq->conn_data;
  134. struct mg_context *ctx = mg_get_context(conn);
  135. tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
  136. mg_lock_context(ctx);
  137. websocket_done(ws_ctx, wsock);
  138. mg_set_user_connection_data(conn, NULL);
  139. mg_unlock_context(ctx);
  140. }
  141. static void *
  142. eventMain(void *arg)
  143. {
  144. char msg[256];
  145. struct mg_context *ctx = (struct mg_context *)arg;
  146. tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
  147. ws_ctx->runLoop = 1;
  148. while (ws_ctx->runLoop) {
  149. time_t t = time(0);
  150. struct tm *timestr = localtime(&t);
  151. strftime(msg, sizeof(msg), "title %c", timestr);
  152. send_to_all_websockets(ctx, msg, strlen(msg));
  153. mg_sleep(1000);
  154. }
  155. return NULL;
  156. }
  157. void
  158. websock_send_broadcast(struct mg_context *ctx, const char *data, int data_len)
  159. {
  160. char buffer[260];
  161. if (data_len <= 256) {
  162. strcpy(buffer, "msg ");
  163. memcpy(buffer + 4, data, data_len);
  164. send_to_all_websockets(ctx, buffer, data_len + 4);
  165. }
  166. }
  167. void
  168. websock_init_lib(const struct mg_context *ctx)
  169. {
  170. tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
  171. memset(ws_ctx, 0, sizeof(*ws_ctx));
  172. /* todo: use mg_start_thread_id instead of mg_start_thread */
  173. mg_start_thread(eventMain, (void *)ctx);
  174. }
  175. void
  176. websock_exit_lib(const struct mg_context *ctx)
  177. {
  178. tWebSockContext *ws_ctx = (tWebSockContext *)mg_get_user_data(ctx);
  179. ws_ctx->runLoop = 0;
  180. /* todo: wait for the thread instead of a timeout */
  181. mg_sleep(2000);
  182. }