Browse Source

Bugfix: Hook CURLOPT_DEBUGFUNCTION to count actual bytes sent/received by libcurl

CURLINFO_SIZE_UPLOAD and CURLINFO_SIZE_DOWNLOAD do not reflect the actual number of bytes transferred over the network, but instead post-processed.
Using CURLOPT_DEBUGFUNCTION, we can count the actual bytes being sent/received on the network.
Luke Dashjr 13 years ago
parent
commit
50152024eb
1 changed files with 44 additions and 14 deletions
  1. 44 14
      util.c

+ 44 - 14
util.c

@@ -261,6 +261,36 @@ static void set_nettime(void)
 	wr_unlock(&netacc_lock);
 }
 
+static int my_curl_debug(__maybe_unused CURL *curl, curl_infotype infotype, char *data, size_t datasz, void *userdata)
+{
+	struct pool *pool = userdata;
+
+	switch (infotype) {
+		case CURLINFO_TEXT:
+		{
+			if (!opt_protocol)
+				break;
+			// data is not null-terminated, so we need to copy and terminate it for applog
+			char datacp[datasz + 1];
+			memcpy(datacp, data, datasz);
+			datacp[datasz] = '\0';
+			applog(LOG_DEBUG, "Pool %u: %s", pool->pool_no, datacp);
+			break;
+		}
+		case CURLINFO_HEADER_IN:
+		case CURLINFO_DATA_IN:
+			pool->cgminer_pool_stats.bytes_received += datasz;
+			break;
+		case CURLINFO_HEADER_OUT:
+		case CURLINFO_DATA_OUT:
+			pool->cgminer_pool_stats.bytes_sent += datasz;
+			break;
+		default:
+			break;
+	}
+	return 0;
+}
+
 json_t *json_rpc_call(CURL *curl, const char *url,
 		      const char *userpass, const char *rpc_req,
 		      bool probe, bool longpoll, int *rolltime,
@@ -275,7 +305,6 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 	struct upload_buffer upload_data;
 	json_t *val, *err_val, *res_val;
 	bool probing = false;
-	double byte_count;
 	json_error_t err;
 	int rc;
 
@@ -287,10 +316,6 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 		probing = !pool->probed;
 	curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
 
-#if 0 /* Disable curl debugging since it spews to stderr */
-	if (opt_protocol)
-		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
-#endif
 	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
 	curl_easy_setopt(curl, CURLOPT_URL, url);
 	curl_easy_setopt(curl, CURLOPT_ENCODING, "");
@@ -308,6 +333,13 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
 	curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, resp_hdr_cb);
 	curl_easy_setopt(curl, CURLOPT_HEADERDATA, &hi);
+
+	/* We use DEBUGFUNCTION to count bytes sent/received, and verbose is needed
+	 * to enable it */
+	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+	curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_curl_debug);
+	curl_easy_setopt(curl, CURLOPT_DEBUGDATA, pool);
+
 	curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
 	if (pool->rpc_proxy) {
 		curl_easy_setopt(curl, CURLOPT_PROXY, pool->rpc_proxy);
@@ -386,11 +418,7 @@ json_t *json_rpc_call(CURL *curl, const char *url,
 	}
 
 	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 (probing) {
 		pool->probed = true;
@@ -1324,7 +1352,6 @@ bool initiate_stratum(struct pool *pool)
 	char curl_err_str[CURL_ERROR_SIZE];
 	char s[RBUFSIZE], *sret = NULL;
 	CURL *curl = NULL;
-	double byte_count;
 	json_error_t err;
 	bool ret = false;
 
@@ -1348,6 +1375,13 @@ bool initiate_stratum(struct pool *pool)
 	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
 	curl_easy_setopt(curl, CURLOPT_URL, s);
 	curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
+
+	/* We use DEBUGFUNCTION to count bytes sent/received, and verbose is needed
+	 * to enable it */
+	curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
+	curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_curl_debug);
+	curl_easy_setopt(curl, CURLOPT_DEBUGDATA, pool);
+
 	curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
 	if (pool->rpc_proxy) {
 		curl_easy_setopt(curl, CURLOPT_PROXY, pool->rpc_proxy);
@@ -1365,11 +1399,7 @@ bool initiate_stratum(struct pool *pool)
 	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;
 
 	sprintf(s, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": []}", swork_id++);