From a6f1a62220ef161068bd6d437c0e0683e2dd1eb3 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 28 Sep 2012 04:35:16 +1000 Subject: [PATCH] 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. --- cgminer.c | 8 +++---- miner.h | 3 +++ util.c | 72 +++++++++++++++++++++++++++++++++++++++++++++---------- util.h | 1 + 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/cgminer.c b/cgminer.c index 4f31b5dc..ac4b85fe 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 af5c4669..a255a6f0 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 b69cf230..25e9a933 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 72304fec..3962f039 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__ */