Refactor StartOpenVPN()

- Split starting the status thread and launch of the
daemon process (openvpn.exe) into separate functions.

This is useful for implementing control of persistent connections
where the daemon is launched externally: e.g., by the
automatic service.

Signed-off-by: Selva Nair <selva.nair@gmail.com>
pull/519/head
Selva Nair 2022-07-03 15:34:48 -04:00
parent 552441e407
commit f8a1495667
1 changed files with 51 additions and 37 deletions

View File

@ -67,8 +67,8 @@
extern options_t o; extern options_t o;
static BOOL static BOOL TerminateOpenVPN(connection_t *c);
TerminateOpenVPN(connection_t *c); static BOOL LaunchOpenVPN(connection_t *c);
const TCHAR *cfgProp = _T("conn"); const TCHAR *cfgProp = _T("conn");
@ -1314,21 +1314,6 @@ OnStop(connection_t *c, UNUSED char *msg)
break; break;
case disconnecting: case disconnecting:
// /* Check for "certificate has expired" message */
// if ((strstr(line, "error=certificate has expired") != NULL))
// {
// StopOpenVPN(config);
// /* Cert expired... */
// ShowLocalizedMsg(IDS_ERR_CERT_EXPIRED);
// }
//
// /* Check for "certificate is not yet valid" message */
// if ((strstr(line, "error=certificate is not yet valid") != NULL))
// {
// StopOpenVPN(config);
// /* Cert not yet valid */
// ShowLocalizedMsg(IDS_ERR_CERT_NOT_YET_VALID);
// }
/* Shutdown was initiated by us */ /* Shutdown was initiated by us */
c->failed_psw_attempts = 0; c->failed_psw_attempts = 0;
c->failed_auth_attempts = 0; c->failed_auth_attempts = 0;
@ -2006,12 +1991,18 @@ ThreadOpenVPNStatus(void *p)
_tcsncpy(conn_name, c->config_file, _countof(conn_name)); _tcsncpy(conn_name, c->config_file, _countof(conn_name));
conn_name[_tcslen(conn_name) - _tcslen(o.ext_string) - 1] = _T('\0'); conn_name[_tcslen(conn_name) - _tcslen(o.ext_string) - 1] = _T('\0');
c->state = (c->state == suspended ? resuming : connecting); c->state = ((c->state == suspended) ? resuming : connecting);
/* Create and Show Status Dialog */ /* Create and Show Status Dialog */
c->hwndStatus = CreateLocalizedDialogParam(ID_DLG_STATUS, StatusDialogFunc, (LPARAM) c); c->hwndStatus = CreateLocalizedDialogParam(ID_DLG_STATUS, StatusDialogFunc, (LPARAM) c);
if (!c->hwndStatus) if (!c->hwndStatus)
{
/* kill daemon process if we started it */
SetEvent(c->exit_event);
Cleanup(c);
c->state = disconnected;
return 1; return 1;
}
CheckAndSetTrayIcon(); CheckAndSetTrayIcon();
SetMenuStatus(c, connecting); SetMenuStatus(c, connecting);
@ -2032,7 +2023,9 @@ ThreadOpenVPNStatus(void *p)
wait_event = c->iserv.hEvent; wait_event = c->iserv.hEvent;
} }
else else
{
wait_event = c->hProcess; wait_event = c->hProcess;
}
if (o.silent_connection == 0) if (o.silent_connection == 0)
ShowWindow(c->hwndStatus, SW_SHOW); ShowWindow(c->hwndStatus, SW_SHOW);
@ -2147,20 +2140,10 @@ out:
} }
#endif #endif
/* /* Start a thread to monitor a connection and launch openvpn.exe if required */
* Launch an OpenVPN process and the accompanying thread to monitor it
*/
BOOL BOOL
StartOpenVPN(connection_t *c) StartOpenVPN(connection_t *c)
{ {
TCHAR cmdline[1024];
TCHAR *options = cmdline + 8;
TCHAR exit_event_name[17];
HANDLE hStdInRead = NULL, hStdInWrite = NULL;
HANDLE hNul = NULL, hThread = NULL;
DWORD written;
BOOL retval = FALSE;
CLEAR(c->ip); CLEAR(c->ip);
if (c->hwndStatus) if (c->hwndStatus)
@ -2177,18 +2160,53 @@ StartOpenVPN(connection_t *c)
} }
return FALSE; return FALSE;
} }
else if (c->state != disconnected)
{
return FALSE;
}
PrintDebug(L"Starting openvpn on config %ls", c->config_name); PrintDebug(L"Starting openvpn on config %ls", c->config_name);
RunPreconnectScript(c);
/* Create thread to show the connection's status dialog */ /* Create thread to show the connection's status dialog */
hThread = CreateThread(NULL, 0, ThreadOpenVPNStatus, c, CREATE_SUSPENDED, &c->threadId); HANDLE hThread = CreateThread(NULL, 0, ThreadOpenVPNStatus, c, CREATE_SUSPENDED, &c->threadId);
if (hThread == NULL) if (hThread == NULL)
{ {
ShowLocalizedMsg(IDS_ERR_CREATE_THREAD_STATUS); ShowLocalizedMsg(IDS_ERR_CREATE_THREAD_STATUS);
goto out; return false;
} }
/* Launch openvpn.exe using the service or directly */
if (!LaunchOpenVPN(c))
{
TerminateThread(hThread, 1);
return false;
}
/* Start the status dialog thread */
ResumeThread(hThread);
if (hThread && hThread != INVALID_HANDLE_VALUE)
CloseHandle(hThread);
return true;
}
/*
* Launch an OpenVPN process
*/
static BOOL
LaunchOpenVPN(connection_t *c)
{
TCHAR cmdline[1024];
TCHAR *options = cmdline + 8;
TCHAR exit_event_name[17];
HANDLE hStdInRead = NULL, hStdInWrite = NULL;
HANDLE hNul = NULL;
DWORD written;
BOOL retval = FALSE;
RunPreconnectScript(c);
/* Create an event object to signal OpenVPN to exit */ /* Create an event object to signal OpenVPN to exit */
_sntprintf_0(exit_event_name, _T("%x%08x"), GetCurrentProcessId(), c->threadId); _sntprintf_0(exit_event_name, _T("%x%08x"), GetCurrentProcessId(), c->threadId);
c->exit_event = CreateEvent(NULL, TRUE, FALSE, exit_event_name); c->exit_event = CreateEvent(NULL, TRUE, FALSE, exit_event_name);
@ -2357,13 +2375,9 @@ StartOpenVPN(connection_t *c)
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
} }
/* Start the status dialog thread */
ResumeThread(hThread);
retval = TRUE; retval = TRUE;
out: out:
if (hThread && hThread != INVALID_HANDLE_VALUE)
CloseHandle(hThread);
if (hStdInWrite && hStdInWrite != INVALID_HANDLE_VALUE) if (hStdInWrite && hStdInWrite != INVALID_HANDLE_VALUE)
CloseHandle(hStdInWrite); CloseHandle(hStdInWrite);
if (hStdInRead && hStdInRead != INVALID_HANDLE_VALUE) if (hStdInRead && hStdInRead != INVALID_HANDLE_VALUE)