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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
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__ */