--- /dev/null
+* 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
outputs server/client data to term useing the sharedmemory API added to umurmur for testing\r
\r
make\r
-./mon-umurmurd
\ No newline at end of file
+./mon-umurmurd\r
+\r
+\r
\r
\r
struct shmid_ds buf;\r
-\r
-int wait = 0, opt;\r
-\r
enum{ NOP_SHM, WAIT_ATTACH_SHM, TRY_ATTACH_SHM, MAT_SHM, CLEAN_UP_SHM, RUN_SHM };\r
\r
-unsigned int shm_statem = TRY_ATTACH_SHM;\r
+\r
\r
void run_shm(void);\r
\r
+\r
int main(int argc, char **argv) \r
{\r
-\r
-key_t key = 0x53021d79;\r
-\r
- while ((opt = getopt(argc, argv, "w")) != -1) {\r
- switch (opt) {\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
case 'w':\r
wait = 1;\r
break;\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
- //key = ftok(".", 'S'); // check if ftok works if both umurmur and mon-umurmur are in same dir\r
- // using my own key for now. makes dev easier will fix\r
- shmptr = NULL;\r
\r
+ \r
if( wait )\r
shm_statem = WAIT_ATTACH_SHM;\r
\r
while( shm_statem )\r
{\r
-\r
switch( shm_statem )\r
{\r
-\r
case RUN_SHM:\r
run_shm();\r
break; \r
shm_statem = MAT_SHM;\r
break;\r
case MAT_SHM: \r
- if( ( shmptr = shmat( shmid, 0, 0 ) ) == (void *) (-1) ) ////MJP BUG? \r
+ if( ( shmptr = shmat( shmid, 0, 0 ) ) == (void *) (-1) )\r
{\r
perror("shmat");\r
exit(EXIT_FAILURE);\r
}\r
printf( "shmid: %i\n\r", shmid );\r
- printf( "umumurd PID: %u\n\r", shmptr->umurmurd_pid );\r
+ printf( "Connected to umumurd PID: %u\n\r", shmptr->umurmurd_pid );\r
+ sleep( 1 );\r
shm_statem = RUN_SHM; \r
break;\r
case CLEAN_UP_SHM: \r
shmdt( shmptr ); \r
- break;\r
- \r
+ break; \r
}\r
}\r
- fflush(stdout);\r
- return 0;\r
+ fflush(stdout);\r
+ return 0;\r
}\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
-int cc;\r
-\r
- \r
- \r
- shmctl( shmid, IPC_STAT, &buf ); //MJP BUG check for errors here\r
-\r
- printf("\033[2J\033[H"); //clear screen VT100\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
- for( cc = 0 ; cc < shmptr->server_max_clients ; cc++ )\r
- {\r
- \r
- if( !shmptr->client[cc].authenticated )\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
continue; \r
\r
- printf( "%s@%s:%i in channel: %s\n\\r
- \tlastActivity/connectTime/idleTime: %llu/%llu/%llu idleTime: %llu \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
-\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
\r
- \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].lastActivity,\r
- shmptr->client[cc].connectTime,\r
- shmptr->client[cc].idleTime,\r
- (long long unsigned int)shmptr->client[cc].lastActivity - shmptr->client[cc].idleTime,\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
- \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
}
\ No newline at end of file
--- /dev/null
+* added a new button to autoupdate web page every second. no ugly page reload\r
+* code clean up \r
+* outputs a more meaningful idle and online time, both are reported in secs
\ No newline at end of file
/*
- * uMurmurd Websocket server - HTTP/JSON serverexample
+ * uMurmurd Websocket - HTTP/JSON server example
*
* Copyright (C) 2014 Michael P. Pounders <>
*
#endif
#include <stdio.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <fcntl.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"
-int max_poll_elements;
-
struct pollfd *pollfds;
-int *fd_lookup;
-int count_pollfds;
-int force_exit = 0;
+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
};
-
-
-char *resource_path = "../web";
-
/*
* We take a strict whitelist approach to stop ../ attacks
*/
if( !shmptr->client[cc].authenticated )
continue;
- client = json_pack( "{:s:s,s:s,s:i,s:s,s:I,s:I,s:I}", "username",
+ 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,
shmptr->client[cc].udp_port,
"channel",
shmptr->client[cc].channel,
- "lastactivity",
- shmptr->client[cc].lastActivity,
- "connecttime",
- shmptr->client[cc].connectTime,
- "idleTime",
- (long long unsigned int)shmptr->client[cc].lastActivity - shmptr->client[cc].idleTime
+ "online_secs",
+ shmptr->client[cc].online_secs,
+ "idle_secs",
+ shmptr->client[cc].idle_secs
);
- json_array_append_new( jarr1, client );
+ 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) );
+ //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__umurmur_json {
+struct per_session_data__umurmurd_json {
int test;
};
static int
-callback_umurmur_json( struct libwebsocket_context *context,
+callback_umurmurd_json( struct libwebsocket_context *context,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 +
LWS_SEND_BUFFER_POST_PADDING];
- //struct per_session_data__umurmur_json *pss = (struct per_session_data__umurmur_json *)user;
+ //struct per_session_data__umurmurd_json *pss = (struct per_session_data__umurmurd_json *)user;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED:
- lwsl_info("callback_umurmur_json: LWS_CALLBACK_ESTABLISHED\n");
+ lwsl_info("callback_umurmurd_json: LWS_CALLBACK_ESTABLISHED\n");
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
case LWS_CALLBACK_RECEIVE:
//fprintf(stderr, "rx %d\n", (int)len);
- if (len < 6)
- break;
- if (strcmp((const char *)in, "update\n") == 0)
+// 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;
+ }
- 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
0, /* max frame size / rx buffer */
},
{
- "umurmur-json-protocol",
- callback_umurmur_json,
- sizeof(struct per_session_data__umurmur_json),
+ "umurmurd-json-protocol",
+ callback_umurmurd_json,
+ sizeof(struct per_session_data__umurmurd_json),
128,
},
{ NULL, NULL, 0, 0 } /* terminator */
int opts = 0;
char interface_name[128] = "";
const char *iface = NULL;
-// unsigned int oldus = 0;
+ uint64_t oldus = 0;
struct lws_context_creation_info info;
int syslog_options = LOG_PID | LOG_PERROR;
* live websocket connection using the DUMB_INCREMENT protocol,
* as soon as it can take more packets (usually immediately)
*/
-
-// if (((unsigned int)tv.tv_usec - oldus) > 50000) {
-// libwebsocket_callback_on_writable_all_protocol(&protocols[PROTOCOL_JSON_UMURMURD]);
-// oldus = tv.tv_usec;
-// }
-
+ 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,
libwebsocket_context_destroy(context);
- lwsl_notice("umurmur_websocket server exited cleanly\n");
+ lwsl_notice("uMurmurd Websocket server exited cleanly\n");
shmdt( shmptr );
closelog();
<div id="output"> </div>
<input type=button id=offset value="Update" onclick="update();">
+<input type=button id=offset value="AutoUpdate" onclick="autoupdate();">
<script src="/js/jquery.min.js"></script>
<script src="/js/crel.js"></script>
<script src="/js/json.human.js"></script>
if (typeof MozWebSocket != "undefined") {
socket_json = new MozWebSocket(get_appropriate_ws_url(),
- "umurmur-json-protocol");
+ "umurmurd-json-protocol");
} else {
socket_json = new WebSocket(get_appropriate_ws_url(),
- "umurmur-json-protocol");
+ "umurmurd-json-protocol");
}
function update() {
socket_json.send("update\n");
}
+function autoupdate() {
+ socket_json.send("autoupdate\n");
+}
</script>
</body>
</html>
\ No newline at end of file
void Sharedmemory_update(void) \r
{\r
\r
- static size_t bt_end = sizeof( bool_t ) * 8, //compute once\r
- et_end = sizeof( etimer_t ) * 3,\r
- pa_end = sizeof( float ) * 4,\r
- pc_end = sizeof( uint32_t ) * 2;\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
- \r
- \r
+ if( shmptr->clientcount )\r
+ {\r
+ Timer_init( &now );\r
while( Client_iterate(&client_itr) != NULL ) {\r
- \r
-\r
- \r
+ \r
if( client_itr->authenticated )\r
- {\r
- \r
+ { \r
channel_t *channel = client_itr->channel;\r
- \r
+ \r
strncpy( shmptr->client[cc].username, client_itr->username, 120 );\r
- strncpy( shmptr->client[cc].ipaddress, Util_clientAddressToString( client_itr ) , 45 );\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
+ \r
memcpy( &shmptr->client[cc].bUDP, &client_itr->bUDP, bt_end );\r
- memcpy( &shmptr->client[cc].lastActivity, &client_itr->lastActivity, et_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
+ cc++; \r
}\r
- \r
+\r
+} \r
}\r
\r
void Sharedmemory_deinit(void) \r
int tcp_port, udp_port;\r
char channel[121];\r
bool_t bUDP, authenticated, deaf, mute, self_deaf, self_mute, recording, bOpus;\r
- etimer_t lastActivity, connectTime, idleTime;\r
+ uint32_t online_secs, idle_secs;\r
float UDPPingAvg, UDPPingVar, TCPPingAvg, TCPPingVar;\r
uint32_t UDPPackets, TCPPackets;\r
\r
{\r
\r
int clientcount, server_max_clients;\r
- unsigned int umurmurd_pid; //Use this to make sure umurmurd is still running so I can allow more than one connection.\r
- shmclient_t client[]; //MJP BUG: Use max usersetting from conf file\r
+ unsigned int umurmurd_pid; \r
+ shmclient_t client[]; \r
\r
}shm_t;
\ No newline at end of file