Browse Source

Merge commit '8fd149e' into stratum

Luke Dashjr 13 years ago
parent
commit
b21f3459da
4 changed files with 141 additions and 1 deletions
  1. 2 0
      miner.c
  2. 4 0
      miner.h
  3. 134 1
      util.c
  4. 1 0
      util.h

+ 2 - 0
miner.c

@@ -665,6 +665,8 @@ static char *set_url(char *arg)
 	if (!extract_sockaddr(pool, arg))
 		return "Failed to extract address from parsed url";
 
+	initiate_stratum(pool);
+
 	opt_set_charp(arg, &pool->rpc_url);
 	if (strncmp(arg, "http://", 7) &&
 	    strncmp(arg, "https://", 8)) {

+ 4 - 0
miner.h

@@ -896,8 +896,12 @@ struct pool {
 	struct cgminer_stats cgminer_stats;
 	struct cgminer_pool_stats cgminer_pool_stats;
 
+	/* Stratum variables */
 	SOCKETTYPE sock;
 	struct sockaddr_in *server, client;
+	char *subscription;
+	char *nonce1;
+	int nonce2;
 };
 
 #define GETWORK_MODE_TESTPOOL 'T'

+ 134 - 1
util.c

@@ -779,7 +779,7 @@ bool extract_sockaddr(struct pool *pool, char *url)
 	char *url_begin, *url_end, *port_start;
 	char *url_address, *port;
 	struct addrinfo hints, *res;
-	size_t url_len, port_len = 0;
+	int url_len, port_len = 0;
 
 	url_begin = strstr(url, "//");
 	if (!url_begin)
@@ -823,3 +823,136 @@ bool extract_sockaddr(struct pool *pool, char *url)
 	pool->server = (struct sockaddr_in *)res->ai_addr;
 	return true;
 }
+
+static bool sock_send(int sock, char *s, ssize_t len)
+{
+	ssize_t sent = 0;
+
+	while (len > 0 ) {
+		sent = send(sock, s + sent, len, 0);
+		if (SOCKETFAIL(sent))
+			return false;
+		len -= sent;
+	}
+	fsync(sock);
+
+	return true;
+}
+
+#define RECVSIZE 8192
+
+bool initiate_stratum(struct pool *pool)
+{
+	json_t *val, *res_val, *err_val, *notify_val;
+	char *s, *buf, *sret = NULL;
+	struct timeval timeout;
+	json_error_t err;
+	bool ret = false;
+	ssize_t len;
+	fd_set rd;
+
+	s = alloca(RECVSIZE);
+	sprintf(s, "{\"id\": 0, \"method\": \"mining.subscribe\", \"params\": []}\n");
+
+	pool->sock = socket(AF_INET, SOCK_STREAM, 0);
+	if (pool->sock == INVSOCK)
+		quit(1, "Failed to create pool socket in initiate_stratum");
+	if (SOCKETFAIL(connect(pool->sock, (struct sockaddr *)pool->server, sizeof(struct sockaddr)))) {
+		applog(LOG_DEBUG, "Failed to connect socket to pool");
+		goto out;
+	}
+
+	if (!sock_send(pool->sock, s, strlen(s))) {
+		applog(LOG_DEBUG, "Failed to send s in initiate_stratum");
+		goto out;
+	}
+
+	/* Use select to timeout instead of waiting forever for a response */
+	FD_ZERO(&rd);
+	FD_SET(pool->sock, &rd);
+	timeout.tv_sec = 60;
+	if (select(pool->sock + 1, &rd, NULL, NULL, &timeout) < 1) {
+		applog(LOG_DEBUG, "Timed out waiting for response in initiate_stratum");
+		goto out;
+	}
+
+	if (SOCKETFAIL(recv(pool->sock, s, RECVSIZE, MSG_PEEK | MSG_DONTWAIT))) {
+		applog(LOG_DEBUG, "Failed to recv sock in initiate_stratum");
+		goto out;
+	}
+
+	sret = strtok(s, "\n");
+	if (!sret) {
+		applog(LOG_DEBUG, "Failed to parse a \\n terminated string in initiate_stratum");
+		goto out;
+	}
+
+	/* We know how much data is in the buffer so this read should not fail */
+	len = strlen(sret);
+	read(pool->sock, s, len);
+
+	val = JSON_LOADS(s, &err);
+	if (!val) {
+		applog(LOG_DEBUG, "JSON decode failed(%d): %s", err.line, err.text);
+		goto out;
+	}
+
+	res_val = json_object_get(val, "result");
+	err_val = json_object_get(val, "error");
+
+	if (!res_val || json_is_null(res_val) ||
+	    (err_val && !json_is_null(err_val))) {
+		char *ss;
+
+		if (err_val)
+			ss = json_dumps(err_val, JSON_INDENT(3));
+		else
+			ss = strdup("(unknown reason)");
+
+		applog(LOG_INFO, "JSON-RPC call failed: %s", ss);
+
+		free(ss);
+
+		goto out;
+	}
+
+	notify_val = json_array_get(res_val, 0);
+	if (!notify_val || json_is_null(notify_val)) {
+		applog(LOG_WARNING, "Failed to parse notify_val in initiate_stratum");
+		goto out;
+	}
+
+	buf = (char *)json_string_value(json_array_get(notify_val, 0));
+	if (!buf || strcasecmp(buf, "mining.notify")) {
+		applog(LOG_WARNING, "Failed to get mining notify in initiate_stratum");
+		goto out;
+	}
+	pool->subscription = (char *)json_string_value(json_array_get(notify_val, 1));
+	if (!pool->subscription) {
+		applog(LOG_WARNING, "Failed to get a subscription in initiate_stratum");
+		goto out;
+	}
+
+	pool->nonce1 = (char *)json_string_value(json_array_get(res_val, 1));
+	if (!pool->nonce1) {
+		applog(LOG_WARNING, "Failed to get nonce1 in initiate_stratum");
+		goto out;
+	}
+	pool->nonce2 = json_integer_value(json_array_get(res_val, 2));
+	if (!pool->nonce2) {
+		applog(LOG_WARNING, "Failed to get nonce2 in initiate_stratum");
+		goto out;
+	}
+
+	ret = true;
+out:
+	if (!ret) {
+		CLOSESOCKET(pool->sock);
+		if (val)
+			json_decref(val);
+	} else if (opt_protocol)
+		applog(LOG_DEBUG, "Pool %d confirmed mining.notify with subscription %s extranonce1 %s extranonce2 %d",
+		       pool->pool_no, pool->subscription, pool->nonce1, pool->nonce2);
+
+	return ret;
+}

+ 1 - 0
util.h

@@ -110,5 +110,6 @@
 #endif
 struct pool;
 bool extract_sockaddr(struct pool *pool, char *url);
+bool initiate_stratum(struct pool *pool);
 
 #endif /* __UTIL_H__ */