From 0382e7990e4704991de767057b11c4f11c7b2ba8 Mon Sep 17 00:00:00 2001 From: Jeremy Lakeman Date: Tue, 12 Sep 2017 15:24:10 +0930 Subject: [PATCH] Enable a more graceful shutdown of the server in most cases --- directory_client.c | 7 +++-- dna_helper.c | 11 ++++--- fdqueue.c | 41 +++++++++++++++--------- fdqueue.h | 2 +- httpd.c | 26 +++++++++++---- jni_server.c | 4 +-- monitor.c | 27 ++++++++++++---- overlay_interface.c | 31 +++++++++++++++--- overlay_interface.h | 3 +- overlay_mdp.c | 23 +++++++++++++- overlay_queue.c | 4 ++- rhizome_sync_keys.c | 74 ++++++++++++++++++++++++++++++++----------- route_link.c | 7 +++-- serval.h | 2 -- server.c | 77 ++++++++++++++++++++++++++++++++------------- server.h | 5 +++ vomp.c | 34 +++++++++++++------- 17 files changed, 278 insertions(+), 100 deletions(-) diff --git a/directory_client.c b/directory_client.c index 485741ff..82012d5f 100644 --- a/directory_client.c +++ b/directory_client.c @@ -139,8 +139,11 @@ int directory_registration(){ return 0; } -static void interface_change(struct overlay_interface *UNUSED(interface)){ - directory_registration(); +static void interface_change(struct overlay_interface *UNUSED(interface), unsigned count){ + if (count) + directory_registration(); + else + unschedule(&directory_alarm); } DEFINE_TRIGGER(iupdown, interface_change); diff --git a/dna_helper.c b/dna_helper.c index c5ce98d3..911ed321 100644 --- a/dna_helper.c +++ b/dna_helper.c @@ -60,6 +60,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "strbuf_helpers.h" #include "dataformats.h" #include "overlay_address.h" +#include "server.h" + +static void dna_helper_shutdown(); /* The challenge with making an interface for calling an external program to @@ -324,19 +327,19 @@ dna_helper_harvest(int blocking) return 0; } -int dna_helper_shutdown() +static void dna_helper_shutdown() { DEBUG(dnahelper, "DNAHELPER shutting down"); dna_helper_close_pipes(); switch (dna_helper_kill()) { case -1: - return -1; case 0: - return 0; + return; default: - return dna_helper_harvest(1); + dna_helper_harvest(1); } } +DEFINE_TRIGGER(shutdown, dna_helper_shutdown); static void monitor_requests(struct sched_ent *alarm) { diff --git a/fdqueue.c b/fdqueue.c index 5001e9c1..0d0561c1 100644 --- a/fdqueue.c +++ b/fdqueue.c @@ -67,27 +67,38 @@ struct profile_total poll_stats={NULL,0,"Idle (in poll)",0,0,0,0}; #define alloca_alarm_name(alarm) ((alarm)->stats ? alloca_str_toprint((alarm)->stats->name) : "Unnamed") -void list_alarms() +int list_alarms(int log_level) { + int count=0; time_ms_t now = gettime_ms(); struct sched_ent *alarm; - _DEBUG("Run now;"); - for (alarm = run_now; alarm; alarm=alarm->_next_run) - _DEBUGF("%p %s deadline in %"PRId64"ms", alarm->function, alloca_alarm_name(alarm), alarm->run_before - now); + LOGF(log_level, "Run now;"); + for (alarm = run_now; alarm; alarm=alarm->_next_run){ + count ++; + LOGF(log_level, "%p %s deadline in %"PRId64"ms", alarm->function, alloca_alarm_name(alarm), alarm->run_before - now); + } - _DEBUG("Run soon;"); - for (alarm = run_soon; alarm; alarm=alarm->_next_run) - _DEBUGF("%p %s run in %"PRId64"ms", alarm->function, alloca_alarm_name(alarm), alarm->run_after - now); - - _DEBUG("Wake at;"); - for (alarm = wake_list; alarm; alarm = alarm->_next_wake) - _DEBUGF("%p %s wake in %"PRId64"ms", alarm->function, alloca_alarm_name(alarm), alarm->wake_at - now); - - _DEBUG("File handles;"); + LOGF(log_level, "Run soon;"); + for (alarm = run_soon; alarm; alarm=alarm->_next_run){ + count ++; + LOGF(log_level, "%p %s run in %"PRId64"ms", alarm->function, alloca_alarm_name(alarm), alarm->run_after - now); + } + + LOGF(log_level, "Wake at;"); + for (alarm = wake_list; alarm; alarm = alarm->_next_wake){ + count ++; + LOGF(log_level, "%p %s wake in %"PRId64"ms", alarm->function, alloca_alarm_name(alarm), alarm->wake_at - now); + } + + LOGF(log_level, "File handles;"); int i; - for (i = 0; i < fdcount; ++i) - _DEBUGF("%s watching #%d for %x", alloca_alarm_name(fd_callbacks[i]), fds[i].fd, fds[i].events); + for (i = 0; i < fdcount; ++i){ + count ++; + LOGF(log_level, "%s watching #%d for %x", alloca_alarm_name(fd_callbacks[i]), fds[i].fd, fds[i].events); + } + + return count; } static void insert_run_now(struct sched_ent *alarm) diff --git a/fdqueue.h b/fdqueue.h index 7399940a..f588dc82 100644 --- a/fdqueue.h +++ b/fdqueue.h @@ -173,6 +173,6 @@ unsigned fd_depth(); #define RETURNVOID do { OUT(); return; } while (0) DECLARE_ALARM(fd_periodicstats); -void list_alarms(); +int list_alarms(int log_level); #endif // __SERVAL_DNA__FDQUEUE_H diff --git a/httpd.c b/httpd.c index 00379e4b..1960ed92 100644 --- a/httpd.c +++ b/httpd.c @@ -23,9 +23,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "net.h" #include "conf.h" #include "str.h" +#include "server.h" #define RHIZOME_SERVER_MAX_LIVE_REQUESTS 32 +static int httpd_dispatch(struct http_request *); +static unsigned int http_request_uuid_counter = 0; +static httpd_request * current_httpd_requests = NULL; +unsigned int current_httpd_request_count = 0; + static int httpd_dispatch(struct http_request *hr) { httpd_request *r = (httpd_request *) hr; @@ -101,6 +107,20 @@ int is_httpd_server_running() return httpd_server_socket != -1; } +static void httpd_server_shutdown() +{ + if (httpd_server_socket==-1) + return; + unwatch(&server_alarm); + close(httpd_server_socket); + httpd_server_socket=-1; + + // forcefully close all requests immediately + while(current_httpd_requests) + http_request_finalise(¤t_httpd_requests->http); +} +DEFINE_TRIGGER(shutdown, httpd_server_shutdown); + /* Start the Rhizome HTTP server by creating a socket, binding it to an available port, and marking it as passive. If called repeatedly and frequently, this function will only try to start the server after a certain time has elapsed since the last attempt. @@ -193,12 +213,6 @@ success: return 0; } -static int httpd_dispatch(struct http_request *); - -static unsigned int http_request_uuid_counter = 0; -static httpd_request * current_httpd_requests = NULL; -unsigned int current_httpd_request_count = 0; - static void httpd_server_finalise_http_request(struct http_request *hr) { httpd_request *r = (httpd_request *) hr; diff --git a/jni_server.c b/jni_server.c index 664120da..51de679e 100644 --- a/jni_server.c +++ b/jni_server.c @@ -37,8 +37,8 @@ static time_ms_t waiting(time_ms_t now, time_ms_t next_run, time_ms_t next_wakeu jlong r = (*server_env)->CallLongMethod(server_env, JniCallback, aboutToWait, (jlong)now, (jlong)next_run, (jlong)next_wakeup); // stop the server if there are any issues if ((*server_env)->ExceptionCheck(server_env)){ - serverMode=SERVER_CLOSING; INFO("Stopping server due to exception"); + server_close(); return now; } return r; @@ -53,7 +53,7 @@ static void wokeup() // stop the server if there are any issues if ((*server_env)->ExceptionCheck(server_env)){ INFO("Stopping server due to exception"); - serverMode=SERVER_CLOSING; + server_close(); } } } diff --git a/monitor.c b/monitor.c index 97e9757d..7531f668 100644 --- a/monitor.c +++ b/monitor.c @@ -178,7 +178,7 @@ static void monitor_close(struct monitor_context *c){ if (serverMode && (c->flags & MONITOR_QUIT_ON_DISCONNECT)){ INFOF("Stopping server due to client disconnecting"); - serverMode=SERVER_CLOSING; + server_close(); } unwatch(&c->alarm); close(c->alarm.poll.fd); @@ -187,6 +187,20 @@ static void monitor_close(struct monitor_context *c){ c->flags=0; } +static void monitor_shutdown() +{ + if (named_socket.poll.fd == -1) + return; + unwatch(&named_socket); + close(named_socket.poll.fd); + named_socket.poll.fd=-1; + + int i; + for(i=monitor_socket_count -1;i>=0;i--) + monitor_close(&monitor_sockets[i]); +} +DEFINE_TRIGGER(shutdown, monitor_shutdown); + void monitor_client_poll(struct sched_ent *alarm) { /* Read available data from a monitor socket */ @@ -652,7 +666,7 @@ int monitor_client_interested(int mask){ int monitor_tell_clients(char *msg, int msglen, int mask) { - int i; + int i, count=0; IN(); for(i=monitor_socket_count -1;i>=0;i--) { if (monitor_sockets[i].flags & mask) { @@ -660,10 +674,12 @@ int monitor_tell_clients(char *msg, int msglen, int mask) if ( write_all_nonblock(monitor_sockets[i].alarm.poll.fd, msg, msglen) == -1) { INFOF("Tear down monitor client #%d due to write error", i); monitor_close(&monitor_sockets[i]); + }else{ + count++; } } } - RETURN(0); + RETURN(count); } int monitor_tell_formatted(int mask, char *fmt, ...){ @@ -674,11 +690,10 @@ int monitor_tell_formatted(int mask, char *fmt, ...){ va_start(ap, fmt); n=vsnprintf(msg, sizeof(msg), fmt, ap); va_end(ap); - monitor_tell_clients(msg, n, mask); - return 0; + return monitor_tell_clients(msg, n, mask); } -static void monitor_interface_change(struct overlay_interface *interface){ +static void monitor_interface_change(struct overlay_interface *interface, unsigned UNUSED(count)){ unsigned i = interface - overlay_interfaces; if (interface->state==INTERFACE_STATE_UP) monitor_tell_formatted(MONITOR_INTERFACE, "\nINTERFACE:%u:%s:UP\n", i, interface->name); diff --git a/overlay_interface.c b/overlay_interface.c index 24d7f58f..97dd6c34 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -97,11 +97,16 @@ void overlay_interface_close(overlay_interface *interface) INFOF("Interface %s addr %s is down", interface->name, alloca_socket_address(&interface->address)); - CALL_TRIGGER(iupdown, interface); - + + unsigned i, count=0; + for (i=0;idestination->transfer_limit.burst_size, interface->destination->transfer_limit.burst_length); - CALL_TRIGGER(iupdown, interface); + unsigned count=0; + for (i=0;ipoll.fd != -1){ + unwatch(alarm); + close(alarm->poll.fd); + DEBUGF(overlayinterfaces, "close(%d)", alarm->poll.fd); + alarm->poll.fd = -1; + } +} +DEFINE_TRIGGER(shutdown, netlink_shutdown); + #else // poll the OS's network interfaces diff --git a/overlay_interface.h b/overlay_interface.h index d78a7567..21af386b 100644 --- a/overlay_interface.h +++ b/overlay_interface.h @@ -126,7 +126,6 @@ int overlay_interface_register(const char *name, struct socket_address *addr, const struct socket_address *netmask, struct socket_address *broadcast); -void overlay_interface_close_all(); overlay_interface * overlay_interface_get_default(); overlay_interface * overlay_interface_find(struct in_addr addr, int return_default); overlay_interface * overlay_interface_find_name_addr(const char *name, struct socket_address *addr); @@ -135,6 +134,6 @@ int overlay_broadcast_ensemble(struct network_destination *destination, struct o void interface_state_html(struct strbuf *b, struct overlay_interface *interface); void overlay_interface_monitor_up(); -DECLARE_TRIGGER(iupdown, struct overlay_interface *); +DECLARE_TRIGGER(iupdown, struct overlay_interface *, unsigned count); #endif // __SERVAL_DNA__OVERLAY_INTERFACE_H diff --git a/overlay_mdp.c b/overlay_mdp.c index 92faa287..184d3522 100644 --- a/overlay_mdp.c +++ b/overlay_mdp.c @@ -224,6 +224,27 @@ static int mdp_bind_socket(const char *name) return sock; } +static void overlay_mdp_shutdown() +{ + if (mdp_sock.poll.fd != -1) { + unwatch(&mdp_sock); + close(mdp_sock.poll.fd); + mdp_sock.poll.fd=-1; + } + if (mdp_sock2.poll.fd != -1) { + unwatch(&mdp_sock2); + close(mdp_sock2.poll.fd); + mdp_sock2.poll.fd=-1; + } + if (mdp_sock2_inet.poll.fd != -1) { + unwatch(&mdp_sock2_inet); + close(mdp_sock2_inet.poll.fd); + mdp_sock2_inet.poll.fd=-1; + } + overlay_mdp_clean_socket_files(); +} +DEFINE_TRIGGER(shutdown, overlay_mdp_shutdown); + int overlay_mdp_setup_sockets() { /* Delete stale socket files from instance directory. */ @@ -1130,7 +1151,7 @@ static void send_route_changed(struct subscriber *subscriber, int UNUSED(prior_r } DEFINE_TRIGGER(link_change, send_route_changed); -static void send_interface_change(struct overlay_interface *interface) +static void send_interface_change(struct overlay_interface *interface, unsigned UNUSED(count)) { struct mdp_header header; bzero(&header, sizeof(header)); diff --git a/overlay_queue.c b/overlay_queue.c index 5c5fd9c8..25911f11 100644 --- a/overlay_queue.c +++ b/overlay_queue.c @@ -27,6 +27,7 @@ #include "str.h" #include "strbuf.h" #include "route_link.h" +#include "server.h" typedef struct overlay_txqueue { struct overlay_frame *first; @@ -103,13 +104,14 @@ overlay_queue_remove(overlay_txqueue *queue, struct overlay_frame *frame){ return next; } -void overlay_queue_release(){ +static void overlay_queue_release(){ unsigned i; for(i=0;iqueue){ + struct transfers *msg = sync_state->queue; + sync_state->queue = msg->next; + clear_transfer(msg); + free(msg); + } +} + +static void free_peer_sync_state(struct subscriber *peer){ + if (sync_tree) + sync_free_peer_state(sync_tree, peer); + + if (!peer->sync_keys_state) + return; + + if (peer->sync_keys_state->connection){ + msp_stop_stream(peer->sync_keys_state->connection); + time_ms_t now = gettime_ms(); + RESCHEDULE(&ALARM_STRUCT(sync_send), now, now, now); + return; + } + + sync_free_transfers(peer->sync_keys_state); + free(peer->sync_keys_state); + peer->sync_keys_state = NULL; +} + static struct transfers **find_and_update_transfer(struct subscriber *peer, struct rhizome_sync_keys *keys_state, const sync_key_t *key, uint8_t state, int rank) { if (rank>0xFF) @@ -499,17 +528,12 @@ void sync_send(struct sched_ent *alarm) DEBUGF(rhizome_sync_keys, "Connection closed %s", alloca_tohex_sid_t(peer->sid)); - // drop all transfer records - while(sync_state->queue){ - struct transfers *msg = sync_state->queue; - sync_state->queue = msg->next; - clear_transfer(msg); - free(msg); - } - + sync_free_transfers(sync_state); + sync_state->connection = NULL; - // eg connection timeout; drop all sync state - if (msp_get_connection_state(connection)& (MSP_STATE_ERROR|MSP_STATE_STOPPED)) + + // connection timeout? drop all sync state + if (sync_tree && msp_get_connection_state(connection) & (MSP_STATE_ERROR|MSP_STATE_STOPPED)) sync_free_peer_state(sync_tree, peer); } @@ -992,8 +1016,9 @@ static int sync_keys_recv(struct internal_mdp_header *header, struct overlay_buf static void sync_neighbour_changed(struct subscriber *neighbour, uint8_t found, unsigned count) { struct sched_ent *alarm = &ALARM_STRUCT(sync_send_keys); - - if (count>0 && is_rhizome_advertise_enabled()){ + int enabled = is_rhizome_advertise_enabled(); + + if (count>0 && enabled){ time_ms_t now = gettime_ms(); if (alarm->alarm == TIME_MS_NEVER_WILL){ DEBUG(rhizome_sync_keys,"Queueing next message now"); @@ -1001,18 +1026,29 @@ static void sync_neighbour_changed(struct subscriber *neighbour, uint8_t found, } }else{ DEBUG(rhizome_sync_keys,"Stop queueing messages"); - RESCHEDULE(alarm, TIME_MS_NEVER_WILL, TIME_MS_NEVER_WILL, TIME_MS_NEVER_WILL); + unschedule(alarm); + unschedule(&ALARM_STRUCT(sync_keys_status)); } - if (!found){ - struct rhizome_sync_keys *sync_state = get_peer_sync_state(neighbour); - // if there's no connection, there shouldn't be any items in the transfer queue - if (sync_state->connection) - msp_stop_stream(sync_state->connection); - } + if (!found || !enabled) + free_peer_sync_state(neighbour); } DEFINE_TRIGGER(nbr_change, sync_neighbour_changed); +static void sync_config_changed(){ + if (!is_rhizome_advertise_enabled()){ + DEBUG(rhizome_sync_keys,"Stop queueing messages"); + unschedule(&ALARM_STRUCT(sync_send_keys)); + unschedule(&ALARM_STRUCT(sync_keys_status)); + + if (sync_tree){ + sync_free_state(sync_tree); + sync_tree = NULL; + } + } +} +DEFINE_TRIGGER(conf_change, sync_config_changed); + static void sync_bundle_add(rhizome_manifest *m) { if (!sync_tree){ diff --git a/route_link.c b/route_link.c index a1befbf0..da41cd2e 100644 --- a/route_link.c +++ b/route_link.c @@ -649,8 +649,7 @@ static void clean_neighbours(time_ms_t now) if (neighbour_count==0){ // clean up the routing table enum_subscribers(NULL, free_subscriber_link_state, NULL); - RESCHEDULE(&ALARM_STRUCT(link_send), - TIME_MS_NEVER_WILL, TIME_MS_NEVER_WILL, TIME_MS_NEVER_WILL); + unschedule(&ALARM_STRUCT(link_send)); } }else{ n_ptr = &n->_next; @@ -1003,6 +1002,8 @@ static void update_alarm(struct __sourceloc __whence, time_ms_t limit) { if (limit == 0) FATALF("limit == 0"); + if (!neighbours) + return; if (ALARM_STRUCT(link_send).alarm>limit){ RESCHEDULE(&ALARM_STRUCT(link_send), limit, limit, limit+20); } @@ -1587,7 +1588,7 @@ void link_explained(struct subscriber *subscriber) update_alarm(__WHENCE__, now + 5); } -static void link_interface_change(struct overlay_interface *UNUSED(interface)) +static void link_interface_change(struct overlay_interface *UNUSED(interface), unsigned UNUSED(count)) { clean_neighbours(gettime_ms()); } diff --git a/serval.h b/serval.h index 7254657b..c3317bb6 100644 --- a/serval.h +++ b/serval.h @@ -248,7 +248,6 @@ int lsif(); int doifaddrs(); int dna_helper_start(); -int dna_helper_shutdown(); int dna_helper_enqueue(struct subscriber *source, mdp_port_t source_port, const char *did); int parseDnaReply(const char *buf, size_t len, char *token, char *did, char *name, char *uri, const char **bufp); @@ -261,7 +260,6 @@ int overlay_send_stun_request(struct subscriber *server, struct subscriber *requ void rhizome_check_connections(struct sched_ent *alarm); int overlay_queue_init(); -void overlay_queue_release(); void monitor_client_poll(struct sched_ent *alarm); void monitor_poll(struct sched_ent *alarm); diff --git a/server.c b/server.c index 6b0ae8b2..ebe20896 100644 --- a/server.c +++ b/server.c @@ -77,6 +77,7 @@ static const char *_server_pidfile_path(struct __sourceloc __whence); static int server_write_proc_state(const char *path, const char *fmt, ...); static int server_get_proc_state(const char *path, char *buff, size_t buff_len); +static void server_stop_alarms(); // Define our own gettid() and tgkill() if doesn't provide them (eg, it does on Android). @@ -303,16 +304,18 @@ int server_bind() void server_loop(time_ms_t (*waiting)(time_ms_t, time_ms_t, time_ms_t), void (*wokeup)()) { + // possible race condition... Shutting down before we even started CALL_TRIGGER(conf_change); - + // This log message is used by tests to wait for the server to start. INFOF("Server initialised, entering main loop"); - + /* Check for activitiy and respond to it */ - while ((serverMode == SERVER_RUNNING) && fd_poll2(waiting, wokeup)) + while (fd_poll2(waiting, wokeup)) ; INFOF("Server finished, exiting main loop"); + fd_showstats(); serverCleanUp(); if (server_pidfd!=-1){ @@ -497,6 +500,11 @@ static int server_get_proc_state(const char *path, char *buff, size_t buff_len) DEFINE_ALARM(server_config_reload); void server_config_reload(struct sched_ent *alarm) { + if (serverMode == SERVER_CLOSING){ + CALL_TRIGGER(shutdown); + return; + } + switch (cf_reload_strict()) { case -1: WARN("server continuing with prior config"); @@ -577,13 +585,13 @@ void server_watchdog(struct sched_ent *alarm) WHY_perror("fork"); break; } - } - if (alarm) { - time_ms_t now = gettime_ms(); - RESCHEDULE(alarm, - now+config.server.watchdog.interval_ms, - now+config.server.watchdog.interval_ms, - now+100); + if (alarm) { + time_ms_t now = gettime_ms(); + RESCHEDULE(alarm, + now+config.server.watchdog.interval_ms, + now+config.server.watchdog.interval_ms, + now+100); + } } } @@ -599,17 +607,14 @@ void rhizome_clean_db(struct sched_ent *alarm) RESCHEDULE(alarm, now + 30*60*1000, TIME_MS_NEVER_WILL, TIME_MS_NEVER_WILL); } -static void server_on_config_change(); - -DEFINE_TRIGGER(conf_change, server_on_config_change); - static void server_on_config_change() { if (!serverMode) return; time_ms_t now = gettime_ms(); - + + // TODO move to their own trigger dna_helper_start(); directory_service_init(); @@ -643,6 +648,7 @@ static void server_on_config_change() rhizome_close_db(); } } +DEFINE_TRIGGER(conf_change, server_on_config_change); static void clean_proc() { @@ -667,16 +673,44 @@ static void clean_proc() } } +void server_close(){ + if (serverMode != SERVER_RUNNING) + return; + + DEBUGF(server,"Graceful shutdown"); + + serverMode = SERVER_CLOSING; + + // trigger an alarm to finish cleanup + time_ms_t now = gettime_ms(); + RESCHEDULE(&ALARM_STRUCT(server_config_reload), + now, + now, + TIME_MS_NEVER_WILL); +} + +static void server_stop_alarms() +{ + DEBUGF(server,"Stopping alarms"); + unschedule(&ALARM_STRUCT(fd_periodicstats)); + unschedule(&ALARM_STRUCT(server_watchdog)); + unschedule(&ALARM_STRUCT(server_config_reload)); + unschedule(&ALARM_STRUCT(rhizome_clean_db)); + unschedule(&ALARM_STRUCT(rhizome_fetch_status)); +} +DEFINE_TRIGGER(shutdown, server_stop_alarms); + static void serverCleanUp() { assert(serverMode != SERVER_NOT_RUNNING); INFOF("Server cleaning up"); - overlay_queue_release(); + + // release alarms, in case we aborted without attempting a graceful close + server_stop_alarms(); + rhizome_close_db(); - dna_helper_shutdown(); - overlay_interface_close_all(); - overlay_mdp_clean_socket_files(); release_my_subscriber(); + serverMode = SERVER_NOT_RUNNING; clean_proc(); } @@ -693,7 +727,7 @@ static void signal_handler(int signum) case SERVER_RUNNING: // Trigger the server to close gracefully after any current alarm has completed. INFOF("Caught signal %s -- attempting clean shutdown", alloca_signal_name(signum)); - serverMode = SERVER_CLOSING; + server_close(); return; case SERVER_CLOSING: // If a second signal is received before the server has gracefully shut down, then forcibly @@ -701,7 +735,8 @@ static void signal_handler(int signum) // serverCleanUp() if the signal was received by the same thread that is running the server, // because serverMode is thread-local. The zero exit status indicates a clean shutdown. So // the "stop" command must send SIGHUP to the correct thread. - WARNF("Caught signal %s -- forced shutdown", alloca_signal_name(signum)); + WHYF("Caught signal %s -- forced shutdown", alloca_signal_name(signum)); + list_alarms(LOG_LEVEL_ERROR); serverCleanUp(); exit(0); case SERVER_NOT_RUNNING: diff --git a/server.h b/server.h index 5a960b9f..ea5bfa87 100644 --- a/server.h +++ b/server.h @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "fdqueue.h" #include "os.h" // for time_ms_t +#include "trigger.h" enum server_mode { SERVER_NOT_RUNNING = 0, @@ -44,8 +45,12 @@ int server_pid(); int server_bind(); +void server_close(); + void server_loop(time_ms_t (*waiting)(time_ms_t, time_ms_t, time_ms_t), void (*wokeup)()); void server_rhizome_add_bundle(uint64_t rowid); +DECLARE_TRIGGER(shutdown); + #endif // __SERVAL_DNA__SERVER_H diff --git a/vomp.c b/vomp.c index 094d6d0e..c1a892ad 100644 --- a/vomp.c +++ b/vomp.c @@ -33,6 +33,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "overlay_address.h" #include "overlay_buffer.h" #include "overlay_packet.h" +#include "server.h" /* Typical call state lifecycle between 2 parties. @@ -572,9 +573,8 @@ static int monitor_call_status(struct vomp_call_state *call) alloca_tohex_sid_t(call->local.subscriber->sid), alloca_tohex_sid_t(call->remote.subscriber->sid), call->local.did,call->remote.did); - - monitor_tell_clients(msg, n, MONITOR_VOMP); - return 0; + + return monitor_tell_clients(msg, n, MONITOR_VOMP); } static int monitor_send_audio(struct vomp_call_state *call, int audio_codec, int time, int sequence, @@ -600,8 +600,7 @@ static int monitor_send_audio(struct vomp_call_state *call, int audio_codec, int bcopy(audio, &msg[msglen], audio_length); msglen+=audio_length; msg[msglen++]='\n'; - monitor_tell_clients(msg, msglen, MONITOR_VOMP); - return 0; + return monitor_tell_clients(msg, msglen, MONITOR_VOMP); } // update local state and notify interested clients with the correct message @@ -776,6 +775,13 @@ static int vomp_call_destroy(struct vomp_call_state *call) return 0; } +static void vomp_shutdown(){ + int i=0; + for(i=vomp_call_count -1; i>=0; i--) + vomp_call_destroy(&vomp_call_states[i]); +} +DEFINE_TRIGGER(shutdown, vomp_shutdown); + int vomp_dial(struct subscriber *local, struct subscriber *remote, const char *local_did, const char *remote_did) { /* TODO use local_did and remote_did start putting the call together. @@ -1083,11 +1089,17 @@ static void vomp_process_tick(struct sched_ent *alarm) struct vomp_call_state *call = (struct vomp_call_state *)alarm; /* See if any calls need to be expired. + if all monitor clients have disconnected Allow vomp.dial_timeout_ms for the other party to ring / request ringing Allow vomp.ring_timeout_ms for the ringing party to answer Allow vomp.network_timeout_ms between received packets */ - + + if (!monitor_client_interested(MONITOR_VOMP)){ + call->rejection_reason=VOMP_REJECT_NOPHONE; + vomp_hangup(call); + } + if ((call->remote.state < VOMP_STATE_RINGINGOUT && call->create_time + config.vomp.dial_timeout_ms < now) || (call->local.state < VOMP_STATE_INCALL && call->create_time + config.vomp.ring_timeout_ms < now) || (call->last_activity+config.vomp.network_timeout_msrejection_reason=VOMP_REJECT_TIMEOUT; vomp_update_local_state(call, VOMP_STATE_CALLENDED); vomp_update_remote_state(call, VOMP_STATE_CALLENDED); - vomp_update(call); } + /* update everyone if the state has changed */ + vomp_update(call); + /* If we are calling ourselves, mdp packets are processed as soon as they are sent. So we can't risk moving call entries around at that time as that will change pointers that are still on the stack. @@ -1110,15 +1124,13 @@ static void vomp_process_tick(struct sched_ent *alarm) return; } - /* update everyone if the state has changed */ - vomp_update(call); /* force a packet to the other party. We are still here */ vomp_send_status_remote(call); - + /* tell local monitor clients the call is still alive */ len = snprintf(msg,sizeof(msg) -1,"\nKEEPALIVE:%06x\n", call->local.session); monitor_tell_clients(msg, len, MONITOR_VOMP); - + alarm->alarm = gettime_ms() + VOMP_CALL_STATUS_INTERVAL; alarm->deadline = alarm->alarm + VOMP_CALL_STATUS_INTERVAL/2; schedule(alarm);