- client: Second pass through the automatic proxy detection code.

During the first pass we learned that the whole process of
        proxy detection on Win XP machines could take a few seconds
        even with no proxies to be detected, now the proxy detection
        code is executed in the same thread that is monitoring for
        power change events.
        
    client/
        cs_cmdline.cpp
        http_curl.cpp
        http_curl.h
        http_curl_win.h
        net_stats.cpp
        sysmon_win.cpp, .h
    lib/
        parse.cpp, .h
        proxy_info.cpp, .h

svn path=/trunk/boinc/; revision=18819
This commit is contained in:
Rom Walton 2009-08-07 18:16:21 +00:00
parent 66bf71e4e1
commit 16156838c5
12 changed files with 418 additions and 263 deletions

View File

@ -6770,3 +6770,23 @@ Charlie 7 Aug 2009
ViewWork.cpp,.h
lib/
gui_rpc_client_ops.cpp
Rom 7 Aug 2009
- client: Second pass through the automatic proxy detection code.
During the first pass we learned that the whole process of
proxy detection on Win XP machines could take a few seconds
even with no proxies to be detected, now the proxy detection
code is executed in the same thread that is monitoring for
power change events.
client/
cs_cmdline.cpp
http_curl.cpp
http_curl.h
http_curl_win.h
net_stats.cpp
sysmon_win.cpp, .h
lib/
parse.cpp, .h
proxy_info.cpp, .h

View File

