remove umurmurd-websocket moving to own git (requested by fatbob)
[umurmur.git] / shm_utils / umurmurd-websocket / src / uMurmurd_Websocket.c
diff --git a/shm_utils/umurmurd-websocket/src/uMurmurd_Websocket.c b/shm_utils/umurmurd-websocket/src/uMurmurd_Websocket.c
deleted file mode 100644 (file)
index d532a1e..0000000
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * uMurmurd Websocket - HTTP/JSON server example
- *
- * Copyright (C) 2014 Michael P. Pounders <>
- *
- *  This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Lesser General Public
- *  License as published by the Free Software Foundation:
- *  version 2.1 of the License.
- *
- *  This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- *  MA  02110-1301  USA
- */
-#ifdef CMAKE_BUILD
-#include "lws_config.h"
-#endif
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <string.h>
-#include <assert.h>
-#include <syslog.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-
-#include <jansson.h>
-#include <libwebsockets.h>
-#include "../../../src/sharedmemory.h"
-
-struct pollfd *pollfds;
-char *resource_path = "../web";
-int max_poll_elements, *fd_lookup, count_pollfds, force_exit = 0, autoupdate = 0;
-
-enum demo_protocols {
-       /* always first */
-       PROTOCOL_HTTP = 0,
-       PROTOCOL_JSON_UMURMURD,
-       /* always last */
-       DEMO_PROTOCOL_COUNT
-};
-
-/*
- * We take a strict whitelist approach to stop ../ attacks
- */
-
-struct serveable {
-       const char *urlpath;
-       const char *mimetype;
-}; 
-
-static const struct serveable whitelist[] = {
-       { "/favicon.ico", "image/x-icon" },
-  { "/css/mon_umurmurd.css", "text/css" },
-  { "/css/json.human.css", "text/css" },
-  { "/js/crel.js", "text/javascript" },
-  { "/js/json.human.js", "text/javascript" },
-  { "/js/jquery.min.js", "text/javascript" },
-  
-       /* last one is the default served if no match */
-       { "/mon_umurmurd.html", "text/html" },
-};
-
-struct per_session_data__http {
-       int fd;
-};
-
-/* this protocol server (always the first one) just knows how to do HTTP */
-
-static int callback_http( struct libwebsocket_context *context,
-                                     struct libwebsocket *wsi,
-                                     enum libwebsocket_callback_reasons reason, void *user,
-                                                                   void *in, size_t len)
-{
-#if 0
-       char client_name[128];
-       char client_ip[128];
-#endif
-       char buf[256];
-       char leaf_path[1024];
-       int n, m;
-       unsigned char *p;
-       static unsigned char buffer[4096];
-       struct stat stat_buf;
-       struct per_session_data__http *pss =
-                       (struct per_session_data__http *)user;
-
-       switch (reason) {
-       case LWS_CALLBACK_HTTP:
-
-               /* check for the "send a big file by hand" example case */
-
-               if (!strcmp((const char *)in, "/leaf.jpg")) {
-                       if (strlen(resource_path) > sizeof(leaf_path) - 10)
-                               return -1;
-                       sprintf(leaf_path, "%s/leaf.jpg", resource_path);
-
-                       /* well, let's demonstrate how to send the hard way */
-
-                       p = buffer;
-
-                       pss->fd = open(leaf_path, O_RDONLY);
-
-                       if (pss->fd < 0)
-                               return -1;
-
-                       fstat(pss->fd, &stat_buf);
-
-                       /*
-                        * we will send a big jpeg file, but it could be
-                        * anything.  Set the Content-Type: appropriately
-                        * so the browser knows what to do with it.
-                        */
-
-                       p += sprintf((char *)p,
-                               "HTTP/1.0 200 OK\x0d\x0a"
-                               "Server: libwebsockets\x0d\x0a"
-                               "Content-Type: image/jpeg\x0d\x0a"
-                                       "Content-Length: %u\x0d\x0a\x0d\x0a",
-                                       (unsigned int)stat_buf.st_size);
-
-                       /*
-                        * send the http headers...
-                        * this won't block since it's the first payload sent
-                        * on the connection since it was established
-                        * (too small for partial)
-                        */
-
-                       n = libwebsocket_write(wsi, buffer,
-                                  p - buffer, LWS_WRITE_HTTP);
-
-                       if (n < 0) {
-                               close(pss->fd);
-                               return -1;
-                       }
-                       /*
-                        * book us a LWS_CALLBACK_HTTP_WRITEABLE callback
-                        */
-                       libwebsocket_callback_on_writable(context, wsi);
-                       break;
-               }
-
-               /* if not, send a file the easy way */
-
-               for (n = 0; n < (sizeof(whitelist) / sizeof(whitelist[0]) - 1); n++)
-                       if (in && strcmp((const char *)in, whitelist[n].urlpath) == 0)
-                               break;
-
-               sprintf(buf, "%s%s", resource_path, whitelist[n].urlpath);
-
-               if (libwebsockets_serve_http_file(context, wsi, buf, whitelist[n].mimetype))
-                       return -1; /* through completion or error, close the socket */
-
-               /*
-                * notice that the sending of the file completes asynchronously,
-                * we'll get a LWS_CALLBACK_HTTP_FILE_COMPLETION callback when
-                * it's done
-                */
-
-               break;
-
-       case LWS_CALLBACK_HTTP_FILE_COMPLETION:
-//             lwsl_info("LWS_CALLBACK_HTTP_FILE_COMPLETION seen\n");
-               /* kill the connection after we sent one file */
-               return -1;
-
-       case LWS_CALLBACK_HTTP_WRITEABLE:
-               /*
-                * we can send more of whatever it is we were sending
-                */
-
-               do {
-                       n = read(pss->fd, buffer, sizeof buffer);
-                       /* problem reading, close conn */
-                       if (n < 0)
-                               goto bail;
-                       /* sent it all, close conn */
-                       if (n == 0)
-                               goto bail;
-                       /*
-                        * because it's HTTP and not websocket, don't need to take
-                        * care about pre and postamble
-                        */
-                       m = libwebsocket_write(wsi, buffer, n, LWS_WRITE_HTTP);
-                       if (m < 0)
-                               /* write failed, close conn */
-                               goto bail;
-                       if (m != n)
-                               /* partial write, adjust */
-                               lseek(pss->fd, m - n, SEEK_CUR);
-
-               } while (!lws_send_pipe_choked(wsi));
-               libwebsocket_callback_on_writable(context, wsi);
-               break;
-
-bail:
-               close(pss->fd);
-               return -1;
-
-       /*
-        * callback for confirming to continue with client IP appear in
-        * protocol 0 callback since no websocket protocol has been agreed
-        * yet.  You can just ignore this if you won't filter on client IP
-        * since the default uhandled callback return is 0 meaning let the
-        * connection continue.
-        */
-
-       case LWS_CALLBACK_FILTER_NETWORK_CONNECTION:
-#if 0
-               libwebsockets_get_peer_addresses(context, wsi, (int)(long)in, client_name,
-                            sizeof(client_name), client_ip, sizeof(client_ip));
-
-               fprintf(stderr, "Received network connect from %s (%s)\n",
-                                                       client_name, client_ip);
-#endif
-               /* if we returned non-zero from here, we kill the connection */
-               break;
-
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-/*
- * this is just an example of parsing handshake headers, you don't need this
- * in your code unless you will filter allowing connections by the header
- * content
- */
-
-static void
-dump_handshake_info(struct libwebsocket *wsi)
-{
-       int n;
-       static const char *token_names[WSI_TOKEN_COUNT] = {
-               /*[WSI_TOKEN_GET_URI]       =*/ "GET URI",
-               /*[WSI_TOKEN_HOST]                    =*/ "Host",
-               /*[WSI_TOKEN_CONNECTION]          =*/ "Connection",
-               /*[WSI_TOKEN_KEY1]                    =*/ "key 1",
-               /*[WSI_TOKEN_KEY2]                    =*/ "key 2",
-               /*[WSI_TOKEN_PROTOCOL]            =*/ "Protocol",
-               /*[WSI_TOKEN_UPGRADE]               =*/ "Upgrade",
-               /*[WSI_TOKEN_ORIGIN]                =*/ "Origin",
-               /*[WSI_TOKEN_DRAFT]                   =*/ "Draft",
-               /*[WSI_TOKEN_CHALLENGE]           =*/ "Challenge",
-
-               /* new for 04 */
-               /*[WSI_TOKEN_KEY]                       =*/ "Key",
-               /*[WSI_TOKEN_VERSION]               =*/ "Version",
-               /*[WSI_TOKEN_SWORIGIN]            =*/ "Sworigin",
-
-               /* new for 05 */
-               /*[WSI_TOKEN_EXTENSIONS]          =*/ "Extensions",
-
-               /* client receives these */
-               /*[WSI_TOKEN_ACCEPT]                =*/ "Accept",
-               /*[WSI_TOKEN_NONCE]                   =*/ "Nonce",
-               /*[WSI_TOKEN_HTTP]                    =*/ "Http",
-               /*[WSI_TOKEN_MUXURL]          =*/ "MuxURL",
-       };
-       char buf[256];
-
-       for (n = 0; n < WSI_TOKEN_COUNT; n++) {
-               if (!lws_hdr_total_length(wsi, n))
-                       continue;
-
-               lws_hdr_copy(wsi, buf, sizeof buf, n);
-
-               fprintf(stderr, "    %s = %s\n", token_names[n], buf);
-       }
-}
-
-void *getJsonData( unsigned char * buf, int *n )
-{
-
-int cc;
-json_t *jarr1;
-char *result = NULL;
-
-json_t *root = NULL, *server = NULL, *client, *clients;
-
-    root = json_object();
-    clients = json_object();
-
-          
-          server = json_pack( "{s:{:s:i,s:i}}", 
-                              "server", 
-                              "clients_max", shmptr->server_max_clients, 
-                              "clients_connected", shmptr->clientcount );
-    
-        json_object_update( root, server );
-          
-        if( shmptr->clientcount )
-        {  
-          jarr1 = json_array();
-              
-          for( cc = 0 ; cc < shmptr->server_max_clients ; cc++ )
-          {
-          
-          if( !shmptr->client[cc].authenticated )
-            continue;
-                                                                               
-          client = json_pack( "{:s:s,s:s,s:i,s:s,s:i,s:i}", 
-                                            "username", 
-                                            shmptr->client[cc].username, 
-                                            "ipaddress", 
-                                            shmptr->client[cc].ipaddress,
-                                            "udp_port",
-                                            shmptr->client[cc].udp_port,
-                                            "channel",
-                                            shmptr->client[cc].channel,
-                                            "online_secs",
-                                            shmptr->client[cc].online_secs,
-                                            "idle_secs",
-                                            shmptr->client[cc].idle_secs                                                                                        
-                                            );                                                                                                                                                   
-          json_array_append_new( jarr1, client );
-                     
-          } 
- json_object_set_new( clients, "clients", jarr1 );         
- json_object_update( root, clients );
-}
-  //json_dump_file(root, "json.txt", JSON_PRESERVE_ORDER | JSON_INDENT(4) );        
-  result = json_dumps(root, JSON_PRESERVE_ORDER | JSON_COMPACT );
-
-  *n = sprintf( (char *)&buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", result  );
-     
-
-  if( result )
-    free( result );
-       
-  
-
-  json_decref(root);
-  return 0;         
-}
-
-struct per_session_data__umurmurd_json {
-       int test;
-};
-
-static int
-callback_umurmurd_json( struct libwebsocket_context *context,
-                                        struct libwebsocket *wsi,
-                                        enum libwebsocket_callback_reasons reason,
-                                                    void *user, void *in, size_t len)
-{
-       int m, n;
-
-       unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 +
-                                                       LWS_SEND_BUFFER_POST_PADDING];
-       
-       //struct per_session_data__umurmurd_json *pss = (struct per_session_data__umurmurd_json *)user;
-
-       switch (reason) {
-
-       case LWS_CALLBACK_ESTABLISHED:
-               lwsl_info("callback_umurmurd_json: LWS_CALLBACK_ESTABLISHED\n");            
-               break;
-
-       case LWS_CALLBACK_SERVER_WRITEABLE:
-    getJsonData( buf, &n );
-    m = libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], n, LWS_WRITE_TEXT);  //printf("N: %d M: %d\n", n, m );
-
-    if( m == n )
-        return 1;
-               break;
-
-       case LWS_CALLBACK_RECEIVE:
-       //fprintf(stderr, "rx %d\n", (int)len);
-//             if (len < 6)
-//                     break;
-               if( strcmp((const char *)in, "update\n") == 0 )
-    {
-                       libwebsocket_callback_on_writable_all_protocol(libwebsockets_get_protocol( wsi ));
-      break;
-    }
-    else if( strcmp((const char *)in, "autoupdate\n") == 0 )
-    {
-      autoupdate = !autoupdate;  //toggle
-      break;
-    }
-      
-       /*
-        * this just demonstrates how to use the protocol filter. If you won't
-        * study and reject connections based on header content, you don't need
-        * to handle this callback
-        */
-
-       case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
-               dump_handshake_info(wsi);
-               /* you could return non-zero here and kill the connection */
-               break;
-
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-
-
-/* list of supported protocols and callbacks */
-
-static struct libwebsocket_protocols protocols[] = {
-       /* first protocol must always be HTTP handler */
-
-       {
-               "http-only",                            /* name */
-               callback_http,                                /* callback */
-               sizeof (struct per_session_data__http), /* per_session_data_size */
-               0,                                                      /* max frame size / rx buffer */
-       },
-       {
-               "umurmurd-json-protocol",
-               callback_umurmurd_json,
-               sizeof(struct per_session_data__umurmurd_json),
-               128,
-       },
-       { NULL, NULL, 0, 0 } /* terminator */
-};
-
-void sighandler(int sig)
-{
-       force_exit = 1;
-}
-
-static struct option options[] = {
-       { "help",       no_argument,            NULL, 'h' },
-       { "debug",      required_argument,      NULL, 'd' },
-       { "port",       required_argument,      NULL, 'p' },
-       { "ssl",        no_argument,            NULL, 's' },
-       { "interface",  required_argument,      NULL, 'i' },
-       { "daemonize",  no_argument,            NULL, 'D' },
-       { "resource_path", required_argument,           NULL, 'r' },
-       { NULL, 0, 0, 0 }
-};
-
-int main(int argc, char **argv)
-{
-       char cert_path[1024];
-       char key_path[1024];
-       int n = 0;
-       int use_ssl = 0;
-       struct libwebsocket_context *context;
-       int opts = 0;
-       char interface_name[128] = "";
-       const char *iface = NULL;
-       uint64_t oldus = 0;
-       struct lws_context_creation_info info;
-
-  int syslog_options = LOG_PID | LOG_PERROR; 
-
-       int debug_level = 7;
-
-       int daemonize = 0;
-
-
-       memset(&info, 0, sizeof info);
-       info.port = 7681;
-
-       while (n >= 0) {
-               n = getopt_long(argc, argv, "i:hsp:d:Dr:", options, NULL);
-               if (n < 0)
-                       continue;
-               switch (n) {
-               case 'D':
-                       daemonize = 1;
-                       syslog_options &= ~LOG_PERROR;
-                       break;
-
-               case 'd':
-                       debug_level = atoi(optarg);
-                       break;
-               case 's':
-                       use_ssl = 1;
-                       break;
-               case 'p':
-                       info.port = atoi(optarg);
-                       break;
-               case 'i':
-                       strncpy(interface_name, optarg, sizeof interface_name);
-                       interface_name[(sizeof interface_name) - 1] = '\0';
-                       iface = interface_name;
-                       break;
-               case 'r':
-                       resource_path = optarg;
-                       printf("Setting resource path to \"%s\"\n", resource_path);
-                       break;
-               case 'h':
-                       fprintf(stderr, "Usage: test-server "
-                                       "[--port=<p>] [--ssl] "
-                                       "[-d <log bitfield>] "
-                                       "[--resource_path <path>]\n");
-                       exit(1);
-               }
-       }
-
-key_t key = 0x53021d79;
-
-                    if( ( shmid = shmget( key, 0, 0) ) == -1 )
-                    {
-                        perror("shmget");
-                        printf( "umurmurd doesn't seem to be running\n\r" );                        
-                        exit(EXIT_FAILURE);
-                    }
-
-                    
-                    if( ( shmptr = shmat( shmid,0, 0 ) ) == (void *) -1 )   
-                    {
-                        perror("shmat");
-                        exit(EXIT_FAILURE);
-                    }
-
-
-       /* 
-        * normally lock path would be /var/lock/lwsts or similar, to
-        * simplify getting started without having to take care about
-        * permissions or running as root, set to /tmp/.lwsts-lock
-        */
-       if (daemonize && lws_daemonize("/tmp/.lwsts-lock")) {
-               fprintf(stderr, "Failed to daemonize\n");
-               return 1;
-       }
-
-
-       signal(SIGINT, sighandler);
-
-
-       /* we will only try to log things according to our debug_level */
-       setlogmask(LOG_UPTO (LOG_DEBUG));
-       openlog("lwsts", syslog_options, LOG_DAEMON);
-
-
-       /* tell the library what debug level to emit and to send it to syslog */
-       lws_set_log_level(debug_level, lwsl_emit_syslog);
-
-       lwsl_notice("uMurmurd Websocket server - "
-                       "(C) Copyright 2014 Michael J. Pounders <> - "
-                                                   "licensed under LGPL2.1\n");
-
-       info.iface = iface;
-       info.protocols = protocols;
-
-       info.extensions = libwebsocket_get_internal_extensions();
-
-       if (!use_ssl) {
-               info.ssl_cert_filepath = NULL;
-               info.ssl_private_key_filepath = NULL;
-       } else {
-               if (strlen(resource_path) > sizeof(cert_path) - 32) {
-                       lwsl_err("resource path too long\n");
-                       return -1;
-               }
-               sprintf(cert_path, "%s/ssl/umurmurd_websocket.pem",
-                                                               resource_path);
-               if (strlen(resource_path) > sizeof(key_path) - 32) {
-                       lwsl_err("resource path too long\n");
-                       return -1;
-               }
-               sprintf(key_path, "%s/ssl/umurmurd_websocket.key.pem",
-                                                               resource_path);
-
-               info.ssl_cert_filepath = cert_path;
-               info.ssl_private_key_filepath = key_path;
-       }
-       info.gid = -1;
-       info.uid = -1;
-       info.options = opts;
-
-       context = libwebsocket_create_context(&info);
-       if (context == NULL) {
-               lwsl_err("libwebsocket init failed\n");
-               return -1;
-       }
-
-       n = 0;
-       while (n >= 0 && !force_exit) {
-               struct timeval tv;
-
-               gettimeofday(&tv, NULL);
-
-               /*
-                * This provokes the LWS_CALLBACK_SERVER_WRITEABLE for every
-                * live websocket connection using the DUMB_INCREMENT protocol,
-                * as soon as it can take more packets (usually immediately)
-                */
-    if( autoupdate )
-    {
-                 if(((unsigned int)tv.tv_sec - oldus) > 1 )
-      {
-                        libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_JSON_UMURMURD]);
-        oldus = tv.tv_sec;
-                 }
-    }
-
-               /*
-                * If libwebsockets sockets are all we care about,
-                * you can use this api which takes care of the poll()
-                * and looping through finding who needed service.
-                *
-                * If no socket needs service, it'll return anyway after
-                * the number of ms in the second argument.
-                */
-
-               n = libwebsocket_service(context, 50);
-
-       }
-
-
-       libwebsocket_context_destroy(context);
-
-       lwsl_notice("uMurmurd Websocket server exited cleanly\n");
-
-  shmdt( shmptr );
-       closelog();
-
-       return 0;
-}