Commit deb0a9b644b4918c954e0a7abe325d25a4fc5b5e

Con Kolivas 2012-10-04T23:18:33

Windows doesn't work with MSG_PEEK on recv so move to a continuously updating buffer for incoming messages.

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);