Switch over to more modern unix sharedmemory API (requested by fatbob)
authorMichael J. Pounders <snowblind@bellsouth.net>
Mon, 17 Nov 2014 04:40:59 +0000 (23:40 -0500)
committerMichael J. Pounders <snowblind@bellsouth.net>
Mon, 17 Nov 2014 04:40:59 +0000 (23:40 -0500)
shm_utils/mon-umurmurd/CHANGES
shm_utils/mon-umurmurd/Makefile
shm_utils/mon-umurmurd/mon-umurmurd.c
src/client.h
src/server.c
src/sharedmemory.c
src/sharedmemory.h
src/sharedmemory_global.h [new file with mode: 0644]
src/sharedmemory_struct.h

index 606e46e10db607b021942eb3abe29c961cdd1b0a..2432255265f561641d519740f07fb522feb36584 100644 (file)
@@ -1,3 +1,10 @@
+* Using a more modern unix sharedmemory API. this requires linking with librt.so  (requested by fatbob)\r
+* Added away to know if umurmurd is not connected/updateing the shm_t struct. I use 8bit timer with \r
+  rollover protection see check_serverTick() and where I use the function near bottum of mon-umurmurd.c \r
+       for     how     to use this.\r
+\r
+\r
 * code clean up and some comments added\r
-* 100% of the useful client data shown\r
-* outputs a more meaningful idle and online time, both are reported in secs
\ No newline at end of file
+* ~95% of the useful client data shown\r
+* outputs a more meaningful idle and online time, both are reported in secs (error reported by fatbob)\r
+    
\ No newline at end of file
index fbe9af79c6b55df4c5089ae7a04f512154d9384d..9ecd325c59eeb40d7a2ec9617228d9f237bbbcca 100644 (file)
@@ -4,8 +4,8 @@
 
 
 # The recommended compiler flags for the Raspberry Pi
-#CCFLAGS=-Wall -Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -g
-#CCFLAGS=
+#CCFLAGS=-Wall -Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -g -lrt
+CCFLAGS= -lrt
 
 # define all programs
 PROGRAMS = mon-umurmurd
index 444456c547bf4928a4f6802138a62366709e6cf8..7a1a5b2eb0396dd7feddf3d8dcccbb98d151c221 100644 (file)
@@ -1,51 +1,43 @@
-#include <stdlib.h>\r
+#include <fcntl.h> /* For O_* constants */\r
 #include <stdio.h>\r
-#include <sys/types.h>\r
-#include <sys/ipc.h>\r
-#include <sys/shm.h>\r
 #include <ctype.h>\r
+#include <stdlib.h>\r
 #include <string.h>\r
 #include <unistd.h>\r
-#include <proc/procps.h>\r
+#include <sys/mman.h>\r
+#include <sys/types.h>\r
 #include "../../src/sharedmemory.h"\r
+#include "../../src/sharedmemory_global.h"\r
 \r
-\r
-struct shmid_ds buf;\r
 enum{ NOP_SHM, WAIT_ATTACH_SHM, TRY_ATTACH_SHM, MAT_SHM, CLEAN_UP_SHM, RUN_SHM };\r
 \r
-\r
+int wait = 0, opt;\r
+uint8_t last, shm_statem = TRY_ATTACH_SHM;\r
 \r
 void run_shm(void);\r
 \r
