diff --git a/src/ckpool.h b/src/ckpool.h index f23dedf4..6bb7784a 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -224,6 +224,7 @@ struct ckpool_instance { char **proxyurl; char **proxyauth; char **proxypass; + server_instance_t *btcdbackup; /* Passthrough redirect options */ int redirecturls; diff --git a/src/connector.c b/src/connector.c index 46142cc4..1c8ff948 100644 --- a/src/connector.c +++ b/src/connector.c @@ -61,6 +61,8 @@ struct client_instance { /* Is this the parent passthrough client */ bool passthrough; + /* Is this a parent relay passthrough node client */ + bool node; /* Linked list of shares in redirector mode.*/ share_t *shares; @@ -897,13 +899,14 @@ static bool client_exists(cdata_t *cdata, const int64_t id) return !!client; } -static void passthrough_client(cdata_t *cdata, client_instance_t *client) +static void passthrough_client(cdata_t *cdata, client_instance_t *client, const bool node) { char *buf; - LOGINFO("Connector adding passthrough client %"PRId64, client->id); + LOGINFO("Connector adding passthrough %sclient %"PRId64, node ? "node " : "", client->id); client->passthrough = true; - ASPRINTF(&buf, "{\"result\": true}\n"); + client->node = node; + ASPRINTF(&buf, "{\"result\": true, \"node\": %s}\n", node ? "true" : "false"); send_client(cdata, client->id, buf); } @@ -1090,7 +1093,22 @@ retry: LOGINFO("Connector failed to find client id %"PRId64" to pass through", client_id); goto retry; } - passthrough_client(cdata, client); + passthrough_client(cdata, client, false); + dec_instance_ref(cdata, client); + } else if (cmdmatch(buf, "node")) { + client_instance_t *client; + + ret = sscanf(buf, "node=%"PRId64, &client_id); + if (ret < 0) { + LOGDEBUG("Connector failed to parse node command: %s", buf); + goto retry; + } + client = ref_client_by_id(cdata, client_id); + if (unlikely(!client)) { + LOGINFO("Connector failed to find client id %"PRId64" to node pass through", client_id); + goto retry; + } + passthrough_client(cdata, client, true); dec_instance_ref(cdata, client); } else if (cmdmatch(buf, "getxfd")) { int fdno = -1; diff --git a/src/generator.c b/src/generator.c index 6ddfa64a..3dae8a1f 100644 --- a/src/generator.c +++ b/src/generator.c @@ -2676,6 +2676,41 @@ static proxy_instance_t *__add_proxy(ckpool_t *ckp, gdata_t *gdata, const int id return proxy; } +static bool alive_btcd(server_instance_t *si) +{ + connsock_t *cs = &si->cs; + char *userpass = NULL; + gbtbase_t gbt; + + if (!extract_sockaddr(si->url, &cs->url, &cs->port)) { + LOGWARNING("Failed to extract address from btcd %s", si->url); + return false; + } + userpass = strdup(si->auth); + realloc_strcat(&userpass, ":"); + realloc_strcat(&userpass, si->pass); + cs->auth = http_base64(userpass); + dealloc(userpass); + if (!cs->auth) { + LOGWARNING("Failed to create base64 auth from btcd %s", userpass); + return false; + } + if (cs->fd < 0) { + LOGWARNING("Failed to connect socket to btcd %s:%s !", cs->url, cs->port); + return false; + } + keep_sockalive(cs->fd); + /* Test we can authorise by getting a gbt, but we won't be using it. */ + memset(&gbt, 0, sizeof(gbtbase_t)); + if (!gen_gbtbase(cs, &gbt)) { + LOGINFO("Failed to get test block template from btcd %s:%s!", + cs->url, cs->port); + return false; + } + clear_gbtbase(&gbt); + return true; +} + static int proxy_mode(ckpool_t *ckp, proc_instance_t *pi) { gdata_t *gdata = ckp->data; @@ -2701,6 +2736,28 @@ static int proxy_mode(ckpool_t *ckp, proc_instance_t *pi) } } + if (ckp->node) { + if (ckp->btcds) { + /* If we also have btcds set up in node mode, try to talk to + * one of them as a way to submit blocks if we find them when + * submitting them upstream. */ + server_instance_t *si = ckp->btcdbackup = ckzalloc(sizeof(server_instance_t)); + + si->url = ckp->btcdurl[0]; + si->auth = ckp->btcdauth[0]; + si->pass = ckp->btcdpass[0]; + if (alive_btcd(si)) { + LOGNOTICE("Node backup btcd %s:%s alive", si->cs.url, si->cs.port); + } else { + LOGWARNING("Node backup btcd %s:%s failed! Will run as ordinary passthrough", + si->cs.url, si->cs.port); + ckp->btcdbackup = NULL; + free(si); + } + } else + LOGWARNING("No backup btcd specified in node mode! Will run as ordinary passthrough"); + } + LOGWARNING("%s generator ready", ckp->name); ret = proxy_loop(pi);