From bfec616da3f148593debe8707d0aa6a567c4fee8 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 27 May 2014 17:28:58 +1000 Subject: [PATCH] Create new proxy entries on the fly with the client reconnect command and switch to it --- src/ckpool.h | 1 + src/generator.c | 91 +++++++++++++++++++++++++++++++++++++++++++----- src/stratifier.c | 1 + 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/ckpool.h b/src/ckpool.h index ea46e183..d23179f6 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -97,6 +97,7 @@ struct ckpool_instance { server_instance_t **servers; char *serverurl; // URL to bind our server/proxy to int update_interval; // Seconds between stratum updates + int chosen_server; // Chosen server for next connection /* Proxy options */ int proxies; diff --git a/src/generator.c b/src/generator.c index cf5197eb..aa21be09 100644 --- a/src/generator.c +++ b/src/generator.c @@ -82,6 +82,7 @@ struct proxy_instance { bool notified; /* Received new template for work */ bool diffed; /* Received new diff */ + bool reconnect; /* We need to drop and reconnect */ pthread_mutex_t notify_lock; notify_instance_t *notify_instances; @@ -516,8 +517,6 @@ out: return ret; } -#define parse_reconnect(a, b) true - static bool parse_notify(proxy_instance_t *proxi, json_t *val) { const char *prev_hash, *bbversion, *nbit, *ntime; @@ -626,6 +625,66 @@ static bool show_message(json_t *val) return true; } +static bool parse_reconnect(proxy_instance_t *proxi, json_t *val) +{ + server_instance_t *newsi, *si = proxi->si; + ckpool_t *ckp = proxi->ckp; + const char *new_url; + bool ret = false; + int new_port; + char *url; + + new_url = json_string_value(json_array_get(val, 0)); + new_port = json_integer_value(json_array_get(val, 1)); + if (new_url && strlen(new_url) && new_port) { + char *dot_pool, *dot_reconnect; + int len; + + dot_pool = strchr(si->url, '.'); + if (!dot_pool) { + LOGWARNING("Denied stratum reconnect request from server without domain %s", + si->url); + goto out; + } + dot_reconnect = strchr(new_url, '.'); + if (!dot_reconnect) { + LOGWARNING("Denied stratum reconnect request to url without domain %s", + new_url); + goto out; + } + len = strlen(dot_reconnect); + if (strncmp(dot_pool, dot_reconnect, len)) { + LOGWARNING("Denied stratum reconnect request from %s to non-matching domain %s", + si->url, new_url); + goto out; + } + asprintf(&url, "%s:%d", new_url, new_port); + } else + url = strdup(si->url); + LOGINFO("Processing reconnect request to %s", url); + + ret = true; + newsi = ckzalloc(sizeof(server_instance_t)); + newsi->id = ckp->proxies++; + ckp->servers = realloc(ckp->servers, sizeof(server_instance_t *) * ckp->proxies); + ckp->servers[newsi->id] = newsi; + ckp->chosen_server = newsi->id; + newsi->url = url; + newsi->auth = strdup(si->auth); + newsi->pass = strdup(si->pass); + proxi->reconnect = true; + + proxi = ckzalloc(sizeof(proxy_instance_t)); + newsi->data = proxi; + proxi->auth = newsi->auth; + proxi->pass = newsi->pass; + proxi->si = newsi; + proxi->ckp = ckp; + proxi->cs = &newsi->cs; +out: + return ret; +} + static bool parse_method(proxy_instance_t *proxi, const char *msg) { json_t *val = NULL, *method, *err_val, *params; @@ -950,6 +1009,12 @@ static void *proxy_recv(void *arg) send_proc(ckp->stratifier, "diff"); proxi->diffed = false; } + if (proxi->reconnect) { + proxi->reconnect = false; + LOGWARNING("Reconnect issue, dropping existing connection"); + send_proc(ckp->generator, "reconnect"); + break; + } continue; } if (parse_share(proxi, cs->buf)) { @@ -1029,7 +1094,7 @@ static proxy_instance_t *live_proxy(ckpool_t *ckp) LOGDEBUG("Attempting to connect to proxy"); retry: - for (i = 0; i < ckp->proxies; i++) { + for (i = ckp->chosen_server; i < ckp->proxies; i++) { proxy_instance_t *proxi; server_instance_t *si; @@ -1060,10 +1125,13 @@ retry: break; } if (!alive) { - LOGWARNING("Failed to connect to any servers as proxy, retrying in 5s!"); - sleep(5); + if (!ckp->chosen_server) { + LOGWARNING("Failed to connect to any servers as proxy, retrying in 5s!"); + sleep(5); + } goto retry; } + ckp->chosen_server = 0; cs = alive->cs; LOGNOTICE("Connected to upstream server %s:%s as proxy", cs->url, cs->port); mutex_init(&alive->notify_lock); @@ -1199,9 +1267,10 @@ static int proxy_mode(ckpool_t *ckp, proc_instance_t *pi) for (i = 0; i < ckp->proxies; i++) { ckp->servers[i] = ckzalloc(sizeof(server_instance_t)); si = ckp->servers[i]; - si->url = ckp->proxyurl[i]; - si->auth = ckp->proxyauth[i]; - si->pass = ckp->proxypass[i]; + si->id = i; + si->url = strdup(ckp->proxyurl[i]); + si->auth = strdup(ckp->proxyauth[i]); + si->pass = strdup(ckp->proxypass[i]); proxi = ckzalloc(sizeof(proxy_instance_t)); si->data = proxi; proxi->auth = si->auth; @@ -1213,13 +1282,17 @@ static int proxy_mode(ckpool_t *ckp, proc_instance_t *pi) ret = proxy_loop(pi); - for (i = 0; i < ckp->proxies; si = ckp->servers[i], i++) { + for (i = 0; i < ckp->proxies; i++) { + si = ckp->servers[i]; close(si->cs.fd); proxi = si->data; free(proxi->enonce1); free(proxi->enonce1bin); free(proxi->sessionid); dealloc(si->data); + dealloc(si->url); + dealloc(si->auth); + dealloc(si->pass); dealloc(si); } dealloc(ckp->servers); diff --git a/src/stratifier.c b/src/stratifier.c index ab14a288..c028ff80 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -872,6 +872,7 @@ static int stratum_loop(ckpool_t *ckp, proc_instance_t *pi) to = &timeout; reset: timeout.tv_sec = ckp->update_interval; + timeout.tv_usec = 0; retry: FD_ZERO(&readfds); FD_SET(us->sockd, &readfds);