Przeglądaj źródła

New + better websocket example

bel 11 lat temu
rodzic
commit
aa2cded31f

+ 1 - 2
VS2012/ex_websocket/ex_websocket.vcxproj

@@ -27,7 +27,6 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v110_xp</PlatformToolset>
     <CharacterSet>Unicode</CharacterSet>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@@ -39,7 +38,6 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v110_xp</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>Unicode</CharacterSet>
     <CharacterSet>Unicode</CharacterSet>
   </PropertyGroup>
   </PropertyGroup>
@@ -150,6 +148,7 @@
     <ClInclude Include="..\..\include\civetweb.h" />
     <ClInclude Include="..\..\include\civetweb.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\..\examples\websocket\WebSockCallbacks.c" />
     <ClCompile Include="..\..\src\civetweb.c" />
     <ClCompile Include="..\..\src\civetweb.c" />
     <ClCompile Include="..\..\examples\websocket\websocket.c" />
     <ClCompile Include="..\..\examples\websocket\websocket.c" />
   </ItemGroup>
   </ItemGroup>

+ 138 - 109
examples/websocket/WebSockCallbacks.c

@@ -7,21 +7,21 @@
 #include <Windows.h>
 #include <Windows.h>
 typedef HANDLE pthread_mutex_t;
 typedef HANDLE pthread_mutex_t;
 static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused) {
 static int pthread_mutex_init(pthread_mutex_t *mutex, void *unused) {
-  unused = NULL;
-  *mutex = CreateMutex(NULL, FALSE, NULL);
-  return *mutex == NULL ? -1 : 0;
+    unused = NULL;
+    *mutex = CreateMutex(NULL, FALSE, NULL);
+    return *mutex == NULL ? -1 : 0;
 }
 }
 
 
 static int pthread_mutex_destroy(pthread_mutex_t *mutex) {
 static int pthread_mutex_destroy(pthread_mutex_t *mutex) {
-  return CloseHandle(*mutex) == 0 ? -1 : 0;
+    return CloseHandle(*mutex) == 0 ? -1 : 0;
 }
 }
 
 
 static int pthread_mutex_lock(pthread_mutex_t *mutex) {
 static int pthread_mutex_lock(pthread_mutex_t *mutex) {
-  return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0? 0 : -1;
+    return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0? 0 : -1;
 }
 }
 
 
 static int pthread_mutex_unlock(pthread_mutex_t *mutex) {
 static int pthread_mutex_unlock(pthread_mutex_t *mutex) {
-  return ReleaseMutex(*mutex) == 0 ? -1 : 0;
+    return ReleaseMutex(*mutex) == 0 ? -1 : 0;
 }
 }
 #define mg_sleep(x) Sleep(x)
 #define mg_sleep(x) Sleep(x)
 #else
 #else
@@ -32,9 +32,9 @@ static int pthread_mutex_unlock(pthread_mutex_t *mutex) {
 
 
 
 
 typedef struct tWebSockInfo {
 typedef struct tWebSockInfo {
-  int webSockState;
-  unsigned long initId;
-  struct mg_connection *conn;
+    int webSockState;
+    unsigned long initId;
+    struct mg_connection *conn;
 } tWebSockInfo;
 } tWebSockInfo;
 
 
 static pthread_mutex_t sMutex;
 static pthread_mutex_t sMutex;
@@ -43,138 +43,167 @@ static pthread_mutex_t sMutex;
 static tWebSockInfo *socketList[MAX_NUM_OF_WEBSOCKS];
 static tWebSockInfo *socketList[MAX_NUM_OF_WEBSOCKS];
 
 
 
 
-void websocket_ready_handler(struct mg_connection *conn) {
+static void send_to_all_websockets(const char * data, int data_len) {
+
+    int i;
 
 
-  int i;
-  struct mg_request_info * rq = mg_get_request_info(conn);
-  tWebSockInfo * wsock = malloc(sizeof(tWebSockInfo));
-  assert(wsock);
-  wsock->webSockState = 0;
-  rq->conn_data = wsock;
-
-  pthread_mutex_lock(&sMutex);
-  for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
-    if (0==socketList[i]) {
-      socketList[i] = wsock;
-      wsock->conn = conn;
-      wsock->webSockState = 1;
-      break;
+    for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
+        if (socketList[i] && (socketList[i]->webSockState==2)) {
+            mg_websocket_write(socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
+        }
     }
     }
-  }
-  pthread_mutex_unlock(&sMutex);
 }
 }
 
 
 
 