-\r
 int main(int argc, char **argv) \r
 {\r
-  int wait = 0, opt;\r
-  unsigned int shm_statem = TRY_ATTACH_SHM;\r
-  \r
-  key_t key = 0x53021d79;\r
-  //key = ftok(".", 'S');  // using my own key for now. makes dev easier will fix\r
 \r
-    while ((opt = getopt(argc, argv, "w")) != -1) \r
-    {\r
-        switch (opt) \r
-        {\r
+\r
+    while ( (opt = getopt(argc, argv, "w")) != -1 ) \r
+               {\r
+        switch(opt) \r
+                               {\r
            case 'w':\r
               wait = 1;\r
               break;\r
-           default: /* '?' */\r
+           default: \r
               fprintf(stderr, "Usage: %s [-w]\n", argv[0]);\r
               fprintf(stderr, "\t-w         - Wait for umurmurd to create shm area. useful if you need to start from init.d script\n" );\r
-                                            //My version of this talks to custom PIC18 hardware acting as a i2c slave to a RaspberryPI to \r
-                                            //sound buzzer and turn on a LED when my umurmurd server has users in it. I leave this in here\r
-                                            //in case you need it.  \r
               exit(EXIT_FAILURE);\r
         }\r
     }\r
 \r
-   \r
+      shmptr = NULL;\r
       \r
-          \r
+      sprintf( shm_file_name, "/umurmurd:%i", 64738 );\r
+            \r
       if( wait )\r
           shm_statem = WAIT_ATTACH_SHM;\r
           \r
@@ -57,88 +49,93 @@ int main(int argc, char **argv)
                     run_shm();\r
                     break;          \r
               case WAIT_ATTACH_SHM:\r
-                    printf( "waiting on umurmurd to be run\n\r"); fflush(stdout);\r
-                    while( ( shmid = shmget( key, 0, 0) ) == -1 )\r
+                    printf( "Waiting for umurmurd to be run\n\r"); fflush(stdout);\r
+                    while( ( shm_fd = shm_open( shm_file_name, O_RDONLY, 0666 ) ) == -1 )\r
                        sleep( 1 );\r
                     shm_statem = MAT_SHM;\r
                     break;\r
               case TRY_ATTACH_SHM:\r
-                    if( ( shmid = shmget( key, 0, 0) ) == -1 )\r
+                    if( ( shm_fd = shm_open( shm_file_name, O_RDONLY, 0666 ) ) == -1 )\r
                     {\r
-                        perror("shmget");\r
                         printf( "umurmurd doesn't seem to be running\n\r" );                        \r
                         exit(EXIT_FAILURE);\r
                     }\r
                     shm_statem = MAT_SHM;\r
                     break;\r
              case MAT_SHM:                                       \r
-                    if( ( shmptr = shmat( shmid, 0, 0 ) ) == (void *) (-1) )\r
+                    if( ( shmptr = mmap(0, 1, PROT_READ, MAP_SHARED, shm_fd, 0) ) == (void *) (-1) )   //MJP BUG? \r
                     {\r
-                        perror("shmat");\r
+                        \r
                         exit(EXIT_FAILURE);\r
-                    }\r
-                    printf( "shmid: %i\n\r", shmid );\r
-                    printf( "Connected to umumurd PID: %u\n\r", shmptr->umurmurd_pid );\r
-                    sleep( 1 );\r
+                    }                    \r
+                    printf( "umumurd PID: %u\n\r", shmptr->umurmurd_pid );\r
                     shm_statem = RUN_SHM;                    \r
                     break;\r
              case CLEAN_UP_SHM:                   \r
-                    shmdt( shmptr );          \r
-                    break;                    \r
+                              \r
+                    break;\r
+                    \r
          }\r
        }\r
-       fflush(stdout);\r
-       return 0;\r
+        fflush(stdout);\r
+        return 0;\r
 }\r
 \r
