From: Martin Johansson Date: Sun, 7 Dec 2014 20:01:03 +0000 (+0100) Subject: Merge pull request #48 from snowblind/sharedmemory X-Git-Url: http://git.code-monkey.de/?a=commitdiff_plain;h=0382e6436faf446f1f39860cdb59159ccd4b3356;hp=d3b46bdd65307efa15cef4a7e97e4e19cdf0efad;p=umurmur.git Merge pull request #48 from snowblind/sharedmemory Sharedmemory API --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ff95a0..7125353 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,8 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH true) option(USE_POLARSSL_TESTCERT "Link to the PolarSSL test certificate and key." OFF) option(USE_POLARSSL_HAVEGE "Use the PolarSSL HAVEGE random generator key." OFF) +option(USE_SHAREDMEMORY_API "Compile with Sharedmemory API support" OFF) + if(USE_POLARSSL_TESTCERT OR USE_POLARSSL_HAVEGE) if(SSL MATCHES "openssl" OR SSL MATCHES "gnutls") message(FATAL_ERROR "Selecting USE_POLARSSL_TESTCERT or USE_POLARSSL_HAVEGE implies SSL=polarssl") diff --git a/configure.ac b/configure.ac index 5a637e1..5b612ca 100644 --- a/configure.ac +++ b/configure.ac @@ -38,8 +38,12 @@ AC_CANONICAL_HOST # Configure options. AC_ARG_WITH([ssl], [AC_HELP_STRING([--with-ssl=@<:@LIB@:>@], [SSL library (openssl|polarssl) @<:@default=polarssl@:>@])], [], [with_ssl=polarssl]) +AC_ARG_ENABLE([shmapi], [AC_HELP_STRING([--enable-shmapi], [compile with Sharedmemory API support @<:@default=no@:>@])],[],[enable_shmapi=no] ) AC_ARG_ENABLE(polarssl-test-cert, [ --enable-polarssl-test-cert Link to PolarSSL test certificate and key @<:@default=no@:>@], [enable_polarssl_test_cert=yes]) -AC_ARG_ENABLE(polarssl-havege, [ --enable-polarssl-havege Link to PolarSSL HAVEGE random generator key @<:@default=no@:>@ Deafult: /dev/urandom], [enable_polarssl_havege=yes]) +AC_ARG_ENABLE(polarssl-havege, [ --enable-polarssl-havege Link to PolarSSL HAVEGE random generator key @<:@default=no@:>@ Default: /dev/urandom], [enable_polarssl_havege=yes]) + + + # Checks for programs. AC_PROG_CC @@ -89,6 +93,16 @@ AS_IF([test "x$with_ssl" = xopenssl], [ AM_CONDITIONAL(USE_OPENSSL, test x$with_ssl = xopenssl) AM_CONDITIONAL(USE_GNUTLS, test x$with_ssl = xgnutls) +AS_IF([test "x$enable_shmapi" != xno], + [ + AM_CONDITIONAL(USE_SHAREDMEMORY_API, true) + AC_DEFINE([USE_SHAREDMEMORY_API],[],[Use sharedmemory API]) + ], [ + AM_CONDITIONAL(USE_SHAREDMEMORY_API, false) +]) + + + AC_DEFINE([DEFAULT_CONFIG], ["/etc/umurmur.conf"], [Default config]) # Checks for header files. diff --git a/shm_utils/mon-umurmurd/CHANGES b/shm_utils/mon-umurmurd/CHANGES new file mode 100644 index 0000000..9b4f768 --- /dev/null +++ b/shm_utils/mon-umurmurd/CHANGES @@ -0,0 +1,19 @@ +* BUG_FIX: Fix the screen not clearing when last person exits the server + + +* Code clean up + + +* Added more client data 99% of the useful client data shown +* rework Sharedmemory_update() to not use memcpy (requested by fatbob) + + +* Using a more modern unix sharedmemory API. this requires linking with librt.so (requested by fatbob) +* Added away to know if umurmurd is not connected/updateing the shm_t struct. I use 8bit timer with + rollover protection see check_serverTick() and where I use the function near bottum of mon-umurmurd.c + for how to use this. + + +* code clean up and some comments added +* ~95% of the useful client data shown +* outputs a more meaningful idle and online time, both are reported in secs (error reported by fatbob) diff --git a/shm_utils/mon-umurmurd/Makefile b/shm_utils/mon-umurmurd/Makefile new file mode 100644 index 0000000..e10e898 --- /dev/null +++ b/shm_utils/mon-umurmurd/Makefile @@ -0,0 +1,25 @@ +############################################################################# +# +# Makefile for mon-umurmurd + + +# The recommended compiler flags for the Raspberry Pi +#CCFLAGS=-Wall -Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -g -lrt +CCFLAGS= -lrt + +# define all programs +PROGRAMS = mon-umurmurd +SOURCES = ${PROGRAMS:=.c} + +all: ${PROGRAMS} + +${PROGRAMS}: ${SOURCES} + gcc ${CCFLAGS} $@.c -o $@ + +clean: + rm -rf $(PROGRAMS) + +install: all + cp mon-umurmurd /usr/local/bin/ + +.PHONY: install diff --git a/shm_utils/mon-umurmurd/README.md b/shm_utils/mon-umurmurd/README.md new file mode 100644 index 0000000..72473de --- /dev/null +++ b/shm_utils/mon-umurmurd/README.md @@ -0,0 +1,7 @@ +mon-umurmurd +============ + +outputs server/client data to term useing the sharedmemory API added to umurmur for testing + +make +./mon-umurmurd diff --git a/shm_utils/mon-umurmurd/mon-umurmurd.c b/shm_utils/mon-umurmurd/mon-umurmurd.c new file mode 100644 index 0000000..7cd5697 --- /dev/null +++ b/shm_utils/mon-umurmurd/mon-umurmurd.c @@ -0,0 +1,164 @@ +#include /* For O_* constants */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../src/sharedmemory.h" +#include "../../src/sharedmemory_global.h" + +enum{ NOP_SHM, WAIT_ATTACH_SHM, TRY_ATTACH_SHM, MAT_SHM, CLEAN_UP_SHM, RUN_SHM }; + +int wait = 0, opt; +uint8_t last, shm_statem = TRY_ATTACH_SHM; + +void run_shm(void); + +int main(int argc, char **argv) +{ + struct stat buf; + int bindport = 0; + + while ( (opt = getopt(argc, argv, "wb:")) != -1 ) + { + switch(opt) + { + case 'w': + wait = 1; + break; + case 'b': + bindport = atoi(optarg); + break; + default: + fprintf(stderr, "Usage: %s [-w] [-b ]\n", argv[0]); + fprintf(stderr, "\t-w - Wait for umurmurd to create shm area. useful if you need to start from init.d script\n" ); + fprintf(stderr, "\t-b - Change this to the port used when starting umurmurd. Defaults to \"/umurmurd:64738\" \n"); + exit(EXIT_FAILURE); + } + } + + shmptr = NULL; + + if( !bindport ) + { + bindport = 64738; + } + + sprintf( shm_file_name, "/umurmurd:%i", bindport ); + + if( wait ) + shm_statem = WAIT_ATTACH_SHM; + + while( shm_statem ) + { + switch( shm_statem ) + { + case RUN_SHM: + run_shm(); + break; + case WAIT_ATTACH_SHM: + printf( "Waiting for umurmurd to be run\n\r"); fflush(stdout); + while( ( shm_fd = shm_open( shm_file_name, O_RDONLY, 0666 ) ) == -1 ) + sleep( 1 ); + shm_statem = MAT_SHM; + break; + case TRY_ATTACH_SHM: + if( ( shm_fd = shm_open( shm_file_name, O_RDONLY, 0666 ) ) == -1 ) + { + printf( "umurmurd doesn't seem to be running\n\r" ); + exit(EXIT_FAILURE); + } + shm_statem = MAT_SHM; + break; + case MAT_SHM: + fstat( shm_fd, &buf); + if( ( shmptr = mmap(0, buf.st_size, PROT_READ, MAP_SHARED, shm_fd, 0) ) == MAP_FAILED ) + { + exit(EXIT_FAILURE); + } + printf( "umumurd PID: %u\n\r", shmptr->umurmurd_pid ); + shm_statem = RUN_SHM; + break; + case CLEAN_UP_SHM: + + break; + + } + } + fflush(stdout); + return 0; +} + +uint8_t check_serverTick(void) +{ + last = shmptr->alive; + sleep( 1 ); // Sleep for 1 sec + return(shmptr->alive - last); +} + +void run_shm(void) +{ + +int cc; + + printf( "\033[2J\033[H" ); fflush(stdout); //clear screen VT100 + printf( "%s Clients(CONECTED/MAX) %i/%i\n\n", shm_file_name, shmptr->clientcount, shmptr->server_max_clients ); + + for( cc = 0 ; cc < shmptr->server_max_clients ; cc++ ) + { + + if( !shmptr->client[cc].authenticated ) + continue; + + printf( "%s@%s:%i in channel: %s\n\ + \tclient_OS: %s %s\n\ + \tclient_info: %s\n\ + \tavailableBandwidth: %i\n\ + \tOnline(secs): %lu Idle(secs): %lu\n\ + \tusingUDP=%i\n\ + \tdeaf=%i, mute=%i\n\ + \tself_deaf=%i, self_mute=%i\n\ + \trecording=%i\n\ + \tbOpus=%i\n\ + \tisAdmin=%i\n\ + \tisSuppressed=%i\n\ + \tUDP_Avg/Var: %3.2f/%3.2f\n\ + \tTCP_Avg/Var: %3.2f/%3.2f\n\ + \tUDP_C/TCP_C: %lu/%lu\n", + shmptr->client[cc].username, + shmptr->client[cc].ipaddress, + shmptr->client[cc].udp_port, + shmptr->client[cc].channel, + shmptr->client[cc].os, + shmptr->client[cc].os_version, + shmptr->client[cc].release, + shmptr->client[cc].availableBandwidth, + shmptr->client[cc].online_secs, + shmptr->client[cc].idle_secs, + + shmptr->client[cc].bUDP, + shmptr->client[cc].deaf, + shmptr->client[cc].mute, + shmptr->client[cc].self_deaf, + shmptr->client[cc].self_mute, + shmptr->client[cc].recording, + shmptr->client[cc].bOpus, + + shmptr->client[cc].isAdmin, + shmptr->client[cc].isSuppressed, + + shmptr->client[cc].UDPPingAvg, + shmptr->client[cc].UDPPingVar, + shmptr->client[cc].TCPPingAvg, + shmptr->client[cc].TCPPingVar, + shmptr->client[cc].UDPPackets, + shmptr->client[cc].TCPPackets ); fflush(stdout); // fflush need because of sleep() call + } + if( !check_serverTick() ) + { + exit(EXIT_FAILURE); //You dont have to exit you could just report the fact that the data is not valid + } +} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a73a5a2..096ef45 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,5 +24,9 @@ elseif(SSL MATCHES "gnutls") list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/ssli_gnutls.c) endif(SSL MATCHES "openssl") +if(USE_SHAREDMEMORY_API) + list(APPEND SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/sharedmemory.c) +endif(USE_SHAREDMEMORY_API) + set(SOURCE ${SOURCE} ${SOURCE_FILES} PARENT_SCOPE) diff --git a/src/Makefile.am b/src/Makefile.am index f280ecf..d8f476f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,3 +38,7 @@ else umurmurd_SOURCES+=ssli_polarssl.c endif endif + +if USE_SHAREDMEMORY_API +umurmurd_SOURCES+=sharedmemory.c +endif diff --git a/src/config.h.in b/src/config.h.in index 3169a19..8fd66f9 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -4,6 +4,9 @@ #cmakedefine USE_POLARSSL #cmakedefine USE_POLARSSL_TESTCERT #cmakedefine USE_POLARSSL_HAVEGE + +#cmakedefine USE_SHAREDMEMORY_API + #define DEFAULT_CONFIG "${CMAKE_INSTALL_PREFIX}/etc/umurmur.conf" #endif // CONFIG_H diff --git a/src/main.c b/src/main.c index c1649b6..89ca280 100644 --- a/src/main.c +++ b/src/main.c @@ -55,6 +55,7 @@ #include "conf.h" #include "version.h" #include "config.h" +#include "sharedmemory.h" char system_string[64], version_string[64]; int bindport; @@ -349,7 +350,11 @@ int main(int argc, char **argv) Chan_init(); Client_init(); Ban_init(); - + +#ifdef USE_SHAREDMEMORY_API + Sharedmemory_init( bindport, bindport6 ); +#endif + #ifdef POSIX_PRIORITY_SCHEDULING if (realtime) setscheduler(); @@ -357,6 +362,10 @@ int main(int argc, char **argv) Server_run(); +#ifdef USE_SHAREDMEMORY_API + Sharedmemory_deinit(); +#endif + Ban_deinit(); SSLi_deinit(); Chan_free(); diff --git a/src/server.c b/src/server.c index 836621a..4b90734 100644 --- a/src/server.c +++ b/src/server.c @@ -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; @@ -194,6 +198,9 @@ void Server_runLoop(struct pollfd* pollfds) if (pollfds[nofServerSocks + i].revents & POLLOUT) Client_write_fd(pollfds[nofServerSocks + i].fd); } +#ifdef USE_SHAREDMEMORY_API + Sharedmemory_update(); +#endif } } diff --git a/src/sharedmemory.c b/src/sharedmemory.c new file mode 100644 index 0000000..9018f5c --- /dev/null +++ b/src/sharedmemory.c @@ -0,0 +1,117 @@ +#include "sharedmemory.h" +#include "sharedmemory_global.h" + +void Sharedmemory_init( int bindport, int bindport6 ) +{ + + int server_max_clients = getIntConf(MAX_CLIENTS); + int shmtotal_size = sizeof( shm_t ) + (sizeof( shmclient_t ) * server_max_clients); + + if( !bindport ) + { + bindport = getIntConf(BINDPORT); + } + + sprintf( shm_file_name, "/umurmurd:%i", bindport ); + Log_info("SHM_API: shm_fd=\"%s\"", shm_file_name ); + + shm_fd = shm_open( shm_file_name, O_CREAT | O_RDWR, 0660 ); + if(shm_fd == -1) + { + Log_fatal( "SHM_API: Open failed:%s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + if( ftruncate( shm_fd, shmtotal_size ) == -1 ) + { + Log_fatal( "SHM_API: ftruncate : %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + shmptr = mmap( 0, shmtotal_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0 ); + if (shmptr == MAP_FAILED) + { + Log_fatal( "SHM_API: mmap failed : %s\n", strerror(errno)); + exit(EXIT_FAILURE); + } + + memset( shmptr, 0, shmtotal_size ); + + shmptr->umurmurd_pid = getpid(); + shmptr->server_max_clients = server_max_clients; + shmptr->shmtotal_size = shmtotal_size; + shmptr->shmclient_size = sizeof( shmclient_t ) * shmptr->server_max_clients; + +} + +void Sharedmemory_update(void) +{ + + uint64_t now; + unsigned int cc = 0; + client_t *client_itr = NULL; + + memset( &shmptr->client[0], 0, shmptr->shmclient_size ); + shmptr->clientcount = Client_count(); + + if( shmptr->clientcount ) + { + Timer_init( &now ); + while( Client_iterate(&client_itr) != NULL ) + { + if( client_itr->authenticated ) + { + channel_t *channel = client_itr->channel; + + strncpy( shmptr->client[cc].username, client_itr->username, 120 ); + strncpy( shmptr->client[cc].ipaddress, Util_clientAddressToString( client_itr ), INET6_ADDRSTRLEN - 1 ); + strncpy( shmptr->client[cc].channel, channel->name, 120 ); + + strncpy( shmptr->client[cc].os, client_itr->os, 120 ); + strncpy( shmptr->client[cc].release, client_itr->release, 120 ); + strncpy( shmptr->client[cc].os_version, client_itr->os_version, 120 ); + + shmptr->client[cc].tcp_port = Util_clientAddressToPortTCP( client_itr ); + shmptr->client[cc].udp_port = Util_clientAddressToPortUDP( client_itr ); + + shmptr->client[cc].online_secs = ( now - client_itr->connectTime ) / 1000000LL; + shmptr->client[cc].idle_secs = ( now - client_itr->idleTime ) / 1000000LL; + + shmptr->client[cc].bUDP = client_itr->bUDP; + shmptr->client[cc].deaf = client_itr->deaf; + shmptr->client[cc].mute = client_itr->mute; + shmptr->client[cc].bOpus = client_itr->bOpus; + shmptr->client[cc].self_deaf = client_itr->self_deaf; + shmptr->client[cc].self_mute = client_itr->self_mute; + shmptr->client[cc].recording = client_itr->recording; + shmptr->client[cc].authenticated = client_itr->authenticated; + + shmptr->client[cc].availableBandwidth = client_itr->availableBandwidth; + + shmptr->client[cc].UDPPingAvg = client_itr->UDPPingAvg; + shmptr->client[cc].UDPPingVar = client_itr->UDPPingVar; + shmptr->client[cc].TCPPingAvg = client_itr->TCPPingAvg; + shmptr->client[cc].TCPPingVar = client_itr->TCPPingVar; + + shmptr->client[cc].isAdmin = client_itr->isAdmin; + shmptr->client[cc].isSuppressed = client_itr->isSuppressed; + + shmptr->client[cc].UDPPackets = client_itr->UDPPackets; + shmptr->client[cc].TCPPackets = client_itr->TCPPackets; + + } + cc++; + } + } +} +void Sharedmemory_alivetick(void) +{ + shmptr->alive++; +} + +void Sharedmemory_deinit(void) +{ + close( shm_fd ); + shm_unlink( shm_file_name ); + shmptr->umurmurd_pid = 0; +} \ No newline at end of file diff --git a/src/sharedmemory.h b/src/sharedmemory.h new file mode 100644 index 0000000..b668c32 --- /dev/null +++ b/src/sharedmemory.h @@ -0,0 +1,23 @@ +#ifndef SHAREDMEMORY_H_777736932196 +#define SHAREDMEMORY_H_777736932196 + +#include +#include + +#include /* For O_* constants */ +#include +#include + +#include +#include "util.h" +#include "conf.h" +#include "client.h" +#include "channel.h" +#include "sharedmemory_struct.h" + +void Sharedmemory_init( int bindport, int bindport6 ); +void Sharedmemory_update(void); +void Sharedmemory_alivetick(void); +void Sharedmemory_deinit(void); + +#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 index 0000000..b68fcde --- /dev/null +++ b/src/sharedmemory_global.h @@ -0,0 +1,3 @@ +int shm_fd; +shm_t *shmptr = NULL; +char shm_file_name[128]; diff --git a/src/sharedmemory_struct.h b/src/sharedmemory_struct.h new file mode 100644 index 0000000..a36382e --- /dev/null +++ b/src/sharedmemory_struct.h @@ -0,0 +1,28 @@ +typedef struct +{ + + char username[121]; + char ipaddress[INET6_ADDRSTRLEN]; + char channel[121]; + char os[121], release[121], os_version[121]; + int tcp_port, udp_port; + bool_t bUDP, authenticated, deaf, mute, self_deaf, self_mute, recording, bOpus; + int availableBandwidth; + uint32_t online_secs, idle_secs; + bool_t isAdmin; + bool_t isSuppressed; + float UDPPingAvg, UDPPingVar, TCPPingAvg, TCPPingVar; + uint32_t UDPPackets, TCPPackets; + +}shmclient_t; + +typedef struct +{ + + int shmtotal_size, shmclient_size; + int clientcount, server_max_clients; + unsigned int umurmurd_pid; + uint8_t alive; + shmclient_t client[]; + +}shm_t; diff --git a/src/ssl.h b/src/ssl.h index f88e301..2d86a05 100644 --- a/src/ssl.h +++ b/src/ssl.h @@ -125,7 +125,7 @@ static inline void SSLi_hash2hex(uint8_t *hash, char *out) } static inline void SSLi_hex2hash(char *in, uint8_t *hash) { - int i, offset = 0; + int i; char byte[3]; int scanned;