Commit a6f1a62220ef161068bd6d437c0e0683e2dd1eb3

Con Kolivas 2012-09-28T04:35:16

Create helper functions for checking when a socket is ready to read on and receive a single line at a time. Begin stratum authorisation process.

diff --git a/cgminer.c b/cgminer.c
index 4f31b5d..ac4b85f 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -3968,10 +3968,10 @@ static bool pool_active(struct pool *pool, bool pinging)
 	int rolltime;
 
 	if (pool->has_stratum) {
-		if (pool->stratum_active && !pinging)
-			return true;
-		if (initiate_stratum(pool))
-			return true;
+		if ((!pool->stratum_active || pinging) && !initiate_stratum(pool))
+			return false;
+		if (!pool->stratum_auth && !auth_stratum(pool))
+			return false;
 		return false;
 	}
 
diff --git a/miner.h b/miner.h
index af5c466..a255a6f 100644
--- a/miner.h
+++ b/miner.h
@@ -842,6 +842,9 @@ struct pool {
 	int nonce2;
 	bool has_stratum;
 	bool stratum_active;
+	bool stratum_auth;
+	/* Store json reference to clear it if we close connection */
+	json_t *stratum_val;
 	struct stratum_work swork;
 };
 
diff --git a/util.c b/util.c
index b69cf23..25e9a93 100644
--- a/util.c
+++ b/util.c
@@ -850,6 +850,9 @@ static bool sock_send(int sock, char *s, ssize_t len)
 {
 	ssize_t sent = 0;
 
+	if (opt_protocol)
+		applog(LOG_DEBUG, "SEND: %s", s);
+
 	while (len > 0 ) {
 		sent = send(sock, s + sent, len, 0);
 		if (SOCKETFAIL(sent))
@@ -870,6 +873,24 @@ static void clear_sock(SOCKETTYPE sock)
 	recv(sock, s, RECVSIZE, MSG_DONTWAIT);
 }
 
+/* Check to see if Santa's been good to you */
+static bool sock_full(SOCKETTYPE sock, bool wait)
+{
+	struct timeval timeout;
+	fd_set rd;
+
+	FD_ZERO(&rd);
+	FD_SET(sock, &rd);
+	timeout.tv_usec = 0;
+	if (wait)
+		timeout.tv_sec = 60;
+	else
+		timeout.tv_sec = 0;
+	if (select(sock + 1, &rd, NULL, NULL, &timeout) > 0)
+		return true;
+	return false;
+}
+
 /* Peeks at a socket to find the first end of line and then reads just that
  * from the socket and returns that as a malloced char */
 static char *recv_line(SOCKETTYPE sock)
@@ -887,28 +908,58 @@ static char *recv_line(SOCKETTYPE sock)
 		applog(LOG_DEBUG, "Failed to parse a \\n terminated string in recv_line");
 		goto out;
 	}
-	len = strlen(sret);
+	len = strlen(sret) + 1;
 	/* We know how much data is in the buffer so this read should not fail */
-	read(sock, s, len);
-	sret = strdup(s);
-
+	if (SOCKETFAIL(recv(sock, s, len, 0)))
+		goto out;
+	if (s)
+		sret = strdup(strtok(s, "\n"));
 out:
 	if (!sret)
 		clear_sock(sock);
+	else if (opt_protocol)
+		applog(LOG_DEBUG, "RECVD: %s", sret);
 	return sret;
 }
 
+bool auth_stratum(struct pool *pool)
+{
+	json_t *val = NULL, *res_val, *err_val, *notify_val;
+	char *s, *buf, *sret = NULL;
+	json_error_t err;
+	bool ret = false;
+
+	s = alloca(RECVSIZE);
+	sprintf(s, "{\"id\": %d, \"method\": \"mining.authorize\", \"params\": [\"%s\", \"%s\"]}\n",
+		pool->swork.id++, pool->rpc_user, pool->rpc_pass);
+
+	while (sock_full(pool->sock, false)) {
+		sret = recv_line(pool->sock);
+		free(sret);
+	}
+
+	if (!sock_send(pool->sock, s, strlen(s)))
+		goto out;
+
+out:
+	if (!ret) {
+		if (val)
+			json_decref(val);
+	} else
+		pool->stratum_val = val;
+
+	return ret;
+}
+
 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;
-	fd_set rd;
 
 	s = alloca(RECVSIZE);
-	sprintf(s, "{\"id\": 0, \"method\": \"mining.subscribe\", \"params\": []}\n");
+	sprintf(s, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": []}\n", pool->swork.id++);
 
 	pool->sock = socket(AF_INET, SOCK_STREAM, 0);
 	if (pool->sock == INVSOCK)
@@ -923,11 +974,7 @@ bool initiate_stratum(struct pool *pool)
 		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) {
+	if (!sock_full(pool->sock, true)) {
 		applog(LOG_DEBUG, "Timed out waiting for response in initiate_stratum");
 		goto out;
 	}
@@ -998,6 +1045,7 @@ out:
 			json_decref(val);
 	} else {
 		pool->stratum_active = true;
+		pool->stratum_val = val;
 		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);
diff --git a/util.h b/util.h
index 72304fe..3962f03 100644
--- a/util.h
+++ b/util.h
@@ -110,6 +110,7 @@
 #endif
 struct pool;
 bool extract_sockaddr(struct pool *pool, char *url);
+bool auth_stratum(struct pool *pool);
 bool initiate_stratum(struct pool *pool);
 
 #endif /* __UTIL_H__ */