WebSockCallbacks.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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 send_to_all_websockets(struct mg_context *ctx, const char * data, int data_len) {
  19. int i;
  20. tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
  21. mg_lock_context(ctx);
  22. for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
  23. if (ws_ctx->socketList[i] && (ws_ctx->socketList[i]->webSockState==2)) {
  24. mg_websocket_write(ws_ctx->socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
  25. }
  26. }
  27. mg_unlock_context(ctx);
  28. }
  29. void websocket_ready_handler(struct mg_connection *conn) {
  30. int i;
  31. struct mg_request_info * rq = mg_get_request_info(conn);
  32. struct mg_context * ctx = mg_get_context(conn);
  33. tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
  34. tWebSockInfo * wsock = malloc(sizeof(tWebSockInfo));
  35. assert(wsock);
  36. wsock->webSockState = 0;
  37. rq->conn_data = wsock;
  38. mg_lock_context(ctx);
  39. for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
  40. if (0==ws_ctx->socketList[i]) {
  41. ws_ctx->socketList[i] = wsock;
  42. wsock->conn = conn;
  43. wsock->webSockState = 1;
  44. break;
  45. }
  46. }
  47. printf("\nNew websocket attached: %s:%u\n", rq->remote_addr, rq->remote_port);
  48. mg_unlock_context(ctx);
  49. }
  50. static void websocket_done(tWebSockContext *ws_ctx, tWebSockInfo * wsock) {
  51. int i;
  52. if (wsock) {
  53. wsock->webSockState = 99;
  54. for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
  55. if (wsock==ws_ctx->socketList[i]) {
  56. ws_ctx->socketList[i] = 0;
  57. break;
  58. }
  59. }
  60. printf("\nClose websocket attached: %s:%u\n", mg_get_request_info(wsock->conn)->remote_addr, mg_get_request_info(wsock->conn)->remote_port);
  61. free(wsock);
  62. }
  63. }
  64. int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len) {
  65. struct mg_request_info * rq = mg_get_request_info(conn);
  66. tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
  67. struct mg_context * ctx = mg_get_context(conn);
  68. tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
  69. char msg[128];
  70. mg_lock_context(ctx);
  71. if (flags==136) {
  72. // close websock
  73. websocket_done(ws_ctx, wsock);
  74. rq->conn_data = 0;
  75. mg_unlock_context(ctx);
  76. return 1;
  77. }
  78. if (((data_len>=5) && (data_len<100) && (flags==129)) || (flags==130)) {
  79. // init command
  80. if ((wsock->webSockState==1) && (!memcmp(data,"init ",5))) {
  81. char * chk;
  82. unsigned long gid;
  83. memcpy(msg,data+5,data_len-5);
  84. msg[data_len-5]=0;
  85. gid = strtoul(msg,&chk,10);
  86. wsock->initId = gid;
  87. if (gid>0 && chk!=NULL && *chk==0) {
  88. wsock->webSockState = 2;
  89. }
  90. mg_unlock_context(ctx);
  91. return 1;
  92. }
  93. // chat message
  94. if ((wsock->webSockState==2) && (!memcmp(data,"msg ",4))) {
  95. send_to_all_websockets(ctx, data, data_len);
  96. mg_unlock_context(ctx);
  97. return 1;
  98. }
  99. }
  100. // keep alive
  101. if ((data_len==4) && !memcmp(data,"ping",4)) {
  102. mg_unlock_context(ctx);
  103. return 1;
  104. }
  105. mg_unlock_context(ctx);
  106. return 0;
  107. }
  108. void connection_close_handler(struct mg_connection *conn) {
  109. struct mg_request_info * rq = mg_get_request_info(conn);
  110. tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
  111. struct mg_context * ctx = mg_get_context(conn);
  112. tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
  113. mg_lock_context(ctx);
  114. websocket_done(ws_ctx, wsock);
  115. rq->conn_data = 0;
  116. mg_unlock_context(ctx);
  117. }
  118. static void * eventMain(void * arg) {
  119. char msg[256];
  120. struct mg_context *ctx = (struct mg_context *)arg;
  121. tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
  122. ws_ctx->runLoop = 1;
  123. while (ws_ctx->runLoop) {
  124. time_t t = time(0);
  125. struct tm * timestr = localtime(&t);
  126. strftime(msg, sizeof(msg), "title %c", timestr);
  127. send_to_all_websockets(ctx, msg, strlen(msg));
  128. mg_sleep(1000);
  129. }
  130. return NULL;
  131. }
  132. void websock_send_broadcast(struct mg_context *ctx, const char * data, int data_len) {
  133. char buffer[260];
  134. if (data_len<=256) {
  135. strcpy(buffer, "msg ");
  136. memcpy(buffer+4, data, data_len);
  137. send_to_all_websockets(ctx, buffer, data_len+4);
  138. }
  139. }
  140. void websock_init_lib(struct mg_context *ctx) {
  141. tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
  142. memset(ws_ctx,0,sizeof(*ws_ctx));
  143. /* todo: use mg_start_thread_id instead of mg_start_thread */
  144. mg_start_thread(eventMain, ctx);
  145. }
  146. void websock_exit_lib(struct mg_context *ctx) {
  147. tWebSockContext *ws_ctx = (tWebSockContext*) mg_get_user_data(ctx);
  148. ws_ctx->runLoop = 0;
  149. /* todo: wait for the thread instead of a timeout */
  150. mg_sleep(2000);
  151. }