1
0
mirror of https://github.com/GOSTSec/sgminer synced 2025-01-12 07:48:22 +00:00

Merge branch 'master' of git://github.com/ckolivas/cgminer.git

This commit is contained in:
Paul Sheppard 2012-10-28 21:33:46 -07:00
commit dd2b7e5fe0
5 changed files with 179 additions and 77 deletions

30
NEWS
View File

@ -1,3 +1,33 @@
Version 2.8.6 - October 29, 2012
- Shorten the initiate stratum connect timeout to 30 seconds.
- Shorten the stratum timeout on read to 90 seconds to detect unresponsive pool.
- Display best share difficulty on exit.
- Make stratum socket fail more robust on windows by disabling the send buffer.
- Reuse the same curl handle forcing a new connection instead of risking
derefencing.
- Add information about submission failure to stratum send.
- Only add stratum share to database if we succeeded in submitting it, with a
debug output saying it succeeded.
- Use keepalive with stratum sockets to improve its ability to detect broken
connections.
- Show only the URL in the status bar to avoid long prefixes making for extra
long lines.
- Display compact status in menu and update README to reflect current menu
entries.
- Add a compact display mode that does not list per device statistics in the
status window.
- Add blank spaces after best share displayed.
- Round a few static string arrays up to 4 byte boundaries for ARM.
- Display best share diff for scrypt as well.
- Show the best diff share as "best share" and add info to the README.
- Display the best diff share submitted so far.
- Redundant check.
- The work struct pointer in struct pc_data in findnonce is never freed yet
there is no need to allocate it separately so make struct work a static part of
the struct pc_data. s
Version 2.8.5 - October 23, 2012 Version 2.8.5 - October 23, 2012
- Handle crash exceptions by trying to restart cgminer unless the --no-restart - Handle crash exceptions by trying to restart cgminer unless the --no-restart

25
README
View File

@ -143,6 +143,7 @@ Options for both config file and command line:
--auto-gpu Automatically adjust all GPU engine clock speeds to maintain a target temperature --auto-gpu Automatically adjust all GPU engine clock speeds to maintain a target temperature
--balance Change multipool strategy from failover to even share balance --balance Change multipool strategy from failover to even share balance
--benchmark Run cgminer in benchmark mode - produces no shares --benchmark Run cgminer in benchmark mode - produces no shares
--compact Use compact display without per device statistics
--debug|-D Enable debug output --debug|-D Enable debug output
--expiry|-E <arg> Upper bound on how many seconds after getting work we consider a share from it stale (default: 120) --expiry|-E <arg> Upper bound on how many seconds after getting work we consider a share from it stale (default: 120)
--failover-only Don't leak work to backup pools when primary pool is lagging --failover-only Don't leak work to backup pools when primary pool is lagging
@ -341,6 +342,7 @@ The following options are available while running with a single keypress:
P gives you: P gives you:
Current pool management strategy: Failover Current pool management strategy: Failover
[F]ailover only disabled
[A]dd pool [R]emove pool [D]isable pool [E]nable pool [A]dd pool [R]emove pool [D]isable pool [E]nable pool
[C]hange management strategy [S]witch pool [I]nformation [C]hange management strategy [S]witch pool [I]nformation
@ -350,15 +352,21 @@ S gives you:
[Q]ueue: 1 [Q]ueue: 1
[S]cantime: 60 [S]cantime: 60
[E]xpiry: 120 [E]xpiry: 120
[R]etries: -1
[P]ause: 5
[W]rite config file [W]rite config file
[C]gminer restart
D gives you: D gives you:
Toggle: [D]ebug [N]ormal [S]ilent [V]erbose [R]PC debug [N]ormal [C]lear [S]ilent mode (disable all output)
[L]og interval [C]lear [D]ebug:off
[P]er-device:off
[Q]uiet:off
[V]erbose:off
[R]PC debug:off
[W]orkTime details:off
co[M]pact: off
[L]og interval:5
Q quits the application. Q quits the application.
@ -441,6 +449,15 @@ diminish return performance even if the hash rate might appear better. A good
starting baseline intensity to try on dedicated miners is 9. Higher values are starting baseline intensity to try on dedicated miners is 9. Higher values are
there to cope with future improvements in hardware. there to cope with future improvements in hardware.
The block display shows:
Block: 0074c5e482e34a506d2a051a... Started: [17:17:22] Best share: 2.71K
This shows a short stretch of the current block, when the new block started,
and the all time best difficulty share you've submitted since starting cgminer
this time.
--- ---
MULTIPOOL MULTIPOOL

