Skip to content

Commit

Permalink
add delay_tunnel_reason and delay_close
Browse files Browse the repository at this point in the history
- As long as the protocol-specific mainloop sets delay_tunnel_reason to a non-NULL value, tunnel
  device creation will be delayed.

- If delay_close is set, mainloop will continue to iterate even if cancel_cmd or pause_cmd is set.

  A protocol should set DELAY_CLOSE_IMMEDIATE_CALLBACK for the case where its mainloop needs an
  immediate callback (e.g. to send some kind of termination request), and DELAY_CLOSE_WAIT for the
  case where its mainloop is waiting to receive something (e.g. a termination acknowledgement).

openconnect_mainloop() will unset both delay_tunnel_reason and delay_close on each iteration. A
protocol mainloop must thus affirmatively extend a delay in order for it to continue.

Signed-off-by: Daniel Lenski <dlenski@gmail.com>
  • Loading branch information
dlenski committed Nov 16, 2020
1 parent ecfc891 commit 4fb6ff7
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 23 deletions.
1 change: 0 additions & 1 deletion dtls.c
Expand Up @@ -712,4 +712,3 @@ void dtls_detect_mtu(struct openconnect_info *vpninfo)
skip_mtu:
free(buf);
}

70 changes: 48 additions & 22 deletions mainloop.c
Expand Up @@ -204,29 +204,34 @@ int openconnect_mainloop(struct openconnect_info *vpninfo,
else
timeout = 1000;

if (vpninfo->dtls_state > DTLS_DISABLED) {
if (!tun_is_up(vpninfo)) {
/* Postpone tun device creation after DTLS is connected so
* we have a better knowledge of the link MTU. We also
* force the creation if DTLS enters sleeping mode - i.e.,
* we failed to connect on time. */
if (!tun_is_up(vpninfo) && (vpninfo->dtls_state == DTLS_CONNECTED ||
vpninfo->dtls_state == DTLS_SLEEPING)) {
ret = setup_tun_device(vpninfo);
if (ret) {
if (ret)
break;
} else if (vpninfo->delay_tunnel_reason) {
vpn_progress(vpninfo, PRG_INFO, _("Delaying tunnel for %d ms with reason: %s\n"),
timeout, vpninfo->delay_tunnel_reason);
/* XX: don't let this spin forever */
vpninfo->delay_tunnel_reason = NULL;
} else {
/* No DTLS, or DTLS failed; setup TUN device unconditionally */
ret = setup_tun_device(vpninfo);
if (ret)
break;
}
}
}

if (vpninfo->dtls_state > DTLS_DISABLED) {
ret = vpninfo->proto->udp_mainloop(vpninfo, &timeout, udp_r);
if (vpninfo->quit_reason)
break;
did_work += ret;

} else if (!tun_is_up(vpninfo)) {
/* No DTLS - setup TUN device unconditionally */
ret = setup_tun_device(vpninfo);
if (ret)
break;
}

ret = vpninfo->proto->tcp_mainloop(vpninfo, &timeout, tcp_r);
Expand All @@ -242,28 +247,49 @@ int openconnect_mainloop(struct openconnect_info *vpninfo,

poll_cmd_fd(vpninfo, 0);
if (vpninfo->got_cancel_cmd) {
if (vpninfo->cancel_type == OC_CMD_CANCEL) {
if (vpninfo->delay_close != NO_DELAY_CLOSE) {
if (vpninfo->delay_close == DELAY_CLOSE_IMMEDIATE_CALLBACK) {
vpn_progress(vpninfo, PRG_DEBUG, _("Delaying cancel (immediate callback).\n"));
did_work++;
} else
vpn_progress(vpninfo, PRG_DEBUG, _("Delaying cancel.\n"));
/* XX: don't let this spin forever */
vpninfo->delay_close = NO_DELAY_CLOSE;
} else if (vpninfo->cancel_type == OC_CMD_CANCEL) {
vpninfo->quit_reason = "Aborted by caller";
vpninfo->got_cancel_cmd = 0;
ret = -EINTR;
break;
} else {
vpninfo->got_cancel_cmd = 0;
ret = -ECONNABORTED;
break;
}
vpninfo->got_cancel_cmd = 0;
break;
}

if (vpninfo->got_pause_cmd) {
/* close all connections and wait for the user to call
openconnect_mainloop() again */
openconnect_close_https(vpninfo, 0);
if (vpninfo->dtls_state > DTLS_DISABLED) {
vpninfo->proto->udp_close(vpninfo);
vpninfo->new_dtls_started = 0;
}
if (vpninfo->delay_close != NO_DELAY_CLOSE) {
/* XX: don't let this spin forever */
if (vpninfo->delay_close == DELAY_CLOSE_IMMEDIATE_CALLBACK) {
vpn_progress(vpninfo, PRG_DEBUG, _("Delaying pause (immediate callback).\n"));
did_work++;
} else
vpn_progress(vpninfo, PRG_DEBUG, _("Delaying pause.\n"));
/* XX: don't let this spin forever */
vpninfo->delay_close = NO_DELAY_CLOSE;
} else {
/* close all connections and wait for the user to call
openconnect_mainloop() again */
openconnect_close_https(vpninfo, 0);
if (vpninfo->dtls_state > DTLS_DISABLED) {
vpninfo->proto->udp_close(vpninfo);
vpninfo->new_dtls_started = 0;
}

vpninfo->got_pause_cmd = 0;
vpn_progress(vpninfo, PRG_INFO, _("Caller paused the connection\n"));
return 0;
vpninfo->got_pause_cmd = 0;
vpn_progress(vpninfo, PRG_INFO, _("Caller paused the connection\n"));
return 0;
}
}

if (did_work)
Expand Down
6 changes: 6 additions & 0 deletions openconnect-internal.h
Expand Up @@ -669,6 +669,12 @@ struct openconnect_info {
char *version_string;

const char *quit_reason;
const char *delay_tunnel_reason; /* If non-null, provides a reason why protocol is not yet ready for tunnel setup */
enum {
NO_DELAY_CLOSE = 0,
DELAY_CLOSE_WAIT,
DELAY_CLOSE_IMMEDIATE_CALLBACK,
} delay_close; /* Delay close of mainloop */

int verbose;
void *cbdata;
Expand Down

0 comments on commit 4fb6ff7

Please sign in to comment.