Browse Source

Move stratum sockets to curl infrastructure with locking around send+recv to begin support for proxies and ssl.

nfactor-troky
Con Kolivas 12 years ago
parent
commit
a8d693029a
  1. 10
      cgminer.c
  2. 3
      configure.ac
  3. 3
      miner.h
  4. 88
      util.c
  5. 2
      util.h

10
cgminer.c

@ -432,6 +432,8 @@ struct pool *add_pool(void) @@ -432,6 +432,8 @@ struct pool *add_pool(void)
quit(1, "Failed to pthread_mutex_init in add_pool");
if (unlikely(pthread_cond_init(&pool->cr_cond, NULL)))
quit(1, "Failed to pthread_cond_init in add_pool");
if (unlikely(pthread_mutex_init(&pool->stratum_lock, NULL)))
quit(1, "Failed to pthread_mutex_init in add_pool");
INIT_LIST_HEAD(&pool->curlring);
/* Make sure the pool doesn't think we've been idle since time 0 */
@ -562,12 +564,6 @@ static char *set_rr(enum pool_strategy *strategy) @@ -562,12 +564,6 @@ static char *set_rr(enum pool_strategy *strategy)
* stratum+tcp or by detecting a stratum server response */
bool detect_stratum(struct pool *pool, char *url)
{
if (pool->rpc_proxy) {
if (!strncasecmp(url, "stratum+tcp://", 14))
applog(LOG_WARNING, "Cannot use a stratum server with a proxy");
return false;
}
if (!extract_sockaddr(pool, url))
return false;
@ -4249,7 +4245,7 @@ retry_stratum: @@ -4249,7 +4245,7 @@ retry_stratum:
/* Detect if a http getwork pool has an X-Stratum header at startup,
* and if so, switch to that in preference to getwork. Currently no
* proxy support so don't try to switch if a proxy is in use. */
if (unlikely(pool->stratum_url && !pool->rpc_proxy)) {
if (unlikely(pool->stratum_url)) {
applog(LOG_NOTICE, "Switching pool %d %s to %s", pool->pool_no, pool->rpc_url, pool->stratum_url);
pool->has_stratum = true;
pool->rpc_url = pool->stratum_url;

3
configure.ac

@ -352,8 +352,7 @@ fi @@ -352,8 +352,7 @@ fi
PKG_PROG_PKG_CONFIG()
PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.15.6], [AC_DEFINE([CURL_HAS_SOCKOPT], [1], [Defined if version of curl supports sockopts.])],
[PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.10.1], ,[AC_MSG_ERROR([Missing required libcurl dev >= 7.10.1])])])
PKG_CHECK_MODULES([LIBCURL], [libcurl >= 7.18.2], ,[AC_MSG_ERROR([Missing required libcurl dev >= 7.18.2])])
AC_SUBST(LIBCURL_LIBS)
dnl CCAN wants to know a lot of vars.

3
miner.h

