mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-11 15:27:53 +00:00
Merge branch 'master' of git://github.com/ckolivas/cgminer.git
Conflicts: cgminer.c
This commit is contained in:
commit
baa480c137
42
API-README
42
API-README
@ -19,8 +19,9 @@ IP addresses are automatically padded with extra '.0's as needed
|
||||
Without a /prefix is the same as specifying /32
|
||||
0/0 means all IP addresses.
|
||||
The 'W:' on the front gives that address/subnet privileged access to commands
|
||||
that modify cgminer.
|
||||
that modify cgminer (thus all API commands)
|
||||
Without it those commands return an access denied status.
|
||||
See --api-groups below to define other groups like W:
|
||||
Privileged access is checked in the order the IP addresses were supplied to
|
||||
"--api-allow"
|
||||
The first match determines the privilege level.
|
||||
@ -28,6 +29,26 @@ Using the "--api-allow" option overides the "--api-network" option if they
|
||||
are both specified
|
||||
With "--api-allow", 127.0.0.1 is not by default given access unless specified
|
||||
|
||||
More groups (like the privileged group W:) can be defined using the
|
||||
--api-groups command
|
||||
Valid groups are only the letters A-Z (except R & W are predefined) and are
|
||||
not case sensitive
|
||||
The R: group is the same as not privileged access
|
||||
The W: group is (as stated) privileged access (thus all API commands)
|
||||
To give an IP address/subnet access to a group you use the group letter
|
||||
in front of the IP address instead of W: e.g. P:192.168.0/32
|
||||
An IP address/subnet can only be a member of one group
|
||||
A sample API group would be:
|
||||
--api-groups P:switchpool:enablepool:addpool:disablepool:removepool:*
|
||||
This would create a group 'P' that can do all current pool commands and all
|
||||
non-priviliged commands - the '*' means all non-priviledged commands
|
||||
Without the '*' the group would only have access to the pool commands
|
||||
Defining multiple groups example:
|
||||
--api-groups Q:quit:restart:*,S:save
|
||||
This would define 2 groups:
|
||||
Q: that can 'quit' and 'restart' as well as all non-priviledged commands
|
||||
S: that can only 'save' and no other commands
|
||||
|
||||
The RPC API request can be either simple text or JSON.
|
||||
|
||||
If the request is JSON (starts with '{'), it will reply with a JSON formatted
|
||||
@ -86,8 +107,8 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
||||
|
||||
Request Reply Section Details
|
||||
------- ------------- -------
|
||||
version VERSION CGMiner=cgminer version
|
||||
API=API version
|
||||
version VERSION CGMiner=cgminer, version
|
||||
API=API| version
|
||||
|
||||
config CONFIG Some miner configuration information:
|
||||
GPU Count=N, <- the number of GPUs
|
||||
@ -243,6 +264,9 @@ The list of requests - a (*) means it requires privileged access - and replies a
|
||||
Device drivers are also able to add stats to the
|
||||
end of the details returned
|
||||
|
||||
check|cmd COMMAND Exists=Y/N, <- 'cmd' exists in this version
|
||||
Access=Y/N| <- you have access to use 'cmd'
|
||||
|
||||
When you enable, disable or restart a GPU or PGA, you will also get Thread messages
|
||||
in the cgminer status window
|
||||
|
||||
@ -285,7 +309,17 @@ miner.php - an example web page to access the API
|
||||
Feature Changelog for external applications using the API:
|
||||
|
||||
|
||||
API V1.12
|
||||
API V1.13
|
||||
|
||||
Added API commands:
|
||||
'check'
|
||||
|
||||
Support was added to cgminer for API access groups with the --api-groups option
|
||||
It's 100% backwards compatible with previous --api-access commands
|
||||
|
||||
----------
|
||||
|
||||
API V1.12 (cgminer v2.4.3)
|
||||
|
||||
Modified API commands:
|
||||
'stats' - more pool stats added
|
||||
|
2
README
2
README
@ -119,6 +119,8 @@ Options for both config file and command line:
|
||||
This overrides --api-network and you must specify 127.0.0.1 if it is required
|
||||
W: in front of the IP address gives that address privileged access to all api commands
|
||||
--api-description Description placed in the API status header (default: cgminer version)
|
||||
--api-groups API one letter groups G:cmd:cmd[,P:cmd:*...]
|
||||
See API-README for usage
|
||||
--api-listen Listen for API requests (default: disabled)
|
||||
By default any command that does not just display data returns access denied
|
||||
See --api-allow to overcome this
|
||||
|
32
adl.c
32
adl.c
@ -13,6 +13,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef HAVE_CURSES
|
||||
#include <curses.h>
|
||||
@ -692,7 +693,11 @@ int gpu_fanpercent(int gpu)
|
||||
unlock_adl();
|
||||
if (unlikely(ga->has_fanspeed && ret == -1)) {
|
||||
applog(LOG_WARNING, "GPU %d stopped reporting fanspeed due to driver corruption", gpu);
|
||||
applog(LOG_WARNING, "You will need to start cgminer from scratch to correct this");
|
||||
if (opt_restart) {
|
||||
applog(LOG_WARNING, "Restart enabled, will attempt to restart cgminer");
|
||||
applog(LOG_WARNING, "You can disable this with the --no-restart option");
|
||||
app_restart();
|
||||
}
|
||||
applog(LOG_WARNING, "Disabling fanspeed monitoring on this device");
|
||||
ga->has_fanspeed = false;
|
||||
if (ga->twin) {
|
||||
@ -1020,6 +1025,7 @@ static int set_powertune(int gpu, int iPercentage)
|
||||
static bool fan_autotune(int gpu, int temp, int fanpercent, int lasttemp, bool *fan_window)
|
||||
{
|
||||
struct cgpu_info *cgpu = &gpus[gpu];
|
||||
int tdiff = round(temp - lasttemp);
|
||||
struct gpu_adl *ga = &cgpu->adl;
|
||||
int top = gpus[gpu].gpu_fan;
|
||||
int bot = gpus[gpu].min_fan;
|
||||
@ -1034,7 +1040,7 @@ static bool fan_autotune(int gpu, int temp, int fanpercent, int lasttemp, bool *
|
||||
cgpu->device_last_not_well = time(NULL);
|
||||
cgpu->device_not_well_reason = REASON_DEV_OVER_HEAT;
|
||||
cgpu->dev_over_heat_count++;
|
||||
} else if (temp > ga->targettemp && fanpercent < top && temp >= lasttemp) {
|
||||
} else if (temp > ga->targettemp && fanpercent < top && tdiff >= 0) {
|
||||
applog(LOG_DEBUG, "Temperature over target, increasing fanspeed");
|
||||
if (temp > ga->targettemp + opt_hysteresis)
|
||||
newpercent = ga->targetfan + 10;
|
||||
@ -1042,18 +1048,26 @@ static bool fan_autotune(int gpu, int temp, int fanpercent, int lasttemp, bool *
|
||||
newpercent = ga->targetfan + 5;
|
||||
if (newpercent > top)
|
||||
newpercent = top;
|
||||
} else if (fanpercent > bot && temp < ga->targettemp - opt_hysteresis && temp <= lasttemp) {
|
||||
applog(LOG_DEBUG, "Temperature %d degrees below target, decreasing fanspeed", opt_hysteresis);
|
||||
newpercent = ga->targetfan - 1;
|
||||
} else if (fanpercent > bot && temp < ga->targettemp - opt_hysteresis) {
|
||||
/* Detect large swings of 5 degrees or more and change fan by
|
||||
* a proportion more */
|
||||
if (tdiff <= 0) {
|
||||
applog(LOG_DEBUG, "Temperature %d degrees below target, decreasing fanspeed", opt_hysteresis);
|
||||
newpercent = ga->targetfan - 1 + tdiff / 5;
|
||||
} else if (tdiff >= 5) {
|
||||
applog(LOG_DEBUG, "Temperature climbed %d while below target, increasing fanspeed", tdiff);
|
||||
newpercent = ga->targetfan + tdiff / 5;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* We're in the optimal range, make minor adjustments if the
|
||||
* temp is still drifting */
|
||||
if (fanpercent > bot && temp < lasttemp && lasttemp < ga->targettemp) {
|
||||
if (fanpercent > bot && tdiff < 0 && lasttemp < ga->targettemp) {
|
||||
applog(LOG_DEBUG, "Temperature dropping while in target range, decreasing fanspeed");
|
||||
newpercent = ga->targetfan - 1;
|
||||
} else if (fanpercent < top && temp > lasttemp && temp > ga->targettemp - opt_hysteresis) {
|
||||
newpercent = ga->targetfan + tdiff;
|
||||
} else if (fanpercent < top && tdiff > 0 && temp > ga->targettemp - opt_hysteresis) {
|
||||
applog(LOG_DEBUG, "Temperature rising while in target range, increasing fanspeed");
|
||||
newpercent = ga->targetfan + 1;
|
||||
newpercent = ga->targetfan + tdiff;
|
||||
}
|
||||
}
|
||||
|
||||
|
322
api.c
322
api.c
@ -158,6 +158,7 @@ static char *msg_buffer = NULL;
|
||||
static SOCKETTYPE sock = INVSOCK;
|
||||
|
||||
static const char *UNAVAILABLE = " - API will not be available";
|
||||
static const char *INVAPIGROUPS = "Invalid --api-groups parameter";
|
||||
|
||||
static const char *BLANK = "";
|
||||
static const char *COMMA = ",";
|
||||
@ -165,7 +166,7 @@ static const char SEPARATOR = '|';
|
||||
#define SEPSTR "|"
|
||||
static const char GPUSEP = ',';
|
||||
|
||||
static const char *APIVERSION = "1.12";
|
||||
static const char *APIVERSION = "1.13";
|
||||
static const char *DEAD = "Dead";
|
||||
static const char *SICK = "Sick";
|
||||
static const char *NOSTART = "NoStart";
|
||||
@ -243,6 +244,7 @@ static const char *OSINFO =
|
||||
#define _BYE "BYE"
|
||||
#define _RESTART "RESTART"
|
||||
#define _MINESTATS "STATS"
|
||||
#define _CHECK "CHECK"
|
||||
|
||||
static const char ISJSON = '{';
|
||||
#define JSON0 "{"
|
||||
@ -277,6 +279,7 @@ static const char ISJSON = '{';
|
||||
#define JSON_RESTART JSON1 _RESTART JSON1
|
||||
#define JSON_CLOSE JSON3
|
||||
#define JSON_MINESTATS JSON1 _MINESTATS JSON2
|
||||
#define JSON_CHECK JSON1 _CHECK JSON2
|
||||
#define JSON_END JSON4
|
||||
|
||||
static const char *JSON_COMMAND = "command";
|
||||
@ -364,6 +367,8 @@ static const char *JSON_PARAMETER = "parameter";
|
||||
#define MSG_REMPOOL 68
|
||||
#define MSG_DEVDETAILS 69
|
||||
#define MSG_MINESTATS 70
|
||||
#define MSG_MISCHK 71
|
||||
#define MSG_CHECK 72
|
||||
|
||||
enum code_severity {
|
||||
SEVERITY_ERR,
|
||||
@ -507,6 +512,8 @@ struct CODES {
|
||||
{ SEVERITY_SUCC, MSG_NOTIFY, PARAM_NONE, "Notify" },
|
||||
{ SEVERITY_SUCC, MSG_DEVDETAILS,PARAM_NONE, "Device Details" },
|
||||
{ SEVERITY_SUCC, MSG_MINESTATS,PARAM_NONE, "CGMiner stats" },
|
||||
{ SEVERITY_ERR, MSG_MISCHK, PARAM_NONE, "Missing check cmd" },
|
||||
{ SEVERITY_SUCC, MSG_CHECK, PARAM_NONE, "Check command" },
|
||||
{ SEVERITY_FAIL, 0, 0, NULL }
|
||||
};
|
||||
|
||||
@ -525,9 +532,23 @@ static time_t when = 0; // when the request occurred
|
||||
struct IP4ACCESS {
|
||||
in_addr_t ip;
|
||||
in_addr_t mask;
|
||||
bool writemode;
|
||||
char group;
|
||||
};
|
||||
|
||||
#define GROUP(g) (toupper(g))
|
||||
#define PRIVGROUP GROUP('W')
|
||||
#define NOPRIVGROUP GROUP('R')
|
||||
#define ISPRIVGROUP(g) (GROUP(g) == PRIVGROUP)
|
||||
#define GROUPOFFSET(g) (GROUP(g) - GROUP('A'))
|
||||
#define VALIDGROUP(g) (GROUP(g) >= GROUP('A') && GROUP(g) <= GROUP('Z'))
|
||||
#define COMMANDS(g) (apigroups[GROUPOFFSET(g)].commands)
|
||||
#define DEFINEDGROUP(g) (ISPRIVGROUP(g) || COMMANDS(g) != NULL)
|
||||
|
||||
struct APIGROUPS {
|
||||
// This becomes a string like: "|cmd1|cmd2|cmd3|" so it's quick to search
|
||||
char *commands;
|
||||
} apigroups['Z' - 'A' + 1]; // only A=0 to Z=25 (R: noprivs, W: allprivs)
|
||||
|
||||
static struct IP4ACCESS *ipaccess = NULL;
|
||||
static int ips = 0;
|
||||
|
||||
@ -796,7 +817,7 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
|
||||
return msg_buffer;
|
||||
}
|
||||
|
||||
static void apiversion(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void apiversion(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
sprintf(io_buffer, isjson
|
||||
? "%s," JSON_VERSION "{\"CGMiner\":\"%s\",\"API\":\"%s\"}" JSON_CLOSE
|
||||
@ -805,7 +826,7 @@ static void apiversion(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
||||
VERSION, APIVERSION);
|
||||
}
|
||||
|
||||
static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char buf[TMPBUFSIZ];
|
||||
int gpucount = 0;
|
||||
@ -1003,7 +1024,7 @@ static void cpustatus(int cpu, bool isjson)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int devcount = 0;
|
||||
int numgpu = 0;
|
||||
@ -1069,7 +1090,7 @@ static void devstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b
|
||||
}
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
static void gpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void gpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int id;
|
||||
|
||||
@ -1103,7 +1124,7 @@ static void gpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_AN_FPGA
|
||||
static void pgadev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void pgadev(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int numpga = numpgas();
|
||||
int id;
|
||||
@ -1137,7 +1158,7 @@ static void pgadev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
strcat(io_buffer, JSON_CLOSE);
|
||||
}
|
||||
|
||||
static void pgaenable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void pgaenable(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int numpga = numpgas();
|
||||
struct thr_info *thr;
|
||||
@ -1193,7 +1214,7 @@ static void pgaenable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
strcpy(io_buffer, message(MSG_PGAENA, id, NULL, isjson));
|
||||
}
|
||||
|
||||
static void pgadisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void pgadisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int numpga = numpgas();
|
||||
int id;
|
||||
@ -1234,7 +1255,7 @@ static void pgadisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
#endif
|
||||
|
||||
#ifdef WANT_CPUMINE
|
||||
static void cpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void cpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int id;
|
||||
|
||||
@ -1268,7 +1289,7 @@ static void cpudev(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char buf[TMPBUFSIZ];
|
||||
char *status, *lp;
|
||||
@ -1345,7 +1366,7 @@ static void poolstatus(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
||||
strcat(io_buffer, JSON_CLOSE);
|
||||
}
|
||||
|
||||
static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
double utility, mhs;
|
||||
|
||||
@ -1379,7 +1400,7 @@ static void summary(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
|
||||
#endif
|
||||
}
|
||||
#ifdef HAVE_OPENCL
|
||||
static void gpuenable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void gpuenable(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct thr_info *thr;
|
||||
int gpu;
|
||||
@ -1425,7 +1446,7 @@ static void gpuenable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
strcpy(io_buffer, message(MSG_GPUREN, id, NULL, isjson));
|
||||
}
|
||||
|
||||
static void gpudisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void gpudisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int id;
|
||||
|
||||
@ -1455,7 +1476,7 @@ static void gpudisable(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
strcpy(io_buffer, message(MSG_GPUDIS, id, NULL, isjson));
|
||||
}
|
||||
|
||||
static void gpurestart(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void gpurestart(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int id;
|
||||
|
||||
@ -1480,7 +1501,7 @@ static void gpurestart(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
strcpy(io_buffer, message(MSG_GPUREI, id, NULL, isjson));
|
||||
}
|
||||
#endif
|
||||
static void gpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void gpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char buf[TMPBUFSIZ];
|
||||
int numgpu = 0;
|
||||
@ -1499,8 +1520,7 @@ static void gpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo
|
||||
strcat(io_buffer, buf);
|
||||
}
|
||||
|
||||
|
||||
static void pgacount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void pgacount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char buf[TMPBUFSIZ];
|
||||
int count = 0;
|
||||
@ -1519,7 +1539,7 @@ static void pgacount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo
|
||||
strcat(io_buffer, buf);
|
||||
}
|
||||
|
||||
static void cpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void cpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char buf[TMPBUFSIZ];
|
||||
int count = 0;
|
||||
@ -1538,7 +1558,7 @@ static void cpucount(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bo
|
||||
strcat(io_buffer, buf);
|
||||
}
|
||||
|
||||
static void switchpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void switchpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct pool *pool;
|
||||
int id;
|
||||
@ -1619,7 +1639,7 @@ exitsama:
|
||||
return false;
|
||||
}
|
||||
|
||||
static void addpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void addpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char *url, *user, *pass;
|
||||
char *ptr;
|
||||
@ -1647,7 +1667,7 @@ static void addpool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
static void enablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void enablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct pool *pool;
|
||||
int id;
|
||||
@ -1681,7 +1701,7 @@ static void enablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
strcpy(io_buffer, message(MSG_ENAPOOL, id, NULL, isjson));
|
||||
}
|
||||
|
||||
static void disablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void disablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct pool *pool;
|
||||
int id;
|
||||
@ -1720,7 +1740,7 @@ static void disablepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
strcpy(io_buffer, message(MSG_DISPOOL, id, NULL, isjson));
|
||||
}
|
||||
|
||||
static void removepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void removepool(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
struct pool *pool;
|
||||
char *rpc_url;
|
||||
@ -1806,7 +1826,7 @@ static bool splitgpuvalue(char *param, int *gpu, char **value, bool isjson)
|
||||
|
||||
return true;
|
||||
}
|
||||
static void gpuintensity(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
static void gpuintensity(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
int id;
|
||||
char *value;
|
||||
@ -1835,7 +1855,7 @@ static void gpuintensity(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
strcpy(io_buffer, message(MSG_GPUINT, id, intensitystr, isjson));
|
||||
}
|
||||
|
||||
static void gpumem(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void gpumem(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
#ifdef HAVE_ADL
|
||||
int id;
|
||||
@ -1856,7 +1876,7 @@ static void gpumem(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gpuengine(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void gpuengine(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
#ifdef HAVE_ADL
|
||||
int id;
|
||||
@ -1877,7 +1897,7 @@ static void gpuengine(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, b
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gpufan(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void gpufan(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
#ifdef HAVE_ADL
|
||||
int id;
|
||||
@ -1898,7 +1918,7 @@ static void gpufan(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gpuvddc(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void gpuvddc(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
#ifdef HAVE_ADL
|
||||
int id;
|
||||
@ -1919,7 +1939,7 @@ static void gpuvddc(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, boo
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
void doquit(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
void doquit(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
if (isjson)
|
||||
strcpy(io_buffer, JSON_START JSON_BYE);
|
||||
@ -1930,7 +1950,7 @@ void doquit(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson
|
||||
do_a_quit = true;
|
||||
}
|
||||
|
||||
void dorestart(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
void dorestart(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
if (isjson)
|
||||
strcpy(io_buffer, JSON_START JSON_RESTART);
|
||||
@ -1941,12 +1961,12 @@ void dorestart(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isj
|
||||
do_a_restart = true;
|
||||
}
|
||||
|
||||
void privileged(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
void privileged(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
strcpy(io_buffer, message(MSG_ACCOK, 0, NULL, isjson));
|
||||
}
|
||||
|
||||
void notifystatus(int device, struct cgpu_info *cgpu, bool isjson)
|
||||
void notifystatus(int device, struct cgpu_info *cgpu, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char buf[TMPBUFSIZ];
|
||||
char *reason;
|
||||
@ -2000,7 +2020,7 @@ void notifystatus(int device, struct cgpu_info *cgpu, bool isjson)
|
||||
strcat(io_buffer, buf);
|
||||
}
|
||||
|
||||
static void notify(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void notify(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, char group)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -2017,13 +2037,13 @@ static void notify(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool
|
||||
}
|
||||
|
||||
for (i = 0; i < total_devices; i++)
|
||||
notifystatus(i, devices[i], isjson);
|
||||
notifystatus(i, devices[i], isjson, group);
|
||||
|
||||
if (isjson)
|
||||
strcat(io_buffer, JSON_CLOSE);
|
||||
}
|
||||
|
||||
static void devdetails(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
static void devdetails(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char buf[TMPBUFSIZ];
|
||||
struct cgpu_info *cgpu;
|
||||
@ -2059,7 +2079,7 @@ static void devdetails(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
||||
strcat(io_buffer, JSON_CLOSE);
|
||||
}
|
||||
|
||||
void dosave(__maybe_unused SOCKETTYPE c, char *param, bool isjson)
|
||||
void dosave(__maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
FILE *fcfg;
|
||||
@ -2135,7 +2155,8 @@ static int itemstats(int i, char *id, struct cgminer_stats *stats, struct cgmine
|
||||
|
||||
return i;
|
||||
}
|
||||
static void minerstats(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson)
|
||||
|
||||
static void minerstats(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
|
||||
{
|
||||
char extra[TMPBUFSIZ];
|
||||
char id[20];
|
||||
@ -2174,10 +2195,12 @@ static void minerstats(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
|
||||
strcat(io_buffer, JSON_CLOSE);
|
||||
}
|
||||
|
||||
static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group);
|
||||
|
||||
struct CMDS {
|
||||
char *name;
|
||||
void (*func)(SOCKETTYPE, char *, bool);
|
||||
bool requires_writemode;
|
||||
void (*func)(SOCKETTYPE, char *, bool, char);
|
||||
bool iswritemode;
|
||||
} cmds[] = {
|
||||
{ "version", apiversion, false },
|
||||
{ "config", minerconfig, false },
|
||||
@ -2220,9 +2243,47 @@ struct CMDS {
|
||||
{ "devdetails", devdetails, false },
|
||||
{ "restart", dorestart, true },
|
||||
{ "stats", minerstats, false },
|
||||
{ "check", checkcommand, false },
|
||||
{ NULL, NULL, false }
|
||||
};
|
||||
|
||||
static void checkcommand(__maybe_unused SOCKETTYPE c, char *param, bool isjson, char group)
|
||||
{
|
||||
char buf[TMPBUFSIZ];
|
||||
char cmdbuf[100];
|
||||
bool found, access;
|
||||
int i;
|
||||
|
||||
if (param == NULL || *param == '\0') {
|
||||
strcpy(io_buffer, message(MSG_MISCHK, 0, NULL, isjson));
|
||||
return;
|
||||
}
|
||||
|
||||
found = false;
|
||||
access = false;
|
||||
for (i = 0; cmds[i].name != NULL; i++) {
|
||||
if (strcmp(cmds[i].name, param) == 0) {
|
||||
found = true;
|
||||
|
||||
sprintf(cmdbuf, "|%s|", param);
|
||||
if (ISPRIVGROUP(group) || strstr(COMMANDS(group), cmdbuf))
|
||||
access = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strcpy(io_buffer, message(MSG_CHECK, 0, NULL, isjson));
|
||||
|
||||
sprintf(buf, isjson
|
||||
? "," JSON_CHECK "{\"Exists\":\"%s\",\"Access\":\"%s\"}" JSON_CLOSE
|
||||
: _CHECK ",Exists=%s,Access=%s" SEPSTR,
|
||||
found ? YES : NO,
|
||||
access ? YES : NO);
|
||||
|
||||
strcat(io_buffer, buf);
|
||||
}
|
||||
|
||||
static void send_result(SOCKETTYPE c, bool isjson)
|
||||
{
|
||||
int n;
|
||||
@ -2277,7 +2338,153 @@ static void tidyup(__maybe_unused void *arg)
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret [R|W:]IP[/Prefix][,[R|W:]IP2[/Prefix2][,...]] --api-allow option
|
||||
* Interpret --api-groups G:cmd1:cmd2:cmd3,P:cmd4,*,...
|
||||
*/
|
||||
static void setup_groups()
|
||||
{
|
||||
char *api_groups = opt_api_groups ? opt_api_groups : (char *)BLANK;
|
||||
char *buf, *ptr, *next, *colon;
|
||||
char group;
|
||||
char commands[TMPBUFSIZ];
|
||||
char cmdbuf[100];
|
||||
char *cmd;
|
||||
bool addstar, did;
|
||||
int i;
|
||||
|
||||
buf = malloc(strlen(api_groups) + 1);
|
||||
if (unlikely(!buf))
|
||||
quit(1, "Failed to malloc ipgroups buf");
|
||||
|
||||
strcpy(buf, api_groups);
|
||||
|
||||
next = buf;
|
||||
// for each group defined
|
||||
while (next && *next) {
|
||||
ptr = next;
|
||||
next = strchr(ptr, ',');
|
||||
if (next)
|
||||
*(next++) = '\0';
|
||||
|
||||
// Validate the group
|
||||
if (*(ptr+1) != ':') {
|
||||
colon = strchr(ptr, ':');
|
||||
if (colon)
|
||||
*colon = '\0';
|
||||
applog(LOG_WARNING, "API invalid group name '%s'", ptr);
|
||||
quit(1, INVAPIGROUPS);
|
||||
}
|
||||
|
||||
group = GROUP(*ptr);
|
||||
if (!VALIDGROUP(group)) {
|
||||
applog(LOG_WARNING, "API invalid group name '%c'", *ptr);
|
||||
quit(1, INVAPIGROUPS);
|
||||
}
|
||||
|
||||
if (group == PRIVGROUP) {
|
||||
applog(LOG_WARNING, "API group name can't be '%c'", PRIVGROUP);
|
||||
quit(1, INVAPIGROUPS);
|
||||
}
|
||||
|
||||
if (group == NOPRIVGROUP) {
|
||||
applog(LOG_WARNING, "API group name can't be '%c'", NOPRIVGROUP);
|
||||
quit(1, INVAPIGROUPS);
|
||||
}
|
||||
|
||||
if (apigroups[GROUPOFFSET(group)].commands != NULL) {
|
||||
applog(LOG_WARNING, "API duplicate group name '%c'", *ptr);
|
||||
quit(1, INVAPIGROUPS);
|
||||
}
|
||||
|
||||
ptr += 2;
|
||||
|
||||
// Validate the command list (and handle '*')
|
||||
cmd = &(commands[0]);
|
||||
*(cmd++) = SEPARATOR;
|
||||
*cmd = '\0';
|
||||
addstar = false;
|
||||
while (ptr && *ptr) {
|
||||
colon = strchr(ptr, ':');
|
||||
if (colon)
|
||||
*(colon++) = '\0';
|
||||
|
||||
if (strcmp(ptr, "*") == 0)
|
||||
addstar = true;
|
||||
else {
|
||||
did = false;
|
||||
for (i = 0; cmds[i].name != NULL; i++) {
|
||||
if (strcasecmp(ptr, cmds[i].name) == 0) {
|
||||
did = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (did) {
|
||||
// skip duplicates
|
||||
sprintf(cmdbuf, "|%s|", cmds[i].name);
|
||||
if (strstr(commands, cmdbuf) == NULL) {
|
||||
strcpy(cmd, cmds[i].name);
|
||||
cmd += strlen(cmds[i].name);
|
||||
*(cmd++) = SEPARATOR;
|
||||
*cmd = '\0';
|
||||
}
|
||||
} else {
|
||||
applog(LOG_WARNING, "API unknown command '%s' in group '%c'", ptr, group);
|
||||
quit(1, INVAPIGROUPS);
|
||||
}
|
||||
}
|
||||
|
||||
ptr = colon;
|
||||
}
|
||||
|
||||
// * = allow all non-iswritemode commands
|
||||
if (addstar) {
|
||||
for (i = 0; cmds[i].name != NULL; i++) {
|
||||
if (cmds[i].iswritemode == false) {
|
||||
// skip duplicates
|
||||
sprintf(cmdbuf, "|%s|", cmds[i].name);
|
||||
if (strstr(commands, cmdbuf) == NULL) {
|
||||
strcpy(cmd, cmds[i].name);
|
||||
cmd += strlen(cmds[i].name);
|
||||
*(cmd++) = SEPARATOR;
|
||||
*cmd = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ptr = apigroups[GROUPOFFSET(group)].commands = malloc(strlen(commands) + 1);
|
||||
if (unlikely(!ptr))
|
||||
quit(1, "Failed to malloc group commands buf");
|
||||
|
||||
strcpy(ptr, commands);
|
||||
}
|
||||
|
||||
// Now define R (NOPRIVGROUP) as all non-iswritemode commands
|
||||
cmd = &(commands[0]);
|
||||
*(cmd++) = SEPARATOR;
|
||||
*cmd = '\0';
|
||||
for (i = 0; cmds[i].name != NULL; i++) {
|
||||
if (cmds[i].iswritemode == false) {
|
||||
strcpy(cmd, cmds[i].name);
|
||||
cmd += strlen(cmds[i].name);
|
||||
*(cmd++) = SEPARATOR;
|
||||
*cmd = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
ptr = apigroups[GROUPOFFSET(NOPRIVGROUP)].commands = malloc(strlen(commands) + 1);
|
||||
if (unlikely(!ptr))
|
||||
quit(1, "Failed to malloc noprivgroup commands buf");
|
||||
|
||||
strcpy(ptr, commands);
|
||||
|
||||
// W (PRIVGROUP) is handled as a special case since it simply means all commands
|
||||
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interpret [W:]IP[/Prefix][,[R|W:]IP2[/Prefix2][,...]] --api-allow option
|
||||
* special case of 0/0 allows /0 (means all IP addresses)
|
||||
*/
|
||||
#define ALLIP4 "0/0"
|
||||
@ -2288,7 +2495,7 @@ static void setup_ipaccess()
|
||||
{
|
||||
char *buf, *ptr, *comma, *slash, *dot;
|
||||
int ipcount, mask, octet, i;
|
||||
bool writemode;
|
||||
char group;
|
||||
|
||||
buf = malloc(strlen(opt_api_allow) + 1);
|
||||
if (unlikely(!buf))
|
||||
@ -2322,16 +2529,16 @@ static void setup_ipaccess()
|
||||
if (comma)
|
||||
*(comma++) = '\0';
|
||||
|
||||
writemode = false;
|
||||
group = NOPRIVGROUP;
|
||||
|
||||
if (isalpha(*ptr) && *(ptr+1) == ':') {
|
||||
if (tolower(*ptr) == 'w')
|
||||
writemode = true;
|
||||
if (DEFINEDGROUP(*ptr))
|
||||
group = GROUP(*ptr);
|
||||
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
ipaccess[ips].writemode = writemode;
|
||||
ipaccess[ips].group = group;
|
||||
|
||||
if (strcmp(ptr, ALLIP4) == 0)
|
||||
ipaccess[ips].ip = ipaccess[ips].mask = 0;
|
||||
@ -2421,10 +2628,11 @@ void api(int api_thr_id)
|
||||
struct sockaddr_in serv;
|
||||
struct sockaddr_in cli;
|
||||
socklen_t clisiz;
|
||||
char cmdbuf[100];
|
||||
char *cmd;
|
||||
char *param;
|
||||
bool addrok;
|
||||
bool writemode;
|
||||
char group;
|
||||
json_error_t json_err;
|
||||
json_t *json_config;
|
||||
json_t *json_val;
|
||||
@ -2437,14 +2645,13 @@ void api(int api_thr_id)
|
||||
pthread_cleanup_push(tidyup, NULL);
|
||||
my_thr_id = api_thr_id;
|
||||
|
||||
/* This should be done first to ensure curl has already called WSAStartup() in windows */
|
||||
sleep(opt_log_interval);
|
||||
|
||||
if (!opt_api_listen) {
|
||||
applog(LOG_DEBUG, "API not running%s", UNAVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
setup_groups();
|
||||
|
||||
if (opt_api_allow) {
|
||||
setup_ipaccess();
|
||||
|
||||
@ -2454,6 +2661,10 @@ void api(int api_thr_id)
|
||||
}
|
||||
}
|
||||
|
||||
/* This should be done before curl in needed
|
||||
* to ensure curl has already called WSAStartup() in windows */
|
||||
sleep(opt_log_interval);
|
||||
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == INVSOCK) {
|
||||
applog(LOG_ERR, "API1 initialisation failed (%s)%s", SOCKERRMSG, UNAVAILABLE);
|
||||
@ -2523,12 +2734,12 @@ void api(int api_thr_id)
|
||||
connectaddr = inet_ntoa(cli.sin_addr);
|
||||
|
||||
addrok = false;
|
||||
writemode = false;
|
||||
group = NOPRIVGROUP;
|
||||
if (opt_api_allow) {
|
||||
for (i = 0; i < ips; i++) {
|
||||
if ((cli.sin_addr.s_addr & ipaccess[i].mask) == ipaccess[i].ip) {
|
||||
addrok = true;
|
||||
writemode = ipaccess[i].writemode;
|
||||
group = ipaccess[i].group;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2622,12 +2833,13 @@ void api(int api_thr_id)
|
||||
if (!did)
|
||||
for (i = 0; cmds[i].name != NULL; i++) {
|
||||
if (strcmp(cmd, cmds[i].name) == 0) {
|
||||
if (cmds[i].requires_writemode && !writemode) {
|
||||
sprintf(cmdbuf, "|%s|", cmd);
|
||||
if (ISPRIVGROUP(group) || strstr(COMMANDS(group), cmdbuf))
|
||||
(cmds[i].func)(c, param, isjson, group);
|
||||
else {
|
||||
strcpy(io_buffer, message(MSG_ACCDENY, 0, cmds[i].name, isjson));
|
||||
applog(LOG_DEBUG, "API: access denied to '%s' for '%s' command", connectaddr, cmds[i].name);
|
||||
}
|
||||
else
|
||||
(cmds[i].func)(c, param, isjson);
|
||||
|
||||
send_result(c, isjson);
|
||||
did = true;
|
||||
|
19
cgminer.c
19
cgminer.c
@ -100,6 +100,7 @@ int opt_scantime = 60;
|
||||
int opt_expiry = 120;
|
||||
int opt_bench_algo = -1;
|
||||
static const bool opt_time = true;
|
||||
unsigned long long global_hashrate;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
int opt_dynamic_interval = 7;
|
||||
@ -131,6 +132,7 @@ bool opt_autofan;
|
||||
bool opt_autoengine;
|
||||
bool opt_noadl;
|
||||
char *opt_api_allow = NULL;
|
||||
char *opt_api_groups;
|
||||
char *opt_api_description = PACKAGE_STRING;
|
||||
int opt_api_port = 4028;
|
||||
bool opt_api_listen;
|
||||
@ -680,6 +682,13 @@ static char *set_api_allow(const char *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *set_api_groups(const char *arg)
|
||||
{
|
||||
opt_set_charp(arg, &opt_api_groups);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *set_api_description(const char *arg)
|
||||
{
|
||||
opt_set_charp(arg, &opt_api_description);
|
||||
@ -730,10 +739,13 @@ static struct opt_table opt_config_table[] = {
|
||||
#endif
|
||||
OPT_WITH_ARG("--api-allow",
|
||||
set_api_allow, NULL, NULL,
|
||||
"Allow API access only to the given list of IP[/Prefix] addresses[/subnets]"),
|
||||
"Allow API access only to the given list of [G:]IP[/Prefix] addresses[/subnets]"),
|
||||
OPT_WITH_ARG("--api-description",
|
||||
set_api_description, NULL, NULL,
|
||||
"Description placed in the API status header, default: cgminer version"),
|
||||
OPT_WITH_ARG("--api-groups",
|
||||
set_api_groups, NULL, NULL,
|
||||
"API one letter groups G:cmd:cmd[,P:cmd:*...] defining the cmds a groups can use"),
|
||||
OPT_WITHOUT_ARG("--api-listen",
|
||||
opt_set_bool, &opt_api_listen,
|
||||
"Enable API, default: disabled"),
|
||||
@ -2872,6 +2884,8 @@ void write_config(FILE *fcfg)
|
||||
fprintf(fcfg, ",\n\"api-allow\" : \"%s\"", opt_api_allow);
|
||||
if (strcmp(opt_api_description, PACKAGE_STRING) != 0)
|
||||
fprintf(fcfg, ",\n\"api-description\" : \"%s\"", opt_api_description);
|
||||
if (opt_api_groups)
|
||||
fprintf(fcfg, ",\n\"api-groups\" : \"%s\"", opt_api_groups);
|
||||
if (opt_icarus_timing)
|
||||
fprintf(fcfg, ",\n\"icarus-timing\" : \"%s\"", opt_icarus_timing);
|
||||
fputs("\n}", fcfg);
|
||||
@ -3387,6 +3401,7 @@ static void hashmeter(int thr_id, struct timeval *diff,
|
||||
|
||||
local_secs = (double)total_diff.tv_sec + ((double)total_diff.tv_usec / 1000000.0);
|
||||
decay_time(&rolling, local_mhashes_done / local_secs);
|
||||
global_hashrate = roundl(rolling) * 1000000;
|
||||
|
||||
timeval_subtract(&total_diff, &total_tv_end, &total_tv_start);
|
||||
total_secs = (double)total_diff.tv_sec +
|
||||
@ -3649,7 +3664,7 @@ static inline bool should_roll(struct work *work)
|
||||
static inline bool can_roll(struct work *work)
|
||||
{
|
||||
return (work->pool && work->rolltime && !work->clone &&
|
||||
work->rolls < 7000 && !stale_work(work, false));
|
||||
work->rolls < 7000 && !stale_work(work, false));
|
||||
}
|
||||
|
||||
static void roll_work(struct work *work)
|
||||
|
2
miner.h
2
miner.h
@ -531,6 +531,7 @@ extern bool opt_autofan;
|
||||
extern bool opt_autoengine;
|
||||
extern bool use_curses;
|
||||
extern char *opt_api_allow;
|
||||
extern char *opt_api_groups;
|
||||
extern char *opt_api_description;
|
||||
extern int opt_api_port;
|
||||
extern bool opt_api_listen;
|
||||
@ -626,6 +627,7 @@ extern unsigned int local_work;
|
||||
extern unsigned int total_go, total_ro;
|
||||
extern const int opt_cutofftemp;
|
||||
extern int opt_log_interval;
|
||||
extern unsigned long long global_hashrate;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
typedef struct {
|
||||
|
23
util.c
23
util.c
@ -256,17 +256,17 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
bool probe, bool longpoll, int *rolltime,
|
||||
struct pool *pool, bool share)
|
||||
{
|
||||
json_t *val, *err_val, *res_val;
|
||||
int rc;
|
||||
struct data_buffer all_data = {NULL, 0};
|
||||
struct upload_buffer upload_data;
|
||||
json_error_t err;
|
||||
struct curl_slist *headers = NULL;
|
||||
char len_hdr[64], user_agent_hdr[128];
|
||||
char curl_err_str[CURL_ERROR_SIZE];
|
||||
char len_hdr[64], user_agent_hdr[128], *ghashrate;
|
||||
long timeout = longpoll ? (60 * 60) : 60;
|
||||
struct data_buffer all_data = {NULL, 0};
|
||||
struct header_info hi = {NULL, 0, NULL};
|
||||
char curl_err_str[CURL_ERROR_SIZE];
|
||||
struct curl_slist *headers = NULL;
|
||||
struct upload_buffer upload_data;
|
||||
json_t *val, *err_val, *res_val;
|
||||
bool probing = false;
|
||||
json_error_t err;
|
||||
int rc;
|
||||
|
||||
memset(&err, 0, sizeof(err));
|
||||
|
||||
@ -325,6 +325,13 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
"Content-type: application/json");
|
||||
headers = curl_slist_append(headers,
|
||||
"X-Mining-Extensions: longpoll midstate rollntime submitold");
|
||||
|
||||
if (likely(global_hashrate)) {
|
||||
asprintf(&ghashrate, "X-Mining-Hashrate: %llu", global_hashrate);
|
||||
headers = curl_slist_append(headers, ghashrate);
|
||||
free(ghashrate);
|
||||
}
|
||||
|
||||
headers = curl_slist_append(headers, len_hdr);
|
||||
headers = curl_slist_append(headers, user_agent_hdr);
|
||||
headers = curl_slist_append(headers, "Expect:"); /* disable Expect hdr*/
|
||||
|
Loading…
Reference in New Issue
Block a user