Commit cef9731fbcd2138888575f6d06df0f84d7156f57

Kano 2012-09-12T07:44:00

CURL support for individual proxy per pool and all proxy types

diff --git a/README b/README
index 1438008..e2a005f 100644
--- a/README
+++ b/README
@@ -168,7 +168,7 @@ Options for both config file and command line:
 --scrypt            Use the scrypt algorithm for mining (litecoin only)
 --sharelog <arg>    Append share log to file
 --shares <arg>      Quit after mining N shares (default: unlimited)
---socks-proxy <arg> Set socks4 proxy (host:port)
+--socks-proxy <arg> Set socks4 proxy (host:port) for all pools without a proxy specified
 --syslog            Use system log for output messages (default: standard error)
 --temp-cutoff <arg> Temperature where a device will be automatically disabled, one value or comma separated list (default: 95)
 --text-only|-T      Disable ncurses formatted screen output
@@ -295,6 +295,28 @@ Add overclocking settings, GPU and fan control with different engine settings fo
 
 cgminer -o http://pool:port -u username -p password -I 9 --auto-fan --auto-gpu --gpu-engine 750-950,945,700-930,960 --gpu-memclock 300
 
+Single pool with a standard http proxy, regular desktop:
+
+cgminer -o http:proxy:port|http://pool:port -u username -p password
+
+Single pool with a socks5 proxy, regular desktop:
+
+cgminer -o socks5:proxy:port|http://pool:port -u username -p password
+
+The list of proxy types are:
+ http:    standard http 1.1 proxy
+ http0:   http 1.0 proxy
+ socks4:  socks4 proxy
+ socks5:  socks5 proxy
+ socks4a: socks4a proxy
+ socks5h: socks5 proxy using a hostname
+
+If you compile cgminer with a version of CURL before 7.19.4 then some of the above will
+not be available. All are available since CURL version 7.19.4
+
+If you specify the --socks-proxy option to cgminer, it will only be applied to all pools
+that don't specify their own proxy setting like above
+
 READ WARNINGS AND DOCUMENTATION BELOW ABOUT OVERCLOCKING
 
 On Linux you virtually always need to export your display settings before
diff --git a/api.c b/api.c
index 4aefcf0..e318518 100644
--- a/api.c
+++ b/api.c
@@ -1841,6 +1841,13 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, 
 		root = api_add_escape(root, "User", pool->rpc_user, false);
 		root = api_add_time(root, "Last Share Time", &(pool->last_share_time), false);
 		root = api_add_int(root, "Diff1 Work", &(pool->diff1), false);
+		if (pool->rpc_proxy) {
+			root = api_add_const(root, "Proxy Type", proxytype(pool->rpc_proxytype), false);
+			root = api_add_escape(root, "Proxy", pool->rpc_proxy, false);
+		} else {
+			root = api_add_const(root, "Proxy Type", BLANK, false);
+			root = api_add_const(root, "Proxy", BLANK, false);
+		}
 
 		if (isjson && (i > 0))
 			strcat(io_buffer, COMMA);
diff --git a/cgminer.c b/cgminer.c
index 69976f3..e1a37a1 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -419,6 +419,8 @@ static struct pool *add_pool(void)
 	/* Make sure the pool doesn't think we've been idle since time 0 */
 	pool->tv_idle.tv_sec = ~0UL;
 
+	pool->rpc_proxy = NULL;
+
 	return pool;
 }
 
@@ -547,6 +549,8 @@ static char *set_url(char *arg)
 		add_pool();
 	pool = pools[total_urls - 1];
 
+	arg = get_proxy(arg, pool);
+
 	opt_set_charp(arg, &pool->rpc_url);
 	if (strncmp(arg, "http://", 7) &&
 	    strncmp(arg, "https://", 8)) {
@@ -4999,6 +5003,8 @@ void add_pool_details(bool live, char *url, char *user, char *pass)
 
 	pool = add_pool();
 
+	url = get_proxy(url, pool);
+
 	pool->rpc_url = url;
 	pool->rpc_user = user;
 	pool->rpc_pass = pass;
diff --git a/miner.h b/miner.h
index 4771176..3167fab 100644
--- a/miner.h
+++ b/miner.h
@@ -592,6 +592,8 @@ extern const uint32_t sha256_init_state[];
 extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
 			     const char *rpc_req, bool, bool, int *,
 			     struct pool *pool, bool);