125
cgminer.c
View File

@ -92,6 +92,7 @@ bool use_syslog;
bool opt_quiet; bool opt_quiet;
bool opt_realquiet; bool opt_realquiet;
bool opt_loginput; bool opt_loginput;
bool opt_compact;
const int opt_cutofftemp = 95; const int opt_cutofftemp = 95;
int opt_log_interval = 5; int opt_log_interval = 5;
int opt_queue = 1; int opt_queue = 1;
@ -213,15 +214,17 @@ const
#endif #endif
bool curses_active; bool curses_active;
static char current_block[37]; static char current_block[40];
static char *current_hash; static char *current_hash;
char *current_fullhash; char *current_fullhash;
static char datestamp[40]; static char datestamp[40];
static char blocktime[30]; static char blocktime[30];
struct timeval block_timeval; struct timeval block_timeval;
static char best_share[8] = "0";
static uint64_t best_diff = 0;
struct block { struct block {
char hash[37]; char hash[40];
UT_hash_handle hh; UT_hash_handle hh;
int block_no; int block_no;
}; };
@ -549,10 +552,10 @@ static char *set_rr(enum pool_strategy *strategy)
* stratum+tcp or by detecting a stratum server response */ * stratum+tcp or by detecting a stratum server response */
bool detect_stratum(struct pool *pool, char *url) bool detect_stratum(struct pool *pool, char *url)
{ {
if (opt_scrypt) if (!extract_sockaddr(pool, url))
return false; return false;
if (!extract_sockaddr(pool, url)) if (opt_scrypt)
return false; return false;
if (!strncasecmp(url, "stratum+tcp://", 14)) { if (!strncasecmp(url, "stratum+tcp://", 14)) {
@ -852,6 +855,13 @@ static struct opt_table opt_config_table[] = {
OPT_WITH_ARG("--bench-algo|-b", OPT_WITH_ARG("--bench-algo|-b",
set_int_0_to_9999, opt_show_intval, &opt_bench_algo, set_int_0_to_9999, opt_show_intval, &opt_bench_algo,
opt_hidden), opt_hidden),
#endif
#ifdef HAVE_CURSES
OPT_WITHOUT_ARG("--compact",
opt_set_bool, &opt_compact,
"Use compact display without per device statistics"),
#endif
#ifdef WANT_CPUMINE
OPT_WITH_ARG("--cpu-threads|-t", OPT_WITH_ARG("--cpu-threads|-t",
force_nthreads_int, opt_show_intval, &opt_n_threads, force_nthreads_int, opt_show_intval, &opt_n_threads,
"Number of miner CPU threads"), "Number of miner CPU threads"),
@ -1578,16 +1588,16 @@ static void curses_print_status(void)
wclrtoeol(statuswin); wclrtoeol(statuswin);
if (pool->has_stratum) { if (pool->has_stratum) {
mvwprintw(statuswin, 4, 0, " Connected to %s with stratum as user %s", mvwprintw(statuswin, 4, 0, " Connected to %s with stratum as user %s",
pool->stratum_url, pool->rpc_user); pool->sockaddr_url, pool->rpc_user);
} else if ((pool_strategy == POOL_LOADBALANCE || pool_strategy == POOL_BALANCE) && total_pools > 1) { } else if ((pool_strategy == POOL_LOADBALANCE || pool_strategy == POOL_BALANCE) && total_pools > 1) {
mvwprintw(statuswin, 4, 0, " Connected to multiple pools with%s LP", mvwprintw(statuswin, 4, 0, " Connected to multiple pools with%s LP",
have_longpoll ? "": "out"); have_longpoll ? "": "out");
} else { } else {
mvwprintw(statuswin, 4, 0, " Connected to %s with%s LP as user %s", mvwprintw(statuswin, 4, 0, " Connected to %s with%s LP as user %s",
pool->rpc_url, have_longpoll ? "": "out", pool->rpc_user); pool->sockaddr_url, have_longpoll ? "": "out", pool->rpc_user);
} }
wclrtoeol(statuswin); wclrtoeol(statuswin);
mvwprintw(statuswin, 5, 0, " Block: %s... Started: %s", current_hash, blocktime); mvwprintw(statuswin, 5, 0, " Block: %s... Started: %s Best share: %s ", current_hash, blocktime, best_share);
mvwhline(statuswin, 6, 0, '-', 80); mvwhline(statuswin, 6, 0, '-', 80);
mvwhline(statuswin, statusy - 1, 0, '-', 80); mvwhline(statuswin, statusy - 1, 0, '-', 80);
mvwprintw(statuswin, devcursor - 1, 1, "[P]ool management %s[S]ettings [D]isplay options [Q]uit", mvwprintw(statuswin, devcursor - 1, 1, "[P]ool management %s[S]ettings [D]isplay options [Q]uit",
@ -1610,7 +1620,7 @@ static void curses_print_devstatus(int thr_id)
char displayed_hashes[16], displayed_rolling[16]; char displayed_hashes[16], displayed_rolling[16];
uint64_t dh64, dr64; uint64_t dh64, dr64;
if (devcursor + cgpu->cgminer_id > LINES - 2) if (devcursor + cgpu->cgminer_id > LINES - 2 || opt_compact)
return; return;
cgpu->utility = cgpu->accepted / total_secs * 60; cgpu->utility = cgpu->accepted / total_secs * 60;
@ -1670,14 +1680,13 @@ static void print_status(int thr_id)
#ifdef HAVE_CURSES #ifdef HAVE_CURSES
/* Check for window resize. Called with curses mutex locked */ /* Check for window resize. Called with curses mutex locked */
static inline bool change_logwinsize(void) static inline void change_logwinsize(void)
{ {
int x, y, logx, logy; int x, y, logx, logy;
bool ret = false;
getmaxyx(mainwin, y, x); getmaxyx(mainwin, y, x);
if (x < 80 || y < 25) if (x < 80 || y < 25)
return ret; return;
if (y > statusy + 2 && statusy < logstart) { if (y > statusy + 2 && statusy < logstart) {
if (y - 2 < logstart) if (y - 2 < logstart)
@ -1687,17 +1696,13 @@ static inline bool change_logwinsize(void)
logcursor = statusy + 1; logcursor = statusy + 1;
mvwin(logwin, logcursor, 0); mvwin(logwin, logcursor, 0);
wresize(statuswin, statusy, x); wresize(statuswin, statusy, x);
ret = true;
} }
y -= logcursor; y -= logcursor;
getmaxyx(logwin, logy, logx); getmaxyx(logwin, logy, logx);
/* Detect screen size change */ /* Detect screen size change */
if (x != logx || y != logy) { if (x != logx || y != logy)
wresize(logwin, y, x); wresize(logwin, y, x);
ret = true;
}
return ret;
} }
static void check_winsizes(void) static void check_winsizes(void)
@ -1707,6 +1712,7 @@ static void check_winsizes(void)
if (curses_active_locked()) { if (curses_active_locked()) {
int y, x; int y, x;
erase();
x = getmaxx(statuswin); x = getmaxx(statuswin);
if (logstart > LINES - 2) if (logstart > LINES - 2)
statusy = LINES - 2; statusy = LINES - 2;
@ -1722,6 +1728,18 @@ static void check_winsizes(void)
} }
} }
static void switch_compact(void)
{
if (opt_compact) {
logstart = devcursor + 1;
logcursor = logstart + 1;
} else {
logstart = devcursor + total_devices + 1;
logcursor = logstart + 1;
}
check_winsizes();
}
/* For mandatory printing when mutex is already locked */ /* For mandatory printing when mutex is already locked */
void wlog(const char *f, ...) void wlog(const char *f, ...)
{ {
@ -1770,6 +1788,7 @@ bool log_curses_only(int prio, const char *f, va_list ap)
void clear_logwin(void) void clear_logwin(void)
{ {
if (curses_active_locked()) { if (curses_active_locked()) {
erase();
wclear(logwin); wclear(logwin);
unlock_curses(); unlock_curses();
} }
@ -1980,17 +1999,26 @@ static uint64_t share_diff(const struct work *work)
if (unlikely(!d64)) if (unlikely(!d64))
d64 = 1; d64 = 1;
ret = diffone / d64; ret = diffone / d64;
if (ret > best_diff) {
best_diff = ret;
suffix_string(best_diff, best_share, 0);
}
return ret; return ret;
} }
static uint32_t scrypt_diff(const struct work *work) static uint32_t scrypt_diff(const struct work *work)
{ {
const uint32_t scrypt_diffone = 0x0000fffful; const uint32_t scrypt_diffone = 0x0000fffful;
uint32_t d32 = work->outputhash; uint32_t d32 = work->outputhash, ret;
if (unlikely(!d32)) if (unlikely(!d32))
d32 = 1; d32 = 1;
return scrypt_diffone / d32; ret = scrypt_diffone / d32;
if (ret > best_diff) {
best_diff = ret;
suffix_string(best_diff, best_share, 0);
}
return ret;
} }
static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit) static bool submit_upstream_work(struct work *work, CURL *curl, bool resubmit)
@ -2887,34 +2915,41 @@ static void *submit_work_thread(void *userdata)
} }
if (work->stratum) { if (work->stratum) {
struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1);
uint32_t *hash32 = (uint32_t *)work->hash, nonce; uint32_t *hash32 = (uint32_t *)work->hash, nonce;
char *noncehex; char *noncehex;
char s[1024]; char s[1024];
memcpy(&sshare->work, work, sizeof(struct work));
/* Give the stratum share a unique id */ /* Give the stratum share a unique id */
mutex_lock(&sshare_lock); swork_id++;
sshare->id = swork_id++;
HASH_ADD_INT(stratum_shares, id, sshare);
mutex_unlock(&sshare_lock);
nonce = *((uint32_t *)(work->data + 76)); nonce = *((uint32_t *)(work->data + 76));
noncehex = bin2hex((const unsigned char *)&nonce, 4); noncehex = bin2hex((const unsigned char *)&nonce, 4);
memset(s, 0, 1024); memset(s, 0, 1024);
sprintf(s, "{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}", sprintf(s, "{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}",
pool->rpc_user, work->job_id, work->nonce2, work->ntime, noncehex, sshare->id); pool->rpc_user, work->job_id, work->nonce2, work->ntime, noncehex, swork_id);
free(noncehex); free(noncehex);
applog(LOG_INFO, "Submitting share %08lx to pool %d", (unsigned long)(hash32[6]), pool->pool_no); applog(LOG_INFO, "Submitting share %08lx to pool %d", (unsigned long)(hash32[6]), pool->pool_no);
if (unlikely(!stratum_send(pool, s, strlen(s)))) { if (likely(stratum_send(pool, s, strlen(s)))) {
struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1);
if (pool_tclear(pool, &pool->submit_fail))
applog(LOG_WARNING, "Pool %d communication resumed, submitting work", pool->pool_no);
applog(LOG_DEBUG, "Successfully submitted, adding to stratum_shares db");
memcpy(&sshare->work, work, sizeof(struct work));
mutex_lock(&sshare_lock); mutex_lock(&sshare_lock);
HASH_DEL(stratum_shares, sshare); sshare->id = swork_id;
HASH_ADD_INT(stratum_shares, id, sshare);
mutex_unlock(&sshare_lock); mutex_unlock(&sshare_lock);
free(sshare); } else {
applog(LOG_INFO, "Failed to submit stratum share");
if (!pool_tset(pool, &pool->submit_fail)) {
total_ro++;
pool->remotefail_occasions++;
applog(LOG_WARNING, "Pool %d share submission failure", pool->pool_no);
}
} }
goto out; goto out;
@ -3143,14 +3178,14 @@ static void set_curblock(char *hexstr, unsigned char *hash)
strcpy(current_block, hexstr); strcpy(current_block, hexstr);
swap256(hash_swap, hash); swap256(hash_swap, hash);
swap256(block_hash_swap, hash+4); swap256(block_hash_swap, hash + 4);
/* Don't free current_hash directly to avoid dereferencing when read /* Don't free current_hash directly to avoid dereferencing when read
* elsewhere - and update block_timeval inside the same lock */ * elsewhere - and update block_timeval inside the same lock */
mutex_lock(&ch_lock); mutex_lock(&ch_lock);
gettimeofday(&block_timeval, NULL); gettimeofday(&block_timeval, NULL);
old_hash = current_hash; old_hash = current_hash;
current_hash = bin2hex(hash_swap, 16); current_hash = bin2hex(hash_swap + 2, 12);
free(old_hash); free(old_hash);
old_hash = current_fullhash; old_hash = current_fullhash;
current_fullhash = bin2hex(block_hash_swap, 32); current_fullhash = bin2hex(block_hash_swap, 32);
@ -3793,13 +3828,16 @@ static void display_options(void)
clear_logwin(); clear_logwin();
retry: retry:
wlogprint("[N]ormal [C]lear [S]ilent mode (disable all output)\n"); wlogprint("[N]ormal [C]lear [S]ilent mode (disable all output)\n");
wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n[R]PC debug:%s\n[W]orkTime details:%s\n[L]og interval:%d\n", wlogprint("[D]ebug:%s\n[P]er-device:%s\n[Q]uiet:%s\n[V]erbose:%s\n"
"[R]PC debug:%s\n[W]orkTime details:%s\nco[M]pact: %s\n"
"[L]og interval:%d\n",
opt_debug ? "on" : "off", opt_debug ? "on" : "off",
want_per_device_stats? "on" : "off", want_per_device_stats? "on" : "off",
opt_quiet ? "on" : "off", opt_quiet ? "on" : "off",
opt_log_output ? "on" : "off", opt_log_output ? "on" : "off",
opt_protocol ? "on" : "off", opt_protocol ? "on" : "off",
opt_worktime ? "on" : "off", opt_worktime ? "on" : "off",
opt_compact ? "on" : "off",
opt_log_interval); opt_log_interval);
wlogprint("Select an option or any other key to return\n"); wlogprint("Select an option or any other key to return\n");
input = getch(); input = getch();
@ -3818,8 +3856,10 @@ retry:
opt_debug = false; opt_debug = false;
opt_quiet = false; opt_quiet = false;
opt_protocol = false; opt_protocol = false;
opt_compact = false;
want_per_device_stats = false; want_per_device_stats = false;
wlogprint("Output mode reset to normal\n"); wlogprint("Output mode reset to normal\n");
switch_compact();
goto retry; goto retry;
} else if (!strncasecmp(&input, "d", 1)) { } else if (!strncasecmp(&input, "d", 1)) {
opt_debug ^= true; opt_debug ^= true;
@ -3828,6 +3868,11 @@ retry:
opt_quiet = false; opt_quiet = false;
wlogprint("Debug mode %s\n", opt_debug ? "enabled" : "disabled"); wlogprint("Debug mode %s\n", opt_debug ? "enabled" : "disabled");
goto retry; goto retry;
} else if (!strncasecmp(&input, "m", 1)) {
opt_compact ^= true;
wlogprint("Compact mode %s\n", opt_compact ? "enabled" : "disabled");
switch_compact();
goto retry;
} else if (!strncasecmp(&input, "p", 1)) { } else if (!strncasecmp(&input, "p", 1)) {
want_per_device_stats ^= true; want_per_device_stats ^= true;
opt_log_output = want_per_device_stats; opt_log_output = want_per_device_stats;
@ -4278,11 +4323,11 @@ static void *stratum_thread(void *userdata)
FD_ZERO(&rd); FD_ZERO(&rd);
FD_SET(pool->sock, &rd); FD_SET(pool->sock, &rd);
timeout.tv_sec = 120; timeout.tv_sec = 90;
timeout.tv_usec = 0; timeout.tv_usec = 0;
/* The protocol specifies that notify messages should be sent /* The protocol specifies that notify messages should be sent
* every minute so if we fail to receive any for 2 minutes we * every minute so if we fail to receive any for 90 seconds we
* assume the connection has been dropped and treat this pool * assume the connection has been dropped and treat this pool
* as dead */ * as dead */
select(pool->sock + 1, &rd, NULL, NULL, &timeout); select(pool->sock + 1, &rd, NULL, NULL, &timeout);
@ -5646,6 +5691,7 @@ static void print_summary(void)
applog(LOG_WARNING, "Average hashrate: %.1f %shash/s", displayed_hashes, mhash_base? "Mega" : "Kilo"); applog(LOG_WARNING, "Average hashrate: %.1f %shash/s", displayed_hashes, mhash_base? "Mega" : "Kilo");
applog(LOG_WARNING, "Solved blocks: %d", found_blocks); applog(LOG_WARNING, "Solved blocks: %d", found_blocks);
applog(LOG_WARNING, "Best share difficulty: %s", best_share);
applog(LOG_WARNING, "Queued work requests: %d", total_getworks); applog(LOG_WARNING, "Queued work requests: %d", total_getworks);
applog(LOG_WARNING, "Share submissions: %d", total_accepted + total_rejected); applog(LOG_WARNING, "Share submissions: %d", total_accepted + total_rejected);
applog(LOG_WARNING, "Accepted shares: %d", total_accepted); applog(LOG_WARNING, "Accepted shares: %d", total_accepted);
@ -6291,12 +6337,13 @@ int main(int argc, char *argv[])
for (i = 0; i < total_devices; ++i) for (i = 0; i < total_devices; ++i)
devices[i]->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET; devices[i]->cgminer_stats.getwork_wait_min.tv_sec = MIN_SEC_UNSET;
logstart += total_devices; if (!opt_compact) {
logcursor = logstart + 1; logstart += total_devices;
logcursor = logstart + 1;
#ifdef HAVE_CURSES #ifdef HAVE_CURSES
check_winsizes(); check_winsizes();
#endif #endif
}
if (!total_pools) { if (!total_pools) {
applog(LOG_WARNING, "Need to specify at least one pool server."); applog(LOG_WARNING, "Need to specify at least one pool server.");

View File

@ -2,7 +2,7 @@
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
m4_define([v_maj], [2]) m4_define([v_maj], [2])
m4_define([v_min], [8]) m4_define([v_min], [8])
m4_define([v_mic], [5]) m4_define([v_mic], [6])
##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--## ##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
m4_define([v_ver], [v_maj.v_min.v_mic]) m4_define([v_ver], [v_maj.v_min.v_mic])
m4_define([lt_rev], m4_eval(v_maj + v_min)) m4_define([lt_rev], m4_eval(v_maj + v_min))

74
util.c
View File

@ -196,39 +196,41 @@ out:
return ptrlen; return ptrlen;
} }
int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd, static int keep_sockalive(SOCKETTYPE fd)
curlsocktype __maybe_unused purpose)
{ {
int tcp_keepidle = 120; const int tcp_keepidle = 60;
int tcp_keepintvl = 120; const int tcp_keepintvl = 60;
const int keepalive = 1;
int ret = 0;
#ifndef WIN32 #ifndef WIN32
int keepalive = 1; const int tcp_keepcnt = 5;
int tcp_keepcnt = 5;
if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)))) if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive))))
return 1; ret = 1;
# ifdef __linux # ifdef __linux
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_keepcnt, sizeof(tcp_keepcnt)))) if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &tcp_keepcnt, sizeof(tcp_keepcnt))))
return 1; ret = 1;
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle)))) if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &tcp_keepidle, sizeof(tcp_keepidle))))
return 1; ret = 1;
if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl)))) if (unlikely(setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &tcp_keepintvl, sizeof(tcp_keepintvl))))
return 1; ret = 1;
# endif /* __linux */ # endif /* __linux */
# ifdef __APPLE_CC__ # ifdef __APPLE_CC__
if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl)))) if (unlikely(setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &tcp_keepintvl, sizeof(tcp_keepintvl))))
return 1; ret = 1;
# endif /* __APPLE_CC__ */ # endif /* __APPLE_CC__ */
#else /* WIN32 */ #else /* WIN32 */
const int zero = 0;
struct tcp_keepalive vals; struct tcp_keepalive vals;
vals.onoff = 1; vals.onoff = 1;
vals.keepalivetime = tcp_keepidle * 1000; vals.keepalivetime = tcp_keepidle * 1000;
@ -236,12 +238,26 @@ int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd,
DWORD outputBytes; DWORD outputBytes;
if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0, &outputBytes, NULL, NULL))) if (unlikely(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&keepalive, sizeof(keepalive))))
return 1; ret = 1;
if (unlikely(WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0, &outputBytes, NULL, NULL)))
ret = 1;
/* Windows happily submits indefinitely to the send buffer blissfully
* unaware nothing is getting there without gracefully failing unless
* we disable the send buffer */
if (unlikely(setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (const char *)&zero, sizeof(zero))))
ret = 1;
#endif /* WIN32 */ #endif /* WIN32 */
return 0; return ret;
}
int json_rpc_call_sockopt_cb(void __maybe_unused *userdata, curl_socket_t fd,
curlsocktype __maybe_unused purpose)
{
return keep_sockalive(fd);
} }
static void last_nettime(struct timeval *last) static void last_nettime(struct timeval *last)
@ -823,6 +839,7 @@ bool extract_sockaddr(struct pool *pool, char *url)
struct addrinfo hints, *res; struct addrinfo hints, *res;
int url_len, port_len = 0; int url_len, port_len = 0;
pool->sockaddr_url = url;
url_begin = strstr(url, "//"); url_begin = strstr(url, "//");
if (!url_begin) if (!url_begin)
url_begin = url; url_begin = url;
@ -881,8 +898,8 @@ static bool __stratum_send(struct pool *pool, char *s, ssize_t len)
while (len > 0 ) { while (len > 0 ) {
struct timeval timeout = {0, 0}; struct timeval timeout = {0, 0};
CURLcode rc = CURLE_SEND_ERROR;
size_t sent = 0; size_t sent = 0;
CURLcode rc;
fd_set wd; fd_set wd;
FD_ZERO(&wd); FD_ZERO(&wd);
@ -891,8 +908,7 @@ static bool __stratum_send(struct pool *pool, char *s, ssize_t len)
applog(LOG_DEBUG, "Write select failed on pool %d sock", pool->pool_no); applog(LOG_DEBUG, "Write select failed on pool %d sock", pool->pool_no);
return false; return false;
} }
if (likely(pool->stratum_curl)) rc = curl_easy_send(pool->stratum_curl, s + ssent, len, &sent);
rc = curl_easy_send(pool->stratum_curl, s + ssent, len, &sent);
if (rc != CURLE_OK) { if (rc != CURLE_OK) {
applog(LOG_DEBUG, "Failed to curl_easy_send in stratum_send"); applog(LOG_DEBUG, "Failed to curl_easy_send in stratum_send");
return false; return false;
@ -925,8 +941,7 @@ static void clear_sock(struct pool *pool)
mutex_lock(&pool->stratum_lock); mutex_lock(&pool->stratum_lock);
/* Ignore return code of curl_easy_recv since we're just clearing /* Ignore return code of curl_easy_recv since we're just clearing
* anything in the socket if it's still alive */ * anything in the socket if it's still alive */
if (likely(pool->stratum_curl)) curl_easy_recv(pool->stratum_curl, pool->sockbuf, RECVSIZE, &n);
curl_easy_recv(pool->stratum_curl, pool->sockbuf, RECVSIZE, &n);
mutex_unlock(&pool->stratum_lock); mutex_unlock(&pool->stratum_lock);
strcpy(pool->sockbuf, ""); strcpy(pool->sockbuf, "");
} }
@ -962,9 +977,9 @@ char *recv_line(struct pool *pool)
size_t n = 0; size_t n = 0;
if (!strstr(pool->sockbuf, "\n")) { if (!strstr(pool->sockbuf, "\n")) {
CURLcode rc = CURLE_RECV_ERROR;
char s[RBUFSIZE]; char s[RBUFSIZE];
size_t sspace; size_t sspace;
CURLcode rc;
if (!sock_full(pool, true)) { if (!sock_full(pool, true)) {
applog(LOG_DEBUG, "Timed out waiting for data on sock_full"); applog(LOG_DEBUG, "Timed out waiting for data on sock_full");
@ -973,8 +988,7 @@ char *recv_line(struct pool *pool)
memset(s, 0, RBUFSIZE); memset(s, 0, RBUFSIZE);
mutex_lock(&pool->stratum_lock); mutex_lock(&pool->stratum_lock);
if (likely(pool->stratum_curl)) rc = curl_easy_recv(pool->stratum_curl, s, RECVSIZE, &n);
rc = curl_easy_recv(pool->stratum_curl, s, RECVSIZE, &n);
mutex_unlock(&pool->stratum_lock); mutex_unlock(&pool->stratum_lock);
if (rc != CURLE_OK) { if (rc != CURLE_OK) {
@ -1314,7 +1328,6 @@ bool initiate_stratum(struct pool *pool)
mutex_lock(&pool->stratum_lock); mutex_lock(&pool->stratum_lock);
pool->stratum_active = false; pool->stratum_active = false;
if (!pool->stratum_curl) { if (!pool->stratum_curl) {
pool->stratum_curl = curl_easy_init(); pool->stratum_curl = curl_easy_init();
if (unlikely(!pool->stratum_curl)) if (unlikely(!pool->stratum_curl))
@ -1327,7 +1340,8 @@ bool initiate_stratum(struct pool *pool)
memset(s, 0, RBUFSIZE); memset(s, 0, RBUFSIZE);
sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port); sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 60); curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_err_str);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_URL, s); curl_easy_setopt(curl, CURLOPT_URL, s);
@ -1346,6 +1360,7 @@ bool initiate_stratum(struct pool *pool)
goto out; goto out;
} }
curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&pool->sock); curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&pool->sock);
keep_sockalive(pool->sock);
sprintf(s, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": []}", swork_id++); sprintf(s, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": []}", swork_id++);
@ -1414,15 +1429,8 @@ out:
applog(LOG_DEBUG, "Pool %d confirmed mining.subscribe with extranonce1 %s extran2size %d", applog(LOG_DEBUG, "Pool %d confirmed mining.subscribe with extranonce1 %s extran2size %d",
pool->pool_no, pool->nonce1, pool->n2size); pool->pool_no, pool->nonce1, pool->n2size);
} }
} else { } else
applog(LOG_DEBUG, "Initiate stratum failed, disabling stratum_active"); applog(LOG_DEBUG, "Initiate stratum failed");
mutex_lock(&pool->stratum_lock);
if (curl) {
curl_easy_cleanup(curl);
pool->stratum_curl = NULL;
}
mutex_unlock(&pool->stratum_lock);
}
return ret; return ret;
} }