@ -237,7 +237,8 @@ void CLIENT_STATE::parse_cmdline(int argc, char** argv) {
#undef ARGX2
void CLIENT_STATE::parse_env_vars() {
char *p, temp[256];
char *p;
std::string temp;
int proto;
p = getenv("HTTP_PROXY");
@ -248,10 +249,10 @@ void CLIENT_STATE::parse_env_vars() {
p = getenv("HTTP_USER_NAME");
if (p) {
proxy_info.use_http_auth = true;
safe_strcpy(proxy_info.http_user_name, p);
proxy_info.http_user_name = p;
p = getenv("HTTP_USER_PASSWD");
if (p) {
safe_strcpy(proxy_info.http_user_passwd, p);
proxy_info.http_user_passwd = p;
}
}
@ -276,12 +277,12 @@ void CLIENT_STATE::parse_env_vars() {
p = getenv("SOCKS5_USER");
if (!p) p = getenv("SOCKS_USER");
if (p) {
safe_strcpy(proxy_info.socks5_user_name, p);
proxy_info.socks5_user_name = p;
}
p = getenv("SOCKS5_PASSWD");
if (p) {
safe_strcpy(proxy_info.socks5_user_passwd, p);
proxy_info.socks5_user_passwd = p;
}
}

View File

@ -45,16 +45,11 @@
#include "base64.h"
#include "client_state.h"
#include "http_curl.h"
#ifdef _WIN32
#include "win_util.h"
#include "http_curl_win.h"
#endif
using std::min;
using std::vector;
static CURLM* g_curlMulti = NULL;
static char g_user_agent_string[256] = {""};
static const char g_content_type[] = {"Content-Type: application/x-www-form-urlencoded"};
@ -64,7 +59,7 @@ static const char g_content_type[] = {"Content-Type: application/x-www-form-urle
// [http[s]://]host.dom.dom[:port][/dir/file]
// [socks]://]host.dom.dom[:port][/dir/file]
//
void parse_url(const char* url, int &protocol, char* host, int &port, char* file) {
void parse_url(const char* url, int &protocol, std::string& host, int &port, std::string& file) {
char* p;
char buf[256];
@ -87,11 +82,11 @@ void parse_url(const char* url, int &protocol, char* host, int &port, char* file
// parse and strip off file part if present
//
p = strchr(buf, '/');
if (p && file) {
strcpy(file, p+1);
if (p) {
file = p+1;
*p = 0;
} else if (file) {
strcpy(file, "");
} else {
file.clear();
}
// parse and strip off port if present
@ -109,14 +104,15 @@ void parse_url(const char* url, int &protocol, char* host, int &port, char* file
// what remains is the host
//
strcpy(host, buf);
host = buf;
}
void get_user_agent_string() {
char* get_user_agent_string() {
sprintf(g_user_agent_string, "BOINC client (%s %d.%d.%d)",
gstate.get_primary_platform(),
BOINC_MAJOR_VERSION, BOINC_MINOR_VERSION, BOINC_RELEASE
);
return (char*)&g_user_agent_string;
}
void HTTP_OP::init() {
@ -258,9 +254,9 @@ bool HTTP_OP::no_proxy_for_url(const char* url) {
if (log_flags.proxy_debug) {
msg_printf(0, MSG_INFO, "[proxy_debug] HTTP_OP::no_proxy_for_url(): %s", url);
}
char hosturl[256];
char hostnoproxy[256];
char file[256];
std::string hosturl;
std::string file;
std::string hostnoproxy;
char noproxy[256];
int protocol;
int port;
@ -270,14 +266,14 @@ bool HTTP_OP::no_proxy_for_url(const char* url) {
// tokenize the noproxy-entry and check for identical hosts
//
strcpy(noproxy, pi.noproxy_hosts);
char* token = strtok(noproxy,",");
strcpy(noproxy, pi.noproxy_hosts.c_str());
char* token = strtok(noproxy, ",");
while(token!= NULL) {
// extract the host from the no_proxy url
parse_url(token, protocol, hostnoproxy, port, file);
if (!strcmp(hostnoproxy, hosturl)) {
if (hostnoproxy == hosturl) {
if (log_flags.proxy_debug) {
msg_printf(0, MSG_INFO, "[proxy_debug] disabling proxy for %s",url);
msg_printf(0, MSG_INFO, "[proxy_debug] disabling proxy for %s", url);
}
return true;
}
@ -286,7 +282,6 @@ bool HTTP_OP::no_proxy_for_url(const char* url) {
if (log_flags.proxy_debug) {
msg_printf(0, MSG_INFO, "[proxy_debug] returning false");
}
return false;
}
@ -648,21 +643,7 @@ int HTTP_OP_SET::nops() {
int HTTP_OP::set_proxy(PROXY_INFO *new_pi) {
pi.use_http_proxy = new_pi->use_http_proxy;
strcpy(pi.http_user_name, new_pi->http_user_name);
strcpy(pi.http_user_passwd, new_pi->http_user_passwd);
strcpy(pi.http_server_name, new_pi->http_server_name);
pi.http_server_port = new_pi->http_server_port;
pi.use_http_auth = new_pi->use_http_auth;
strcpy(pi.noproxy_hosts, new_pi->noproxy_hosts);
pi.use_socks_proxy = new_pi->use_socks_proxy;
strcpy(pi.socks5_user_name, new_pi->socks5_user_name);
strcpy(pi.socks5_user_passwd, new_pi->socks5_user_passwd);
strcpy(pi.socks_server_name, new_pi->socks_server_name);
pi.socks_server_port = new_pi->socks_server_port;
pi.socks_version = new_pi->socks_version;
pi = *new_pi;
return 0;
}
@ -804,20 +785,6 @@ int libcurl_debugfunction(
}
// PROXY_INFO pi useful members:
// pi.http_server_name
// pi.http_server_port
// pi.http_user_name
// pi.http_user_passwd
// pi.socks5_user_name
// pi.socks5_user_passwd
// pi.socks_server_name
// pi.socks_server_port
// pi.socks_version
// pi.use_http_auth
// pi.use_http_proxy
// pi.use_socks_proxy
//
// Curl self-explanatory setopt params for proxies:
// CURLOPT_HTTPPROXYTUNNEL
// CURLOPT_PROXYTYPE (pass in CURLPROXY_HTTP or CURLPROXY_SOCKS5)
@ -830,101 +797,39 @@ int libcurl_debugfunction(
void HTTP_OP::setup_proxy_session(bool no_proxy) {
CURLcode curlErr;
// CMC Note: the string szCurlProxyUserPwd must remain in memory
// CMC Note: the string m_curl_user_credentials must remain in memory
// outside of this method (libcurl relies on it later when it makes
// the proxy connection), so it has been placed as a member data for HTTP_OP
//
strcpy(szCurlProxyUserPwd, "");
strcpy(m_curl_user_credentials, "");
if (no_proxy) {
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, "");
return;
}
#ifdef _WIN32
if (!pi.autodetect_server_name.empty()) {
// Windows provides an API on Windows 2000 or higher to auto detect
// the need for proxy servers using the WPAD and PAC standards.
//
HMODULE hModWinHttp = LoadLibrary("winhttp.dll");
if (hModWinHttp) {
pfnWinHttpOpen pWinHttpOpen =
(pfnWinHttpOpen)GetProcAddress(hModWinHttp, "WinHttpOpen");
pfnWinHttpCloseHandle pWinHttpCloseHandle =
(pfnWinHttpCloseHandle)(GetProcAddress(hModWinHttp, "WinHttpCloseHandle"));
pfnWinHttpGetProxyForUrl pWinHttpGetProxyForUrl =
(pfnWinHttpGetProxyForUrl)(GetProcAddress(hModWinHttp, "WinHttpGetProxyForUrl"));
if (pWinHttpOpen && pWinHttpCloseHandle && pWinHttpGetProxyForUrl) {
HINTERNET hWinHttp = NULL;
WINHTTP_AUTOPROXY_OPTIONS autoproxy_options;
WINHTTP_PROXY_INFO proxy_info;
int proxy_protocol = 0;
memset(&autoproxy_options, 0, sizeof(autoproxy_options));
memset(&proxy_info, 0, sizeof(proxy_info));
hWinHttp = pWinHttpOpen(
A2W(std::string(g_user_agent_string)).c_str(),
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
NULL
if (log_flags.proxy_debug) {
msg_printf(0, MSG_INFO,
"[proxy_debug] HTTP_OP::setup_proxy_session(): setting up automatic proxy %s:%d",
pi.autodetect_server_name, pi.autodetect_server_port
);
autoproxy_options.dwFlags =
WINHTTP_AUTOPROXY_AUTO_DETECT;
autoproxy_options.dwAutoDetectFlags =
WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
autoproxy_options.fAutoLogonIfChallenged = TRUE;
if (pWinHttpGetProxyForUrl(
hWinHttp, A2W(std::string(m_url)).c_str(), &autoproxy_options, &proxy_info
)
) {
std::string proxy(W2A(std::wstring(proxy_info.lpszProxy)));
if (!proxy.empty()) {
// Trim string if more than one proxy is defined
// proxy list is defined as:
// ([<scheme>=][<scheme>"://"]<server>[":"<port>])
proxy.erase(proxy.find(';'));
proxy.erase(proxy.find(' '));
parse_url(proxy.c_str(), proxy_protocol, pi.autodetect_server_name, pi.autodetect_server_port, NULL);
if (log_flags.proxy_debug) {
msg_printf(0, MSG_INFO,
"[proxy_debug] HTTP_OP::setup_proxy_session(): setting up automatic proxy %s:%d",
pi.autodetect_server_name, pi.autodetect_server_port
);
}
switch(proxy_protocol) {
case URL_PROTOCOL_SOCKS:
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
break;
case URL_PROTOCOL_HTTP:
case URL_PROTOCOL_HTTPS:
default:
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
break;
}
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.autodetect_server_port);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.autodetect_server_name);
}
// Clean up
if (proxy_info.lpszProxy) GlobalFree(proxy_info.lpszProxy);
if (proxy_info.lpszProxyBypass) GlobalFree(proxy_info.lpszProxyBypass);
}
if (hWinHttp) pWinHttpCloseHandle(hWinHttp);
}
FreeLibrary(hModWinHttp);
}
#endif
switch(pi.autodetect_server_protocol) {
case URL_PROTOCOL_SOCKS:
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
break;
case URL_PROTOCOL_HTTP:
case URL_PROTOCOL_HTTPS:
default:
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
break;
}
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.autodetect_server_port);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.autodetect_server_name.c_str());
}
if (pi.use_http_proxy) {
@ -938,7 +843,7 @@ void HTTP_OP::setup_proxy_session(bool no_proxy) {
// setup a basic http proxy
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.http_server_port);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.http_server_name);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.http_server_name.c_str());
if (pi.use_http_auth) {
if (config.force_auth == "basic") {
@ -952,8 +857,8 @@ void HTTP_OP::setup_proxy_session(bool no_proxy) {
} else {
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
}
sprintf(szCurlProxyUserPwd, "%s:%s", pi.http_user_name, pi.http_user_passwd);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYUSERPWD, szCurlProxyUserPwd);
sprintf(m_curl_user_credentials, "%s:%s", pi.http_user_name, pi.http_user_passwd);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYUSERPWD, m_curl_user_credentials);
}
} else if (pi.use_socks_proxy) {
@ -963,16 +868,16 @@ void HTTP_OP::setup_proxy_session(bool no_proxy) {
//
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.socks_server_port);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.socks_server_name);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.socks_server_name.c_str());
// libcurl uses blocking sockets with socks proxy, so limit timeout.
// - imlemented with local patch to libcurl
curlErr = curl_easy_setopt(curlEasy, CURLOPT_CONNECTTIMEOUT, 20L);
if (
strlen(pi.socks5_user_passwd)>0 || strlen(pi.socks5_user_name)>0
pi.socks5_user_passwd.length()>0 || pi.socks5_user_name.length()>0
) {
sprintf(szCurlProxyUserPwd, "%s:%s", pi.socks5_user_name, pi.socks5_user_passwd);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYUSERPWD, szCurlProxyUserPwd);
sprintf(m_curl_user_credentials, "%s:%s", pi.socks5_user_name.c_str(), pi.socks5_user_passwd.c_str());
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYUSERPWD, m_curl_user_credentials);
curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_ANY & ~CURLAUTH_NTLM);
}
}

View File

@ -64,7 +64,7 @@ public:
/// string needed for ssl support
char m_curl_ca_bundle_location[256];
/// string needed for proxy username/password
char szCurlProxyUserPwd[128];
char m_curl_user_credentials[128];
int content_length;
double file_offset;
@ -201,6 +201,7 @@ public:
#define URL_PROTOCOL_HTTPS 2
#define URL_PROTOCOL_SOCKS 3
extern void parse_url(const char* url, int &protocol, char* host, int &port, char* file);
extern char* get_user_agent_string();
extern void parse_url(const char* url, int &protocol, std::string& host, int &port, std::string& file);
#endif //__HTTP_H

View File

@ -18,71 +18,4 @@
#ifndef _HTTP_CURL_WIN_
#define _HTTP_CURL_WIN_
// Originally from WinHttp.h
// Which is not included in the VS 2005 platform SDK
typedef LPVOID HINTERNET;
typedef struct {
DWORD dwAccessType; // see WINHTTP_ACCESS_* types below
LPWSTR lpszProxy; // proxy server list
LPWSTR lpszProxyBypass; // proxy bypass list
} WINHTTP_PROXY_INFO, * LPWINHTTP_PROXY_INFO;
typedef struct {
DWORD dwFlags;
DWORD dwAutoDetectFlags;
LPCWSTR lpszAutoConfigUrl;
LPVOID lpvReserved;
DWORD dwReserved;
BOOL fAutoLogonIfChallenged;
} WINHTTP_AUTOPROXY_OPTIONS;
typedef struct {
BOOL fAutoDetect;
LPWSTR lpszAutoConfigUrl;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
extern "C" {
typedef HINTERNET (WINAPI * pfnWinHttpOpen)
(
IN LPCWSTR pwszUserAgent,
IN DWORD dwAccessType,
IN LPCWSTR pwszProxyName OPTIONAL,
IN LPCWSTR pwszProxyBypass OPTIONAL,
IN DWORD dwFlags
);
typedef BOOL (STDAPICALLTYPE * pfnWinHttpCloseHandle)
(
IN HINTERNET hInternet
);
typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetProxyForUrl)
(
IN HINTERNET hSession,
IN LPCWSTR lpcwszUrl,
IN WINHTTP_AUTOPROXY_OPTIONS * pAutoProxyOptions,
OUT WINHTTP_PROXY_INFO * pProxyInfo
);
typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetIEProxyConfig)
(
IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig
);
} // extern "C"
#define WINHTTP_AUTOPROXY_AUTO_DETECT 0x00000001
#define WINHTTP_AUTOPROXY_CONFIG_URL 0x00000002
#define WINHTTP_AUTOPROXY_RUN_INPROCESS 0x00010000
#define WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY 0x00020000
#define WINHTTP_AUTO_DETECT_TYPE_DHCP 0x00000001
#define WINHTTP_AUTO_DETECT_TYPE_DNS_A 0x00000002
#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY 0
#define WINHTTP_ACCESS_TYPE_NO_PROXY 1
#define WINHTTP_ACCESS_TYPE_NAMED_PROXY 3
#define WINHTTP_NO_PROXY_NAME NULL
#define WINHTTP_NO_PROXY_BYPASS NULL
#endif // _HTTP_CURL_WIN

View File

@ -218,6 +218,10 @@ int LOOKUP_WEBSITE_OP::do_rpc(string& url) {
error_num = retval;
net_status.need_physical_connection = true;
net_status.last_comm_time = 0;
// Check for a proxy
gstate.proxy_info.detect_autoproxy_settings();
msg_printf(0, MSG_USER_ERROR,
"BOINC can't access Internet - check network connection or proxy configuration."
);

View File

@ -21,12 +21,11 @@
#include "str_util.h"
#include "str_replace.h"
#include "util.h"
#include "unix_util.h"
#include "win_util.h"
#include "prefs.h"
#include "filesys.h"
#include "network.h"
#include "client_state.h"
#include "file_names.h"
#include "log_flags.h"
#include "client_msgs.h"
#include "http_curl.h"
@ -37,6 +36,7 @@
static HANDLE g_hWindowsMonitorSystemThread = NULL;
static DWORD g_WindowsMonitorSystemThreadID = NULL;
static HWND g_hWndWindowsMonitorSystem = NULL;
// The following 3 functions are called in a separate thread,
@ -70,7 +70,7 @@ static void resume_client() {
}
// Process console messages sent by the system
static BOOL WINAPI ConsoleControlHandler( DWORD dwCtrlType ){
static BOOL WINAPI console_control_handler( DWORD dwCtrlType ){
BOOL bReturnStatus = FALSE;
BOINCTRACE("***** Console Event Detected *****\n");
switch( dwCtrlType ){
@ -96,11 +96,110 @@ static BOOL WINAPI ConsoleControlHandler( DWORD dwCtrlType ){
return bReturnStatus;
}
// Detect any proxy configuration settings automatically.
static void windows_detect_autoproxy_settings() {
HMODULE hModWinHttp = LoadLibrary("winhttp.dll");
if (hModWinHttp) {
pfnWinHttpOpen pWinHttpOpen =
(pfnWinHttpOpen)GetProcAddress(hModWinHttp, "WinHttpOpen");
pfnWinHttpCloseHandle pWinHttpCloseHandle =
(pfnWinHttpCloseHandle)(GetProcAddress(hModWinHttp, "WinHttpCloseHandle"));
pfnWinHttpGetProxyForUrl pWinHttpGetProxyForUrl =
(pfnWinHttpGetProxyForUrl)(GetProcAddress(hModWinHttp, "WinHttpGetProxyForUrl"));
if (pWinHttpOpen && pWinHttpCloseHandle && pWinHttpGetProxyForUrl) {
HINTERNET hWinHttp = NULL;
WINHTTP_AUTOPROXY_OPTIONS autoproxy_options;
WINHTTP_PROXY_INFO proxy_info;
int proxy_protocol = 0;
std::string proxy_server;
int proxy_port = 0;
std::string proxy_file;
memset(&autoproxy_options, 0, sizeof(autoproxy_options));
memset(&proxy_info, 0, sizeof(proxy_info));
hWinHttp = pWinHttpOpen(
A2W(std::string(get_user_agent_string())).c_str(),
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
NULL
);
autoproxy_options.dwFlags =
WINHTTP_AUTOPROXY_AUTO_DETECT;
autoproxy_options.dwAutoDetectFlags =
WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
autoproxy_options.fAutoLogonIfChallenged = TRUE;
if (pWinHttpGetProxyForUrl(
hWinHttp, A2W(config.network_test_url).c_str(), &autoproxy_options, &proxy_info
)
) {
std::string proxy(W2A(std::wstring(proxy_info.lpszProxy)));
if (!proxy.empty()) {
// Trim string if more than one proxy is defined
// proxy list is defined as:
// ([<scheme>=][<scheme>"://"]<server>[":"<port>])
proxy.erase(proxy.find(';'));
proxy.erase(proxy.find(' '));
parse_url(
proxy.c_str(),
proxy_protocol,
proxy_server,
proxy_port,
proxy_file
);
// Store the results for future use.
gstate.proxy_info.set_autoproxy_settings(
proxy_protocol,
proxy_server,
proxy_port
);
}
// Clean up
if (proxy_info.lpszProxy) GlobalFree(proxy_info.lpszProxy);
if (proxy_info.lpszProxyBypass) GlobalFree(proxy_info.lpszProxyBypass);
} else {
// We can get here if the user is switching from a network that
// requires a proxy to one that does not require a proxy.
gstate.proxy_info.set_autoproxy_settings(
0,
std::string(""),
0
);
}
if (hWinHttp) pWinHttpCloseHandle(hWinHttp);
}
FreeLibrary(hModWinHttp);
}
}
// Trap events on Windows so we can clean ourselves up.
static LRESULT CALLBACK WindowsMonitorSystemWndProc(
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
) {
switch(uMsg) {
// Process Timer Events
case WM_TIMER:
switch(wParam) {
// System Monitor 1 second timer
case 1:
if (gstate.proxy_info.should_detect_autoproxy_settings()) {
windows_detect_autoproxy_settings();
}
default:
break;
}
break;
// On Windows power events are broadcast via the WM_POWERBROADCAST
// window message. It has the following parameters:
// PBT_APMQUERYSUSPEND
@ -143,6 +242,10 @@ static LRESULT CALLBACK WindowsMonitorSystemWndProc(
// System is resuming from a normal power event
case PBT_APMRESUMESUSPEND:
msg_printf(NULL, MSG_INFO, "Windows is resuming operations");
// Check for a proxy
gstate.proxy_info.detect_autoproxy_settings();
resume_client();
break;
}
@ -155,7 +258,6 @@ static LRESULT CALLBACK WindowsMonitorSystemWndProc(
// Create a thread to monitor system events
static DWORD WINAPI WindowsMonitorSystemThread( LPVOID ) {
HWND hwndMain;
WNDCLASS wc;
MSG msg;
@ -171,12 +273,12 @@ static DWORD WINAPI WindowsMonitorSystemThread( LPVOID ) {
wc.lpszClassName = "BOINCWindowsMonitorSystem";
if (!RegisterClass(&wc)) {
fprintf(stderr, "Failed to register the WindowsMonitorSystem window class.\n");
log_message_error("Failed to register the WindowsMonitorSystem window class.");
return 1;
}
/* Create an invisible window */
hwndMain = CreateWindow(
g_hWndWindowsMonitorSystem = CreateWindow(
wc.lpszClassName,
"BOINC Monitor System",
WS_OVERLAPPEDWINDOW & ~WS_VISIBLE,
@ -189,11 +291,18 @@ static DWORD WINAPI WindowsMonitorSystemThread( LPVOID ) {
NULL,
NULL);
if (!hwndMain) {
fprintf(stderr, "Failed to create the WindowsMonitorSystem window.\n");
if (!g_hWndWindowsMonitorSystem) {
log_message_error("Failed to create the WindowsMonitorSystem window.");
return 0;
}
if (!SetTimer(g_hWndWindowsMonitorSystem, 1, 1000, NULL)) {
log_message_error("Failed to create the WindowsMonitorSystem timer.");
}
// Check for a proxy at startup
gstate.proxy_info.detect_autoproxy_settings();
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
@ -205,7 +314,7 @@ static DWORD WINAPI WindowsMonitorSystemThread( LPVOID ) {
int initialize_system_monitor(int /*argc*/, char** /*argv*/) {
// Windows: install console controls
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleControlHandler, TRUE)){
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)console_control_handler, TRUE)){
log_message_error("Failed to register the console control handler.");
return ERR_IO;
}
@ -224,6 +333,7 @@ int initialize_system_monitor(int /*argc*/, char** /*argv*/) {
if (!g_hWindowsMonitorSystemThread) {
g_hWindowsMonitorSystemThread = NULL;
g_WindowsMonitorSystemThreadID = NULL;
g_hWndWindowsMonitorSystem = NULL;
}
return 0;
@ -232,6 +342,8 @@ int initialize_system_monitor(int /*argc*/, char** /*argv*/) {
// Cleanup the system event monitor
int cleanup_system_monitor() {
KillTimer(g_hWndWindowsMonitorSystem, 1);
if (g_WindowsMonitorSystemThreadID) {
PostThreadMessage(g_WindowsMonitorSystemThreadID, WM_QUIT, 0, 0);
WaitForSingleObject(g_hWindowsMonitorSystemThread, 10000);
@ -241,6 +353,7 @@ int cleanup_system_monitor() {
CloseHandle(g_hWindowsMonitorSystemThread);
g_hWindowsMonitorSystemThread = NULL;
g_WindowsMonitorSystemThreadID = NULL;
g_hWndWindowsMonitorSystem = NULL;
}
return 0;

View File

@ -18,8 +18,6 @@
#ifndef _SYSMON_WIN_H
#define _SYSMON_WIN_H
#if defined(_WIN32) && defined(_CONSOLE)
#ifdef __cplusplus
extern "C" {
#endif
@ -51,10 +49,72 @@ extern VOID LogEventErrorMessage(LPTSTR lpszMsg);
extern VOID LogEventWarningMessage(LPTSTR lpszMsg);
extern VOID LogEventInfoMessage(LPTSTR lpszMsg);
// Originally from WinHttp.h
// Which is not included in the VS 2005 platform SDK
typedef LPVOID HINTERNET;
typedef struct {
DWORD dwAccessType; // see WINHTTP_ACCESS_* types below
LPWSTR lpszProxy; // proxy server list
LPWSTR lpszProxyBypass; // proxy bypass list
} WINHTTP_PROXY_INFO, * LPWINHTTP_PROXY_INFO;
typedef struct {
DWORD dwFlags;
DWORD dwAutoDetectFlags;
LPCWSTR lpszAutoConfigUrl;
LPVOID lpvReserved;
DWORD dwReserved;
BOOL fAutoLogonIfChallenged;
} WINHTTP_AUTOPROXY_OPTIONS;
typedef struct {
BOOL fAutoDetect;
LPWSTR lpszAutoConfigUrl;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
typedef HINTERNET (WINAPI * pfnWinHttpOpen)
(
IN LPCWSTR pwszUserAgent,
IN DWORD dwAccessType,
IN LPCWSTR pwszProxyName OPTIONAL,
IN LPCWSTR pwszProxyBypass OPTIONAL,
IN DWORD dwFlags
);
typedef BOOL (STDAPICALLTYPE * pfnWinHttpCloseHandle)
(
IN HINTERNET hInternet
);
typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetProxyForUrl)
(
IN HINTERNET hSession,
IN LPCWSTR lpcwszUrl,
IN WINHTTP_AUTOPROXY_OPTIONS * pAutoProxyOptions,
OUT WINHTTP_PROXY_INFO * pProxyInfo
);
typedef BOOL (STDAPICALLTYPE * pfnWinHttpGetIEProxyConfig)
(
IN OUT WINHTTP_CURRENT_USER_IE_PROXY_CONFIG * pProxyConfig
);
#define WINHTTP_AUTOPROXY_AUTO_DETECT 0x00000001
#define WINHTTP_AUTOPROXY_CONFIG_URL 0x00000002
#define WINHTTP_AUTOPROXY_RUN_INPROCESS 0x00010000
#define WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY 0x00020000
#define WINHTTP_AUTO_DETECT_TYPE_DHCP 0x00000001
#define WINHTTP_AUTO_DETECT_TYPE_DNS_A 0x00000002
#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY 0
#define WINHTTP_ACCESS_TYPE_NO_PROXY 1
#define WINHTTP_ACCESS_TYPE_NAMED_PROXY 3
#define WINHTTP_NO_PROXY_NAME NULL
#define WINHTTP_NO_PROXY_BYPASS NULL
#ifdef __cplusplus
}
#endif
#endif
#endif

View File

@ -370,6 +370,12 @@ void xml_escape(const char* in, char* out, int len) {
// output buffer need not be larger than input
//
void xml_unescape(string& in) {
char buf[2048];
xml_unescape(in.c_str(), buf, sizeof(buf));
in = buf;
}
void xml_unescape(const char* in, char* out, int len) {
char* p = out;
while (*in) {

View File

@ -114,6 +114,7 @@ extern bool remove_element(char* buf, const char* start, const char* end);
extern bool str_replace(char* str, const char* old, const char* neww);
extern char* sgets(char* buf, int len, char* &in);
extern void xml_escape(const char*, char*, int len);
extern void xml_unescape(std::string&);
extern void xml_unescape(const char*, char*, int len);
extern void extract_venue(const char*, const char*, char*);
extern int skip_unrecognized(char* buf, MIOFILE&);

View File

@ -25,42 +25,109 @@
#include <string>
#endif
using std::string;
#include "parse.h"
#include "error_numbers.h"
#include "proxy_info.h"
int PROXY_INFO::parse(MIOFILE& in) {
char buf[1024];
string s5un, s5up, hun, hup, temp;
memset(this, 0, sizeof(PROXY_INFO));
while (in.fgets(buf, 256)) {
PROXY_INFO::PROXY_INFO() {
clear();
#ifdef _WIN32
autodetect_mutex = CreateMutex(NULL, FALSE, NULL);
#endif
}
PROXY_INFO::~PROXY_INFO() {
#ifdef _WIN32
if (autodetect_mutex) CloseHandle(autodetect_mutex);
#endif
}
bool PROXY_INFO::get_autoproxy_settings(
int& server_protocol, std::string& server_name, int& server_port
) {
bool retval = false;
#ifdef _WIN32
// Request ownership of mutex.
DWORD result = WaitForSingleObject(autodetect_mutex, 1000);
if (result == WAIT_OBJECT_0) {
#endif
server_protocol = autodetect_server_protocol;
server_name = autodetect_server_name;
server_port = autodetect_server_port;
retval = true;
#ifdef _WIN32
}
ReleaseMutex(autodetect_mutex);
#endif
return retval;
}
bool PROXY_INFO::set_autoproxy_settings(
int server_protocol, std::string server_name, int server_port
) {
bool retval = false;
#ifdef _WIN32
// Request ownership of mutex.
DWORD result = WaitForSingleObject(autodetect_mutex, 1000);
if (result == WAIT_OBJECT_0) {
#endif
autodetect_server_protocol = server_protocol;
autodetect_server_name = server_name;
autodetect_server_port = server_port;
autodetect_proxy_settings = false;
retval = true;
#ifdef _WIN32
}
ReleaseMutex(autodetect_mutex);
#endif
return retval;
}
int PROXY_INFO::parse(MIOFILE& in) {
char buf[2048];
clear();
while (in.fgets(buf, 2048)) {
if (match_tag(buf, "</proxy_info>")) return 0;
else if (parse_bool(buf, "use_http_proxy", use_http_proxy)) continue;
else if (parse_bool(buf, "use_socks_proxy", use_socks_proxy)) continue;
else if (parse_bool(buf, "use_http_auth", use_http_auth)) continue;
else if (parse_int(buf, "<socks_version>", socks_version)) continue;
else if (parse_str(buf, "<socks_server_name>", socks_server_name, sizeof(socks_server_name))) continue;
else if (parse_str(buf, "<socks_server_name>", socks_server_name)) continue;
else if (parse_int(buf, "<socks_server_port>", socks_server_port)) continue;
else if (parse_str(buf, "<http_server_name>", http_server_name, sizeof(http_server_name))) continue;
else if (parse_str(buf, "<http_server_name>", http_server_name)) continue;
else if (parse_int(buf, "<http_server_port>", http_server_port)) continue;
else if (parse_str(buf, "<socks5_user_name>", socks5_user_name,sizeof(socks5_user_name))) continue;
else if (parse_str(buf, "<socks5_user_passwd>", socks5_user_passwd,sizeof(socks5_user_passwd))) continue;
else if (parse_str(buf, "<http_user_name>", http_user_name,sizeof(http_user_name))) continue;
else if (parse_str(buf, "<http_user_passwd>", http_user_passwd,sizeof(http_user_passwd))) continue;
else if (parse_str(buf, "<no_proxy>", noproxy_hosts, sizeof(noproxy_hosts))) continue;
else if (parse_str(buf, "<socks5_user_name>", socks5_user_name)) {
xml_unescape(socks5_user_name);
continue;
}
else if (parse_str(buf, "<socks5_user_passwd>", socks5_user_passwd)) {
xml_unescape(socks5_user_passwd);
continue;
}
else if (parse_str(buf, "<http_user_name>", http_user_name)) {
xml_unescape(http_user_name);
continue;
}
else if (parse_str(buf, "<http_user_passwd>", http_user_passwd)) {
xml_unescape(http_user_passwd);
continue;
}
else if (parse_str(buf, "<no_proxy>", noproxy_hosts)) continue;
}
return ERR_XML_PARSE;
}
int PROXY_INFO::write(MIOFILE& out) {
char s5un[2048], s5up[2048], hun[2048], hup[2048];
xml_escape(socks5_user_name, s5un, sizeof(s5un));
xml_escape(socks5_user_passwd, s5up, sizeof(s5up));
xml_escape(http_user_name, hun, sizeof(hun));
xml_escape(http_user_passwd, hup, sizeof(hup));
xml_escape(socks5_user_name.c_str(), s5un, sizeof(s5un));
xml_escape(socks5_user_passwd.c_str(), s5up, sizeof(s5up));
xml_escape(http_user_name.c_str(), hun, sizeof(hun));
xml_escape(http_user_passwd.c_str(), hup, sizeof(hup));
out.printf(
"<proxy_info>\n"
"%s"
@ -81,15 +148,15 @@ int PROXY_INFO::write(MIOFILE& out) {
use_socks_proxy?" <use_socks_proxy/>\n":"",
use_http_auth?" <use_http_auth/>\n":"",
socks_version,
socks_server_name,
socks_server_name.c_str(),
socks_server_port,
http_server_name,
http_server_name.c_str(),
http_server_port,
s5un,
s5up,
hun,
hup,
noproxy_hosts
noproxy_hosts.c_str()
);
return 0;
}
@ -98,18 +165,48 @@ void PROXY_INFO::clear() {
use_http_proxy = false;
use_socks_proxy = false;
use_http_auth = false;
strcpy(socks_server_name, "");
strcpy(http_server_name, "");
socks_server_name.clear();
http_server_name.clear();
socks_server_port = 80;
http_server_port = 80;
strcpy(socks5_user_name, "");
strcpy(socks5_user_passwd, "");
strcpy(http_user_name, "");
strcpy(http_user_passwd, "");
socks5_user_name.clear();
socks5_user_passwd.clear();
http_user_name.clear();
http_user_passwd.clear();
socks_version = 0;
strcpy(autodetect_server_name, "");
autodetect_server_protocol = 0;
autodetect_server_name.clear();
autodetect_server_port = 80;
strcpy(noproxy_hosts, "");
noproxy_hosts.clear();
}
PROXY_INFO& PROXY_INFO::operator=(const PROXY_INFO& new_pi) {
#ifdef _WIN32
// Request ownership of mutex.
DWORD result = WaitForSingleObject(autodetect_mutex, 1000);
if (result == WAIT_OBJECT_0) {
#endif
use_http_proxy = new_pi.use_http_proxy;
use_socks_proxy = new_pi.use_socks_proxy;
use_http_auth = new_pi.use_http_auth;
socks_server_name = new_pi.socks_server_name;
http_server_name = new_pi.http_server_name;
socks_server_port = new_pi.socks_server_port;
http_server_port = new_pi.http_server_port;
socks5_user_name = new_pi.socks5_user_name;
socks5_user_passwd = new_pi.socks5_user_passwd;
http_user_name = new_pi.http_user_name;
http_user_passwd = new_pi.http_user_passwd;
socks_version = new_pi.socks_version;
autodetect_server_protocol = new_pi.autodetect_server_protocol;
autodetect_server_name = new_pi.autodetect_server_name;
autodetect_server_port = new_pi.autodetect_server_port;
noproxy_hosts = new_pi.noproxy_hosts;
#ifdef _WIN32
}
ReleaseMutex(autodetect_mutex);
#endif
return *this;
}
const char *BOINC_RCSID_af13db88e5 = "$Id$";

View File

@ -20,30 +20,44 @@
#include "miofile.h"
struct PROXY_INFO {
class PROXY_INFO {
public:
PROXY_INFO();
~PROXY_INFO();
bool use_http_proxy;
bool use_http_auth;
char http_server_name[256];
std::string http_server_name;
int http_server_port;
char http_user_name[256];
char http_user_passwd[256];
std::string http_user_name;
std::string http_user_passwd;
bool use_socks_proxy;
int socks_version;
char socks_server_name[256];
std::string socks_server_name;
int socks_server_port;
char socks5_user_name[256];
char socks5_user_passwd[256];
std::string socks5_user_name;
std::string socks5_user_passwd;
char noproxy_hosts[256];
std::string noproxy_hosts;
char autodetect_server_name[256];
int autodetect_server_protocol;
std::string autodetect_server_name;
int autodetect_server_port;
bool autodetect_proxy_settings;
#ifdef _WIN32
HANDLE autodetect_mutex;
#endif
void detect_autoproxy_settings() { autodetect_proxy_settings = true; }
bool should_detect_autoproxy_settings() { return autodetect_proxy_settings; }
bool get_autoproxy_settings(int& server_protocol, std::string& server_name, int& server_port);
bool set_autoproxy_settings(int server_protocol, std::string server_name, int server_port);
int parse(MIOFILE&);
int write(MIOFILE&);
void clear();
PROXY_INFO& operator=(const PROXY_INFO&);
};
#endif