Commit 31aa4f6cebc51e26b349606fd78d71954bda87da

Con Kolivas 2013-05-08T21:59:58

Use raw sockets without curl for stratum communications.

diff --git a/miner.h b/miner.h
index 94c6207..7690f14 100644
--- a/miner.h
+++ b/miner.h
@@ -13,6 +13,9 @@
 #include "uthash.h"
 #include "logging.h"
 #include "util.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
 
 #ifdef HAVE_OPENCL
 #ifdef __APPLE_CC__
@@ -1104,7 +1107,7 @@ struct pool {
 	/* Stratum variables */
 	char *stratum_url;
 	char *stratum_port;
-	CURL *stratum_curl;
+	struct addrinfo stratum_hints;
 	SOCKETTYPE sock;
 	char *sockbuf;
 	size_t sockbuf_size;
diff --git a/util.c b/util.c
index 0cc14da..944cc8e 100644
--- a/util.c
+++ b/util.c
@@ -199,23 +199,6 @@ out:
 	return ptrlen;
 }
 
-#if CURL_HAS_KEEPALIVE
-static void keep_curlalive(CURL *curl)
-{
-	const int tcp_keepidle = 45;
-	const int tcp_keepintvl = 30;
-	const long int keepalive = 1;
-
-	curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, keepalive);
-	curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, tcp_keepidle);
-	curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, tcp_keepintvl);
-}
-
-static void keep_alive(CURL *curl, __maybe_unused SOCKETTYPE fd)
-{
-	keep_curlalive(curl);
-}
-#else
 static void keep_sockalive(SOCKETTYPE fd)
 {
 	const int tcp_keepidle = 45;
@@ -234,6 +217,18 @@ static void keep_sockalive(SOCKETTYPE fd)
 # endif /* __APPLE_CC__ */
 }
 
+#if CURL_HAS_KEEPALIVE
+static void keep_curlalive(CURL *curl)
+{
+	const int tcp_keepidle = 45;
+	const int tcp_keepintvl = 30;
+	const long int keepalive = 1;
+
+	curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, keepalive);
+	curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, tcp_keepidle);
+	curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, tcp_keepintvl);
+}
+#else
 static void keep_curlalive(CURL *curl)
 {
 	SOCKETTYPE sock;
@@ -241,11 +236,6 @@ static void keep_curlalive(CURL *curl)
 	curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&sock);
 	keep_sockalive(sock);
 }
-
-static void keep_alive(CURL __maybe_unused *curl, SOCKETTYPE fd)
-{
-	keep_sockalive(fd);
-}
 #endif
 
 static void last_nettime(struct timeval *last)
@@ -1043,11 +1033,13 @@ static void clear_sock(struct pool *pool)
 {
 	ssize_t n;
 
-	mutex_lock(&pool->stratum_lock);
-	do {
-		n = recv(pool->sock, pool->sockbuf, RECVSIZE, 0);
-	} while (n > 0);
-	mutex_unlock(&pool->stratum_lock);
+	if (socket_full(pool, false)) {
+		mutex_lock(&pool->stratum_lock);
+		do {
+			n = recv(pool->sock, pool->sockbuf, RECVSIZE, 0);
+		} while (n > 0);
+		mutex_unlock(&pool->stratum_lock);
+	}
 
 	clear_sockbuf(pool);
 }
@@ -1496,70 +1488,59 @@ out:
 	return ret;
 }
 
