mirror of
https://github.com/GOSTSec/sgminer
synced 2025-02-05 11:34:16 +00:00
Move stratum sockets to curl infrastructure with locking around send+recv to begin support for proxies and ssl.
This commit is contained in:
parent
591c433477
commit
a8d693029a
10
cgminer.c
10
cgminer.c
@ -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)
|
||||
* 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:
|
||||
/* 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;
|
||||
|
@ -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
3
miner.h
@ -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 {
|
||||
bool stratum_auth;
|
||||
struct stratum_work swork;
|
||||
pthread_t stratum_thread;
|
||||
pthread_mutex_t stratum_lock;
|
||||
};
|
||||
|
||||
#define GETWORK_MODE_TESTPOOL 'T'
|
||||
|
88
util.c
88
util.c
@ -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,
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void last_nettime(struct timeval *last)
|
||||
{
|
||||
@ -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)
|
||||
|
||||
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)
|
||||
/* 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)
|
||||
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)
|
||||
* 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:
|
||||
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:
|
||||
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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user