|
|
@ -29,12 +29,6 @@ |
|
|
|
#include "miner.h" |
|
|
|
#include "miner.h" |
|
|
|
#include "util.h" |
|
|
|
#include "util.h" |
|
|
|
|
|
|
|
|
|
|
|
// Big enough for largest API request
|
|
|
|
|
|
|
|
// data is truncated at the end of the last record that fits
|
|
|
|
|
|
|
|
// but still closed correctly for JSON
|
|
|
|
|
|
|
|
// Current code assumes it can socket send this size + JSON_CLOSE + JSON_END
|
|
|
|
|
|
|
|
#define SOCKBUFSIZ 65432 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// BUFSIZ varies on Windows and Linux
|
|
|
|
// BUFSIZ varies on Windows and Linux
|
|
|
|
#define TMPBUFSIZ 8192 |
|
|
|
#define TMPBUFSIZ 8192 |
|
|
|
|
|
|
|
|
|
|
@ -126,7 +120,11 @@ static const char SEPARATOR = '|'; |
|
|
|
#define SEPSTR "|" |
|
|
|
#define SEPSTR "|" |
|
|
|
static const char GPUSEP = ','; |
|
|
|
static const char GPUSEP = ','; |
|
|
|
|
|
|
|
|
|
|
|
static const char *APIVERSION = "3.0"; |
|
|
|
#define CMDJOIN '+' |
|
|
|
|
|
|
|
#define JOIN_CMD "CMD=" |
|
|
|
|
|
|
|
#define BETWEEN_JOIN SEPSTR |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *APIVERSION = "3.1"; |
|
|
|
static const char *DEAD = "Dead"; |
|
|
|
static const char *DEAD = "Dead"; |
|
|
|
static const char *SICK = "Sick"; |
|
|
|
static const char *SICK = "Sick"; |
|
|
|
static const char *NOSTART = "NoStart"; |
|
|
|
static const char *NOSTART = "NoStart"; |
|
|
@ -215,9 +213,10 @@ static const char ISJSON = '{'; |
|
|
|
#define JSON_MINECOIN JSON1 _MINECOIN JSON2 |
|
|
|
#define JSON_MINECOIN JSON1 _MINECOIN JSON2 |
|
|
|
#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2 |
|
|
|
#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2 |
|
|
|
#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2 |
|
|
|
#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2 |
|
|
|
#define JSON_USBSTATS JSON1 _USBSTATS JSON2 |
|
|
|
|
|
|
|
#define JSON_END JSON4 JSON5 |
|
|
|
#define JSON_END JSON4 JSON5 |
|
|
|
#define JSON_END_TRUNCATED JSON4_TRUNCATED JSON5 |
|
|
|
#define JSON_END_TRUNCATED JSON4_TRUNCATED JSON5 |
|
|
|
|
|
|
|
#define JSON_BETWEEN_JOIN "," |
|
|
|
|
|
|
|
|
|
|
|
static const char *JSON_COMMAND = "command"; |
|
|
|
static const char *JSON_COMMAND = "command"; |
|
|
|
static const char *JSON_PARAMETER = "parameter"; |
|
|
|
static const char *JSON_PARAMETER = "parameter"; |
|
|
@ -296,7 +295,7 @@ static const char *JSON_PARAMETER = "parameter"; |
|
|
|
#define MSG_INVNUM 84 |
|
|
|
#define MSG_INVNUM 84 |
|
|
|
#define MSG_CONPAR 85 |
|
|
|
#define MSG_CONPAR 85 |
|
|
|
#define MSG_CONVAL 86 |
|
|
|
#define MSG_CONVAL 86 |
|
|
|
#define MSG_USBSTA 87 |
|
|
|
|
|
|
|
#define MSG_NOUSTA 88 |
|
|
|
#define MSG_NOUSTA 88 |
|
|
|
|
|
|
|
|
|
|
|
#define MSG_ZERMIS 94 |
|
|
|
#define MSG_ZERMIS 94 |
|
|
@ -418,7 +417,6 @@ struct CODES { |
|
|
|
{ SEVERITY_SUCC, MSG_SETQUOTA,PARAM_SET, "Set pool '%s' to quota %d'" }, |
|
|
|
{ SEVERITY_SUCC, MSG_SETQUOTA,PARAM_SET, "Set pool '%s' to quota %d'" }, |
|
|
|
{ SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name,N'" }, |
|
|
|
{ SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name,N'" }, |
|
|
|
{ SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" }, |
|
|
|
{ SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" }, |
|
|
|
{ SEVERITY_SUCC, MSG_USBSTA, PARAM_NONE, "USB Statistics" }, |
|
|
|
|
|
|
|
{ SEVERITY_INFO, MSG_NOUSTA, PARAM_NONE, "No USB Statistics" }, |
|
|
|
{ SEVERITY_INFO, MSG_NOUSTA, PARAM_NONE, "No USB Statistics" }, |
|
|
|
{ SEVERITY_ERR, MSG_ZERMIS, PARAM_NONE, "Missing zero parameters" }, |
|
|
|
{ SEVERITY_ERR, MSG_ZERMIS, PARAM_NONE, "Missing zero parameters" }, |
|
|
|
{ SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" }, |
|
|
|
{ SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" }, |
|
|
@ -1061,10 +1059,8 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p |
|
|
|
|
|
|
|
|
|
|
|
int i; |
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
io_reinit(io_data); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isjson) |
|
|
|
if (isjson) |
|
|
|
io_put(io_data, JSON_START JSON_STATUS); |
|
|
|
io_add(io_data, JSON_START JSON_STATUS); |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; codes[i].severity != SEVERITY_FAIL; i++) { |
|
|
|
for (i = 0; codes[i].severity != SEVERITY_FAIL; i++) { |
|
|
|
if (codes[i].code == messageid) { |
|
|
|
if (codes[i].code == messageid) { |
|
|
@ -3045,44 +3041,45 @@ struct CMDS { |
|
|
|
char *name; |
|
|
|
char *name; |
|
|
|
void (*func)(struct io_data *, SOCKETTYPE, char *, bool, char); |
|
|
|
void (*func)(struct io_data *, SOCKETTYPE, char *, bool, char); |
|
|
|
bool iswritemode; |
|
|
|
bool iswritemode; |
|
|
|
|
|
|
|
bool joinable; |
|
|
|
} cmds[] = { |
|
|
|
} cmds[] = { |
|
|
|
{ "version", apiversion, false }, |
|
|
|
{ "version", apiversion, false, true }, |
|
|
|
{ "config", minerconfig, false }, |
|
|
|
{ "config", minerconfig, false, true }, |
|
|
|
{ "devs", devstatus, false }, |
|
|
|
{ "devs", devstatus, false, true }, |
|
|
|
{ "pools", poolstatus, false }, |
|
|
|
{ "pools", poolstatus, false, true }, |
|
|
|
{ "summary", summary, false }, |
|
|
|
{ "summary", summary, false, true }, |
|
|
|
{ "gpuenable", gpuenable, true }, |
|
|
|
{ "gpuenable", gpuenable, true, false }, |
|
|
|
{ "gpudisable", gpudisable, true }, |
|
|
|
{ "gpudisable", gpudisable, true, false }, |
|
|
|
{ "gpurestart", gpurestart, true }, |
|
|
|
{ "gpurestart", gpurestart, true, false }, |
|
|
|
{ "gpu", gpudev, false }, |
|
|
|
{ "gpu", gpudev, false, false }, |
|
|
|
{ "gpucount", gpucount, false }, |
|
|
|
{ "gpucount", gpucount, false, true }, |
|
|
|
{ "switchpool", switchpool, true }, |
|
|
|
{ "switchpool", switchpool, true, false }, |
|
|
|
{ "addpool", addpool, true }, |
|
|
|
{ "addpool", addpool, true, false }, |
|
|
|
{ "poolpriority", poolpriority, true }, |
|
|
|
{ "poolpriority", poolpriority, true, false }, |
|
|
|
{ "poolquota", poolquota, true }, |
|
|
|
{ "poolquota", poolquota, true, false }, |
|
|
|
{ "enablepool", enablepool, true }, |
|
|
|
{ "enablepool", enablepool, true, false }, |
|
|
|
{ "disablepool", disablepool, true }, |
|
|
|
{ "disablepool", disablepool, true, false }, |
|
|
|
{ "removepool", removepool, true }, |
|
|
|
{ "removepool", removepool, true, false }, |
|
|
|
{ "gpuintensity", gpuintensity, true }, |
|
|
|
{ "gpuintensity", gpuintensity, true, false }, |
|
|
|
{ "gpumem", gpumem, true }, |
|
|
|
{ "gpumem", gpumem, true, false }, |
|
|
|
{ "gpuengine", gpuengine, true }, |
|
|
|
{ "gpuengine", gpuengine, true, false }, |
|
|
|
{ "gpufan", gpufan, true }, |
|
|
|
{ "gpufan", gpufan, true, false }, |
|
|
|
{ "gpuvddc", gpuvddc, true }, |
|
|
|
{ "gpuvddc", gpuvddc, true, false }, |
|
|
|
{ "save", dosave, true }, |
|
|
|
{ "save", dosave, true, false }, |
|
|
|
{ "quit", doquit, true }, |
|
|
|
{ "quit", doquit, true, false }, |
|
|
|
{ "privileged", privileged, true }, |
|
|
|
{ "privileged", privileged, true, false }, |
|
|
|
{ "notify", notify, false }, |
|
|
|
{ "notify", notify, false, true }, |
|
|
|
{ "devdetails", devdetails, false }, |
|
|
|
{ "devdetails", devdetails, false, true }, |
|
|
|
{ "restart", dorestart, true }, |
|
|
|
{ "restart", dorestart, true, false }, |
|
|
|
{ "stats", minerstats, false }, |
|
|
|
{ "stats", minerstats, false, true }, |
|
|
|
{ "check", checkcommand, false }, |
|
|
|
{ "check", checkcommand, false, false }, |
|
|
|
{ "failover-only", failoveronly, true }, |
|
|
|
{ "failover-only", failoveronly, true, false }, |
|
|
|
{ "coin", minecoin, false }, |
|
|
|
{ "coin", minecoin, false, true }, |
|
|
|
{ "debug", debugstate, true }, |
|
|
|
{ "debug", debugstate, true, false }, |
|
|
|
{ "setconfig", setconfig, true }, |
|
|
|
{ "setconfig", setconfig, true, false }, |
|
|
|
{ "zero", dozero, true }, |
|
|
|
{ "zero", dozero, true, false }, |
|
|
|
{ "lockstats", lockstats, true }, |
|
|
|
{ "lockstats", lockstats, true, true }, |
|
|
|
{ NULL, NULL, false } |
|
|
|
{ NULL, NULL, false, false } |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group) |
|
|
|
static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, char group) |
|
|
@ -3125,6 +3122,49 @@ static void checkcommand(struct io_data *io_data, __maybe_unused SOCKETTYPE c, c |
|
|
|
io_close(io_data); |
|
|
|
io_close(io_data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void head_join(struct io_data *io_data, char *cmdptr, bool isjson, bool *firstjoin) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char *ptr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (*firstjoin) { |
|
|
|
|
|
|
|
if (isjson) |
|
|
|
|
|
|
|
io_add(io_data, JSON0); |
|
|
|
|
|
|
|
*firstjoin = false; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (isjson) |
|
|
|
|
|
|
|
io_add(io_data, JSON_BETWEEN_JOIN); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// External supplied string
|
|
|
|
|
|
|
|
ptr = escape_string(cmdptr, isjson); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isjson) { |
|
|
|
|
|
|
|
io_add(io_data, JSON1); |
|
|
|
|
|
|
|
io_add(io_data, ptr); |
|
|
|
|
|
|
|
io_add(io_data, JSON2); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
io_add(io_data, JOIN_CMD); |
|
|
|
|
|
|
|
io_add(io_data, ptr); |
|
|
|
|
|
|
|
io_add(io_data, BETWEEN_JOIN); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ptr != cmdptr) |
|
|
|
|
|
|
|
free(ptr); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void tail_join(struct io_data *io_data, bool isjson) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (io_data->close) { |
|
|
|
|
|
|
|
io_add(io_data, JSON_CLOSE); |
|
|
|
|
|
|
|
io_data->close = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isjson) { |
|
|
|
|
|
|
|
io_add(io_data, JSON_END); |
|
|
|
|
|
|
|
io_add(io_data, JSON3); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void send_result(struct io_data *io_data, SOCKETTYPE c, bool isjson) |
|
|
|
static void send_result(struct io_data *io_data, SOCKETTYPE c, bool isjson) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int count, sendc, res, tosend, len, n; |
|
|
|
int count, sendc, res, tosend, len, n; |
|
|
@ -3689,7 +3729,7 @@ void api(int api_thr_id) |
|
|
|
struct sockaddr_in cli; |
|
|
|
struct sockaddr_in cli; |
|
|
|
socklen_t clisiz; |
|
|
|
socklen_t clisiz; |
|
|
|
char cmdbuf[100]; |
|
|
|
char cmdbuf[100]; |
|
|
|
char *cmd = NULL; |
|
|
|
char *cmd = NULL, *cmdptr, *cmdsbuf; |
|
|
|
char *param; |
|
|
|
char *param; |
|
|
|
bool addrok; |
|
|
|
bool addrok; |
|
|
|
char group; |
|
|
|
char group; |
|
|
@ -3697,7 +3737,7 @@ void api(int api_thr_id) |
|
|
|
json_t *json_config = NULL; |
|
|
|
json_t *json_config = NULL; |
|
|
|
json_t *json_val; |
|
|
|
json_t *json_val; |
|
|
|
bool isjson; |
|
|
|
bool isjson; |
|
|
|
bool did; |
|
|
|
bool did, isjoin, firstjoin; |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
SOCKETTYPE *apisock; |
|
|
|
SOCKETTYPE *apisock; |
|
|
@ -3898,27 +3938,80 @@ void api(int api_thr_id) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!did) { |
|
|
|
if (!did) { |
|
|
|
for (i = 0; cmds[i].name != NULL; i++) { |
|
|
|
if (strchr(cmd, CMDJOIN)) { |
|
|
|
if (strcmp(cmd, cmds[i].name) == 0) { |
|
|
|
firstjoin = isjoin = true; |
|
|
|
sprintf(cmdbuf, "|%s|", cmd); |
|
|
|
// cmd + leading '|' + '\0'
|
|
|
|
if (ISPRIVGROUP(group) || strstr(COMMANDS(group), cmdbuf)) |
|
|
|
cmdsbuf = malloc(strlen(cmd) + 2); |
|
|
|
(cmds[i].func)(io_data, c, param, isjson, group); |
|
|
|
if (!cmdsbuf) |
|
|
|
else { |
|
|
|
quithere(1, "OOM cmdsbuf"); |
|
|
|
message(io_data, MSG_ACCDENY, 0, cmds[i].name, isjson); |
|
|
|
strcpy(cmdsbuf, "|"); |
|
|
|
applog(LOG_DEBUG, "API: access denied to '%s' for '%s' command", connectaddr, cmds[i].name); |
|
|
|
param = NULL; |
|
|
|
|
|
|
|
} else |
|
|
|
|
|
|
|
firstjoin = isjoin = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmdptr = cmd; |
|
|
|
|
|
|
|
do { |
|
|
|
|
|
|
|
did = false; |
|
|
|
|
|
|
|
if (isjoin) { |
|
|
|
|
|
|
|
cmd = strchr(cmdptr, CMDJOIN); |
|
|
|
|
|
|
|
if (cmd) |
|
|
|
|
|
|
|
*(cmd++) = '\0'; |
|
|
|
|
|
|
|
if (!*cmdptr) |
|
|
|
|
|
|
|
goto inochi; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; cmds[i].name != NULL; i++) { |
|
|
|
|
|
|
|
if (strcmp(cmdptr, cmds[i].name) == 0) { |
|
|
|
|
|
|
|
sprintf(cmdbuf, "|%s|", cmdptr); |
|
|
|
|
|
|
|
if (isjoin) { |
|
|
|
|
|
|
|
if (strstr(cmdsbuf, cmdbuf)) { |
|
|
|
|
|
|
|
did = true; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
strcat(cmdsbuf, cmdptr); |
|
|
|
|
|
|
|
strcat(cmdsbuf, "|"); |
|
|
|
|
|
|
|
head_join(io_data, cmdptr, isjson, &firstjoin); |
|
|
|
|
|
|
|
if (!cmds[i].joinable) { |
|
|
|
|
|
|
|
message(io_data, MSG_ACCDENY, 0, cmds[i].name, isjson); |
|
|
|
|
|
|
|
did = true; |
|
|
|
|
|
|
|
tail_join(io_data, isjson); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (ISPRIVGROUP(group) || strstr(COMMANDS(group), cmdbuf)) |
|
|
|
|
|
|
|
(cmds[i].func)(io_data, c, param, isjson, group); |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
message(io_data, MSG_ACCDENY, 0, cmds[i].name, isjson); |
|
|
|
|
|
|
|
applog(LOG_DEBUG, "API: access denied to '%s' for '%s' command", connectaddr, cmds[i].name); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
did = true; |
|
|
|
|
|
|
|
if (!isjoin) |
|
|
|
|
|
|
|
send_result(io_data, c, isjson); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
tail_join(io_data, isjson); |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
send_result(io_data, c, isjson); |
|
|
|
if (!did) { |
|
|
|
did = true; |
|
|
|
if (isjoin) |
|
|
|
break; |
|
|
|
head_join(io_data, cmdptr, isjson, &firstjoin); |
|
|
|
|
|
|
|
message(io_data, MSG_INVCMD, 0, NULL, isjson); |
|
|
|
|
|
|
|
if (isjoin) |
|
|
|
|
|
|
|
tail_join(io_data, isjson); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
send_result(io_data, c, isjson); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
inochi: |
|
|
|
|
|
|
|
if (isjoin) |
|
|
|
|
|
|
|
cmdptr = cmd; |
|
|
|
|
|
|
|
} while (isjoin && cmdptr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!did) { |
|
|
|
if (isjoin) |
|
|
|
message(io_data, MSG_INVCMD, 0, NULL, isjson); |
|
|
|
|
|
|
|
send_result(io_data, c, isjson); |
|
|
|
send_result(io_data, c, isjson); |
|
|
|
} |
|
|
|
|
|
|
|
if (isjson && json_is_object(json_config)) |
|
|
|
if (isjson && json_is_object(json_config)) |
|
|
|
json_decref(json_config); |
|
|
|
json_decref(json_config); |
|
|
|
} |
|
|
|
} |
|
|
|