Browse Source

Parse a proxy subscribe response as flexibly as possible

master
Con Kolivas 11 years ago
parent
commit
0f4dff3144
  1. 135
      src/generator.c

135
src/generator.c

@ -27,6 +27,7 @@ struct proxy_instance {
char *enonce1; char *enonce1;
char *enonce1bin; char *enonce1bin;
char *sessionid; char *sessionid;
int nonce2len;
tv_t last_message; tv_t last_message;
@ -196,8 +197,83 @@ static bool connect_proxy(connsock_t *cs)
return true; return true;
} }
/* Decode a string that should have a json message and return just the contents
* of the result key or NULL. */
static json_t *json_result(json_t *val)
{
json_t *res_val = NULL, *err_val;
res_val = json_object_get(val, "result");
if (json_is_null(res_val))
res_val = NULL;
if (!res_val) {
char *ss;
err_val = json_object_get(val, "error");
if (err_val)
ss = json_dumps(err_val, 0);
else
ss = strdup("(unknown reason)");
LOGWARNING("JSON-RPC decode failed: %s", ss);
free(ss);
}
return res_val;
}
/* Parse a string and return the json value it contains, if any, and the
* result in res_val. Return NULL if no result key is found. */
static json_t *json_msg_result(char *msg, json_t **res_val)
{
json_error_t err;
json_t *val;
*res_val = NULL;
val = json_loads(msg, 0, &err);
if (!val) {
LOGWARNING("Json decode failed(%d): %s", err.line, err.text);
goto out;
}
*res_val = json_result(val);
if (!*res_val) {
LOGWARNING("No json result found");
json_decref(val);
val = NULL;
}
out:
return val;
}
/* For some reason notify is buried at various different array depths so use
* a reentrant function to try and find it. */
static json_t *find_notify(json_t *val)
{
int arr_size, i;
json_t *ret;
const char *entry;
if (!json_is_array(val))
return NULL;
arr_size = json_array_size(val);
entry = json_string_value(json_array_get(val, 0));
if (entry && !strncasecmp(entry, "mining.notify", 13))
return val;
for (i = 0; i < arr_size; i++) {
json_t *arr_val;
arr_val = json_array_get(val, i);
ret = find_notify(arr_val);
if (ret)
break;
}
return ret;
}
static bool parse_subscribe(connsock_t *cs, proxy_instance_t *proxi) static bool parse_subscribe(connsock_t *cs, proxy_instance_t *proxi)
{ {
json_t *val = NULL, *res_val, *notify_val, *tmp;
const char *string;
bool ret = false; bool ret = false;
int size; int size;
@ -206,10 +282,63 @@ static bool parse_subscribe(connsock_t *cs, proxy_instance_t *proxi)
LOGWARNING("Failed to receive line in parse_subscribe"); LOGWARNING("Failed to receive line in parse_subscribe");
goto out; goto out;
} }
LOGWARNING("Got message: %s", cs->buf); val = json_msg_result(cs->buf, &res_val);
ret = true; if (!val) {
LOGWARNING("Failed to get a json result in parse_subscribe, got: %s", cs->buf);
goto out;
}
if (!json_is_array(res_val)) {
LOGWARNING("Result in parse_subscribe not an array");
goto out;
}
size = json_array_size(res_val);
if (size < 3) {
LOGWARNING("Result in parse_subscribe array too small");
goto out;
}
notify_val = find_notify(res_val);
if (!notify_val) {
LOGWARNING("Failed to find notify in parse_subscribe");
goto out;
}
if (!proxi->no_params && !proxi->no_sessionid && json_array_size(notify_val) > 1) {
/* Copy the session id if one exists. */
string = json_string_value(json_array_get(notify_val, 1));
if (string)
proxi->sessionid = strdup(string);
}
tmp = json_array_get(res_val, 1);
if (!tmp || !json_is_string(tmp)) {
LOGWARNING("Failed to parse enonce1 in parse_subscribe");
goto out;
}
string = json_string_value(tmp);
if (strlen(string) < 1) {
LOGWARNING("Invalid string length for enonce1 in parse_subscribe");
goto out;
}
proxi->enonce1 = strdup(string);
size = strlen(proxi->enonce1) / 2;
proxi->enonce1bin = ckalloc(size);
hex2bin(proxi->enonce1bin, proxi->enonce1, size);
tmp = json_array_get(res_val, 2);
if (!tmp || !json_is_integer(tmp)) {
LOGWARNING("Failed to parse nonce2len in parse_subscribe");
goto out;
}
size = json_integer_value(tmp);
if (size < 1 || size > 8) {
LOGWARNING("Invalid nonce2len %d in parse_subscribe", size);
goto out;
}
proxi->nonce2len = size;
LOGWARNING("Found notify with enonce %s nonce2len %d !", proxi->enonce1,
proxi->nonce2len);
out: out:
if (val)
json_decref(val);
return ret; return ret;
} }
@ -303,7 +432,7 @@ static int proxy_mode(ckpool_t *ckp, proc_instance_t *pi, connsock_t *cs,
const char *auth, const char *pass) const char *auth, const char *pass)
{ {
proxy_instance_t proxi; proxy_instance_t proxi;
int ret; int ret = 1;
memset(&proxi, 0, sizeof(proxi)); memset(&proxi, 0, sizeof(proxi));
if (!connect_proxy(cs)) { if (!connect_proxy(cs)) {

Loading…
Cancel
Save