From 7f794eec3d245b614ba4477417243d1f85d83dda Mon Sep 17 00:00:00 2001 From: Selva Nair Date: Thu, 7 Jul 2022 20:49:00 -0400 Subject: [PATCH] Add a button for detaching from the management interface Useful for releasing the management interface if the user wants to connect to it by other means. Detached connections are set to state = detached (no disconnected) and auto_connect disabled, so that they could be handled properly during a re-attach. Signed-off-by: Selva Nair --- main.c | 6 +++--- openvpn-gui-res.h | 1 + openvpn.c | 40 ++++++++++++++++++++++++++++++++++----- options.h | 2 ++ res/openvpn-gui-res-en.rc | 1 + tray.c | 6 +++--- 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/main.c b/main.c index bde0385..34dcfe2 100644 --- a/main.c +++ b/main.c @@ -358,7 +358,7 @@ StopAllOpenVPN() */ for (i = 0; i < o.num_configs; i++) { - if (o.conn[i].state != disconnected) + if (o.conn[i].state != disconnected && o.conn[i].state != detached) { if (o.conn[i].flags & FLAG_DAEMON_PERSISTENT) { @@ -374,7 +374,7 @@ StopAllOpenVPN() /* Wait for all connections to terminate (Max 5 sec) */ for (i = 0; i < 20; i++, Sleep(250)) { - if (CountConnState(disconnected) == o.num_configs) + if (CountConnState(disconnected) + CountConnState(detached) == o.num_configs) break; } } @@ -522,7 +522,7 @@ ManagePersistent(HWND hwnd, UINT UNUSED msg, UINT_PTR id, DWORD UNUSED now) { if (o.conn[i].flags & FLAG_DAEMON_PERSISTENT && o.conn[i].auto_connect - && o.conn[i].state == disconnected) + && (o.conn[i].state == disconnected || o.conn[i].state == detached)) { /* disable auto-connect to avoid repeated re-connect * after unrecoverable errors. Re-enabled on successful diff --git a/openvpn-gui-res.h b/openvpn-gui-res.h index 5cd0353..e4711e3 100644 --- a/openvpn-gui-res.h +++ b/openvpn-gui-res.h @@ -48,6 +48,7 @@ #define ID_RESTART 164 #define ID_HIDE 165 #define ID_TXT_VERSION 166 +#define ID_DETACH 167 #define ID_TXT_BYTECOUNT 168 #define ID_TXT_IP 169 diff --git a/openvpn.c b/openvpn.c index 0747bed..1cd8d32 100644 --- a/openvpn.c +++ b/openvpn.c @@ -140,7 +140,8 @@ void OnHold(connection_t *c, UNUSED char *msg) { EnableWindow(GetDlgItem(c->hwndStatus, ID_RESTART), TRUE); - if ((c->flags & FLAG_DAEMON_PERSISTENT) && (c->state == disconnecting)) + if ((c->flags & FLAG_DAEMON_PERSISTENT) + && (c->state == disconnecting || c->state == resuming)) { /* retain the hold state if we are here while disconnecting */ c->state = onhold; @@ -1343,11 +1344,25 @@ OnStop(connection_t *c, UNUSED char *msg) c->failed_psw_attempts = 0; c->failed_auth_attempts = 0; c->state = disconnected; + if (c->flags & FLAG_DAEMON_PERSISTENT) + { + /* user initiated disconnection -- stay detached and do not auto-reconnect */ + c->state = detached; + c->auto_connect = false; + } CheckAndSetTrayIcon(); SetDlgItemText(c->hwndStatus, ID_TXT_STATUS, LoadLocalizedString(IDS_NFO_STATE_DISCONNECTED)); SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); break; + case onhold: + /* stop triggered while on hold -- possibly the daemon exited. Treat same as detaching */ + case detaching: + c->state = detached; + CheckAndSetTrayIcon(); + SendMessage(c->hwndStatus, WM_CLOSE, 0, 0); + break; + case suspending: c->state = suspended; CheckAndSetTrayIcon(); @@ -1844,6 +1859,7 @@ RenderStatusWindow(HWND hwndDlg, UINT w, UINT h) MoveWindow(GetDlgItem(hwndDlg, ID_TXT_VERSION), w-DPI_SCALE(180), h - DPI_SCALE(55), DPI_SCALE(170), DPI_SCALE(15), TRUE); MoveWindow(GetDlgItem(hwndDlg, ID_DISCONNECT), DPI_SCALE(20), h - DPI_SCALE(30), DPI_SCALE(110), DPI_SCALE(23), TRUE); MoveWindow(GetDlgItem(hwndDlg, ID_RESTART), DPI_SCALE(145), h - DPI_SCALE(30), DPI_SCALE(110), DPI_SCALE(23), TRUE); + MoveWindow(GetDlgItem(hwndDlg, ID_DETACH), DPI_SCALE(270), h - DPI_SCALE(30), DPI_SCALE(110), DPI_SCALE(23), TRUE); MoveWindow(GetDlgItem(hwndDlg, ID_HIDE), w - DPI_SCALE(130), h - DPI_SCALE(30), DPI_SCALE(110), DPI_SCALE(23), TRUE); } @@ -1908,6 +1924,14 @@ StatusDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) rect.top + rand()%100, 0, 0, SWP_NOSIZE); GetClientRect(hwndDlg, &rect); RenderStatusWindow(hwndDlg, rect.right, rect.bottom); + if (c->flags & FLAG_DAEMON_PERSISTENT && o.enable_persistent > 0) + { + EnableWindow(GetDlgItem(hwndDlg, ID_DETACH), TRUE); + } + else + { + ShowWindow(GetDlgItem(hwndDlg, ID_DETACH), SW_HIDE); + } /* Set focus on the LogWindow so it scrolls automatically */ SetFocus(hLogWnd); return FALSE; @@ -1944,6 +1968,11 @@ StatusDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) SetFocus(GetDlgItem(c->hwndStatus, ID_EDT_LOG)); RestartOpenVPN(c); return TRUE; + + case ID_DETACH: + SetFocus(GetDlgItem(c->hwndStatus, ID_EDT_LOG)); + DetachOpenVPN(c); + return TRUE; } break; @@ -1958,7 +1987,7 @@ StatusDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) case WM_CLOSE: c = (connection_t *) GetProp(hwndDlg, cfgProp); - if (c->state != disconnected) + if (c->state != disconnected && c->state != detached) ShowWindow(hwndDlg, SW_HIDE); else DestroyWindow(hwndDlg); @@ -2004,7 +2033,7 @@ StatusDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) case WM_OVPN_DETACH: c = (connection_t *) GetProp(hwndDlg, cfgProp); /* just stop the thread keeping openvpn.exe running */ - c->state = disconnecting; + c->state = detaching; EnableWindow(GetDlgItem(c->hwndStatus, ID_DISCONNECT), FALSE); EnableWindow(GetDlgItem(c->hwndStatus, ID_RESTART), FALSE); OnStop(c, NULL); @@ -2071,7 +2100,7 @@ ThreadOpenVPNStatus(void *p) _tcsncpy(conn_name, c->config_file, _countof(conn_name)); conn_name[_tcslen(conn_name) - _tcslen(o.ext_string) - 1] = _T('\0'); - c->state = ((c->state == suspended) ? resuming : connecting); + c->state = (c->state == suspended || c->state == detached) ? resuming : connecting; /* Create and Show Status Dialog */ c->hwndStatus = CreateLocalizedDialogParam(ID_DLG_STATUS, StatusDialogFunc, (LPARAM) c); @@ -2271,7 +2300,7 @@ StartOpenVPN(connection_t *c) } return FALSE; } - else if (c->state != disconnected) + else if (c->state != disconnected && c->state != detached) { return FALSE; } @@ -2517,6 +2546,7 @@ DetachOpenVPN(connection_t *c) /* currently supported only for persistent connections */ if (c->flags & FLAG_DAEMON_PERSISTENT) { + c->auto_connect = false; PostMessage(c->hwndStatus, WM_OVPN_DETACH, 0, 0); } } diff --git a/options.h b/options.h index f65ed97..cc7248a 100644 --- a/options.h +++ b/options.h @@ -73,6 +73,8 @@ typedef enum { suspending, suspended, resuming, + detaching, + detached, } conn_state_t; /* Interactive Service IO parameters */ diff --git a/res/openvpn-gui-res-en.rc b/res/openvpn-gui-res-en.rc index 7922b97..f22179d 100644 --- a/res/openvpn-gui-res-en.rc +++ b/res/openvpn-gui-res-en.rc @@ -102,6 +102,7 @@ BEGIN LTEXT "", ID_TXT_IP, 20, 160, 300, 10 PUSHBUTTON "&Disconnect", ID_DISCONNECT, 50, 190, 50, 14 PUSHBUTTON "&Reconnect", ID_RESTART, 150, 190, 50, 14 + PUSHBUTTON "De&tach", ID_DETACH, 180, 190, 50, 14, WS_DISABLED PUSHBUTTON "&Hide", ID_HIDE, 100, 190, 50, 14 END diff --git a/tray.c b/tray.c index 31af721..ff05bde 100644 --- a/tray.c +++ b/tray.c @@ -511,11 +511,11 @@ SetMenuStatusById(int i, conn_state_t state) int checked = 0; if (state == connected || state == disconnecting) checked = 1; - else if (state != disconnected) checked = 2; + else if (state != disconnected && state != detached && state != onhold) checked = 2; if (o.num_configs == 1) { - if (state == disconnected) + if (state == disconnected || state == detached) { EnableMenuItem(hMenu, IDM_CONNECTMENU, MF_ENABLED); EnableMenuItem(hMenu, IDM_DISCONNECTMENU, MF_GRAYED); @@ -581,7 +581,7 @@ SetMenuStatusById(int i, conn_state_t state) } } - if (state == disconnected) + if (state == disconnected || state == detached) { EnableMenuItem(hMenuConn[i], IDM_CONNECTMENU, MF_ENABLED); EnableMenuItem(hMenuConn[i], IDM_DISCONNECTMENU, MF_GRAYED);