diff --git a/src/connector.c b/src/connector.c index 1046a869..576636c1 100644 --- a/src/connector.c +++ b/src/connector.c @@ -73,6 +73,8 @@ struct client_instance { /* Has this client already been told to redirect */ bool redirected; + /* Has this client been authorised in redirector mode */ + bool authorised; /* Time this client started blocking, 0 when not blocked */ time_t blocked_time; @@ -587,6 +589,19 @@ static client_instance_t *ref_client_by_id(cdata_t *cdata, int64_t id) return client; } +static void redirect_client(ckpool_t *ckp, client_instance_t *client); + +static bool redirect_matches(cdata_t *cdata, client_instance_t *client) +{ + redirect_t *redirect; + + ck_rlock(&cdata->lock); + HASH_FIND_STR(cdata->redirects, client->address_name, redirect); + ck_runlock(&cdata->lock); + + return redirect; +} + static void client_event_processor(ckpool_t *ckp, struct epoll_event *event) { const uint32_t events = event->events; @@ -1004,8 +1019,15 @@ static void send_client(cdata_t *cdata, const int64_t id, char *buf) json_object_set_new_nocheck(val, "server", json_integer(client->server)); stratifier_add_recv(ckp, val); } - if (ckp->redirector && !client->redirected) - redirect = test_redirector_shares(cdata, client, buf); + if (ckp->redirector && !client->redirected && client->authorised) { + /* If clients match the IP of clients that have already + * been whitelisted as finding valid shares then + * redirect them immediately. */ + if (redirect_matches(cdata, client)) + redirect = true; + else + redirect = test_redirector_shares(cdata, client, buf); + } } out: sender_send = ckzalloc(sizeof(sender_send_t)); @@ -1019,7 +1041,7 @@ out: pthread_cond_signal(&cdata->sender_cond); mutex_unlock(&cdata->sender_lock); - /* Redirect after sending response to shares */ + /* Redirect after sending response to shares and authorise */ if (unlikely(redirect)) redirect_client(ckp, client); } @@ -1257,6 +1279,7 @@ out: static void client_message_processor(ckpool_t *ckp, json_t *json_msg) { + cdata_t *cdata = ckp->cdata; int64_t client_id; char *msg; @@ -1268,8 +1291,23 @@ static void client_message_processor(ckpool_t *ckp, json_t *json_msg) if (client_id > 0xffffffffll) json_object_set_new_nocheck(json_msg, "client_id", json_integer(client_id & 0xffffffffll)); + /* Flag redirector clients once they've been authorised */ + if (ckp->redirector) { + client_instance_t *client = ref_client_by_id(cdata, client_id); + + if (likely(client)) { + if (!client->redirected && !client->authorised) { + json_t *method_val = json_object_get(json_msg, "node.method"); + const char *method = json_string_value(method_val); + + if (!safecmp(method, stratum_msgs[SM_AUTHRESULT])) + client->authorised = true; + } + dec_instance_ref(cdata, client); + } + } msg = json_dumps(json_msg, JSON_EOL | JSON_COMPACT); - send_client(ckp->cdata, client_id, msg); + send_client(cdata, client_id, msg); json_decref(json_msg); }