-static void websocket_done(tWebSockInfo * wsock) { 
-  int i;
-  if (wsock) {
-    wsock->webSockState = 99;
+void websocket_ready_handler(struct mg_connection *conn) {
+
+    int i;
+    struct mg_request_info * rq = mg_get_request_info(conn);
+    tWebSockInfo * wsock = malloc(sizeof(tWebSockInfo));
+    assert(wsock);
+    wsock->webSockState = 0;
+    rq->conn_data = wsock;
+
+    pthread_mutex_lock(&sMutex);
     for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
     for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
-      if (wsock==socketList[i]) {
-        socketList[i] = 0;
-        break;
-      }
+        if (0==socketList[i]) {
+            socketList[i] = wsock;
+            wsock->conn = conn;
+            wsock->webSockState = 1;
+            break;
+        }
+    }
+    pthread_mutex_unlock(&sMutex);
+}
+
+
+static void websocket_done(tWebSockInfo * wsock) {
+    int i;
+    if (wsock) {
+        wsock->webSockState = 99;
+        for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
+            if (wsock==socketList[i]) {
+                socketList[i] = 0;
+                break;
+            }
+        }
+        free(wsock);
     }
     }
-    free(wsock);
-  }
 }
 }
 
 
 
 
 int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len) {
 int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len) {
-  struct mg_request_info * rq = mg_get_request_info(conn);
-  tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
-  char msg[128];
-  int i;
-
-  pthread_mutex_lock(&sMutex);
-  if (flags==136) {
-    // close websock
-    websocket_done(wsock);
-    rq->conn_data = 0;
-    pthread_mutex_unlock(&sMutex);
-    return 1;
-  }
-  if ((data_len>=5) && (data_len<100) && (flags==129) || (flags==130)) {
-
-    // init command
-    if ((wsock->webSockState==1) && (!memcmp(data,"init ",5))) {
-      char * chk;
-      unsigned long gid;
-      memcpy(msg,data+5,data_len-5);
-      msg[data_len-5]=0;
-      gid = strtoul(msg,&chk,10);
-      wsock->initId = gid;
-      if (gid>0 && chk!=NULL && *chk==0) {
-        wsock->webSockState = 2;
-      }
-      pthread_mutex_unlock(&sMutex);
-      return 1;
+    struct mg_request_info * rq = mg_get_request_info(conn);
+    tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
+    char msg[128];
+
+    pthread_mutex_lock(&sMutex);
+    if (flags==136) {
+        // close websock
+        websocket_done(wsock);
+        rq->conn_data = 0;
+        pthread_mutex_unlock(&sMutex);
+        return 1;
     }
     }
-        
-    // chat message
-    if ((wsock->webSockState==2) && (!memcmp(data,"msg ",4))) {     
-      for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
-        if (socketList[i] && (socketList[i]->webSockState==2)) {
-          mg_websocket_write(socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
+    if ((data_len>=5) && (data_len<100) && (flags==129) || (flags==130)) {
+
+        // init command
+        if ((wsock->webSockState==1) && (!memcmp(data,"init ",5))) {
+            char * chk;
+            unsigned long gid;
+            memcpy(msg,data+5,data_len-5);
+            msg[data_len-5]=0;
+            gid = strtoul(msg,&chk,10);
+            wsock->initId = gid;
+            if (gid>0 && chk!=NULL && *chk==0) {
+                wsock->webSockState = 2;
+            }
+            pthread_mutex_unlock(&sMutex);
+            return 1;
+        }
+
+        // chat message
+        if ((wsock->webSockState==2) && (!memcmp(data,"msg ",4))) {
+            send_to_all_websockets(data, data_len);
+            pthread_mutex_unlock(&sMutex);
+            return 1;
         }
         }
-      }
-      pthread_mutex_unlock(&sMutex);
-      return 1;
     }
     }
-  }
 
 
-  // keep alive
-  if ((data_len==4) && !memcmp(data,"ping",4)) {
-    pthread_mutex_unlock(&sMutex);
-    return 1;
-  }
+    // keep alive
+    if ((data_len==4) && !memcmp(data,"ping",4)) {
+        pthread_mutex_unlock(&sMutex);
+        return 1;
+    }
 
 
-  pthread_mutex_unlock(&sMutex);
-  return 0;
+    pthread_mutex_unlock(&sMutex);
+    return 0;
 }
 }
 
 
 
 
-void connection_close_handler(struct mg_connection *conn) {   
-  struct mg_request_info * rq = mg_get_request_info(conn);
-  tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
+void connection_close_handler(struct mg_connection *conn) {
+    struct mg_request_info * rq = mg_get_request_info(conn);
+    tWebSockInfo * wsock = (tWebSockInfo*)rq->conn_data;
 
 
-  pthread_mutex_lock(&sMutex);
-  websocket_done(wsock);
-  rq->conn_data = 0;
-  pthread_mutex_unlock(&sMutex);
+    pthread_mutex_lock(&sMutex);
+    websocket_done(wsock);
+    rq->conn_data = 0;
+    pthread_mutex_unlock(&sMutex);
 }
 }
 
 
 
 
