Windows doesn't work with MSG_PEEK on recv so move to a continuously updating buffer for incoming messages.
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 172 173 174 175 176
diff --git a/cgminer.c b/cgminer.c
index b5d7402..36adc5b 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -4161,7 +4161,7 @@ static void *stratum_thread(void *userdata)
sleep(5);
}
}
- s = recv_line(pool->sock);
+ s = recv_line(pool);
if (unlikely(!s))
continue;
if (!parse_method(pool, s) && !parse_stratum_response(s))
diff --git a/miner.h b/miner.h
index 7bf1309..42c1935 100644
--- a/miner.h
+++ b/miner.h
@@ -795,6 +795,9 @@ struct stratum_work {
int diff;
};
+#define RECVSIZE 8191
+#define RBUFSIZE (RECVSIZE + 1)
+
struct pool {
int pool_no;
int prio;
@@ -861,6 +864,7 @@ struct pool {
/* Stratum variables */
char *stratum_url;
SOCKETTYPE sock;
+ char sockbuf[RBUFSIZE];
struct sockaddr_in *server, client;
char *sockaddr_url; /* stripped url used for sockaddr */
char *nonce1;
diff --git a/util.c b/util.c
index 713776e..f1d4def 100644
--- a/util.c
+++ b/util.c
@@ -888,19 +888,24 @@ out_unlock:
#define RECVSIZE 8191
#define RBUFSIZE (RECVSIZE + 1)
-static void clear_sock(SOCKETTYPE sock)
+static void clear_sock(struct pool *pool)
{
- char s[RBUFSIZE];
+ SOCKETTYPE sock = pool->sock;
- recv(sock, s, RECVSIZE, MSG_DONTWAIT);
+ recv(sock, pool->sockbuf, RECVSIZE, MSG_DONTWAIT);
+ strcpy(pool->sockbuf, "");
}
/* Check to see if Santa's been good to you */
-static bool sock_full(SOCKETTYPE sock, bool wait)
+static bool sock_full(struct pool *pool, bool wait)
{
+ SOCKETTYPE sock = pool->sock;
struct timeval timeout;
fd_set rd;
+ if (strlen(pool->sockbuf))
+ return true;
+
FD_ZERO(&rd);
FD_SET(sock, &rd);
timeout.tv_usec = 0;
@@ -915,30 +920,41 @@ static bool sock_full(SOCKETTYPE sock, bool wait)
/* 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 */
-char *recv_line(SOCKETTYPE sock)
+char *recv_line(struct pool *pool)
{
- char *sret = NULL, s[RBUFSIZE], c;
- ssize_t offset = 0;
+ SOCKETTYPE sock = pool->sock;
+ ssize_t len, buflen;
+ char *tok, *sret = NULL;
- if (SOCKETFAIL(recv(sock, s, RECVSIZE, MSG_PEEK))) {
- applog(LOG_DEBUG, "Failed to recv sock in recv_line");
- goto out;
+ if (!strstr(pool->sockbuf, "\n")) {
+ char s[RBUFSIZE];
+
+ memset(s, 0, RBUFSIZE);
+ if (SOCKETFAIL(recv(sock, s, RECVSIZE, 0))) {
+ applog(LOG_DEBUG, "Failed to recv sock in recv_line");
+ goto out;
+ }
+ strcat(pool->sockbuf, s);
}
- sret = strtok(s, "\n");
- if (!sret) {
+
+ buflen = strlen(pool->sockbuf);
+ tok = strtok(pool->sockbuf, "\n");
+ if (!tok) {
applog(LOG_DEBUG, "Failed to parse a \\n terminated string in recv_line");
goto out;
}
+ sret = strdup(tok);
+ len = strlen(sret);
- do {
- read(sock, &c, 1);
- memcpy(s + offset++, &c, 1);
- } while (strncmp(&c, "\n", 1));
- sret = strdup(s);
- strcpy(sret + offset - 1, "\0");
+ /* Copy what's left in the buffer after the \n, including the
+ * terminating \0 */
+ if (buflen > len + 1)
+ memmove(pool->sockbuf, pool->sockbuf + len + 1, buflen - len + 1);
+ else
+ strcpy(pool->sockbuf, "");
out:
if (!sret)
- clear_sock(sock);
+ clear_sock(pool);
else if (opt_protocol)
applog(LOG_DEBUG, "RECVD: %s", sret);
return sret;
@@ -1138,10 +1154,10 @@ bool auth_stratum(struct pool *pool)
swork_id++, pool->rpc_user, pool->rpc_pass);
/* Parse all data prior sending auth request */
- while (sock_full(pool->sock, false)) {
- sret = recv_line(pool->sock);
+ while (sock_full(pool, false)) {
+ sret = recv_line(pool);
if (!parse_method(pool, sret)) {
- clear_sock(pool->sock);
+ clear_sock(pool);
applog(LOG_WARNING, "Failed to parse stratum buffer");
free(sret);
return ret;
@@ -1152,7 +1168,7 @@ bool auth_stratum(struct pool *pool)
if (!stratum_send(pool, s, strlen(s)))
goto out;
- sret = recv_line(pool->sock);
+ sret = recv_line(pool);
if (!sret)
goto out;
val = JSON_LOADS(sret, &err);
@@ -1208,12 +1224,12 @@ bool initiate_stratum(struct pool *pool)
goto out;
}
- if (!sock_full(pool->sock, true)) {
+ if (!sock_full(pool, true)) {
applog(LOG_DEBUG, "Timed out waiting for response in initiate_stratum");
goto out;
}
- sret = recv_line(pool->sock);
+ sret = recv_line(pool);
if (!sret)
goto out;
diff --git a/util.h b/util.h
index 3829c07..fb520ca 100644
--- a/util.h
+++ b/util.h
@@ -44,7 +44,7 @@
struct pool;
bool stratum_send(struct pool *pool, char *s, ssize_t len);
-char *recv_line(SOCKETTYPE sock);
+char *recv_line(struct pool *pool);
bool parse_method(struct pool *pool, char *s);
bool extract_sockaddr(struct pool *pool, char *url);
bool auth_stratum(struct pool *pool);