diff --git a/cgminer.c b/cgminer.c index b5d7402e..36adc5b5 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 7bf1309f..42c19351 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 713776e6..f1d4defd 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 3829c07f..fb520ca7 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);