Browse Source

Parse and act upon upstream auth responses in trusted mode.

master
Con Kolivas 8 years ago
parent
commit
17d9c837d1
  1. 4
      src/connector.c
  2. 166
      src/stratifier.c
  3. 2
      src/stratifier.h

4
src/connector.c

@ -1204,7 +1204,9 @@ static void *urecv_process(void *arg)
goto decref; goto decref;
} }
if (!safecmp(method, stratum_msgs[SM_TRANSACTIONS])) if (!safecmp(method, stratum_msgs[SM_TRANSACTIONS]))
parse_remote_txns(ckp, val); parse_upstream_txns(ckp, val);
else if (!safecmp(method, stratum_msgs[SM_AUTHRESULT]))
parse_upstream_auth(ckp, val);
else if (!safecmp(method, "submitblock")) else if (!safecmp(method, "submitblock"))
parse_remote_submitblock(ckp, val, cs->buf); parse_remote_submitblock(ckp, val, cs->buf);
else if (!safecmp(method, "pong")) else if (!safecmp(method, "pong"))

166
src/stratifier.c

@ -312,6 +312,7 @@ struct stratum_instance {
int subproxyid; /* Which subproxy */ int subproxyid; /* Which subproxy */
bool trusted; /* Is this a trusted remote server */ bool trusted; /* Is this a trusted remote server */
bool remote; /* Is this a remote client on a trusted remote server */
}; };
struct share { struct share {
@ -5218,6 +5219,41 @@ static void check_global_user(ckpool_t *ckp, user_instance_t *user, stratum_inst
send_generator(ckp, buf, GEN_LAX); send_generator(ckp, buf, GEN_LAX);
} }
/* Manage the response to auth, client must hold ref */
static void client_auth(ckpool_t *ckp, stratum_instance_t *client, user_instance_t *user,
const bool ret)
{
if (ret) {
client->authorised = ret;
user->authorised = ret;
if (ckp->proxy) {
LOGNOTICE("Authorised client %s to proxy %d:%d, worker %s as user %s",
client->identity, client->proxyid, client->subproxyid,
client->workername, user->username);
if (ckp->userproxy)
check_global_user(ckp, user, client);
} else {
LOGNOTICE("Authorised client %s worker %s as user %s",
client->identity, client->workername, user->username);
}
user->failed_authtime = 0;
user->auth_backoff = DEFAULT_AUTH_BACKOFF; /* Reset auth backoff time */
user->throttled = false;
} else {
LOGNOTICE("Client %s %s worker %s failed to authorise as user %s",
client->identity, client->address, client->workername,
user->username);
user->failed_authtime = time(NULL);
user->auth_backoff <<= 1;
/* Cap backoff time to 10 mins */
if (user->auth_backoff > 600)
user->auth_backoff = 600;
client->reject = 3;
}
/* We can set this outside of lock safely */
client->authorising = false;
}
/* Needs to be entered with client holding a ref count. */ /* Needs to be entered with client holding a ref count. */
static json_t *parse_authorise(stratum_instance_t *client, const json_t *params_val, static json_t *parse_authorise(stratum_instance_t *client, const json_t *params_val,
json_t **err_val, int *errnum) json_t **err_val, int *errnum)
@ -5308,35 +5344,8 @@ static json_t *parse_authorise(stratum_instance_t *client, const json_t *params_
/* We do the preauth etc. in remote mode, and leave final auth to /* We do the preauth etc. in remote mode, and leave final auth to
* upstream pool to complete. */ * upstream pool to complete. */
if (ckp->remote) if (!ckp->remote)
goto out; client_auth(ckp, client, user, ret);
if (ret) {
client->authorised = ret;
user->authorised = ret;
if (ckp->proxy) {
LOGNOTICE("Authorised client %s to proxy %d:%d, worker %s as user %s",
client->identity, client->proxyid, client->subproxyid, buf, user->username);
if (ckp->userproxy)
check_global_user(ckp, user, client);
} else {
LOGNOTICE("Authorised client %s worker %s as user %s",
client->identity, buf, user->username);
}
user->failed_authtime = 0;
user->auth_backoff = DEFAULT_AUTH_BACKOFF; /* Reset auth backoff time */
user->throttled = false;
} else {
LOGNOTICE("Client %s %s worker %s failed to authorise as user %s",
client->identity, client->address, buf,user->username);
user->failed_authtime = time(NULL);
user->auth_backoff <<= 1;
/* Cap backoff time to 10 mins */
if (user->auth_backoff > 600)
user->auth_backoff = 600;
}
/* We can set this outside of lock safely */
client->authorising = false;
out: out:
return json_boolean(ret); return json_boolean(ret);
} }
@ -6507,6 +6516,70 @@ void parse_remote_txns(ckpool_t *ckp, const json_t *val)
LOGNOTICE("Submitted %d remote transactions", added); LOGNOTICE("Submitted %d remote transactions", added);
} }
static void send_auth_response(sdata_t *sdata, const int64_t client_id, const bool ret,
json_t *id_val, json_t *err_val)
{
json_t *json_msg = json_object();
json_object_set_new_nocheck(json_msg, "result", json_boolean(ret));
json_object_set_new_nocheck(json_msg, "error", err_val ? err_val : json_null());
json_object_set(json_msg, "id", id_val);
stratum_add_send(sdata, json_msg, client_id, SM_AUTHRESULT);
}
static void send_auth_success(ckpool_t *ckp, sdata_t *sdata, stratum_instance_t *client)
{
char *buf;
ASPRINTF(&buf, "Authorised, welcome to %s %s!", ckp->name,
client->user_instance->username);
stratum_send_message(sdata, client, buf);
free(buf);
}
static void send_auth_failure(sdata_t *sdata, stratum_instance_t *client)
{
stratum_send_message(sdata, client, "Failed authorisation :(");
}
void parse_upstream_auth(ckpool_t *ckp, json_t *val)
{
json_t *json_msg, *id_val = NULL, *err_val = NULL;
sdata_t *sdata = ckp->sdata;
stratum_instance_t *client;
bool ret, warn = false;
int64_t client_id;
id_val = json_object_get(val, "id");
if (unlikely(!id_val))
goto out;
if (unlikely(!json_get_int64(&client_id, val, "client_id")))
goto out;
if (unlikely(!json_get_bool(&ret, val, "result")))
goto out;
err_val = json_object_get(val, "error");
client = ref_instance_by_id(sdata, client_id);
if (!client) {
LOGINFO("Failed to find client id %"PRId64" in parse_upstream_auth",
client_id);
goto out;
}
if (ret)
send_auth_success(ckp, sdata, client);
else
send_auth_failure(sdata, client);
send_auth_response(sdata, client_id, ret, id_val, err_val);
client_auth(ckp, client, client->user_instance, ret);
dec_instance_ref(sdata, client);
out:
if (unlikely(warn)) {
char *s = json_dumps(val, 0);
LOGWARNING("Failed to get valid upstream result in parse_upstream_auth %s", s);
free(s);
}
}
#define parse_remote_workinfo(ckp, val) add_node_base(ckp, val) #define parse_remote_workinfo(ckp, val) add_node_base(ckp, val)
static void parse_remote_auth(ckpool_t *ckp, sdata_t *sdata, json_t *val, stratum_instance_t *remote, static void parse_remote_auth(ckpool_t *ckp, sdata_t *sdata, json_t *val, stratum_instance_t *remote,
@ -6534,11 +6607,12 @@ static void parse_remote_auth(ckpool_t *ckp, sdata_t *sdata, json_t *val, stratu
if (likely(!client)) if (likely(!client))
client = __stratum_add_instance(ckp, client_id, remote->address, remote->server); client = __stratum_add_instance(ckp, client_id, remote->address, remote->server);
__inc_instance_ref(client); __inc_instance_ref(client);
ck_wunlock(&sdata->instance_lock); client->remote = true;
json_strdup(&client->useragent, val, "useragent"); json_strdup(&client->useragent, val, "useragent");
json_strcpy(client->enonce1, val, "enonce1"); json_strcpy(client->enonce1, val, "enonce1");
json_strcpy(client->address, val, "address"); json_strcpy(client->address, val, "address");
ck_wunlock(&sdata->instance_lock);
ckmsgq_add(sdata->sauthq, jp); ckmsgq_add(sdata->sauthq, jp);
} }
@ -7031,11 +7105,12 @@ static void upstream_auth(ckpool_t *ckp, stratum_instance_t *client, json_params
static void sauth_process(ckpool_t *ckp, json_params_t *jp) static void sauth_process(ckpool_t *ckp, json_params_t *jp)
{ {
json_t *result_val, *json_msg, *err_val = NULL; json_t *result_val, *err_val = NULL;
sdata_t *sdata = ckp->sdata; sdata_t *sdata = ckp->sdata;
stratum_instance_t *client; stratum_instance_t *client;
int64_t mindiff, client_id; int64_t mindiff, client_id;
int errnum = 0; int errnum = 0;
bool ret;
client_id = jp->client_id; client_id = jp->client_id;
@ -7046,34 +7121,31 @@ static void sauth_process(ckpool_t *ckp, json_params_t *jp)
} }
result_val = parse_authorise(client, jp->params, &err_val, &errnum); result_val = parse_authorise(client, jp->params, &err_val, &errnum);
if (json_is_true(result_val)) { ret = json_is_true(result_val);
char *buf; if (ret) {
/* So far okay in remote mode, remainder to be done by upstream /* So far okay in remote mode, remainder to be done by upstream
* pool */ * pool */
if (ckp->remote) { if (ckp->remote) {
upstream_auth(ckp, client, jp); upstream_auth(ckp, client, jp);
goto out; goto out;
} }
send_auth_success(ckp, sdata, client);
ASPRINTF(&buf, "Authorised, welcome to %s %s!", ckp->name,
client->user_instance->username);
stratum_send_message(sdata, client, buf);
free(buf);
} else { } else {
if (errnum < 0) if (errnum < 0)
stratum_send_message(sdata, client, "Authorisations temporarily offline :("); stratum_send_message(sdata, client, "Authorisations temporarily offline :(");
else else
stratum_send_message(sdata, client, "Failed authorisation :("); send_auth_failure(sdata, client);
} }
json_msg = json_object(); send_auth_response(sdata, client_id, ret, jp->id_val, err_val);
json_object_set_new_nocheck(json_msg, "result", result_val); if (!ret)
json_object_set_new_nocheck(json_msg, "error", err_val ? err_val : json_null()); goto out;
steal_json_id(json_msg, jp);
stratum_add_send(sdata, json_msg, client_id, SM_AUTHRESULT);
if (!json_is_true(result_val)) if (client->remote) {
/* We don't need to keep a record of clients on remote trusted
* servers after auth'ing them. */
client->dropped = true;
goto out; goto out;
}
/* Update the client now if they have set a valid mindiff different /* Update the client now if they have set a valid mindiff different
* from the startdiff. suggest_diff overrides worker mindiff */ * from the startdiff. suggest_diff overrides worker mindiff */

2
src/stratifier.h

@ -11,6 +11,8 @@
#define STRATIFIER_H #define STRATIFIER_H
void parse_remote_txns(ckpool_t *ckp, const json_t *val); void parse_remote_txns(ckpool_t *ckp, const json_t *val);
#define parse_upstream_txns(ckp, val) parse_remote_txns(ckp, val)
void parse_upstream_auth(ckpool_t *ckp, json_t *val);
void stratifier_add_recv(ckpool_t *ckp, json_t *val); void stratifier_add_recv(ckpool_t *ckp, json_t *val);
void *stratifier(void *arg); void *stratifier(void *arg);

Loading…
Cancel
Save