+uint8_t check_serverTick(void)\r
+{\r
+  last = shmptr->alive;\r
+       sleep( 1 );  // Sleep for 1 sec\r
+       return(shmptr->alive - last); \r
+}\r
 \r
 void run_shm(void)\r
 {\r
-  int cc;\r
-    \r
-    shmctl( shmid, IPC_STAT, &buf );   //MJP BUG check for errors here\r
 \r
-      printf("\033[2J\033[H"); //clear screen VT100\r
+int cc;\r
+\r
+               printf( "\033[2J\033[H" ); //clear screen VT100\r
           \r
-      printf( "attach: %lu SCC: %i SMC: %i\n", (unsigned long int)buf.shm_nattch, shmptr->clientcount, shmptr->server_max_clients );\r
-      \r
-      for( cc = 0 ; cc < shmptr->server_max_clients ; cc++ )\r
-      {    \r
-        if( !shmptr->client[cc].authenticated )\r
+          \r
+               for( cc = 0 ; cc < shmptr->server_max_clients ; cc++ )\r
+        {\r
+          \r
+          if( !shmptr->client[cc].authenticated )\r
             continue; \r
             \r
-        printf( "%s@%s:%i in channel: %s\n\\r
-                \tOnline(secs): %lu Idle(secs): %lu\n\\r
-                \tusingUDP=%i\n\\r
-                \tdeaf=%i, mute=%i\n\\r
-                \tself_deaf=%i, self_mute=%i\n\\r
-                \trecording=%i\n\\r
-                \tbOpus=%i\n\\r
-                \tUDP_Avg/Var: %3.2f/%3.2f \n\\r
-                \tTCP_Avg/Var: %3.2f/%3.2f \n\\r
-                \tUDP_C/TCP_C: %lu/%lu\n", \r
-                                          shmptr->client[cc].username,\r
-                                          shmptr->client[cc].ipaddress,\r
-                                          shmptr->client[cc].udp_port,\r
-                                          shmptr->client[cc].channel,\r
-                                          shmptr->client[cc].online_secs,\r
-                                          shmptr->client[cc].idle_secs,\r
+                                       printf( "%s@%s:%i in channel: %s\n\\r
+                               \tOnline(secs): %lu Idle(secs): %lu\n\\r
+                               \tusingUDP=%i\n\\r
+                               \tdeaf=%i, mute=%i\n\\r
+                               \tself_deaf=%i, self_mute=%i\n\\r
+                               \trecording=%i\n\\r
+                               \tbOpus=%i\n\\r
+                               \tUDP_Avg/Var: %3.2f/%3.2f \n\\r
+                               \tTCP_Avg/Var: %3.2f/%3.2f \n\\r
+                               \tUDP_C/TCP_C: %lu/%lu\n", \r
+                                                       shmptr->client[cc].username,\r
+                                                       shmptr->client[cc].ipaddress,\r
+                                                       shmptr->client[cc].udp_port,\r
+                                                       shmptr->client[cc].channel,\r
+                                                       shmptr->client[cc].online_secs,\r
+                                                       shmptr->client[cc].idle_secs,\r
                                                              \r
-                                          shmptr->client[cc].bUDP,\r
-                                          shmptr->client[cc].deaf,\r
-                                          shmptr->client[cc].mute,\r
-                                          shmptr->client[cc].self_deaf,\r
-                                          shmptr->client[cc].self_mute,\r
-                                          shmptr->client[cc].recording,\r
-                                          shmptr->client[cc].bOpus,\r
+                                                       shmptr->client[cc].bUDP,\r
+                                                       shmptr->client[cc].deaf,\r
+                                                       shmptr->client[cc].mute,\r
+                                                       shmptr->client[cc].self_deaf,\r
+                                                       shmptr->client[cc].self_mute,\r
+                                                       shmptr->client[cc].recording,\r
+                                                       shmptr->client[cc].bOpus,\r
                                                                               \r
-                                          shmptr->client[cc].UDPPingAvg,\r
-                                          shmptr->client[cc].UDPPingVar,\r
-                                          shmptr->client[cc].TCPPingAvg,\r
-                                          shmptr->client[cc].TCPPingVar,\r
-                                          shmptr->client[cc].UDPPackets,\r
-                                          shmptr->client[cc].TCPPackets\r
-                                                                         ); fflush(stdout);  // fflush need because of sleep() call\r
-      }          \r
-      sleep( 1 );  // Sleep for 1 sec\r
+                                                       shmptr->client[cc].UDPPingAvg,\r
+                                                       shmptr->client[cc].UDPPingVar,\r
+                                                       shmptr->client[cc].TCPPingAvg,\r
+                                                       shmptr->client[cc].TCPPingVar,\r
+                                                       shmptr->client[cc].UDPPackets,\r
+                                                       shmptr->client[cc].TCPPackets ); fflush(stdout);  // fflush need because of sleep() call\r
+        }\r
+                               if( !check_serverTick() )          \r
+        {\r
+                                               exit(EXIT_FAILURE); //You dont have to exit you could just report the fact that the data is not valid \r
+                               }\r
 }
\ No newline at end of file
index a710f5c8a63d93eafbec883b8807c7a14984ed5a..9f17ddf3d822ec32d708a5523ec62eee69d892ea 100644 (file)
@@ -59,7 +59,7 @@
 
 #define IS_AUTH(_a_) ((_a_)->authenticated)
 
