Notify clients about server's restart/shutdown
PATCH 1/1 Notify clients about server's restart/shutdown
When server gets shutdown signal (SIGUSR1, SIGTERM, SIGHUP, SIGINT), it broadcasts new OCC_SHUTTING_DOWN command to all clients and reschedules received signal in 2 secs.
When client receives OCC_SHUTTING_DOWN, it fires SIGUSR1 and switches to the next remote.
--- src/openvpn/multi.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/openvpn/multi.h | 14 +++++++++++- src/openvpn/occ.c | 8 +++++++ src/openvpn/occ.h | 6 +++++ 4 files changed, 86 insertions(+), 5 deletions(-)
src/openvpn/multi.c +59 -4
@@ -396,6 +396,8 @@ multi_init (struct multi_context *m, struct context *t, bool tcp_mode, int threa t->options.stale_routes_check_interval, t->options.stale_routes_ageing_time);event_timeout_init (&m->stale_routes_check_et, t->options.stale_routes_check_interval,0 ); } + + m->deferred_signal.signal_received =0 ; } const char *
@@ -603,6 +605,25 @@ multi_close_instance (struct multi_context *m,perf_pop (); } +void +multi_broadcast_shutdown (struct multi_context *m) +{ +msg (D_LOW ,"multi_broadcast_shutdown" ); + +struct gc_arena gc =gc_new (); +struct buffer buf =alloc_buf_gc (BUF_SIZE (&m->top.c2.frame), &gc); + +buf_init (&buf,FRAME_HEADROOM (&m->top.c2.frame)); +buf_safe (&buf,MAX_RW_SIZE_TUN (&m->top.c2.frame)); +buf_write (&buf, occ_magic,OCC_STRING_SIZE ); + +buf_write_u8 (&buf,OCC_SHUTTING_DOWN ); + +multi_bcast (m, &buf,NULL ,NULL ); + +gc_free (&gc); +} +/* * Called on shutdown or restart. */
@@ -1952,7 +1973,7 @@ multi_unicast (struct multi_context *m,/* * Broadcast a packet to all clients. */ -static void +void multi_bcast (struct multi_context *m, const struct buffer *buf, const struct multi_instance *sender_instance,
@@ -2571,10 +2592,18 @@ multi_process_timeout (struct multi_context *m, const unsigned int mpp_flags)/* instance marked for wakeup? */ if (m->earliest_wakeup) { -set_prefix (m->earliest_wakeup); - ret =multi_process_post (m, m->earliest_wakeup, mpp_flags); +if (m->earliest_wakeup == (struct multi_instance *)&m->deferred_signal) + { +schedule_remove_entry (m->schedule, (struct schedule_entry *) &m->deferred_signal); +throw_signal (m->deferred_signal.signal_received); + } +else + { +set_prefix (m->earliest_wakeup); + ret =multi_process_post (m, m->earliest_wakeup, mpp_flags); +clear_prefix (); + } m->earliest_wakeup =NULL ; -clear_prefix (); }return ret; }
@@ -2699,6 +2728,10 @@ multi_top_free (struct multi_context *m)free_context_buffers (m->top.c2.buffers); } +bool is_shutdown_signal (int sig) { +return (sig ==SIGUSR1 || sig ==SIGTERM || sig ==SIGHUP || sig ==SIGINT ); +} +/* * Return true if event loop should break, * false if it should continue.
@@ -2714,6 +2747,28 @@ multi_process_signal (struct multi_context *m) m->top.sig->signal_received =0 ;return false; } +else if (proto_is_dgram (m->top.options.ce.proto) && +is_shutdown_signal (m->top.sig->signal_received) && + (m->deferred_signal.signal_received ==0 )) + { +// broadcast OCC_SHUTTING_DOWN to all connected clients +multi_broadcast_shutdown (m); + +// schedule signal +openvpn_gettimeofday (&m->deferred_signal.wakeup,NULL ); +struct timeval tv; + tv.tv_sec =2 ; + tv.tv_usec =0 ; +tv_add (&m->deferred_signal.wakeup, &tv); + + m->deferred_signal.signal_received = m->top.sig->signal_received; + +schedule_add_entry (m->schedule, (struct schedule_entry *) &m->deferred_signal, + &m->deferred_signal.wakeup,compute_wakeup_sigma (&m->deferred_signal.wakeup)); + + m->top.sig->signal_received =0 ; +return false; + }return true; }
src/openvpn/multi.h +13 -1
@@ -57,6 +57,13 @@ struct multi_reap }; +struct deferred_signal_schedule_entry +{ +struct schedule_entry se; +int signal_received; +struct timeval wakeup; +}; +/** * Server-mode state structure for one single VPN tunnel. *
@@ -172,6 +179,8 @@ struct multi_context {* Timer object for stale route check */ struct event_timeout stale_routes_check_et; + +struct deferred_signal_schedule_entry deferred_signal; };/*
@@ -190,7 +199,6 @@ struct multi_routetime_t last_reference; }; -/**************************************************************************/ /** * Main event loop for OpenVPN in server mode.
@@ -290,6 +298,10 @@ bool multi_process_post (struct multi_context *m, struct multi_instance *mi, conbool multi_process_incoming_link (struct multi_context *m,struct multi_instance *instance,const unsigned int mpp_flags); +void multi_bcast (struct multi_context *m,const struct buffer *buf, +const struct multi_instance *sender_instance, +const struct mroute_addr *sender_addr); +/** * Determine the destination VPN tunnel of a packet received over the * virtual tun/tap network interface and then process it accordingly.
src/openvpn/occ.c +8 -0
@@ -390,6 +390,14 @@ process_received_occ_msg (struct context *c) c->sig->signal_received =SIGTERM ; c->sig->signal_text ="remote-exit" ;break ; + +case OCC_SHUTTING_DOWN : +msg (D_LOW ,"RECEIVED OCC_SHUTTING_DOWN" ); + c->sig->signal_received =SIGUSR1 ; + c->sig->signal_text ="remote-shutdown" ; + c->options.no_advance = false; +break ; + } c->c2.buf.len =0 ;/* don't pass packet on */ }
src/openvpn/occ.h +6 -0
@@ -69,6 +69,12 @@*/ #define OCC_EXIT 6 + +/* +* Notifies clients that server is shutting down +*/ +#define OCC_SHUTTING_DOWN 7 +/* * Used to conduct a load test command sequence * of UDP connection for empirical MTU measurement.
Signature · 1 line
1.9.1