WebSockCallbacks.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. typedef struct tWebSockInfo {
  15. int webSockState;
  16. unsigned long initId;
  17. struct mg_connection *conn;
  18. } tWebSockInfo;
  19. #define MAX_NUM_OF_WEBSOCKS (256)
  20. static tWebSockInfo *socketList[MAX_NUM_OF_WEBSOCKS];
  21. static void send_to_all_websockets(struct mg_context *ctx, const char * data, int data_len) {
  22. int i;
  23. mg_lock_context(ctx);
  24. for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
  25. if (socketList[i] && (socketList[i]->webSockState==2)) {
  26. mg_websocket_write(socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
  27. }
  28. }
  29. mg_unlock_context(ctx);
  30. }
  31. void websocket_ready_handler(struct mg_connection *conn) {
  32. int i;
  33. struct mg_request_info * rq = mg_get_request_info(conn);
  34. struct mg_context * ctx = mg_get_context(conn);
  35. tWebSockInfo * wsock = malloc(sizeof(tWebSockInfo));
  36. assert(wsock);
  37. wsock->webSockState = 0;
  38. rq->conn_data = wsock;
  39. mg_lock_context(ctx);
  40. for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
  41. if (0==socketList[i]) {
  42. socketList[i] = wsock;
  43. wsock->conn = conn;
  44. wsock->webSockState = 1;
  45. break;
  46. }
  47. }
  48. printf("\nNew websocket attached: %08lx:%u\n", rq->remote_ip, rq->remote_port);
  49. mg_unlock_context(ctx);
  50. }
  51. static void websocket_done(tWebSockInfo * wsock) {
  52. int i;
  53. if (wsock) {
  54. wsock->webSockState = 99;
  55. for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
  56. if (wsock==socketList[i]) {
  57. socketList[i] = 0;
  58. break;
  59. }
  60. }
  61. printf("\nClose websocket attached: %08lx:%u\n", mg_get_request_info(wsock->conn)->remote_ip, mg_get_request_info(wsock->conn)->remote_port);
  62. free(wsock);
  63. }
  64. }
  65. int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len) {
  66. struct mg_request_info * rq = mg_get_request_info(conn);
  67. struct mg_context * ctx = mg_get_context(conn);
  68. tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
  69. char msg[128];
  70. mg_lock_context(ctx);
  71. if (flags==136) {
  72. // close websock
  73. websocket_done(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. struct mg_context * ctx = mg_get_context(conn);
  111. tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
  112. mg_lock_context(ctx);
  113. websocket_done(wsock);
  114. rq->conn_data = 0;
  115. mg_unlock_context(ctx);
  116. }
  117. static int runLoop = 0;
  118. static void * eventMain(void * arg) {
  119. char msg[256];
  120. struct mg_context *ctx = (struct mg_context *)arg;
  121. runLoop = 1;
  122. while (runLoop) {
  123. time_t t = time(0);
  124. struct tm * timestr = localtime(&t);
  125. sprintf(msg,"title %s",asctime(timestr));
  126. send_to_all_websockets(ctx, msg, strlen(msg));
  127. mg_sleep(1000);
  128. }
  129. return NULL;
  130. }
  131. void websock_send_broadcast(struct mg_context *ctx, const char * data, int data_len) {
  132. char buffer[260];
  133. if (data_len<=256) {
  134. strcpy(buffer, "msg ");
  135. memcpy(buffer+4, data, data_len);
  136. send_to_all_websockets(ctx, buffer, data_len+4);
  137. }
  138. }
  139. void websock_init_lib(struct mg_context *ctx) {
  140. /* todo: use variable in the ctx instead of static ones */
  141. memset(socketList,0,sizeof(socketList));
  142. mg_start_thread(eventMain, ctx);
  143. }
  144. void websock_exit_lib(struct mg_context *ctx) {
  145. runLoop = 0;
  146. /* todo: wait for the thread instead of a timeout */
  147. mg_sleep(2000);
  148. }