-typedef struct {
+typedef struct {   /* You can add new lines to this struct, any reordering of some of the lines will break the sharedmemory API */
        int tcpfd;
        SSL_handle_t *ssl;
        bool_t SSLready;
index a0ed7f5ceb256bb861afe3abca34d8c9d3aabb18..74a736d32fa2add70186d254cf0327aceea8ef05 100644 (file)
@@ -141,6 +141,10 @@ void Server_runLoop(struct pollfd* pollfds)
        while (!shutdown_server) {
                struct sockaddr_storage remote;
                int i;
+               
+#ifdef USE_SHAREDMEMORY_API
+    Sharedmemory_alivetick();
+#endif
 
                for(i = 0; i < nofServerSocks; i++) {
                        pollfds[i].revents = 0;
index 4ede9d39258491db223ab73b16cf699a05f48279..6af3f752fe3c057c0e074d0261c739be0b97ee99 100644 (file)
@@ -1,23 +1,42 @@
 #include "sharedmemory.h"\r
+#include "sharedmemory_global.h"\r
 \r
 void Sharedmemory_init(void) \r
 {\r
 \r
-  key_t key = 0x53021d79;\r
-  int server_max_clients = getIntConf(MAX_CLIENTS);  \r
+  int bindport = getIntConf(BINDPORT);                                                         //MJP BUG commandline option for address and port dont work this way going to have \r
+  int server_max_clients = getIntConf(MAX_CLIENTS);   //to bring them across as prameters to Sharedmemory_init(void)\r
   int shmptr_size =  sizeof( shm_t  ) + (sizeof( shmclient_t ) * server_max_clients);\r
   \r
-  //key =  ftok( ".", 'S' );  //MJP BUG this needs fixing.. also how to handle multi copys of umurmur bound to diff ports or IPs  option to pass key on cmdline?  \r
-  shmid = shmget( key, shmptr_size, IPC_CREAT | 0666 );    \r
 \r
-  Log_info("SHM_KEY: 0x%x", key );\r
 \r
-        if( ( shmptr = ( shm_t *) shmat( shmid, 0, 0 ) ) == (shm_t *) (-1) )\r
-        {\r
-                perror("shmat");\r
-                exit(1); //MJP BUG should report error and just not use shm dont exit\r
-        }\r
-        memset( shmptr, 0, shmptr_size );                                     \r
+       sprintf( shm_file_name, "umurmurd:%i", bindport );\r
+\r
+  Log_info("SHM_FD: %s", shm_file_name  );\r
+\r
+shm_fd = shm_open( shm_file_name, O_CREAT | O_RDWR, 0666 );\r
+if(shm_fd == -1)\r
+{\r
+    fprintf(stderr, "Open failed:%s\n", strerror(errno)); //MJP BUG make this Log_ calls once I get this working\r
+    exit(1);\r
+}  \r
+\r
+if( ftruncate( shm_fd, shmptr_size ) == -1 )\r
+{\r
+    fprintf(stderr, "ftruncate : %s\n", strerror(errno));  //MJP BUG make this Log_ calls once I get this working\r
+    exit(1);\r
+}\r
+\r
+  shmptr = mmap(0, shmptr_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);\r
+  if (shmptr == (void *) -1) \r
+       {\r
+     fprintf(stderr, "mmap failed : %s\n", strerror(errno)); //MJP BUG make this Log_ calls once I get this working\r
+     exit(1);\r
+  } \r
+\r
+\r
+  memset( shmptr, 0, shmptr_size );\r
+                                            \r
   shmptr->umurmurd_pid = getpid();\r
   shmptr->server_max_clients = server_max_clients;  \r
 }\r
@@ -25,47 +44,51 @@ void Sharedmemory_init(void)
 void Sharedmemory_update(void) \r
 {\r
 \r
- static size_t bt_end = sizeof(  bool_t  ) * 8,   //compute once\r
-               pa_end = sizeof(  float   ) * 4,\r
-               pc_end = sizeof( uint32_t ) * 2;\r
+  uint64_t now;\r
+  unsigned int cc = 0;\r
+  client_t *client_itr = NULL;\r
+  static size_t bt_end = sizeof(  bool_t  ) * 8,   //compute once\r
+                pa_end = sizeof(  float   ) * 4,\r
+                pc_end = sizeof( uint32_t ) * 2;\r
                 \r
- unsigned int cc = 0;\r
- client_t *client_itr = NULL;\r
- uint64_t now;\r
  \r
- memset( &shmptr->client[0], 0, sizeof( shmclient_t ) * shmptr->server_max_clients );\r
- shmptr->clientcount = Client_count();\r
\r
- if( shmptr->clientcount )\r
- {\r
-   Timer_init( &now );\r
- while( Client_iterate(&client_itr) != NULL ) {\r
-                                                                                               \r
-      if( client_itr->authenticated )\r
-      {        \r
-        channel_t *channel = client_itr->channel;\r
   memset( &shmptr->client[0], 0, sizeof( shmclient_t ) * shmptr->server_max_clients );\r
   shmptr->clientcount = Client_count();\r
+    \r
     if( shmptr->clientcount )\r
     {\r
+        Timer_init( &now );\r
+          while( Client_iterate(&client_itr) != NULL )\r
+          {                                                                                   \r
+            if( client_itr->authenticated )\r
+            {        \r
+              channel_t *channel = client_itr->channel;\r
         \r
-        strncpy( shmptr->client[cc].username, client_itr->username, 120 );\r
-        strncpy( shmptr->client[cc].ipaddress, Util_clientAddressToString( client_itr ), 45 );\r
-        shmptr->client[cc].tcp_port = Util_clientAddressToPortTCP( client_itr );\r
-        shmptr->client[cc].udp_port = Util_clientAddressToPortUDP( client_itr );\r
-        strncpy( shmptr->client[cc].channel, channel->name, 120 );\r
+                strncpy( shmptr->client[cc].username, client_itr->username, 120 );\r
+                strncpy( shmptr->client[cc].ipaddress, Util_clientAddressToString( client_itr ), 45 );\r
+                shmptr->client[cc].tcp_port = Util_clientAddressToPortTCP( client_itr );\r
+                shmptr->client[cc].udp_port = Util_clientAddressToPortUDP( client_itr );\r
+                strncpy( shmptr->client[cc].channel, channel->name, 120 );\r
         \r
-        shmptr->client[cc].online_secs = ( now - client_itr->connectTime ) / 1000000LL;\r
-        shmptr->client[cc].idle_secs = ( now - client_itr->idleTime ) / 1000000LL;\r
+                shmptr->client[cc].online_secs = ( now - client_itr->connectTime ) / 1000000LL;\r
+                shmptr->client[cc].idle_secs = ( now - client_itr->idleTime ) / 1000000LL;\r
         \r
-        memcpy( &shmptr->client[cc].bUDP, &client_itr->bUDP, bt_end );\r
-        memcpy( &shmptr->client[cc].UDPPingAvg, &client_itr->UDPPingAvg, pa_end );\r
-        memcpy( &shmptr->client[cc].UDPPackets, &client_itr->UDPPackets, pc_end );\r
-      }  \r
-      cc++;     \r
- }\r
-\r
-} \r
+                memcpy( &shmptr->client[cc].bUDP, &client_itr->bUDP, bt_end );\r
+                memcpy( &shmptr->client[cc].UDPPingAvg, &client_itr->UDPPingAvg, pa_end );\r
+                memcpy( &shmptr->client[cc].UDPPackets, &client_itr->UDPPackets, pc_end );\r
+            }  \r
+          cc++;     \r
+        }\r
+      } \r
+}\r
+void Sharedmemory_alivetick(void)\r
+{\r
+ shmptr->alive++;\r
 }\r
 \r
 void Sharedmemory_deinit(void) \r
 {\r
-  shmctl( shmid, IPC_RMID, 0 );   //Mark shmid for removal.\r
-  shmdt( shmptr );\r
+  close( shm_fd );\r
+  unlink( shm_file_name );\r
+  shmptr->umurmurd_pid = 0;\r
 }
\ No newline at end of file
index e4d44949fd3907a9aa3aced9b30fde2e9309c523..fd9c1209b3ec8aac38c614cf7104c1d63698f797 100644 (file)
@@ -4,19 +4,19 @@
 #include <stdlib.h>\r
 #include <string.h>\r
 \r
-#include <sys/shm.h>\r
+#include <fcntl.h> /* For O_* constants */ \r
+#include <unistd.h>\r
+#include <sys/mman.h>\r
 \r
 #include "util.h"\r
 #include "conf.h" \r
 #include "client.h"\r
 #include "channel.h"\r
-#include "sharedmemory_struct.h"\r
-\r
-int shmid;\r
-shm_t *shmptr; \r
+#include "sharedmemory_struct.h" \r
 \r
 void Sharedmemory_init(void);\r
 void Sharedmemory_update(void);\r
+void Sharedmemory_alivetick(void);\r
 void Sharedmemory_deinit(void);\r
 \r
-#endif  // SHAREDMEMORY_H_777736932196
\ No newline at end of file
+#endif // SHAREDMEMORY_H_777736932196
\ No newline at end of file
diff --git a/src/sharedmemory_global.h b/src/sharedmemory_global.h
new file mode 100644 (file)
index 0000000..217ef9a
--- /dev/null
@@ -0,0 +1,3 @@
+int shm_fd;\r
+shm_t *shmptr = NULL;\r
+char shm_file_name[128];
\ No newline at end of file
index a4011b35f7a4794992cdacbb89e69074e86bf209..61d6488c96846d970230bbcd180740753303c008 100644 (file)
@@ -1,5 +1,6 @@
 typedef struct\r
 {\r
+\r
   char username[121];\r
   char ipaddress[46];\r
   int tcp_port, udp_port;\r
@@ -15,7 +16,8 @@ typedef struct
 {\r
 \r
   int clientcount, server_max_clients;\r
-  unsigned int umurmurd_pid; \r
+  unsigned int umurmurd_pid;\r
+       uint8_t alive; \r
   shmclient_t client[];    \r
   \r
-}shm_t;
\ No newline at end of file
+}shm_t;\r