+* 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
# 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
-#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
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
#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;
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;
#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
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
#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
--- /dev/null
+int shm_fd;\r
+shm_t *shmptr = NULL;\r
+char shm_file_name[128];
\ No newline at end of file
typedef struct\r
{\r
+\r
char username[121];\r
char ipaddress[46];\r
int tcp_port, udp_port;\r
{\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