]> www.infradead.org Git - users/dwmw2/openconnect.git/commitdiff
add delay_tunnel_reason and delay_close
authorDaniel Lenski <dlenski@gmail.com>
Sun, 17 May 2020 00:06:10 +0000 (17:06 -0700)
committerDaniel Lenski <dlenski@gmail.com>
Wed, 20 May 2020 06:31:30 +0000 (23:31 -0700)
- If delay_tunnel_reason is set, mainloop will defer tunnel device creation for one more iteration.

- If delay_close is set, mainloop will continue to iterate even if cancel_cmd or pause_cmd is set.
  - If delay_close==1, we don't set did_work; if >=1 we do.
  - This allows a protocol to set delay_close=2 for the case where its
    mainloop needs an immediate callback to send a termination request, and
    delay_close=1 for the case where a protocol needs to wait for a
    termination acknowledgment.

openconnect_mainloop() decrements delay_close, and set delay_tunnel_reason to NULL, 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>
dtls.c
mainloop.c
openconnect-internal.h

diff --git a/dtls.c b/dtls.c
index ca68fede05f44764ead361cf857f75ef20d25395..5025f6b07d4da319b4fb2fe3f1050c1f8f2cac65 100644 (file)
--- a/dtls.c
+++ b/dtls.c
@@ -712,4 +712,3 @@ void dtls_detect_mtu(struct openconnect_info *vpninfo)
  skip_mtu:
        free(buf);
 }
-
index e58e87a057f227346a2a9f23aa3f788f349dd3dd..e2afe4437c1a265ae223b5690283b608ebfa136e 100644 (file)
@@ -204,7 +204,7 @@ 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.,
@@ -212,21 +212,26 @@ int openconnect_mainloop(struct openconnect_info *vpninfo,
                        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);
@@ -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 > 0) {
+                               if (vpninfo->delay_close > 1) {
+                                       vpn_progress(vpninfo, PRG_DEBUG, _("Delaying cancel in order to send again.\n"));
+                                       did_work++;
+                               } else
+                                       vpn_progress(vpninfo, PRG_DEBUG, _("Delaying cancel for %d ms in order to receive again).\n"), timeout);
+                               /* XX: don't let this spin forever */
+                               --vpninfo->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 > 0) {
+                                /* XX: don't let this spin forever */
+                               if (vpninfo->delay_close > 1) {
+                                       vpn_progress(vpninfo, PRG_DEBUG, _("Delaying cancel (need to send again).\n"));
+                                       did_work++;
+                               } else
+                                       vpn_progress(vpninfo, PRG_DEBUG, _("Delaying cancel (need to receive again).\n"));
+                               /* XX: don't let this spin forever */
+                               --vpninfo->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)
index 92edf763da382092f6724f9eb4ea516103c3a255..fc50de4294a9fda551a73ccb8f0e8d4e2ee15891 100644 (file)
@@ -667,6 +667,8 @@ struct openconnect_info {
        char *version_string;
 
        const char *quit_reason;
+       const char *delay_tunnel_reason;        /* Delay tunnel setup */
+       int delay_close;                        /* Delay close of mainloop (2 for immediate callback, 1 for wait) */
 
        int verbose;
        void *cbdata;