+extern const char *proxytype(curl_proxytype proxytype);
+extern char *get_proxy(char *url, struct pool *pool);
 extern char *bin2hex(const unsigned char *p, size_t len);
 extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
 
@@ -770,6 +772,8 @@ struct pool {
 	char *rpc_url;
 	char *rpc_userpass;
 	char *rpc_user, *rpc_pass;
+	curl_proxytype rpc_proxytype;
+	char *rpc_proxy;
 
 	pthread_mutex_t pool_lock;
 
diff --git a/util.c b/util.c
index 724ffa9..2786653 100644
--- a/util.c
+++ b/util.c
@@ -305,7 +305,10 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, resp_hdr_cb);
 	curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hi);
 	curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
-	if (opt_socks_proxy) {
+	if (pool->rpc_proxy) {
+		curl_easy_setopt(curl, CURLOPT_PROXY, pool->rpc_proxy);
+		curl_easy_setopt(curl, CURLOPT_PROXYTYPE, pool->rpc_proxytype);
+	} else if (opt_socks_proxy) {
 		curl_easy_setopt(curl, CURLOPT_PROXY, opt_socks_proxy);
 		curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
 	}
@@ -460,6 +463,68 @@ err_out:
 	return NULL;
 }
 
+#if (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 10) || (LIBCURL_VERSION_MAJOR > 7)
+static struct {
+	const char *name;
+	curl_proxytype proxytype;
+} proxynames[] = {
+	{ "http:",	CURLPROXY_HTTP },
+#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR > 19) || (LIBCURL_VERSION_MINOR == 19 && LIBCURL_VERSION_PATCH >= 4)
+	{ "http0:",	CURLPROXY_HTTP_1_0 },
+#endif
+#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR > 15) || (LIBCURL_VERSION_MINOR == 15 && LIBCURL_VERSION_PATCH >= 2)
+	{ "socks4:",	CURLPROXY_SOCKS4 },
+#endif
+	{ "socks5:",	CURLPROXY_SOCKS5 },
+#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MINOR >= 18)
+	{ "socks4a:",	CURLPROXY_SOCKS4A },
+	{ "socks5h:",	CURLPROXY_SOCKS5_HOSTNAME },
+#endif
+};
+#endif
+
+const char *proxytype(curl_proxytype proxytype)
+{
+	int i;
+
+	for (i = 0; proxynames[i].name; i++)
+		if (proxynames[i].proxytype == proxytype)
+			return proxynames[i].name;
+
+	return "invalid";
+}
+
+char *get_proxy(char *url, struct pool *pool)
+{
+	pool->rpc_proxy = NULL;
+
+#if (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 10) || (LIBCURL_VERSION_MAJOR > 7)
+	char *split;
+	int plen, len, i;
+
+	for (i = 0; proxynames[i].name; i++) {
+		plen = strlen(proxynames[i].name);
+		if (strncmp(url, proxynames[i].name, plen) == 0) {
+			if (!(split = strchr(url, '|')))
+				return url;
+
+			*split = '\0';
+			len = split - url;
+			pool->rpc_proxy = malloc(1 + len - plen);
+			if (!(pool->rpc_proxy))
+				quit(1, "Failed to malloc rpc_proxy");
+
+			strcpy(pool->rpc_proxy, url);
+			pool->rpc_proxytype = proxynames[i].proxytype;
+			url = split + 1;
+			break;
+		}
+	}
+#endif
+	return url;
+}
+
+
 char *bin2hex(const unsigned char *p, size_t len)
 {
 	char *s = malloc((len * 2) + 1);