|
|
@ -157,7 +157,7 @@ static const char *COMMA = ","; |
|
|
|
static const char SEPARATOR = '|'; |
|
|
|
static const char SEPARATOR = '|'; |
|
|
|
static const char GPUSEP = ','; |
|
|
|
static const char GPUSEP = ','; |
|
|
|
|
|
|
|
|
|
|
|
static const char *APIVERSION = "1.6"; |
|
|
|
static const char *APIVERSION = "1.7"; |
|
|
|
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"; |
|
|
@ -337,6 +337,10 @@ static const char *JSON_PARAMETER = "parameter"; |
|
|
|
#define MSG_PGAUNW 65 |
|
|
|
#define MSG_PGAUNW 65 |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define MSG_REMLASTP 66 |
|
|
|
|
|
|
|
#define MSG_ACTPOOL 67 |
|
|
|
|
|
|
|
#define MSG_REMPOOL 68 |
|
|
|
|
|
|
|
|
|
|
|
enum code_severity { |
|
|
|
enum code_severity { |
|
|
|
SEVERITY_ERR, |
|
|
|
SEVERITY_ERR, |
|
|
|
SEVERITY_WARN, |
|
|
|
SEVERITY_WARN, |
|
|
@ -456,6 +460,9 @@ struct CODES { |
|
|
|
{ SEVERITY_ERR, MSG_INVPDP, PARAM_STR, "Invalid addpool details '%s'" }, |
|
|
|
{ SEVERITY_ERR, MSG_INVPDP, PARAM_STR, "Invalid addpool details '%s'" }, |
|
|
|
{ SEVERITY_ERR, MSG_TOOMANYP,PARAM_NONE, "Reached maximum number of pools (%d)" }, |
|
|
|
{ SEVERITY_ERR, MSG_TOOMANYP,PARAM_NONE, "Reached maximum number of pools (%d)" }, |
|
|
|
{ SEVERITY_SUCC, MSG_ADDPOOL, PARAM_STR, "Added pool '%s'" }, |
|
|
|
{ SEVERITY_SUCC, MSG_ADDPOOL, PARAM_STR, "Added pool '%s'" }, |
|
|
|
|
|
|
|
{ SEVERITY_ERR, MSG_REMLASTP,PARAM_POOL, "Cannot remove last pool %d:'%s'" }, |
|
|
|
|
|
|
|
{ SEVERITY_ERR, MSG_ACTPOOL, PARAM_POOL, "Cannot remove active pool %d:'%s'" }, |
|
|
|
|
|
|
|
{ SEVERITY_SUCC, MSG_REMPOOL, PARAM_BOTH, "Removed pool %d:'%s'" }, |
|
|
|
{ SEVERITY_SUCC, MSG_NOTIFY, PARAM_NONE, "Notify" }, |
|
|
|
{ SEVERITY_SUCC, MSG_NOTIFY, PARAM_NONE, "Notify" }, |
|
|
|
{ SEVERITY_FAIL, 0, 0, NULL } |
|
|
|
{ SEVERITY_FAIL, 0, 0, NULL } |
|
|
|
}; |
|
|
|
}; |
|
|
@ -483,6 +490,68 @@ extern struct device_api bitforce_api; |
|
|
|
extern struct device_api icarus_api; |
|
|
|
extern struct device_api icarus_api; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This is only called when expected to be needed (rarely)
|
|
|
|
|
|
|
|
// i.e. strings outside of the codes control (input from the user)
|
|
|
|
|
|
|
|
static char *escape_string(char *str, bool isjson) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
char *buf, *ptr; |
|
|
|
|
|
|
|
int count; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
count = 0; |
|
|
|
|
|
|
|
for (ptr = str; *ptr; ptr++) { |
|
|
|
|
|
|
|
switch (*ptr) { |
|
|
|
|
|
|
|
case ',': |
|
|
|
|
|
|
|
case '|': |
|
|
|
|
|
|
|
case '=': |
|
|
|
|
|
|
|
if (!isjson) |
|
|
|
|
|
|
|
count++; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case '"': |
|
|
|
|
|
|
|
if (isjson) |
|
|
|
|
|
|
|
count++; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case '\\': |
|
|
|
|
|
|
|
count++; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (count == 0) |
|
|
|
|
|
|
|
return str; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf = malloc(strlen(str) + count + 1); |
|
|
|
|
|
|
|
if (unlikely(!buf)) |
|
|
|
|
|
|
|
quit(1, "Failed to malloc escape buf"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ptr = buf; |
|
|
|
|
|
|
|
while (*str) |
|
|
|
|
|
|
|
switch (*str) { |
|
|
|
|
|
|
|
case ',': |
|
|
|
|
|
|
|
case '|': |
|
|
|
|
|
|
|
case '=': |
|
|
|
|
|
|
|
if (!isjson) |
|
|
|
|
|
|
|
*(ptr++) = '\\'; |
|
|
|
|
|
|
|
*(ptr++) = *(str++); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case '"': |
|
|
|
|
|
|
|
if (isjson) |
|
|
|
|
|
|
|
*(ptr++) = '\\'; |
|
|
|
|
|
|
|
*(ptr++) = *(str++); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case '\\': |
|
|
|
|
|
|
|
*(ptr++) = '\\'; |
|
|
|
|
|
|
|
*(ptr++) = *(str++); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
*(ptr++) = *(str++); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*ptr = '\0'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return buf; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if defined(USE_BITFORCE) || defined(USE_ICARUS) |
|
|
|
#if defined(USE_BITFORCE) || defined(USE_ICARUS) |
|
|
|
static int numpgas() |
|
|
|
static int numpgas() |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1102,6 +1171,8 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, |
|
|
|
{ |
|
|
|
{ |
|
|
|
char buf[BUFSIZ]; |
|
|
|
char buf[BUFSIZ]; |
|
|
|
char *status, *lp; |
|
|
|
char *status, *lp; |
|
|
|
|
|
|
|
char *rpc_url; |
|
|
|
|
|
|
|
char *rpc_user; |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
if (total_pools == 0) { |
|
|
|
if (total_pools == 0) { |
|
|
@ -1133,27 +1204,40 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, |
|
|
|
else |
|
|
|
else |
|
|
|
lp = (char *)NO; |
|
|
|
lp = (char *)NO; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rpc_url = escape_string(pool->rpc_url, isjson); |
|
|
|
|
|
|
|
rpc_user = escape_string(pool->rpc_user, isjson); |
|
|
|
|
|
|
|
|
|
|
|
if (isjson) |
|
|
|
if (isjson) |
|
|
|
sprintf(buf, "%s{\"POOL\":%d,\"URL\":\"%s\",\"Status\":\"%s\",\"Priority\":%d,\"Long Poll\":\"%s\",\"Getworks\":%d,\"Accepted\":%d,\"Rejected\":%d,\"Discarded\":%d,\"Stale\":%d,\"Get Failures\":%d,\"Remote Failures\":%d}", |
|
|
|
sprintf(buf, "%s{\"POOL\":%d,\"URL\":\"%s\",\"Status\":\"%s\",\"Priority\":%d,\"Long Poll\":\"%s\",\"Getworks\":%d,\"Accepted\":%d,\"Rejected\":%d,\"Discarded\":%d,\"Stale\":%d,\"Get Failures\":%d,\"Remote Failures\":%d,\"User\":\"%s\"}", |
|
|
|
(i > 0) ? COMMA : "", |
|
|
|
(i > 0) ? COMMA : "", |
|
|
|
i, pool->rpc_url, status, pool->prio, lp, |
|
|
|
i, rpc_url, status, pool->prio, lp, |
|
|
|
pool->getwork_requested, |
|
|
|
pool->getwork_requested, |
|
|
|
pool->accepted, pool->rejected, |
|
|
|
pool->accepted, pool->rejected, |
|
|
|
pool->discarded_work, |
|
|
|
pool->discarded_work, |
|
|
|
pool->stale_shares, |
|
|
|
pool->stale_shares, |
|
|
|
pool->getfail_occasions, |
|
|
|
pool->getfail_occasions, |
|
|
|
pool->remotefail_occasions); |
|
|
|
pool->remotefail_occasions, |
|
|
|
|
|
|
|
rpc_user); |
|
|
|
else |
|
|
|
else |
|
|
|
sprintf(buf, "POOL=%d,URL=%s,Status=%s,Priority=%d,Long Poll=%s,Getworks=%d,Accepted=%d,Rejected=%d,Discarded=%d,Stale=%d,Get Failures=%d,Remote Failures=%d%c", |
|
|
|
sprintf(buf, "POOL=%d,URL=%s,Status=%s,Priority=%d,Long Poll=%s,Getworks=%d,Accepted=%d,Rejected=%d,Discarded=%d,Stale=%d,Get Failures=%d,Remote Failures=%d,User=%s%c", |
|
|
|
i, pool->rpc_url, status, pool->prio, lp, |
|
|
|
i, rpc_url, status, pool->prio, lp, |
|
|
|
pool->getwork_requested, |
|
|
|
pool->getwork_requested, |
|
|
|
pool->accepted, pool->rejected, |
|
|
|
pool->accepted, pool->rejected, |
|
|
|
pool->discarded_work, |
|
|
|
pool->discarded_work, |
|
|
|
pool->stale_shares, |
|
|
|
pool->stale_shares, |
|
|
|
pool->getfail_occasions, |
|
|
|
pool->getfail_occasions, |
|
|
|
pool->remotefail_occasions, SEPARATOR); |
|
|
|
pool->remotefail_occasions, |
|
|
|
|
|
|
|
rpc_user, SEPARATOR); |
|
|
|
|
|
|
|
|
|
|
|
strcat(io_buffer, buf); |
|
|
|
strcat(io_buffer, buf); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (rpc_url != pool->rpc_url) |
|
|
|
|
|
|
|
free(rpc_url); |
|
|
|
|
|
|
|
rpc_url = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (rpc_user != pool->rpc_user) |
|
|
|
|
|
|
|
free(rpc_user); |
|
|
|
|
|
|
|
rpc_user = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (isjson) |
|
|
|
if (isjson) |
|
|
@ -1443,6 +1527,7 @@ exitsama: |
|
|
|
static void addpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
static void addpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char *url, *user, *pass; |
|
|
|
char *url, *user, *pass; |
|
|
|
|
|
|
|
char *ptr; |
|
|
|
|
|
|
|
|
|
|
|
if (param == NULL || *param == '\0') { |
|
|
|
if (param == NULL || *param == '\0') { |
|
|
|
strcpy(io_buffer, message(MSG_MISPDP, 0, NULL, isjson)); |
|
|
|
strcpy(io_buffer, message(MSG_MISPDP, 0, NULL, isjson)); |
|
|
@ -1450,7 +1535,11 @@ static void addpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!pooldetails(param, &url, &user, &pass)) { |
|
|
|
if (!pooldetails(param, &url, &user, &pass)) { |
|
|
|
strcpy(io_buffer, message(MSG_INVPDP, 0, param, isjson)); |
|
|
|
ptr = escape_string(param, isjson); |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_INVPDP, 0, ptr, isjson)); |
|
|
|
|
|
|
|
if (ptr != param) |
|
|
|
|
|
|
|
free(ptr); |
|
|
|
|
|
|
|
ptr = NULL; |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -1459,7 +1548,11 @@ static void addpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_ADDPOOL, 0, url, isjson)); |
|
|
|
ptr = escape_string(url, isjson); |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_ADDPOOL, 0, ptr, isjson)); |
|
|
|
|
|
|
|
if (ptr != url) |
|
|
|
|
|
|
|
free(ptr); |
|
|
|
|
|
|
|
ptr = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void enablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
static void enablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
@ -1535,6 +1628,57 @@ static void disablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
strcpy(io_buffer, message(MSG_DISPOOL, id, NULL, isjson)); |
|
|
|
strcpy(io_buffer, message(MSG_DISPOOL, id, NULL, isjson)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void removepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
struct pool *pool; |
|
|
|
|
|
|
|
char *rpc_url; |
|
|
|
|
|
|
|
bool dofree = false; |
|
|
|
|
|
|
|
int id; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (total_pools == 0) { |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_NOPOOL, 0, NULL, isjson)); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (param == NULL || *param == '\0') { |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_MISPID, 0, NULL, isjson)); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
id = atoi(param); |
|
|
|
|
|
|
|
if (id < 0 || id >= total_pools) { |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_INVPID, id, NULL, isjson)); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (total_pools <= 1) { |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_REMLASTP, id, NULL, isjson)); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pool = pools[id]; |
|
|
|
|
|
|
|
if (pool == current_pool()) |
|
|
|
|
|
|
|
switch_pools(NULL); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pool == current_pool()) { |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_ACTPOOL, id, NULL, isjson)); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pool->enabled = false; |
|
|
|
|
|
|
|
rpc_url = escape_string(pool->rpc_url, isjson); |
|
|
|
|
|
|
|
if (rpc_url != pool->rpc_url) |
|
|
|
|
|
|
|
dofree = true; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
remove_pool(pool); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_REMPOOL, id, rpc_url, isjson)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (dofree) |
|
|
|
|
|
|
|
free(rpc_url); |
|
|
|
|
|
|
|
rpc_url = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool splitgpuvalue(char *param, int *gpu, char **value, bool isjson) |
|
|
|
static bool splitgpuvalue(char *param, int *gpu, char **value, bool isjson) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int id; |
|
|
|
int id; |
|
|
@ -1792,6 +1936,7 @@ static void notify(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool |
|
|
|
void dosave(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
void dosave(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
{ |
|
|
|
{ |
|
|
|
FILE *fcfg; |
|
|
|
FILE *fcfg; |
|
|
|
|
|
|
|
char *ptr; |
|
|
|
|
|
|
|
|
|
|
|
if (param == NULL || *param == '\0') { |
|
|
|
if (param == NULL || *param == '\0') { |
|
|
|
strcpy(io_buffer, message(MSG_MISFN, 0, NULL, isjson)); |
|
|
|
strcpy(io_buffer, message(MSG_MISFN, 0, NULL, isjson)); |
|
|
@ -1800,14 +1945,22 @@ void dosave(__maybe_unused SOCKETTYPE c, char *param, bool isjson) |
|
|
|
|
|
|
|
|
|
|
|
fcfg = fopen(param, "w"); |
|
|
|
fcfg = fopen(param, "w"); |
|
|
|
if (!fcfg) { |
|
|
|
if (!fcfg) { |
|
|
|
strcpy(io_buffer, message(MSG_BADFN, 0, param, isjson)); |
|
|
|
ptr = escape_string(param, isjson); |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_BADFN, 0, ptr, isjson)); |
|
|
|
|
|
|
|
if (ptr != param) |
|
|
|
|
|
|
|
free(ptr); |
|
|
|
|
|
|
|
ptr = NULL; |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
write_config(fcfg); |
|
|
|
write_config(fcfg); |
|
|
|
fclose(fcfg); |
|
|
|
fclose(fcfg); |
|
|
|
|
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_SAVED, 0, param, isjson)); |
|
|
|
ptr = escape_string(param, isjson); |
|
|
|
|
|
|
|
strcpy(io_buffer, message(MSG_SAVED, 0, ptr, isjson)); |
|
|
|
|
|
|
|
if (ptr != param) |
|
|
|
|
|
|
|
free(ptr); |
|
|
|
|
|
|
|
ptr = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct CMDS { |
|
|
|
struct CMDS { |
|
|
@ -1839,6 +1992,7 @@ struct CMDS { |
|
|
|
{ "addpool", addpool, true }, |
|
|
|
{ "addpool", addpool, true }, |
|
|
|
{ "enablepool", enablepool, true }, |
|
|
|
{ "enablepool", enablepool, true }, |
|
|
|
{ "disablepool", disablepool, true }, |
|
|
|
{ "disablepool", disablepool, true }, |
|
|
|
|
|
|
|
{ "removepool", removepool, true }, |
|
|
|
{ "gpuintensity", gpuintensity, true }, |
|
|
|
{ "gpuintensity", gpuintensity, true }, |
|
|
|
{ "gpumem", gpumem, true }, |
|
|
|
{ "gpumem", gpumem, true }, |
|
|
|
{ "gpuengine", gpuengine, true }, |
|
|
|
{ "gpuengine", gpuengine, true }, |
|
|
|