WebSockCallbacks.c 5.0 KB

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