diff --git a/miner.h b/miner.h index 50ed607e..df2888e9 100644 --- a/miner.h +++ b/miner.h @@ -859,8 +859,8 @@ struct stratum_work { double diff; }; -#define RECVSIZE 8192 -#define RBUFSIZE (RECVSIZE + 4) +#define RBUFSIZE 8192 +#define RECVSIZE (RBUFSIZE - 4) struct pool { int pool_no; @@ -929,7 +929,8 @@ struct pool { char *stratum_port; CURL *stratum_curl; SOCKETTYPE sock; - char sockbuf[RBUFSIZE]; + char *sockbuf; + size_t sockbuf_size; char *sockaddr_url; /* stripped url used for sockaddr */ char *nonce1; uint32_t nonce2; diff --git a/util.c b/util.c index 9ca31d63..e628af45 100644 --- a/util.c +++ b/util.c @@ -968,37 +968,59 @@ static void clear_sock(struct pool *pool) strcpy(pool->sockbuf, ""); } +/* Make sure the pool sockbuf is large enough to cope with any coinbase size + * by reallocing it to a large enough size rounded up to a multiple of RBUFSIZE + * and zeroing the new memory */ +static void recalloc_sock(struct pool *pool, size_t len) +{ + size_t old, new; + + old = strlen(pool->sockbuf); + new = old + len + 1; + if (new < pool->sockbuf_size) + return; + new = new + (RBUFSIZE - (new % RBUFSIZE)); + applog(LOG_DEBUG, "Recallocing pool sockbuf to %d", new); + pool->sockbuf = realloc(pool->sockbuf, new); + if (!pool->sockbuf) + quit(1, "Failed to realloc pool sockbuf in recalloc_sock"); + memset(pool->sockbuf + old, 0, new - old); + pool->sockbuf_size = new; +} + /* 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(struct pool *pool) { ssize_t len, buflen; char *tok, *sret = NULL; - ssize_t n; if (!strstr(pool->sockbuf, "\n")) { - char s[RBUFSIZE]; - size_t sspace; + struct timeval rstart, now; + gettimeofday(&rstart, NULL); if (!socket_full(pool, true)) { applog(LOG_DEBUG, "Timed out waiting for data on socket_full"); goto out; } - memset(s, 0, RBUFSIZE); mutex_lock(&pool->stratum_lock); - n = recv(pool->sock, s, RECVSIZE, 0); + do { + char s[RBUFSIZE]; + size_t slen, n; + + memset(s, 0, RBUFSIZE); + n = recv(pool->sock, s, RECVSIZE, 0); + if (n < 1 && errno != EAGAIN && errno != EWOULDBLOCK) { + applog(LOG_DEBUG, "Failed to recv sock in recv_line"); + break; + } + slen = strlen(s); + recalloc_sock(pool, slen); + strcat(pool->sockbuf, s); + gettimeofday(&now, NULL); + } while (tdiff(&now, &rstart) < 60 && !strstr(pool->sockbuf, "\n")); mutex_unlock(&pool->stratum_lock); - - if (n < 1 && errno != EAGAIN && errno != EWOULDBLOCK) { - applog(LOG_DEBUG, "Failed to recv sock in recv_line"); - goto out; - } - /* Prevent buffer overflows, but if 8k is still not enough, - * likely we have had some comms issues and the data is all - * useless anyway */ - sspace = RECVSIZE - strlen(pool->sockbuf); - strncat(pool->sockbuf, s, sspace); } buflen = strlen(pool->sockbuf); @@ -1350,6 +1372,13 @@ bool initiate_stratum(struct pool *pool) mutex_unlock(&pool->stratum_lock); curl = pool->stratum_curl; + if (!pool->sockbuf) { + pool->sockbuf = calloc(RBUFSIZE, 1); + if (!pool->sockbuf) + quit(1, "Failed to calloc pool sockbuf in initiate_stratum"); + pool->sockbuf_size = RBUFSIZE; + } + /* Create a http url for use with curl */ memset(s, 0, RBUFSIZE); sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port);