diff --git a/cgminer.c b/cgminer.c index 000782c2..63412c14 100644 --- a/cgminer.c +++ b/cgminer.c @@ -557,6 +557,8 @@ static char *set_url(char *arg) if (!extract_sockaddr(pool, arg)) return "Failed to extract address from parsed url"; + initiate_stratum(pool); + opt_set_charp(arg, &pool->rpc_url); if (strncmp(arg, "http://", 7) && strncmp(arg, "https://", 8)) { diff --git a/util.c b/util.c index 6ac80641..79c7e8fd 100644 --- a/util.c +++ b/util.c @@ -845,3 +845,96 @@ bool extract_sockaddr(struct pool *pool, char *url) pool->server = (struct sockaddr_in *)res->ai_addr; return true; } + +static bool sock_send(int sock, char *s, ssize_t len) +{ + size_t sent = 0; + + while (len > 0 ) { + sent = send(sock, s + sent, len, 0); + if (sent < 1) + return false; + len -= sent; + } + fsync(sock); + + return true; +} + +#define RECVSIZE 8192 + +bool initiate_stratum(struct pool *pool) +{ + json_t *val, *res_val, *err_val; + struct timeval timeout; + char *s, *ret = NULL; + json_error_t err; + ssize_t len; + fd_set rd; + + s = alloca(RECVSIZE); + sprintf(s, "{\"id\": 0, \"method\": \"mining.subscribe\", \"params\": []}\n"); + + pool->sock = socket(AF_INET, SOCK_STREAM, 0); + if (pool->sock == INVSOCK) + quit(1, "Failed to create pool socket in initiate_stratum"); + if (SOCKETFAIL(connect(pool->sock, (struct sockaddr *)pool->server, sizeof(struct sockaddr)))) { + applog(LOG_DEBUG, "Failed to connect socket to pool"); + return false; + } + + if (!sock_send(pool->sock, s, strlen(s))) { + applog(LOG_DEBUG, "Failed to send s in initiate_stratum"); + return false; + } + + /* 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) { + applog(LOG_DEBUG, "Timed out waiting for response in initiate_stratum"); + return false; + } + + if (recv(pool->sock, s, RECVSIZE, MSG_PEEK | MSG_DONTWAIT) < 1) { + applog(LOG_DEBUG, "Failed to recv sock in initiate_stratum"); + return false; + } + + ret = strtok(s, "\n"); + if (!ret) { + applog(LOG_DEBUG, "Failed to parse a \\n terminated string in initiate_stratum"); + return false; + } + + len = strlen(ret); + read(pool->sock, s, len); + + val = JSON_LOADS(s, &err); + if (!val) { + applog(LOG_DEBUG, "JSON decode failed(%d): %s", err.line, err.text); + return false; + } + + res_val = json_object_get(val, "result"); + err_val = json_object_get(val, "error"); + + if (!res_val || json_is_null(res_val) || + (err_val && !json_is_null(err_val))) { + char *ss; + + if (err_val) + ss = json_dumps(err_val, JSON_INDENT(3)); + else + ss = strdup("(unknown reason)"); + + applog(LOG_INFO, "JSON-RPC call failed: %s", ss); + + free(ss); + + return false; + } + + return true; +} diff --git a/util.h b/util.h index c99ecfd2..72304fec 100644 --- a/util.h +++ b/util.h @@ -110,5 +110,6 @@ #endif struct pool; bool extract_sockaddr(struct pool *pool, char *url); +bool initiate_stratum(struct pool *pool); #endif /* __UTIL_H__ */