+static int runLoop = 0;
+
 static void * eventMain(void * _ignored) {
 static void * eventMain(void * _ignored) {
-  int i;
-  char msg[256];
-  for (;;) {
-    time_t t = time(0);
-    struct tm * timestr = localtime(&t);
-    sprintf(msg,"title %s",asctime(timestr));
+    int i;
+    char msg[256];
+
+    runLoop = 1;
+    while (runLoop) {
+        time_t t = time(0);
+        struct tm * timestr = localtime(&t);
+        sprintf(msg,"title %s",asctime(timestr));
+
+        pthread_mutex_lock(&sMutex);
+        for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
+            if (socketList[i] && (socketList[i]->webSockState==2)) {
+                mg_websocket_write(socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, msg, strlen(msg));
+            }
+        }
+        pthread_mutex_unlock(&sMutex);
 
 
-    pthread_mutex_lock(&sMutex);
-    for (i=0;i<MAX_NUM_OF_WEBSOCKS;i++) {
-      if (socketList[i] && (socketList[i]->webSockState==2)) {
-        mg_websocket_write(socketList[i]->conn, WEBSOCKET_OPCODE_TEXT, msg, strlen(msg));
-      }
+        mg_sleep(1000);
     }
     }
-    pthread_mutex_unlock(&sMutex);
-
-    mg_sleep(1000);
-  }
 
 
-  return _ignored;
+    return _ignored;
 }
 }
 
 
+void websock_send_broadcast(const char * data, int data_len) {
+
+    char buffer[260];
+
+    if (data_len<=256) {
+        strcpy(buffer, "msg ");
+        memcpy(buffer+4, data, data_len);
+        
+        pthread_mutex_lock(&sMutex);        
+        send_to_all_websockets(buffer, data_len+4);
+        pthread_mutex_unlock(&sMutex);
+    }
+}
 
 
 void websock_init_lib(void) {
 void websock_init_lib(void) {
-  int ret;
-  ret = pthread_mutex_init(&sMutex, 0);
-  assert(ret==0);
 
 
-  memset(socketList,0,sizeof(socketList));
+    int ret;
+    ret = pthread_mutex_init(&sMutex, 0);
+    assert(ret==0);
+
+    memset(socketList,0,sizeof(socketList));
 
 
-  mg_start_thread(eventMain, 0);
+    mg_start_thread(eventMain, 0);
 }
 }
 
 
+void websock_exit_lib(void) {
+
+    runLoop = 0;
+}

+ 4 - 0
examples/websocket/WebSockCallbacks.h

@@ -9,6 +9,10 @@ extern "C" {
 #endif
 #endif
 
 
 void websock_init_lib(void);
 void websock_init_lib(void);
+void websock_exit_lib(void);
+
+void websock_send_broadcast(const char * data, int data_len);
+
 void websocket_ready_handler(struct mg_connection *conn);
 void websocket_ready_handler(struct mg_connection *conn);
 int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len);
 int websocket_data_handler(struct mg_connection *conn, int flags, char *data, size_t data_len);
 void connection_close_handler(struct mg_connection *conn);
 void connection_close_handler(struct mg_connection *conn);

+ 47 - 0
examples/websocket/websocket.c

@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "civetweb.h"
+#include "WebSockCallbacks.h"
+
+int main(void)
+{
+    struct mg_context *ctx = 0;
+    struct mg_callbacks callback_funcs = {0};
+    char inbuf[4];
+
+    const char *server_options[] = {
+        /* document_root: The path to the test function websock.htm */
+        "document_root",     "../../examples/websocket",
+
+        /* port: use http standard to match websocket url in websock.htm: ws://127.0.0.1/MyWebSock  */
+        /*       if the port is changed here, it needs to be changed in websock.htm as wenn         */
+        "listening_ports",   "80",
+
+        NULL
+    };
+
+    websock_init_lib();
+
+    callback_funcs.websocket_ready = websocket_ready_handler;
+    callback_funcs.websocket_data = websocket_data_handler;
+    callback_funcs.connection_close = connection_close_handler;
+    ctx = mg_start(&callback_funcs, NULL, server_options);
+
+    puts("Enter an (ASCII) character or * to exit:");
+    for (;;) {
+        fgets(inbuf, sizeof(inbuf), stdin);
+
+        if (inbuf[0]=='*') {
+           break;
+        }
+        inbuf[0] = toupper(inbuf[0]);
+        websock_send_broadcast(inbuf, 1);
+    }
+
+    mg_stop(ctx);
+    websock_exit_lib();
+
+    return 0;
+}