@ -863,6 +863,8 @@ struct pool { @@ -863,6 +863,8 @@ struct pool {
/* Stratum variables */
char *stratum_url;
char *stratum_port;
CURL *stratum_curl;
SOCKETTYPE sock;
char sockbuf[RBUFSIZE];
struct sockaddr_in *server, client;
@ -875,6 +877,7 @@ struct pool { @@ -875,6 +877,7 @@ struct pool {
bool stratum_auth;
struct stratum_work swork;
pthread_t stratum_thread;
pthread_mutex_t stratum_lock;
};
#define GETWORK_MODE_TESTPOOL 'T'

88
util.c

@ -196,7 +196,6 @@ out: @@ -196,7 +196,6 @@ out:
return ptrlen;
}
#ifdef CURL_HAS_SOCKOPT
int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd,
curlsocktype __maybe_unused purpose)
{
@ -244,7 +243,6 @@ int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd, @@ -244,7 +243,6 @@ int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd,
return 0;
}
#endif
static void last_nettime(struct timeval *last)
{
@ -319,10 +317,8 @@ json_t *json_rpc_call(CURL *curl, const char *url, @@ -319,10 +317,8 @@ json_t *json_rpc_call(CURL *curl, const char *url,
curl_easy_setopt(curl, CURLOPT_USERPWD, userpass);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
}
#ifdef CURL_HAS_SOCKOPT
if (longpoll)
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, json_rpc_call_sockopt_cb);
#endif
curl_easy_setopt(curl, CURLOPT_POST, 1);
if (opt_protocol)
@ -835,11 +831,12 @@ bool extract_sockaddr(struct pool *pool, char *url) @@ -835,11 +831,12 @@ bool extract_sockaddr(struct pool *pool, char *url)
sprintf(url_address, "%.*s", url_len, url_begin);
if (port_len) {
if (port_len)
sprintf(port, "%.*s", port_len, port_start);
} else {
else
strcpy(port, "80");
}
pool->stratum_port = strdup(port);
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
@ -859,8 +856,7 @@ bool extract_sockaddr(struct pool *pool, char *url) @@ -859,8 +856,7 @@ bool extract_sockaddr(struct pool *pool, char *url)
/* Send a single command across a socket, appending \n to it */
bool stratum_send(struct pool *pool, char *s, ssize_t len)
{
SOCKETTYPE sock = pool->sock;
ssize_t sent = 0;
ssize_t ssent = 0;
bool ret = false;
if (opt_protocol)
@ -869,19 +865,21 @@ bool stratum_send(struct pool *pool, char *s, ssize_t len) @@ -869,19 +865,21 @@ bool stratum_send(struct pool *pool, char *s, ssize_t len)
strcat(s, "\n");
len++;
mutex_lock(&pool->pool_lock);
mutex_lock(&pool->stratum_lock);
while (len > 0 ) {
sent = send(sock, s + sent, len, 0);
if (SOCKETFAIL(sent)) {
size_t sent = 0;
if (curl_easy_send(pool->stratum_curl, s + ssent, len, &sent) != CURLE_OK) {
applog(LOG_DEBUG, "Failed to curl_easy_send in stratum_send");
ret = false;
goto out_unlock;
}
len -= sent;
ssent += sent;
len -= ssent;
}
ret = true;
fsync(sock);
out_unlock:
mutex_unlock(&pool->pool_lock);
mutex_unlock(&pool->stratum_lock);
return ret;;
}
@ -922,15 +920,25 @@ static bool sock_full(struct pool *pool, bool wait) @@ -922,15 +920,25 @@ static bool sock_full(struct pool *pool, bool wait)
* from the socket and returns that as a malloced char */
char *recv_line(struct pool *pool)
{
SOCKETTYPE sock = pool->sock;
ssize_t len, buflen;
char *tok, *sret = NULL;
size_t n;
if (!strstr(pool->sockbuf, "\n")) {
char s[RBUFSIZE];
CURLcode rc;
if (!sock_full(pool, true)) {
applog(LOG_DEBUG, "Timed out waiting for data on sock_full");
goto out;
}
memset(s, 0, RBUFSIZE);
if (SOCKETFAIL(recv(sock, s, RECVSIZE, 0))) {
mutex_lock(&pool->stratum_lock);
rc = curl_easy_recv(pool->stratum_curl, s, RECVSIZE, &n);
mutex_unlock(&pool->stratum_lock);
if (rc != CURLE_OK) {
applog(LOG_DEBUG, "Failed to recv sock in recv_line");
goto out;
}
@ -1202,22 +1210,48 @@ out: @@ -1202,22 +1210,48 @@ out:
bool initiate_stratum(struct pool *pool)
{
json_t *val = NULL, *res_val, *err_val;
char curl_err_str[CURL_ERROR_SIZE];
char s[RBUFSIZE], *sret = NULL;
CURL *curl = NULL;
json_error_t err;
bool ret = false;
if (pool->stratum_active)
return true;
sprintf(s, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": []}", swork_id++);
if (!pool->stratum_curl) {
pool->stratum_curl = curl_easy_init();
if (unlikely(!pool->stratum_curl))
quit(1, "Failed to curl_easy_init in initiate_stratum");
}
curl = pool->stratum_curl;
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");
/* Create a http url for use with curl */
memset(s, 0, RBUFSIZE);
sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 60);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_URL, s);
curl_easy_setopt(curl, CURLOPT_TCP_NODELAY, 1);
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1);
if (pool->rpc_proxy) {
curl_easy_setopt(curl, CURLOPT_PROXY, pool->rpc_proxy);
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, pool->rpc_proxytype);
} else if (opt_socks_proxy) {
curl_easy_setopt(curl, CURLOPT_PROXY, opt_socks_proxy);
curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
}
curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1);
if (curl_easy_perform(curl)) {
applog(LOG_ERR, "Stratum connect failed: %s", curl_err_str);
goto out;
}
curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&pool->sock);
sprintf(s, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": []}", swork_id++);
if (!stratum_send(pool, s, strlen(s))) {
applog(LOG_DEBUG, "Failed to send s in initiate_stratum");
@ -1283,8 +1317,12 @@ out: @@ -1283,8 +1317,12 @@ out:
applog(LOG_DEBUG, "Pool %d confirmed mining.subscribe with extranonce1 %s extran2size %d",
pool->pool_no, pool->nonce1, pool->n2size);
}
} else
CLOSESOCKET(pool->sock);
} else {
if (curl) {
curl_easy_cleanup(curl);
pool->stratum_curl = NULL;
}
}
return ret;
}

2
util.h

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#define SOCKETTYPE int
#define SOCKETTYPE long
#define SOCKETFAIL(a) ((a) < 0)
#define INVSOCK -1
#define INVINETADDR -1

Loading…
Cancel
Save