-static bool setup_stratum_curl(struct pool *pool)
+static bool setup_stratum_socket(struct pool *pool)
 {
-	char curl_err_str[CURL_ERROR_SIZE];
-	CURL *curl = NULL;
-	double byte_count;
-	char s[RBUFSIZE];
+	struct addrinfo *servinfo, *hints, *p;
+	int sockd;
 
 	mutex_lock(&pool->stratum_lock);
 	pool->stratum_active = false;
-	if (pool->stratum_curl) {
-		/* See above in suspend_stratum */
+	if (pool->sock)
 		CLOSESOCKET(pool->sock);
-	}
-	pool->stratum_curl = curl_easy_init();
-	if (unlikely(!pool->stratum_curl))
-		quit(1, "Failed to curl_easy_init in initiate_stratum");
+	pool->sock = 0;
 	mutex_unlock(&pool->stratum_lock);
 
-	curl = pool->stratum_curl;
-
-	if (!pool->sockbuf) {
-		pool->sockbuf = calloc(RBUFSIZE, 1);
-		if (!pool->sockbuf)
-			quit(1, "Failed to calloc pool sockbuf in initiate_stratum");
-		pool->sockbuf_size = RBUFSIZE;
+	hints = &pool->stratum_hints;
+	memset(hints, 0, sizeof(struct addrinfo));
+	hints->ai_family = AF_UNSPEC;
+	hints->ai_socktype = SOCK_STREAM;
+	if (getaddrinfo(pool->sockaddr_url, pool->stratum_port, hints, &servinfo) != 0) {
+		applog(LOG_WARNING, "Failed to getaddrinfo on %s:%s",
+		       pool->sockaddr_url, pool->stratum_port);
+		return false;
 	}
 
-	/* Create a http url for use with curl */
-	sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port);
+	for (p = servinfo; p != NULL; p = p->ai_next) {
+		sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
+		if (sockd == -1) {
+			applog(LOG_DEBUG, "Failed socket");
+			continue;
+		}
 
-	curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
-	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
-	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
-	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
-	curl_easy_setopt(curl, CURLOPT_URL, s);
-	if (!opt_delaynet)
-		curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
-	curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
-	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);
+		if (connect(sockd, p->ai_addr, p->ai_addrlen) == -1) {
+			CLOSESOCKET(sockd);
+			applog(LOG_DEBUG, "Failed connect");
+			continue;
+		}
+
+		break;
 	}
-	curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1);
-	if (curl_easy_perform(curl)) {
-		applog(LOG_INFO, "Stratum connect failed to pool %d: %s",
-		       pool->pool_no, curl_err_str);
-		/* Hopefully we can just clean this curl handle up properly */
-		curl_easy_cleanup(curl);
-		pool->stratum_curl = NULL;
+	freeaddrinfo(servinfo);
+	if (p == NULL) {
+		applog(LOG_WARNING, "Failed to find servinfo on %s:%s",
+		       pool->sockaddr_url, pool->stratum_port);
 		return false;
 	}
-	curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&pool->sock);
-	keep_alive(curl, pool->sock);
 
-	pool->cgminer_pool_stats.times_sent++;
-	if (curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &byte_count) == CURLE_OK)
-		pool->cgminer_pool_stats.bytes_sent += byte_count;
-	pool->cgminer_pool_stats.times_received++;
-	if (curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &byte_count) == CURLE_OK)
-		pool->cgminer_pool_stats.bytes_received += byte_count;
+	if (!pool->sockbuf) {
+		pool->sockbuf = calloc(RBUFSIZE, 1);
+		if (!pool->sockbuf)
+			quit(1, "Failed to calloc pool sockbuf in initiate_stratum");
+		pool->sockbuf_size = RBUFSIZE;
+	}
 
+	pool->sock = sockd;
+	keep_sockalive(sockd);
 	return true;
 }
 
@@ -1598,13 +1579,9 @@ void suspend_stratum(struct pool *pool)
 
 	mutex_lock(&pool->stratum_lock);
 	pool->stratum_active = pool->stratum_notify = false;
-	if (pool->stratum_curl) {
-		/* libcurl seems to crash occasionally on this since so just
-		 * sacrifice the ram knowing we leak one curl handle every
-		 * time we disconnect stratum. */
+	if (pool->sock)
 		CLOSESOCKET(pool->sock);
-	}
-	pool->stratum_curl = NULL;
+	pool->sock = 0;
 	mutex_unlock(&pool->stratum_lock);
 }
 
@@ -1617,7 +1594,7 @@ bool initiate_stratum(struct pool *pool)
 	int n2size;
 
 resend:
-	if (!setup_stratum_curl(pool)) {
+	if (!setup_stratum_socket(pool)) {
 		sockd = false;
 		goto out;
 	}