Browse Source

Merge branch 'config-parser' into v5_0

djm34
Noel Maersk 11 years ago
parent
commit
0886740a5f
  1. 19
      AUTHORS.md
  2. 3
      Makefile.am
  3. 18
      NEWS.md
  4. 2
      adl.c
  5. 1
      adl.h
  6. 593
      api.c
  7. 398
      api.h
  8. 2029
      config_parser.c
  9. 122
      config_parser.h
  10. 406
      doc/API.md
  11. 0
      doc/GPU.md
  12. 2187
      doc/configuration.md
  13. 145
      example.conf
  14. 45
      miner.h
  15. 987
      sgminer.c

19
AUTHORS.md

@ -2,12 +2,19 @@
## Core ## Core
* Multiple algorithms and switching: Jan Berdajs <mrbrdo at mrbrdo dot net> 15bULC8snaKAMeFb3xBmmhbWj1xyTmBUfm * Jan Berdajs <mrbrdo at mrbrdo dot net> 15bULC8snaKAMeFb3xBmmhbWj1xyTmBUfm
* Historical scrypt-only refactor: Noel Maersk <veox at wemakethings dot net> 12jF1VExtmmMu8D36vo4Y4CYqLK5yCtLC4 * Noel Maersk <veox at wemakethings dot net> 12jF1VExtmmMu8D36vo4Y4CYqLK5yCtLC4
* Core: Martin Danielsen <kalroth {at} gmail _dot_ com> 1DNBcSEENBwDKrcTyTW61ezWhzsPy5imkn * troky <troky2001 at yahoo dot com> Letoqz4yEnJxjWw9B7Ysn8h9VDQTMDnT29
* ystarnaud <**FIXME**>
* lasybear <**FIXME**>
* Luke Dashjr <luke-jr+cgminer @at@ utopios .dot. org> 1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh
* Andrew Smith <kan0i {at} kano-kun [dot] net> 1Jjk2LmktEQKnv8r2cZ9MvLiZwZ9gxabKm
## Core (history)
* Core: Con Kolivas <kernel [at] kolivas {dot} org> 15qSxP1SQcUX3o4nhkfdbgyoWEFMomJ4rZ * Core: Con Kolivas <kernel [at] kolivas {dot} org> 15qSxP1SQcUX3o4nhkfdbgyoWEFMomJ4rZ
* Core: Luke Dashjr <luke-jr+cgminer @at@ utopios .dot. org> 1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh * Martin Danielsen <kalroth {at} gmail _dot_ com> 1DNBcSEENBwDKrcTyTW61ezWhzsPy5imkn
* API: Andrew Smith <kan0i {at} kano-kun [dot] net> 1Jjk2LmktEQKnv8r2cZ9MvLiZwZ9gxabKm
## Cross-platform support ## Cross-platform support
@ -21,6 +28,8 @@
## OpenCL kernels ## OpenCL kernels
**FIXME**: this section is outdated.
All current kernels are based on `scrypt`, originally by Colin Percival, All current kernels are based on `scrypt`, originally by Colin Percival,
updated by many others. updated by many others.

3
Makefile.am

@ -32,7 +32,7 @@ sgminer_CPPFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
endif endif
sgminer_SOURCES := sgminer.c sgminer_SOURCES := sgminer.c
sgminer_SOURCES += api.c sgminer_SOURCES += api.c api.h
sgminer_SOURCES += elist.h miner.h compat.h bench_block.h sgminer_SOURCES += elist.h miner.h compat.h bench_block.h
sgminer_SOURCES += util.c util.h uthash.h sgminer_SOURCES += util.c util.h uthash.h
sgminer_SOURCES += logging.c logging.h sgminer_SOURCES += logging.c logging.h
@ -42,6 +42,7 @@ sgminer_SOURCES += findnonce.c findnonce.h
sgminer_SOURCES += adl.c adl.h adl_functions.h sgminer_SOURCES += adl.c adl.h adl_functions.h
sgminer_SOURCES += pool.c pool.h sgminer_SOURCES += pool.c pool.h
sgminer_SOURCES += algorithm.c algorithm.h sgminer_SOURCES += algorithm.c algorithm.h
sgminer_SOURCES += config_parser.c config_parser.h
sgminer_SOURCES += ocl/patch_kernel.c ocl/patch_kernel.h sgminer_SOURCES += ocl/patch_kernel.c ocl/patch_kernel.h
sgminer_SOURCES += ocl/build_kernel.c ocl/build_kernel.h sgminer_SOURCES += ocl/build_kernel.c ocl/build_kernel.h
sgminer_SOURCES += ocl/binary_kernel.c ocl/binary_kernel.h sgminer_SOURCES += ocl/binary_kernel.c ocl/binary_kernel.h

18
NEWS.md

@ -4,11 +4,19 @@
* Added support for animecoin, darkcoin, fuguecoin, groestlcoin, inkcoin, * Added support for animecoin, darkcoin, fuguecoin, groestlcoin, inkcoin,
marucoin, myriadcoin-groestl, quarkcoin, qubitcoin, sifcoin, twecoin, marucoin, myriadcoin-groestl, quarkcoin, qubitcoin, sifcoin, twecoin,
darkcoin-mod ("X11-mod"), marucoin-mod ("X13-mod"), maxcoin (by mrbrdo). darkcoin-mod ("X11-mod"), marucoin-mod ("X13-mod"), maxcoin (by
* intensity, xintensity, rawintensity, gpu-memclock, gpu-engine, _mrbrdo_).
thread-concurrency, gpu-threads now also have a `pool-*` version to * `intensity`, `xintensity`, `rawintensity`, `gpu-memclock`,
configure them for each pool separately (by mrbrdo). `gpu-engine`, `thread-concurrency`, `gpu-threads` now also have a
* Extranonce support for stratum (by bitbandi). `pool-*` version to configure them for each pool separately
(by _mrbrdo_).
* Initial configuration system revamping (by _ystarnaud_).
* Algorithm profile configuration (by _ystarnaud_).
* Complete configuration documentation, see `doc/configuration.md` (by
_ystarnaud_).
* API documentation update, see `doc/API.md` (by _ystarnaud_).
* Extranonce support for stratum (by _bitbandi_).
## Version 4.2.1 - 22nd May 2014 ## Version 4.2.1 - 22nd May 2014

2
adl.c

@ -1208,7 +1208,7 @@ int set_fanspeed(int gpu, int iFanSpeed)
} }
#ifdef HAVE_CURSES #ifdef HAVE_CURSES
static int set_powertune(int gpu, int iPercentage) int set_powertune(int gpu, int iPercentage)
{ {
struct gpu_adl *ga; struct gpu_adl *ga;
int dummy, ret = 1; int dummy, ret = 1;

1
adl.h

@ -15,6 +15,7 @@ float gpu_vddc(int gpu);
int gpu_activity(int gpu); int gpu_activity(int gpu);
int gpu_fanspeed(int gpu); int gpu_fanspeed(int gpu);
int gpu_fanpercent(int gpu); int gpu_fanpercent(int gpu);
extern int set_powertune(int gpu, int iPercentage);
bool gpu_stats(int gpu, float *temp, int *engineclock, int *memclock, float *vddc, bool gpu_stats(int gpu, float *temp, int *engineclock, int *memclock, float *vddc,
int *activity, int *fanspeed, int *fanpercent, int *powertune); int *activity, int *fanspeed, int *fanpercent, int *powertune);
void change_gpusettings(int gpu); void change_gpusettings(int gpu);

593
api.c

@ -26,77 +26,17 @@
#include <sys/types.h> #include <sys/types.h>
#include "compat.h" #include "compat.h"
#include "api.h"
#include "miner.h" #include "miner.h"
#include "pool.h" #include "pool.h"
#include "util.h" #include "util.h"
#include "pool.h" #include "pool.h"
// BUFSIZ varies on Windows and Linux #include "config_parser.h"
#define TMPBUFSIZ 8192
// Number of requests to queue - normally would be small #ifdef WIN32
#define QUEUE 100
#if defined WIN32
static char WSAbuf[1024]; static char WSAbuf[1024];
struct WSAERRORS {
int id;
char *code;
} WSAErrors[] = {
{ 0, "No error" },
{ WSAEINTR, "Interrupted system call" },
{ WSAEBADF, "Bad file number" },
{ WSAEACCES, "Permission denied" },
{ WSAEFAULT, "Bad address" },
{ WSAEINVAL, "Invalid argument" },
{ WSAEMFILE, "Too many open sockets" },
{ WSAEWOULDBLOCK, "Operation would block" },
{ WSAEINPROGRESS, "Operation now in progress" },
{ WSAEALREADY, "Operation already in progress" },
{ WSAENOTSOCK, "Socket operation on non-socket" },
{ WSAEDESTADDRREQ, "Destination address required" },
{ WSAEMSGSIZE, "Message too long" },
{ WSAEPROTOTYPE, "Protocol wrong type for socket" },
{ WSAENOPROTOOPT, "Bad protocol option" },
{ WSAEPROTONOSUPPORT, "Protocol not supported" },
{ WSAESOCKTNOSUPPORT, "Socket type not supported" },
{ WSAEOPNOTSUPP, "Operation not supported on socket" },
{ WSAEPFNOSUPPORT, "Protocol family not supported" },
{ WSAEAFNOSUPPORT, "Address family not supported" },
{ WSAEADDRINUSE, "Address already in use" },
{ WSAEADDRNOTAVAIL, "Can't assign requested address" },
{ WSAENETDOWN, "Network is down" },
{ WSAENETUNREACH, "Network is unreachable" },
{ WSAENETRESET, "Net connection reset" },
{ WSAECONNABORTED, "Software caused connection abort" },
{ WSAECONNRESET, "Connection reset by peer" },
{ WSAENOBUFS, "No buffer space available" },
{ WSAEISCONN, "Socket is already connected" },
{ WSAENOTCONN, "Socket is not connected" },
{ WSAESHUTDOWN, "Can't send after socket shutdown" },
{ WSAETOOMANYREFS, "Too many references, can't splice" },
{ WSAETIMEDOUT, "Connection timed out" },
{ WSAECONNREFUSED, "Connection refused" },
{ WSAELOOP, "Too many levels of symbolic links" },
{ WSAENAMETOOLONG, "File name too long" },
{ WSAEHOSTDOWN, "Host is down" },
{ WSAEHOSTUNREACH, "No route to host" },
{ WSAENOTEMPTY, "Directory not empty" },
{ WSAEPROCLIM, "Too many processes" },
{ WSAEUSERS, "Too many users" },
{ WSAEDQUOT, "Disc quota exceeded" },
{ WSAESTALE, "Stale NFS file handle" },
{ WSAEREMOTE, "Too many levels of remote in path" },
{ WSASYSNOTREADY, "Network system is unavailable" },
{ WSAVERNOTSUPPORTED, "Winsock version out of range" },
{ WSANOTINITIALISED, "WSAStartup not yet called" },
{ WSAEDISCON, "Graceful shutdown in progress" },
{ WSAHOST_NOT_FOUND, "Host not found" },
{ WSANO_DATA, "No host data of that type was found" },
{ -1, "Unknown error code" }
};
char *WSAErrorMsg(void) { char *WSAErrorMsg(void) {
int i; int i;
int id = WSAGetLastError(); int id = WSAGetLastError();
@ -112,236 +52,8 @@ char *WSAErrorMsg(void) {
} }
#endif #endif
static const char *UNAVAILABLE = " - API will not be available";
static const char *MUNAVAILABLE = " - API multicast listener will not be available";
static const char *BLANK = "";
static const char *COMMA = ",";
#define COMSTR ","
static const char SEPARATOR = '|';
#define SEPSTR "|"
static const char GPUSEP = ',';
#define CMDJOIN '+'
#define JOIN_CMD "CMD="
#define BETWEEN_JOIN SEPSTR
static const char *APIVERSION = "3.2";
static const char *DEAD = "Dead";
static const char *SICK = "Sick";
static const char *NOSTART = "NoStart";
static const char *INIT = "Initialising";
static const char *DISABLED = "Disabled";
static const char *ALIVE = "Alive";
static const char *REJECTING = "Rejecting";
static const char *UNKNOWN = "Unknown";
#define _DYNAMIC "D"
static const char *DYNAMIC = _DYNAMIC;
static __maybe_unused const char *NONE = "None";
static const char *YES = "Y";
static const char *NO = "N";
static const char *NULLSTR = "(null)";
static const char *TRUESTR = "true";
static const char *FALSESTR = "false";
static const char *DEVICECODE = "GPU ";
static const char *OSINFO =
#if defined(__linux__)
"Linux";
#elif defined(__APPLE__)
"Apple";
#elif defined(WIN32)
"Windows";
#elif defined(__CYGWIN__)
"Cygwin";
#elif defined(__unix__)
"Unix";
#else
"Unknown";
#endif
#define _DEVS "DEVS"
#define _POOLS "POOLS"
#define _SUMMARY "SUMMARY"
#define _STATUS "STATUS"
#define _VERSION "VERSION"
#define _MINECONFIG "CONFIG"
#define _GPU "GPU"
#define _GPUS "GPUS"
#define _NOTIFY "NOTIFY"
#define _DEVDETAILS "DEVDETAILS"
#define _BYE "BYE"
#define _RESTART "RESTART"
#define _MINESTATS "STATS"
#define _CHECK "CHECK"
#define _MINECOIN "COIN"
#define _DEBUGSET "DEBUG"
#define _SETCONFIG "SETCONFIG"
static const char ISJSON = '{';
#define JSON0 "{"
#define JSON1 "\""
#define JSON2 "\":["
#define JSON3 "]"
#define JSON4 ",\"id\":1"
// If anyone cares, id=0 for truncated output
#define JSON4_TRUNCATED ",\"id\":0"
#define JSON5 "}"
#define JSON_START JSON0
#define JSON_DEVS JSON1 _DEVS JSON2
#define JSON_POOLS JSON1 _POOLS JSON2
#define JSON_SUMMARY JSON1 _SUMMARY JSON2
#define JSON_STATUS JSON1 _STATUS JSON2
#define JSON_VERSION JSON1 _VERSION JSON2
#define JSON_MINECONFIG JSON1 _MINECONFIG JSON2
#define JSON_GPU JSON1 _GPU JSON2
#define JSON_GPUS JSON1 _GPUS JSON2
#define JSON_NOTIFY JSON1 _NOTIFY JSON2
#define JSON_DEVDETAILS JSON1 _DEVDETAILS JSON2
#define JSON_CLOSE JSON3
#define JSON_MINESTATS JSON1 _MINESTATS JSON2
#define JSON_CHECK JSON1 _CHECK JSON2
#define JSON_MINECOIN JSON1 _MINECOIN JSON2
#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2
#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2
#define JSON_END JSON4 JSON5
#define JSON_END_TRUNCATED JSON4_TRUNCATED JSON5
#define JSON_BETWEEN_JOIN ","
static const char *JSON_COMMAND = "command";
static const char *JSON_PARAMETER = "parameter";
#define MSG_INVGPU 1
#define MSG_ALRENA 2
#define MSG_ALRDIS 3
#define MSG_GPUMRE 4
#define MSG_GPUREN 5
#define MSG_GPUNON 6
#define MSG_POOL 7
#define MSG_NOPOOL 8
#define MSG_DEVS 9
#define MSG_NODEVS 10
#define MSG_SUMM 11
#define MSG_GPUDIS 12
#define MSG_GPUREI 13
#define MSG_INVCMD 14
#define MSG_MISID 15
#define MSG_GPUDEV 17
#define MSG_NUMGPU 20
#define MSG_VERSION 22
#define MSG_INVJSON 23
#define MSG_MISCMD 24
#define MSG_MISPID 25
#define MSG_INVPID 26
#define MSG_SWITCHP 27
#define MSG_MISVAL 28
#define MSG_NOADL 29
#define MSG_NOGPUADL 30
#define MSG_INVINT 31
#define MSG_GPUINT 32
#define MSG_MINECONFIG 33
#define MSG_GPUMERR 34
#define MSG_GPUMEM 35
#define MSG_GPUEERR 36
#define MSG_GPUENG 37
#define MSG_GPUVERR 38
#define MSG_GPUVDDC 39
#define MSG_GPUFERR 40
#define MSG_GPUFAN 41
#define MSG_MISFN 42
#define MSG_BADFN 43
#define MSG_SAVED 44
#define MSG_ACCDENY 45
#define MSG_ACCOK 46
#define MSG_ENAPOOL 47
#define MSG_DISPOOL 48
#define MSG_ALRENAP 49
#define MSG_ALRDISP 50
#define MSG_MISPDP 52
#define MSG_INVPDP 53
#define MSG_TOOMANYP 54
#define MSG_ADDPOOL 55
#define MSG_NOTIFY 60
#define MSG_REMLASTP 66
#define MSG_ACTPOOL 67
#define MSG_REMPOOL 68
#define MSG_DEVDETAILS 69
#define MSG_MINESTATS 70
#define MSG_MISCHK 71
#define MSG_CHECK 72
#define MSG_POOLPRIO 73
#define MSG_DUPPID 74
#define MSG_MISBOOL 75
#define MSG_INVBOOL 76
#define MSG_FOO 77
#define MSG_MINECOIN 78
#define MSG_DEBUGSET 79
#define MSG_SETCONFIG 82
#define MSG_UNKCON 83
#define MSG_INVNUM 84
#define MSG_CONPAR 85
#define MSG_CONVAL 86
#define MSG_NOUSTA 88
#define MSG_ZERMIS 94
#define MSG_ZERINV 95
#define MSG_ZERSUM 96
#define MSG_ZERNOSUM 97
#define MSG_BYE 0x101
#define MSG_INVNEG 121
#define MSG_SETQUOTA 122
#define MSG_LOCKOK 123
#define MSG_LOCKDIS 124
enum code_severity {
SEVERITY_ERR,
SEVERITY_WARN,
SEVERITY_INFO,
SEVERITY_SUCC,
SEVERITY_FAIL
};
enum code_parameters {
PARAM_GPU,
PARAM_PID,
PARAM_GPUMAX,
PARAM_PMAX,
PARAM_POOLMAX,
// Single generic case: have the code resolve it - see below
PARAM_DMAX,
PARAM_CMD,
PARAM_POOL,
PARAM_STR,
PARAM_BOTH,
PARAM_BOOL,
PARAM_SET,
PARAM_INT,
PARAM_NONE
};
struct CODES { struct CODES codes[] = {
const enum code_severity severity;
const int code;
const enum code_parameters params;
const char *description;
} codes[] = {
{ SEVERITY_ERR, MSG_INVGPU, PARAM_GPUMAX, "Invalid GPU id %d - range is 0 - %d" }, { SEVERITY_ERR, MSG_INVGPU, PARAM_GPUMAX, "Invalid GPU id %d - range is 0 - %d" },
{ SEVERITY_INFO, MSG_ALRENA, PARAM_GPU, "GPU %d already enabled" }, { SEVERITY_INFO, MSG_ALRENA, PARAM_GPU, "GPU %d already enabled" },
{ SEVERITY_INFO, MSG_ALRDIS, PARAM_GPU, "GPU %d already disabled" }, { SEVERITY_INFO, MSG_ALRDIS, PARAM_GPU, "GPU %d already disabled" },
@ -424,10 +136,78 @@ struct CODES {
{ SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" }, { SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" },
{ SEVERITY_SUCC, MSG_LOCKOK, PARAM_NONE, "Lock stats created" }, { SEVERITY_SUCC, MSG_LOCKOK, PARAM_NONE, "Lock stats created" },
{ SEVERITY_WARN, MSG_LOCKDIS, PARAM_NONE, "Lock stats not enabled" }, { SEVERITY_WARN, MSG_LOCKDIS, PARAM_NONE, "Lock stats not enabled" },
{ SEVERITY_SUCC, MSG_CHSTRAT, PARAM_STR, "Multipool strategy changed to '%s'" },
{ SEVERITY_ERR, MSG_MISSTRAT, PARAM_NONE, "Missing multipool strategy" },
{ SEVERITY_ERR, MSG_INVSTRAT, PARAM_NONE, "Invalid multipool strategy %d" },
{ SEVERITY_ERR, MSG_MISSTRATINT, PARAM_NONE, "Missing rotate interval" },
{ SEVERITY_SUCC, MSG_PROFILE, PARAM_PRMAX, "%d Profile(s)" },
{ SEVERITY_ERR, MSG_NOPROFILE, PARAM_NONE, "No profiles" },
{ SEVERITY_ERR, MSG_PROFILEEXIST, PARAM_STR, "Profile '%s' already exists" },
{ SEVERITY_ERR, MSG_MISPRD, PARAM_NONE, "Missing addprofile details" },
{ SEVERITY_SUCC, MSG_ADDPROFILE, PARAM_STR, "Added profile '%s'" },
{ SEVERITY_ERR, MSG_MISPRID, PARAM_STR, "Profile name missing" },
{ SEVERITY_ERR, MSG_PRNOEXIST, PARAM_STR, "Profile '%s' doesn't exist" },
{ SEVERITY_ERR, MSG_PRISDEFAULT, PARAM_STR, "Profile '%s' is the default profile" },
{ SEVERITY_ERR, MSG_PRINUSE, PARAM_STR, "Profile '%s' is used by a pool" },
{ SEVERITY_SUCC, MSG_REMPROFILE, PARAM_BOTH, "Removed pool %d:'%s'" },
{ SEVERITY_SUCC, MSG_CHPOOLPR, PARAM_BOTH, "Changed pool %d to profile '%s'" },
{ SEVERITY_SUCC, MSG_BYE, PARAM_STR, "%s" }, { SEVERITY_SUCC, MSG_BYE, PARAM_STR, "%s" },
{ SEVERITY_FAIL, 0, (enum code_parameters)0, NULL } { SEVERITY_FAIL, 0, (enum code_parameters)0, NULL }
}; };
static const char *UNAVAILABLE = " - API will not be available";
static const char *MUNAVAILABLE = " - API multicast listener will not be available";
static const char *BLANK = "";
static const char *COMMA = ",";
static const char SEPARATOR = '|';
static const char GPUSEP = ',';
static const char *APIVERSION = "4.0";
static const char *DEAD = "Dead";
static const char *SICK = "Sick";
static const char *NOSTART = "NoStart";
static const char *INIT = "Initialising";
static const char *DISABLED = "Disabled";
static const char *ALIVE = "Alive";
static const char *REJECTING = "Rejecting";
static const char *UNKNOWN = "Unknown";
static const char *DYNAMIC = _DYNAMIC;
static __maybe_unused const char *NONE = "None";
static const char *YES = "Y";
static const char *NO = "N";
static const char *NULLSTR = "(null)";
static const char *TRUESTR = "true";
static const char *FALSESTR = "false";
static const char *DEVICECODE = "GPU ";
static const char *OSINFO =
#if defined(__linux__)
"Linux";
#elif defined(__APPLE__)
"Apple";
#elif defined(WIN32)
"Windows";
#elif defined(__CYGWIN__)
"Cygwin";
#elif defined(__unix__)
"Unix";
#else
"Unknown";
#endif
static const char *JSON_COMMAND = "command";
static const char *JSON_PARAMETER = "parameter";
static const char ISJSON = '{';
static const char *localaddr = "127.0.0.1"; static const char *localaddr = "127.0.0.1";
static int my_thr_id = 0; static int my_thr_id = 0;
@ -441,50 +221,11 @@ static bool do_a_restart;
static time_t when = 0; // when the request occurred static time_t when = 0; // when the request occurred
struct IP4ACCESS {
in_addr_t ip;
in_addr_t mask;
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 struct IP4ACCESS *ipaccess = NULL;
static int ips = 0; static int ips = 0;
struct io_data {
size_t siz;
char *ptr;
char *cur;
bool sock;
bool close;
};
struct io_list {
struct io_data *io_data;
struct io_list *prev;
struct io_list *next;
};
static struct io_list *io_head = NULL; static struct io_list *io_head = NULL;
#define SOCKBUFALLOCSIZ 65536
#define io_new(init) _io_new(init, false)
#define sock_io_new() _io_new(SOCKBUFALLOCSIZ, true)
static void io_reinit(struct io_data *io_data) static void io_reinit(struct io_data *io_data)
{ {
io_data->cur = io_data->ptr; io_data->cur = io_data->ptr;
@ -521,7 +262,7 @@ static struct io_data *_io_new(size_t initial, bool socket_buf)
return io_data; return io_data;
} }
static bool io_add(struct io_data *io_data, char *buf) bool io_add(struct io_data *io_data, char *buf)
{ {
size_t len, dif, tot; size_t len, dif, tot;
@ -547,12 +288,12 @@ static bool io_add(struct io_data *io_data, char *buf)
return true; return true;
} }
static void io_close(struct io_data *io_data) void io_close(struct io_data *io_data)
{ {
io_data->close = true; io_data->close = true;
} }
static void io_free() void io_free()
{ {
struct io_list *io_list, *io_next; struct io_list *io_list, *io_next;
@ -902,7 +643,7 @@ struct api_data *api_add_avg(struct api_data *root, char *name, float *data, boo
return api_add_data_full(root, name, API_AVG, (void *)data, copy_data); return api_add_data_full(root, name, API_AVG, (void *)data, copy_data);
} }
static struct api_data *print_data(struct api_data *root, char *buf, bool isjson, bool precom) struct api_data *print_data(struct api_data *root, char *buf, bool isjson, bool precom)
{ {
struct api_data *tmp; struct api_data *tmp;
bool first = true; bool first = true;
@ -1045,7 +786,7 @@ static struct api_data *print_data(struct api_data *root, char *buf, bool isjson
// All replies (except BYE and RESTART) start with a message // All replies (except BYE and RESTART) start with a message
// thus for JSON, message() inserts JSON_START at the front // thus for JSON, message() inserts JSON_START at the front
// and send_result() adds JSON_END at the end // and send_result() adds JSON_END at the end
static void message(struct io_data *io_data, int messageid, int paramid, char *param2, bool isjson) void message(struct io_data *io_data, int messageid, int paramid, char *param2, bool isjson)
{ {
struct api_data *root = NULL; struct api_data *root = NULL;
char buf[TMPBUFSIZ]; char buf[TMPBUFSIZ];
@ -1091,6 +832,9 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p
case PARAM_PMAX: case PARAM_PMAX:
sprintf(buf, codes[i].description, total_pools); sprintf(buf, codes[i].description, total_pools);
break; break;
case PARAM_PRMAX:
sprintf(buf, codes[i].description, total_profiles);
break;
case PARAM_POOLMAX: case PARAM_POOLMAX:
sprintf(buf, codes[i].description, paramid, total_pools - 1); sprintf(buf, codes[i].description, paramid, total_pools - 1);
break; break;
@ -1147,49 +891,6 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p
#if LOCK_TRACKING #if LOCK_TRACKING
#define LOCK_FMT_FFL " - called from %s %s():%d"
#define LOCKMSG(fmt, ...) fprintf(stderr, "APILOCK: " fmt "\n", ##__VA_ARGS__)
#define LOCKMSGMORE(fmt, ...) fprintf(stderr, " " fmt "\n", ##__VA_ARGS__)
#define LOCKMSGFFL(fmt, ...) fprintf(stderr, "APILOCK: " fmt LOCK_FMT_FFL "\n", ##__VA_ARGS__, file, func, linenum)
#define LOCKMSGFLUSH() fflush(stderr)
typedef struct lockstat {
uint64_t lock_id;
const char *file;
const char *func;
int linenum;
struct timeval tv;
} LOCKSTAT;
typedef struct lockline {
struct lockline *prev;
struct lockstat *stat;
struct lockline *next;
} LOCKLINE;
typedef struct lockinfo {
void *lock;
enum cglock_typ typ;
const char *file;
const char *func;
int linenum;
uint64_t gets;
uint64_t gots;
uint64_t tries;
uint64_t dids;
uint64_t didnts; // should be tries - dids
uint64_t unlocks;
LOCKSTAT lastgot;
LOCKLINE *lockgets;
LOCKLINE *locktries;
} LOCKINFO;
typedef struct locklist {
LOCKINFO *info;
struct locklist *next;
} LOCKLIST;
static uint64_t lock_id = 1; static uint64_t lock_id = 1;
static LOCKLIST *lockhead; static LOCKLIST *lockhead;
@ -1532,6 +1233,23 @@ void show_locks()
} }
#endif #endif
static void copyadvanceafter(char ch, char **param, char **buf)
{
#define src_p (*param)
#define dst_b (*buf)
while (*src_p && *src_p != ch) {
if (*src_p == '\\' && *(src_p+1) != '\0')
src_p++;
*(dst_b++) = *(src_p++);
}
if (*src_p)
src_p++;
*(dst_b++) = '\0';
}
static void lockstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group) static void lockstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
{ {
#if LOCK_TRACKING #if LOCK_TRACKING
@ -1822,6 +1540,7 @@ static void poolstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
root = api_add_string(root, "Name", get_pool_name(pool), true); root = api_add_string(root, "Name", get_pool_name(pool), true);
mutex_unlock(&pool->stratum_lock); mutex_unlock(&pool->stratum_lock);
root = api_add_escape(root, "URL", pool->rpc_url, false); root = api_add_escape(root, "URL", pool->rpc_url, false);
root = api_add_string(root, "Profile", pool->profile, false);
root = api_add_string(root, "Algorithm", pool->algorithm.name, false); root = api_add_string(root, "Algorithm", pool->algorithm.name, false);
root = api_add_string(root, "Description", pool->description, false); root = api_add_string(root, "Description", pool->description, false);
root = api_add_string(root, "Status", status, false); root = api_add_string(root, "Status", status, false);
@ -2099,25 +1818,74 @@ static void switchpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
message(io_data, MSG_SWITCHP, id, NULL, isjson); message(io_data, MSG_SWITCHP, id, NULL, isjson);
} }
static void copyadvanceafter(char ch, char **param, char **buf) static void api_pool_strategy(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
{ {
#define src_p (*param) char *p;
#define dst_b (*buf) int strategy;
while (*src_p && *src_p != ch) { if (total_pools == 0)
if (*src_p == '\\' && *(src_p+1) != '\0') {
src_p++; message(io_data, MSG_NOPOOL, 0, NULL, isjson);
return;
}
*(dst_b++) = *(src_p++); if (param == NULL || *param == '\0')
{
message(io_data, MSG_MISSTRAT, 0, NULL, isjson);
return;
} }
if (*src_p)
src_p++;
*(dst_b++) = '\0'; //get strategy in parameter 1
if(!(p = strtok(param, ",")))
{
message(io_data, MSG_MISSTRAT, 0, NULL, isjson);
return;
}
strategy = atoi(p);
//invalid strategy
if(strategy < 0 || strategy > TOP_STRATEGY)
{
message(io_data, MSG_INVSTRAT, strategy, NULL, isjson);
return;
}
//if set to rotate, get second param
if(strategy == POOL_ROTATE)
{
//if second param is missing then invalid
if(!(p = strtok(NULL, ",")))
{
message(io_data, MSG_MISSTRATINT, 0, NULL, isjson);
return;
}
//get interval in parameter 2
int interval;
interval = atoi(p);
//interval can only be between 0 and 9999
if(interval < 0 || interval > 9999)
{
message(io_data, MSG_INVNUM, interval, "interval", isjson);
return;
}
//set interval
opt_rotate_period = interval;
}
//set pool strategy
pool_strategy = (enum pool_strategy)strategy;
//initiate new strategy
switch_pools(NULL);
message(io_data, MSG_CHSTRAT, 0, (char *)strategies[strategy].s, isjson);
} }
static bool pooldetails(char *param, char **url, char **user, char **pass, static bool pooldetails(char *param, char **url, char **user, char **pass,
char **name, char **desc, char **algo) char **name, char **desc, char **profile, char **algo)
{ {
char *ptr, *buf; char *ptr, *buf;
@ -2132,23 +1900,28 @@ static bool pooldetails(char *param, char **url, char **user, char **pass,
*user = buf; *user = buf;
copyadvanceafter(',', &param, &buf); copyadvanceafter(',', &param, &buf);
if (!*param) // missing pass if (!(*param)) // missing pass
goto exitsama; goto exitsama;
*pass = buf; *pass = buf;
copyadvanceafter(',', &param, &buf); copyadvanceafter(',', &param, &buf);
if (!*param) // missing name (allowed) if (!(*param)) // missing name (allowed)
return true; return true;
*name = buf; *name = buf;
copyadvanceafter(',', &param, &buf); copyadvanceafter(',', &param, &buf);
if (!*param) // missing desc if (!(*param)) // missing desc
goto exitsama; return true;
*desc = buf; *desc = buf;
copyadvanceafter(',', &param, &buf); copyadvanceafter(',', &param, &buf);
if (!*param) // missing algo if (!(*param)) // missing profile
goto exitsama; return true;
*profile = buf;
copyadvanceafter(',', &param, &buf);
if (!(*param)) // missing algo
return true;
*algo = buf; *algo = buf;
copyadvanceafter(',', &param, &buf); copyadvanceafter(',', &param, &buf);
@ -2163,7 +1936,7 @@ exitsama:
static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
{ {
char *url, *user, *pass; char *url, *user, *pass;
char *name = NULL, *desc = NULL, *algo = NULL; char *name = NULL, *desc = NULL, *algo = NULL, *profile = NULL;
struct pool *pool; struct pool *pool;
char *ptr; char *ptr;
@ -2173,7 +1946,7 @@ static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *
} }
if (!pooldetails(param, &url, &user, &pass, if (!pooldetails(param, &url, &user, &pass,
&name, &desc, &algo)) { &name, &desc, &profile, &algo)) {
ptr = escape_string(param, isjson); ptr = escape_string(param, isjson);
message(io_data, MSG_INVPDP, 0, ptr, isjson); message(io_data, MSG_INVPDP, 0, ptr, isjson);
if (ptr != param) if (ptr != param)
@ -2183,13 +1956,14 @@ static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *
} }
/* If API client is old, it might not have provided all fields. */ /* If API client is old, it might not have provided all fields. */
if (name == NULL) name = strdup(""); name = ((name == NULL)?strdup(""):name);
if (desc == NULL) desc = strdup(""); desc = ((desc == NULL)?strdup(""):desc);
if (algo == NULL) algo = strdup("scrypt"); // FIXME? profile = ((profile == NULL)?strdup(""):profile);
algo = ((algo == NULL)?strdup(""):algo);
pool = add_pool(); pool = add_pool();
detect_stratum(pool, url); detect_stratum(pool, url);
add_pool_details(pool, true, url, user, pass, name, desc, algo); add_pool_details(pool, true, url, user, pass, name, desc, profile, algo);
ptr = escape_string(url, isjson); ptr = escape_string(url, isjson);
message(io_data, MSG_ADDPOOL, 0, ptr, isjson); message(io_data, MSG_ADDPOOL, 0, ptr, isjson);
@ -2727,7 +2501,7 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
FILE *fcfg; // FILE *fcfg;
char *ptr; char *ptr;
if (param == NULL || *param == '\0') { if (param == NULL || *param == '\0') {
@ -2735,7 +2509,7 @@ void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, b
param = filename; param = filename;
} }
fcfg = fopen(param, "w"); /*fcfg = fopen(param, "w");
if (!fcfg) { if (!fcfg) {
ptr = escape_string(param, isjson); ptr = escape_string(param, isjson);
message(io_data, MSG_BADFN, 0, ptr, isjson); message(io_data, MSG_BADFN, 0, ptr, isjson);
@ -2743,10 +2517,10 @@ void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, b
free(ptr); free(ptr);
ptr = NULL; ptr = NULL;
return; return;
} }*/
write_config(fcfg); write_config(param);
fclose(fcfg); //fclose(fcfg);
ptr = escape_string(param, isjson); ptr = escape_string(param, isjson);
message(io_data, MSG_SAVED, 0, ptr, isjson); message(io_data, MSG_SAVED, 0, ptr, isjson);
@ -3062,6 +2836,7 @@ struct CMDS {
{ "config", minerconfig, false, true }, { "config", minerconfig, false, true },
{ "devs", devstatus, false, true }, { "devs", devstatus, false, true },
{ "pools", poolstatus, false, true }, { "pools", poolstatus, false, true },
{ "profiles", api_profile_list, false, true },
{ "summary", summary, false, true }, { "summary", summary, false, true },
{ "gpuenable", gpuenable, true, false }, { "gpuenable", gpuenable, true, false },
{ "gpudisable", gpudisable, true, false }, { "gpudisable", gpudisable, true, false },
@ -3069,12 +2844,16 @@ struct CMDS {
{ "gpu", gpudev, false, false }, { "gpu", gpudev, false, false },
{ "gpucount", gpucount, false, true }, { "gpucount", gpucount, false, true },
{ "switchpool", switchpool, true, false }, { "switchpool", switchpool, true, false },
{ "changestrategy", api_pool_strategy, true, false },
{ "addpool", addpool, true, false }, { "addpool", addpool, true, false },
{ "poolpriority", poolpriority, true, false }, { "poolpriority", poolpriority, true, false },
{ "poolquota", poolquota, true, false }, { "poolquota", poolquota, true, false },
{ "enablepool", enablepool, true, false }, { "enablepool", enablepool, true, false },
{ "disablepool", disablepool, true, false }, { "disablepool", disablepool, true, false },
{ "removepool", removepool, true, false }, { "removepool", removepool, true, false },
{ "changepoolprofile", api_pool_profile, true, false },
{ "addprofile", api_profile_add, true, false },
{ "removeprofile", api_profile_remove, true, false },
{ "gpuintensity", gpuintensity, true, false }, { "gpuintensity", gpuintensity, true, false },
{ "gpumem", gpumem, true, false }, { "gpumem", gpumem, true, false },
{ "gpuengine", gpuengine, true, false }, { "gpuengine", gpuengine, true, false },

398
api.h

@ -0,0 +1,398 @@
#ifndef API_H
#define API_H
#include "config.h"
#include "miner.h"
// BUFSIZ varies on Windows and Linux
#define TMPBUFSIZ 8192
// Number of requests to queue - normally would be small
#define QUEUE 100
#ifdef WIN32
struct WSAERRORS {
int id;
char *code;
} WSAErrors[] = {
{ 0, "No error" },
{ WSAEINTR, "Interrupted system call" },
{ WSAEBADF, "Bad file number" },
{ WSAEACCES, "Permission denied" },
{ WSAEFAULT, "Bad address" },
{ WSAEINVAL, "Invalid argument" },
{ WSAEMFILE, "Too many open sockets" },
{ WSAEWOULDBLOCK, "Operation would block" },
{ WSAEINPROGRESS, "Operation now in progress" },
{ WSAEALREADY, "Operation already in progress" },
{ WSAENOTSOCK, "Socket operation on non-socket" },
{ WSAEDESTADDRREQ, "Destination address required" },
{ WSAEMSGSIZE, "Message too long" },
{ WSAEPROTOTYPE, "Protocol wrong type for socket" },
{ WSAENOPROTOOPT, "Bad protocol option" },
{ WSAEPROTONOSUPPORT, "Protocol not supported" },
{ WSAESOCKTNOSUPPORT, "Socket type not supported" },
{ WSAEOPNOTSUPP, "Operation not supported on socket" },
{ WSAEPFNOSUPPORT, "Protocol family not supported" },
{ WSAEAFNOSUPPORT, "Address family not supported" },
{ WSAEADDRINUSE, "Address already in use" },
{ WSAEADDRNOTAVAIL, "Can't assign requested address" },
{ WSAENETDOWN, "Network is down" },
{ WSAENETUNREACH, "Network is unreachable" },
{ WSAENETRESET, "Net connection reset" },
{ WSAECONNABORTED, "Software caused connection abort" },
{ WSAECONNRESET, "Connection reset by peer" },
{ WSAENOBUFS, "No buffer space available" },
{ WSAEISCONN, "Socket is already connected" },
{ WSAENOTCONN, "Socket is not connected" },
{ WSAESHUTDOWN, "Can't send after socket shutdown" },
{ WSAETOOMANYREFS, "Too many references, can't splice" },
{ WSAETIMEDOUT, "Connection timed out" },
{ WSAECONNREFUSED, "Connection refused" },
{ WSAELOOP, "Too many levels of symbolic links" },
{ WSAENAMETOOLONG, "File name too long" },
{ WSAEHOSTDOWN, "Host is down" },
{ WSAEHOSTUNREACH, "No route to host" },
{ WSAENOTEMPTY, "Directory not empty" },
{ WSAEPROCLIM, "Too many processes" },
{ WSAEUSERS, "Too many users" },
{ WSAEDQUOT, "Disc quota exceeded" },
{ WSAESTALE, "Stale NFS file handle" },
{ WSAEREMOTE, "Too many levels of remote in path" },
{ WSASYSNOTREADY, "Network system is unavailable" },
{ WSAVERNOTSUPPORTED, "Winsock version out of range" },
{ WSANOTINITIALISED, "WSAStartup not yet called" },
{ WSAEDISCON, "Graceful shutdown in progress" },
{ WSAHOST_NOT_FOUND, "Host not found" },
{ WSANO_DATA, "No host data of that type was found" },
{ -1, "Unknown error code" }
};
#endif
#define COMSTR ","
#define SEPSTR "|"
#define CMDJOIN '+'
#define JOIN_CMD "CMD="
#define BETWEEN_JOIN SEPSTR
#define _DYNAMIC "D"
#define _DEVS "DEVS"
#define _POOLS "POOLS"
#define _PROFILES "PROFILES"
#define _SUMMARY "SUMMARY"
#define _STATUS "STATUS"
#define _VERSION "VERSION"
#define _MINECONFIG "CONFIG"
#define _GPU "GPU"
#define _GPUS "GPUS"
#define _NOTIFY "NOTIFY"
#define _DEVDETAILS "DEVDETAILS"
#define _BYE "BYE"
#define _RESTART "RESTART"
#define _MINESTATS "STATS"
#define _CHECK "CHECK"
#define _MINECOIN "COIN"
#define _DEBUGSET "DEBUG"
#define _SETCONFIG "SETCONFIG"
#define JSON0 "{"
#define JSON1 "\""
#define JSON2 "\":["
#define JSON3 "]"
#define JSON4 ",\"id\":1"
// If anyone cares, id=0 for truncated output
#define JSON4_TRUNCATED ",\"id\":0"
#define JSON5 "}"
#define JSON_START JSON0
#define JSON_DEVS JSON1 _DEVS JSON2
#define JSON_POOLS JSON1 _POOLS JSON2
#define JSON_PROFILES JSON1 _POOLS JSON2
#define JSON_SUMMARY JSON1 _SUMMARY JSON2
#define JSON_STATUS JSON1 _STATUS JSON2
#define JSON_VERSION JSON1 _VERSION JSON2
#define JSON_MINECONFIG JSON1 _MINECONFIG JSON2
#define JSON_GPU JSON1 _GPU JSON2
#define JSON_GPUS JSON1 _GPUS JSON2
#define JSON_NOTIFY JSON1 _NOTIFY JSON2
#define JSON_DEVDETAILS JSON1 _DEVDETAILS JSON2
#define JSON_CLOSE JSON3
#define JSON_MINESTATS JSON1 _MINESTATS JSON2
#define JSON_CHECK JSON1 _CHECK JSON2
#define JSON_MINECOIN JSON1 _MINECOIN JSON2
#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2
#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2
#define JSON_END JSON4 JSON5
#define JSON_END_TRUNCATED JSON4_TRUNCATED JSON5
#define JSON_BETWEEN_JOIN ","
#define MSG_INVGPU 1
#define MSG_ALRENA 2
#define MSG_ALRDIS 3
#define MSG_GPUMRE 4
#define MSG_GPUREN 5
#define MSG_GPUNON 6
#define MSG_POOL 7
#define MSG_NOPOOL 8
#define MSG_DEVS 9
#define MSG_NODEVS 10
#define MSG_SUMM 11
#define MSG_GPUDIS 12
#define MSG_GPUREI 13
#define MSG_INVCMD 14
#define MSG_MISID 15
#define MSG_GPUDEV 17
#define MSG_NUMGPU 20
#define MSG_VERSION 22
#define MSG_INVJSON 23
#define MSG_MISCMD 24
#define MSG_MISPID 25
#define MSG_INVPID 26
#define MSG_SWITCHP 27
#define MSG_MISVAL 28
#define MSG_NOADL 29
#define MSG_NOGPUADL 30
#define MSG_INVINT 31
#define MSG_GPUINT 32
#define MSG_MINECONFIG 33
#define MSG_GPUMERR 34
#define MSG_GPUMEM 35
#define MSG_GPUEERR 36
#define MSG_GPUENG 37
#define MSG_GPUVERR 38
#define MSG_GPUVDDC 39
#define MSG_GPUFERR 40
#define MSG_GPUFAN 41
#define MSG_MISFN 42
#define MSG_BADFN 43
#define MSG_SAVED 44
#define MSG_ACCDENY 45
#define MSG_ACCOK 46
#define MSG_ENAPOOL 47
#define MSG_DISPOOL 48
#define MSG_ALRENAP 49
#define MSG_ALRDISP 50
#define MSG_MISPDP 52
#define MSG_INVPDP 53
#define MSG_TOOMANYP 54
#define MSG_ADDPOOL 55
#define MSG_NOTIFY 60
#define MSG_REMLASTP 66
#define MSG_ACTPOOL 67
#define MSG_REMPOOL 68
#define MSG_DEVDETAILS 69
#define MSG_MINESTATS 70
#define MSG_MISCHK 71
#define MSG_CHECK 72
#define MSG_POOLPRIO 73
#define MSG_DUPPID 74
#define MSG_MISBOOL 75
#define MSG_INVBOOL 76
#define MSG_FOO 77
#define MSG_MINECOIN 78
#define MSG_DEBUGSET 79
#define MSG_SETCONFIG 82
#define MSG_UNKCON 83
#define MSG_INVNUM 84
#define MSG_CONPAR 85
#define MSG_CONVAL 86
#define MSG_NOUSTA 88
#define MSG_ZERMIS 94
#define MSG_ZERINV 95
#define MSG_ZERSUM 96
#define MSG_ZERNOSUM 97
#define MSG_BYE 0x101
#define MSG_INVNEG 121
#define MSG_SETQUOTA 122
#define MSG_LOCKOK 123
#define MSG_LOCKDIS 124
#define MSG_CHSTRAT 125
#define MSG_MISSTRAT 126
#define MSG_INVSTRAT 127
#define MSG_MISSTRATINT 128
#define MSG_PROFILE 129
#define MSG_NOPROFILE 130
#define MSG_PROFILEEXIST 131
#define MSG_MISPRD 132
#define MSG_ADDPROFILE 133
#define MSG_MISPRID 134
#define MSG_PRNOEXIST 135
#define MSG_PRISDEFAULT 136
#define MSG_PRINUSE 137
#define MSG_REMPROFILE 138
#define MSG_CHPOOLPR 139
enum code_severity {
SEVERITY_ERR,
SEVERITY_WARN,
SEVERITY_INFO,
SEVERITY_SUCC,
SEVERITY_FAIL
};
enum code_parameters {
PARAM_GPU,
PARAM_PID,
PARAM_GPUMAX,
PARAM_PMAX,
PARAM_PRMAX,
PARAM_POOLMAX,
// Single generic case: have the code resolve it - see below
PARAM_DMAX,
PARAM_CMD,
PARAM_POOL,
PARAM_STR,
PARAM_BOTH,
PARAM_BOOL,
PARAM_SET,
PARAM_INT,
PARAM_NONE
};
struct CODES {
const enum code_severity severity;
const int code;
const enum code_parameters params;
const char *description;
};
extern struct CODES codes[];
struct IP4ACCESS {
in_addr_t ip;
in_addr_t mask;
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)
struct io_data {
size_t siz;
char *ptr;
char *cur;
bool sock;
bool close;
};
struct io_list {
struct io_data *io_data;
struct io_list *prev;
struct io_list *next;
};
extern void message(struct io_data *io_data, int messageid, int paramid, char *param2, bool isjson);
extern bool io_add(struct io_data *io_data, char *buf);
extern void io_close(struct io_data *io_data);
extern void io_free();
extern struct api_data *api_add_escape(struct api_data *root, char *name, char *data, bool copy_data);
extern struct api_data *api_add_string(struct api_data *root, char *name, char *data, bool copy_data);
extern struct api_data *api_add_const(struct api_data *root, char *name, const char *data, bool copy_data);
extern struct api_data *api_add_uint8(struct api_data *root, char *name, uint8_t *data, bool copy_data);
extern struct api_data *api_add_uint16(struct api_data *root, char *name, uint16_t *data, bool copy_data);
extern struct api_data *api_add_int(struct api_data *root, char *name, int *data, bool copy_data);
extern struct api_data *api_add_uint(struct api_data *root, char *name, unsigned int *data, bool copy_data);
extern struct api_data *api_add_uint32(struct api_data *root, char *name, uint32_t *data, bool copy_data);
extern struct api_data *api_add_hex32(struct api_data *root, char *name, uint32_t *data, bool copy_data);
extern struct api_data *api_add_uint64(struct api_data *root, char *name, uint64_t *data, bool copy_data);
extern struct api_data *api_add_double(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_elapsed(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_bool(struct api_data *root, char *name, bool *data, bool copy_data);
extern struct api_data *api_add_timeval(struct api_data *root, char *name, struct timeval *data, bool copy_data);
extern struct api_data *api_add_time(struct api_data *root, char *name, time_t *data, bool copy_data);
extern struct api_data *api_add_mhs(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_khs(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_mhtotal(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_temp(struct api_data *root, char *name, float *data, bool copy_data);
extern struct api_data *api_add_utility(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_freq(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_volts(struct api_data *root, char *name, float *data, bool copy_data);
extern struct api_data *api_add_hs(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_diff(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_percent(struct api_data *root, char *name, double *data, bool copy_data);
extern struct api_data *api_add_avg(struct api_data *root, char *name, float *data, bool copy_data);
extern struct api_data *print_data(struct api_data *root, char *buf, bool isjson, bool precom);
#define SOCKBUFALLOCSIZ 65536
#define io_new(init) _io_new(init, false)
#define sock_io_new() _io_new(SOCKBUFALLOCSIZ, true)
#if LOCK_TRACKING
#define LOCK_FMT_FFL " - called from %s %s():%d"
#define LOCKMSG(fmt, ...) fprintf(stderr, "APILOCK: " fmt "\n", ##__VA_ARGS__)
#define LOCKMSGMORE(fmt, ...) fprintf(stderr, " " fmt "\n", ##__VA_ARGS__)
#define LOCKMSGFFL(fmt, ...) fprintf(stderr, "APILOCK: " fmt LOCK_FMT_FFL "\n", ##__VA_ARGS__, file, func, linenum)
#define LOCKMSGFLUSH() fflush(stderr)
typedef struct lockstat {
uint64_t lock_id;
const char *file;
const char *func;
int linenum;
struct timeval tv;
} LOCKSTAT;
typedef struct lockline {
struct lockline *prev;
struct lockstat *stat;
struct lockline *next;
} LOCKLINE;
typedef struct lockinfo {
void *lock;
enum cglock_typ typ;
const char *file;
const char *func;
int linenum;
uint64_t gets;
uint64_t gots;
uint64_t tries;
uint64_t dids;
uint64_t didnts; // should be tries - dids
uint64_t unlocks;
LOCKSTAT lastgot;
LOCKLINE *lockgets;
LOCKLINE *locktries;
} LOCKINFO;
typedef struct locklist {
LOCKINFO *info;
struct locklist *next;
} LOCKLIST;
#endif
#endif /* API_H */

2029
config_parser.c

File diff suppressed because it is too large Load Diff

122
config_parser.h

@ -0,0 +1,122 @@
#ifndef CONFIG_PARSER_H
#define CONFIG_PARSER_H
#include "config.h"
#include "miner.h"
#include "api.h"
#include "algorithm.h"
//helper to check for empty or NULL strings
#ifndef empty_string
#define empty_string(str) ((str && str[0] != '\0')?0:1)
#endif
#ifndef safe_cmp
#define safe_cmp(val1, val2) (((val1 && strcmp(val1, val2) != 0) || empty_string(val1))?1:0)
#endif
#ifndef isnull
#define isnull(str, default_str) ((str == NULL)?default_str:str)
#endif
//helper function to get a gpu option value
#ifndef gpu_opt
#define gpu_opt(i,optname) gpus[i].optname
#endif
//profile structure
struct profile {
int profile_no;
char *name;
bool removed;
algorithm_t algorithm;
const char *devices;
const char *intensity;
const char *xintensity;
const char *rawintensity;
const char *lookup_gap;
const char *gpu_engine;
const char *gpu_memclock;
const char *gpu_threads;
const char *gpu_fan;
const char *gpu_powertune;
const char *gpu_vddc;
const char *shaders;
const char *thread_concurrency;
const char *worksize;
};
/* globals needed outside */
extern char *cnfbuf;
extern int fileconf_load;
extern const char def_conf[];
extern char *default_config;
extern bool config_loaded;
extern int json_array_index;
extern struct profile default_profile;
extern struct profile **profiles;
extern int total_profiles;
/* option parser functions */
extern char *set_default_devices(const char *arg);
extern char *set_default_lookup_gap(const char *arg);
extern char *set_default_intensity(const char *arg);
extern char *set_default_xintensity(const char *arg);
extern char *set_default_rawintensity(const char *arg);
extern char *set_default_thread_concurrency(const char *arg);
#ifdef HAVE_ADL
extern char *set_default_gpu_engine(const char *arg);
extern char *set_default_gpu_memclock(const char *arg);
extern char *set_default_gpu_threads(const char *arg);
extern char *set_default_gpu_fan(const char *arg);
extern char *set_default_gpu_powertune(const char *arg);
extern char *set_default_gpu_vddc(const char *arg);
#endif
extern char *set_default_profile(char *arg);
extern char *set_default_shaders(const char *arg);
extern char *set_default_worksize(const char *arg);
extern char *set_profile_name(const char *arg);
extern char *set_profile_algorithm(const char *arg);
extern char *set_profile_devices(const char *arg);
extern char *set_profile_lookup_gap(const char *arg);
extern char *set_profile_intensity(const char *arg);
extern char *set_profile_xintensity(const char *arg);
extern char *set_profile_rawintensity(const char *arg);
extern char *set_profile_thread_concurrency(const char *arg);
#ifdef HAVE_ADL
extern char *set_profile_gpu_engine(const char *arg);
extern char *set_profile_gpu_memclock(const char *arg);
extern char *set_profile_gpu_threads(const char *arg);
extern char *set_profile_gpu_fan(const char *arg);
extern char *set_profile_gpu_powertune(const char *arg);
extern char *set_profile_gpu_vddc(const char *arg);
#endif
extern char *set_profile_nfactor(const char *arg);
extern char *set_profile_shaders(const char *arg);
extern char *set_profile_worksize(const char *arg);
/* config parser functions */
extern char *parse_config(json_t *val, const char *key, const char *parentkey, bool fileconf, int parent_iteration);
extern char *load_config(const char *arg, const char *parentkey, void __maybe_unused *unused);
extern char *set_default_config(const char *arg);
extern void load_default_config(void);
/* startup functions */
extern void load_default_profile();
extern void apply_defaults();
extern void apply_pool_profiles();
extern void apply_pool_profile(struct pool *pool);
/* config writer */
extern void write_config(const char *filename);
/* API functions */
extern void api_profile_list(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group);
extern void api_profile_add(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group);
extern void api_profile_remove(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group);
extern void api_pool_profile(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group);
#endif // CONFIG_PARSER_H

406
doc/API → doc/API.md

@ -1,155 +1,183 @@
This README contains details about the sgminer RPC API # sgminer RPC API Documentation
It also includes some detailed information at the end, *Work in Progress!*
about using miner.php
This README contains details about the sgminer RPC API and also includes some detailed information
at the end, about using [miner.php](#miner-php).
If you start sgminer with the "--api-listen" option, it will listen on a
simple TCP/IP socket for single string API requests from the same machine ---
running sgminer and reply with a string and then close the socket each time
If you add the "--api-network" option, it will accept API requests from any ## API Configuration
network attached computer.
If you start sgminer with the `--api-listen` option, it will listen on a simple TCP/IP socket for single string API requests from the same machine running sgminer and reply with a string and then close the socket each time If you add the `--api-network` option, it will accept API requests from any network attached computer.
You can only access the comands that reply with data in this mode.
By default, you cannot access any privileged command that affects the miner - You can only access the comands that reply with data in this mode. By default, you cannot access any privileged command that affects the miner - you will receive an access denied status message see `--api-allow` below.
you will receive an access denied status message see --api-allow below.
You can specify IP addresses/prefixes that are only allowed to access the API with the `--api-allow` option.
You can specify IP addresses/prefixes that are only allowed to access the API
with the "--api-allow" option e.g. --api-allow W:192.168.0.1,10.0.0/24 ```
will allow 192.168.0.1 or any address matching 10.0.0.*, but nothing else --api-allow W:192.168.0.1,10.0.0/24
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 example above will allow 192.168.0.1 or any address matching 10.0.0.*, but nothing else. 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 sgminer (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. 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.
The 'W:' on the front gives that address/subnet privileged access to commands
that modify sgminer (thus all API commands) If you start sgminer also with the `--api-mcast` option, it will listen for a multicast message and reply to it with a message containing it's API port number, but only if the IP address of the sender is allowed API access.
Without it those commands return an access denied status.
See --api-groups below to define other groups like W: 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
Privileged access is checked in the order the IP addresses were supplied to
"--api-allow"
The first match determines the privilege level.
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
If you start sgminer also with the "--api-mcast" option, it will listen for
a multicast message and reply to it with a message containing it's API port
number, but only if the IP address of the sender is allowed API access
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: A sample API group would be:
--api-groups
P:switchpool:enablepool:addpool:disablepool:removepool:poolpriority:* ```
This would create a group 'P' that can do all current pool commands and all --api-groups P:switchpool:enablepool:addpool:disablepool:removepool:poolpriority:*
non-priviliged commands - the '*' means all non-priviledged commands ```
Without the '*' the group would only have access to the pool commands
This would create a group `P` that can do all current pool commands and all non-priviliged commands - the asterisk (\*) means all non-priviledged commands. Without the asterisk (\*), the group would only have access to the pool commands.
Defining multiple groups example: 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 --api-groups Q:quit:restart:*,S:save
S: that can only 'save' and no other commands ```
This would define 2 groups: `Q:`, that can `quit` and `restart` as well as all non-priviledged commands, and `S:`, that can only `save` and no other commands.
For API configuration options, see `doc/configuration.md`.
---
## API Requests
The RPC API request can be either simple text or JSON. 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 If the request is JSON (starts with `{`), it will reply with a JSON formatted
response, otherwise it replies with text formatted as described further below. response, otherwise it replies with text formatted as described further below.
The JSON request format required is '{"command":"CMD","parameter":"PARAM"}' The JSON request format required is `{"command":"CMD","parameter":"PARAM"}`
(though of course parameter is not required for all requests) (though of course parameter is not required for all requests)
where "CMD" is from the "Request" column below and "PARAM" would be e.g. where "CMD" is from the "Request" column below and "PARAM" would be e.g.
the ASC/GPU number if required. the ASC/GPU number if required.
An example request in both formats to set GPU 0 fan to 80%: An example request in both formats to set GPU 0 fan to 80%:
```
gpufan|0,80 gpufan|0,80
{"command":"gpufan","parameter":"0,80"} {"command":"gpufan","parameter":"0,80"}
```
The format of each reply (unless stated otherwise) is a STATUS section The format of each reply (unless stated otherwise) is a STATUS section
followed by an optional detail section followed by an optional detail section
From API version 1.7 onwards, reply strings in JSON and Text have the From API version 1.7 onwards, reply strings in JSON and Text have the
necessary escaping as required to avoid ambiguity - they didn't before 1.7 necessary escaping as required to avoid ambiguity - they didn't before 1.7
For JSON the 2 characters '"' and '\' are escaped with a '\' before them For JSON the 2 characters `"` and `\` are escaped with a `\` before them
For Text the 4 characters '|' ',' '=' and '\' are escaped the same way For Text the 4 characters `|` `,` `=` and `\` are escaped the same way
Only user entered information will contain characters that require being Only user entered information will contain characters that require being
escaped, such as Pool URL, User and Password or the Config save filename, escaped, such as Pool URL, User and Password or the Config save filename,
when they are returned in messages or as their values by the API when they are returned in messages or as their values by the API
For API version 1.4 and later: For API version 1.4 and later the STATUS section is:
The STATUS section is:
STATUS=X,When=NNN,Code=N,Msg=string,Description=string| `STATUS=X,When=NNN,Code=N,Msg=string,Description=string|`
STATUS=X Where X is one of: * `STATUS=X` Where X is one of:
W - Warning `W` Warning
I - Informational `I` Informational
S - Success `S` Success
E - Error `E` Error
F - Fatal (code bug) `F` Fatal (code bug)
When=NNN * `When=NNN`
Standard long time of request in seconds Standard long time of request in seconds
Code=N * `Code=N`
Each unique reply has a unigue Code (See api.c - #define MSG_NNNNNN) Each unique reply has a unigue Code (See `api.c` and `api.h` - #define MSG_NNNNNN)
Msg=string * `Msg=string`
Message matching the Code value N Message matching the Code value N
Description=string * `Description=string`
This defaults to the sgminer version but is the value of --api-description This defaults to the sgminer version but is the value of `--api-description`
if it was specified at runtime. if it was specified at runtime.
With API V3.1 you can also request multiple report replies in a single command With API V3.1 you can also request multiple report replies in a single command
request request: e.g. to request both `summary` and `devs`, the command would be `summary+devs`
e.g. to request both summary and devs, the command would be summary+devs
This is only available for report commands that don't need parameters, **Note:** This is only available for report commands that don't need parameters,
and is not available for commands that change anything and is not available for commands that change anything. Any parameters supplied will be ignored.
Any parameters supplied will be ignored
The extra formatting of the result is to have a section for each command The extra formatting of the result is to have a section for each command:
e.g. CMD=summary|STATUS=....|CMD=devs|STATUS=... `CMD=summary|STATUS=....|CMD=devs|STATUS=...`
With JSON, each result is within a section of the command name
e.g. {"summary":{"STATUS":[{"STATUS":"S"...}],"SUMMARY":[...],"id":1},
"devs":{"STATUS":[{"STATUS:"S"...}],"DEVS":[...],"id":1},"id":1}
As before, if you supply bad JSON you'll just get a single 'E' STATUS section With JSON, each result is within a section of the command name
```
{
"summary":{
"STATUS":[
{"STATUS":"S"...}
],
"SUMMARY":[...],
"id":1
},
"devs":{
"STATUS":[
{"STATUS:"S"...}
],
"DEVS":[...],
"id":1
},
"id":1
}
````
As before, if you supply bad JSON you'll just get a single `E` STATUS section
in the old format, since it doesn't switch to using the new format until it in the old format, since it doesn't switch to using the new format until it
correctly processes the JSON and can match a '+' in the command correctly processes the JSON and can match a `+` in the command.
If you request a command multiple times, e.g. devs+devs If you request a command multiple times, e.g. `devs+devs`, you'll just get it once.
you'll just get it once
If this results in only one command, it will still use the new layout If this results in only one command, it will still use the new layout
with just the one command with just the one command
If you request a command that can't be used due to requiring parameters, If you request a command that can't be used due to requiring parameters,
a command that isn't a report, or an invalid command, you'll get an 'E' STATUS a command that isn't a report, or an invalid command, you'll get an `E` STATUS
for that one but it will still attempt to process all other commands supplied for that one but it will still attempt to process all other commands supplied
Blank/missing commands are ignore e.g. +devs++ Blank/missing commands are ignored. `+devs++` will just show `devs` using the new
will just show 'devs' using the new layout layout.
---
## API Commands
### version
Returns the version information of sgminer.
*Syntax:* `version`
*Arguments:* None
*Access*: `Non-priviledged`
For API version 1.10 and later: *Returns:*
```
Miner="sgminer " <sgminer version>
CGMiner=<sgminer version>
API=<API version>
```
The list of requests - a (*) means it requires privileged access - and replies: ### config
Request Reply Section Details Returns some miner configuration information
------- ------------- -------
version VERSION Miner="sgminer " sgminer version
CGMiner=sgminer version
API=API version
config CONFIG Some miner configuration information: *Syntax:* `config`
*Arguments:* None
*Access*: `Non-priviledged`
*Returns:*
```
GPU Count=N, <- the number of GPUs GPU Count=N, <- the number of GPUs
ASC Count=N, <- the number of ASCs ASC Count=N, <- the number of ASCs
PGA Count=N, <- the number of PGAs PGA Count=N, <- the number of PGAs
@ -158,45 +186,114 @@ The list of requests - a (*) means it requires privileged access - and replies:
ADL in use=X, <- Y or N if any GPU has ADL ADL in use=X, <- Y or N if any GPU has ADL
Strategy=Name, <- the current pool strategy Strategy=Name, <- the current pool strategy
Log Interval=N, <- log interval (--log N) Log Interval=N, <- log interval (--log N)
Device Code=GPU ICA , <- spaced list of compiled Device Code=GPU ICA, <- spaced list of compiled device drivers
device drivers
OS=Linux/Apple/..., <- operating System OS=Linux/Apple/..., <- operating System
Failover-Only=true/false, <- failover-only setting Failover-Only=true/false, <- failover-only setting
ScanTime=N, <- --scan-time setting ScanTime=N, <- --scan-time setting
Queue=N, <- --queue setting Queue=N, <- --queue setting
Expiry=N| <- --expiry setting Expiry=N| <- --expiry setting
```
summary SUMMARY The status summary of the miner ### summary
e.g. Elapsed=NNN,Found Blocks=N,Getworks=N,...|
pools POOLS The status of each pool e.g. Returns the status summary of the miner
Pool=0,URL=http://pool.com:6311,Status=Alive,...|
devs DEVS Each available GPU, PGA and ASC with their details *Syntax:* `summary`
e.g. GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in sec
(or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Last Valid Work=NNN, <- standand long time in sec
of last work returned that wasn't an HW:
Will not report PGAs if PGA mining is disabled
Will not report ASCs if ASC mining is disabled
gpu|N GPU The details of a single GPU number N in the same *Arguments:* None
format and details as for DEVS
pga|N PGA The details of a single PGA number N in the same *Access*: `Non-priviledged`
format and details as for DEVS
This is only available if PGA mining is enabled *Returns:* `Elapsed=NNN,Found Blocks=N,Getworks=N,...|`
Use 'pgacount' or 'config' first to see if there
are any ### devs
Returns each available GPU, PGA and ASC with their details. **Note** that this will not return PGAs or ASCs if PGA or ASC mining is not enabled.
gpucount GPUS Count=N| <- the number of GPUs *Syntax:* `devs`
pgacount PGAS Count=N| <- the number of PGAs *Arguments:* None
Always returns 0 if PGA mining is disabled
switchpool|N (*) *Access*: `Non-priviledged`
*Returns:*
```
GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in sec (or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Last Valid Work=NNN, <- standand long time in sec of last work returned that wasn't an HW
```
### gpu
Returns the details of a single GPU in the same format and details as [devs](#devs).
*Syntax:* `gpu|<N>`
*Arguments:* `number` GPU Number
*Access*: `Non-priviledged`
*Returns:*
```
GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in sec (or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Last Valid Work=NNN, <- standand long time in sec of last work returned that wasn't an HW
```
### pga
Returns the details of a single PGA in the same format and details as [devs](#devs). **Note** that this is only available if PGA mining is enabled. Use [pgacount](#pgacount) or [config](#config) first to see if there are any PGA devices.
*Syntax:* `pga|<N>`
*Arguments:* `number` PGA Number
*Access*: `Non-priviledged`
*Returns:*
```
PGA=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in sec (or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Last Valid Work=NNN, <- standand long time in sec of last work returned that wasn't an HW
```
### gpucount
Returns the number of GPU devices.
*Syntax:* `gpucount`
*Arguments:* None
*Access*: `Non-priviledged`
*Returns:*
```
Count=N| <- number of GPUs
```
### pgacount
Returns the number of PGA devices.
*Syntax:* `pgacount`
*Arguments:* None
*Access*: `Non-priviledged`
*Returns:*
```
Count=N| <- number of PGAs
```
---
```
switchpool|N (*)
none There is no reply section just the STATUS section none There is no reply section just the STATUS section
stating the results of switching pool N to the stating the results of switching pool N to the
highest priority (the pool is also enabled) highest priority (the pool is also enabled)
@ -207,13 +304,13 @@ The list of requests - a (*) means it requires privileged access - and replies:
stating the results of enabling pool N stating the results of enabling pool N
The Msg includes the pool URL The Msg includes the pool URL
addpool|URL,USR,PASS[,NAME,DESC,ALGO] (*) addpool|URL,USR,PASS[,NAME,DESC,PROFILE,ALGO] (*)
none There is no reply section just the STATUS section none There is no reply section just the STATUS section
stating the results of attempting to add pool N stating the results of attempting to add pool N
The Msg includes the pool URL The Msg includes the pool URL
Use '\\' to get a '\' and '\,' to include a comma Use '\\' to get a '\' and '\,' to include a comma
inside URL, USR or PASS inside URL, USR or PASS
Name, description and algorithm are optional Name, description, profile and algorithm are optional
poolpriority|N,... (*) poolpriority|N,... (*)
none There is no reply section just the STATUS section none There is no reply section just the STATUS section
@ -235,7 +332,36 @@ The list of requests - a (*) means it requires privileged access - and replies:
The Msg includes the pool URL The Msg includes the pool URL
N.B. all details for the pool will be lost N.B. all details for the pool will be lost
gpuenable|N (*) changestrategy|STRAT,INT (*)
none There is no reply section just the STATUS section
stating the results of changing multipool strategy
to STRAT. If the strategy requested is "rotate",
the interval INT must be specified as a number
between 0 and 9999 seconds. INT is not required
otherwise.
changepoolprofile|N,NAME (*)
none There is no reply section just the STATUS section
stating the results of changing the profile of
pool N to profile NAME.
addprofile|NAME:ALGORITHM:NFACTOR:LOOKUPGAP:DEVICE:INTENSITY:XINTENSITY:RAWINTENSITY:GPUENGINE:GPUMEMCLOCK
:GPUTHREADS:GPUFAN:GPUPOWERTUNE:GPUVDDC:SHADERS:THREADCONCURRENCY:WORKSIZE (*)
none There is no reply section just the STATUS section
stating the results of attempting to add profile NAME
The Msg includes the profile NAME. Parameters NAME and
ALGORITHM are required. Everything else is optional.
Note that these parameters are colon (:) delimited.
removeprofile|NAME (*)
none There is no reply section just the STATUS section
stating the results of removing profile NAME.
The Msg includes the profile NAME. The profile NAME
must exist and not be in use by any of the pools or
as default profile.
N.B. all details for the profile will be lost
gpuenable|N (*)
none There is no reply section just the STATUS section none There is no reply section just the STATUS section
stating the results of the enable request stating the results of the enable request
@ -474,6 +600,7 @@ The list of requests - a (*) means it requires privileged access - and replies:
A warning reply means lock stats are not compiled A warning reply means lock stats are not compiled
into sgminer into sgminer
The API writes all the lock stats to stderr The API writes all the lock stats to stderr
```
When you enable, disable or restart a GPU, PGA or ASC, you will also get When you enable, disable or restart a GPU, PGA or ASC, you will also get
Thread messages in the sgminer status window Thread messages in the sgminer status window
@ -524,15 +651,18 @@ miner.php - an example web page to access the API
See the end of this API readme for details of how to tune the display See the end of this API readme for details of how to tune the display
and also to use the option to display a multi-rig summary and also to use the option to display a multi-rig summary
---------- ## API Version History
Feature Changelog for external applications using the API:
API V4.0 (sgminer v5.0)
API V Modified API command:
'addpool' - supports profile and algorithm is correctly set to default if none is selected
Modified API commands: Added API commands:
'version' - add 'Miner' 'changestrategy' - change multi pool strategy on the fly from API
'changepoolprofile' - change pool profile
'addprofile' - add a new profile
'removeprofile' - removes a profile
'profiles' - list profiles
---------- ----------
@ -957,8 +1087,8 @@ Commands:
---------------------------------------- ----------------------------------------
miner.php ## miner.php
=========
miner.php is a PHP based interface to the sgminer RPC API miner.php is a PHP based interface to the sgminer RPC API
(referred to simply as the API below) (referred to simply as the API below)

0
doc/GPU → doc/GPU.md

2187
doc/configuration.md

File diff suppressed because it is too large Load Diff

145
example.conf

@ -1,71 +1,94 @@
{ {
"pools" : [ "pools": [
{ {
"name" : "Preferred Pool", "name":"Testpool X11",
"url" : "http://url1:8332", "url": "stratum+tcp://url1:4440",
"user" : "user1", "user": "user",
"pass" : "pass1" "pass": "x",
"priority": "1",
"profile": "x11"
}, },
{ {
"name" : "Failover Pool", "name":"Testpool Scrypt",
"url" : "http://url2:8344", "url": "stratum+tcp://url2:3339",
"user" : "user2", "user": "user",
"pass" : "pass2", "pass": "x",
"state" : "enabled" "priority": "2",
"profile": "scrypt"
}, },
{ {
"name" : "Failover Pool", "name":"Testpool X11 with other profile",
"url" : "http://url3:8344", "url": "stratum+tcp://url3:4440",
"user" : "user3", "user": "user",
"pass" : "pass3", "pass": "x",
"algorithm" : "adaptive-n-factor", "priority": "0",
"state" : "disabled" "profile": "x11test"
}, },
{ {
"name" : "Testing Pool", "name":"Testpool Using default profile",
"url" : "http://url4:8332", "url": "stratum+tcp://url4:3333",
"user" : "user4", "user": "user",
"pass" : "pass4", "pass": "x"
"state" : "hidden"
} }
], ],
"profiles": [
"failover-only" : true, {
"failover-switch-delay" : "60", "name": "x11",
"no-pool-disable" : true, "algorithm": "darkcoin-mod",
"intensity": "19",
"kernel-path" : "/usr/local/bin", "thread-concurrency": "10696,8192",
"kernel" : "alexkarold,ckolivas,zuikkis", "worksize": "128",
"gpu-engine": "1100",
"algorithm" : "scrypt", "gpu-threads": "2",
"gpu-fan": "75"
"intensity" : "d,9,9,9", },
"xintensity" : "0,0,0", {
"rawintensity" : "0,0,0", "name": "scrypt",
"lookup-gap" : "2,2,2", "algorithm": "ckolivas",
"lookup-gap": "2",
"thread-concurrency" : "15508,15508,15508", "intensity": "19,13",
"shaders" : "0,0,0", "thread-concurrency": "19656,8192",
"worksize": "256",
"gpu-threads" : "2", "gpu-engine": "1000,1065",
"gpu-engine" : "0-985,0-950,0-1000", "gpu-memclock": "1500",
"gpu-memclock" : "860,825,875", "gpu-threads": "1,2",
"gpu-powertune" : "20,20,20", "gpu-fan": "85",
"gpu-powertune": "20"
"gpu-vddc" : "0.000,0.000,0.000", },
"gpu-fan" : "0-85,0-85,0-85", {
"name": "x11test",
"auto-gpu" : true, "algorithm": "darkcoin-mod",
"auto-fan" : true, "device": "1",
"intensity": "19",
"temp-target" : "75,75,75", "thread-concurrency": "10696,8192",
"temp-overheat" : "80,85,90", "worksize": "512",
"temp-cutoff" : "95", "gpu-engine": "1100",
"temp-hysteresis" : "3", "gpu-threads": "2",
"gpu-fan": "75"
"queue" : "1", }
"scan-time" : "7", ],
"expiry" : "28", "failover-only": true,
"default-profile": "scrypt",
"log" : "5" "temp-cutoff": "95,95",
"temp-overheat": "90,90",
"temp-target": "80,80",
"gpu-memdiff": "0,0",
"shares": "0",
"kernel-path": "/usr/local/bin",
"api-allow": "W:127.0.0.1",
"api-listen": true,
"api-mcast-port": "4028",
"api-port": "4028",
"expiry": "1",
"failover-switch-delay": "60",
"gpu-dyninterval": "7",
"gpu-platform": "-1",
"hamsi-expand-big": "4",
"log": "5",
"no-pool-disable": true,
"no-client-reconnect": true,
"queue": "0",
"scan-time": "1",
"tcp-keepalive": "30",
"temp-hysteresis": "3"
} }

45
miner.h

@ -124,6 +124,8 @@ static inline int fsync (int fd)
#include "ADL_SDK/adl_sdk.h" #include "ADL_SDK/adl_sdk.h"
#endif #endif
#include <ccan/opt/opt.h>
#if (!defined(WIN32) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ #if (!defined(WIN32) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|| (defined(WIN32) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || (defined(WIN32) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
#ifndef bswap_16 #ifndef bswap_16
@ -251,7 +253,6 @@ enum alive {
LIFE_INIT, LIFE_INIT,
}; };
enum pool_strategy { enum pool_strategy {
POOL_FAILOVER, POOL_FAILOVER,
POOL_ROUNDROBIN, POOL_ROUNDROBIN,
@ -266,6 +267,9 @@ struct strategies {
const char *s; const char *s;
}; };
extern enum pool_strategy pool_strategy;
extern struct strategies strategies[];
struct cgpu_info; struct cgpu_info;
#ifdef HAVE_ADL #ifdef HAVE_ADL
@ -932,7 +936,21 @@ extern bool opt_protocol;
extern bool have_longpoll; extern bool have_longpoll;
extern char *opt_kernel_path; extern char *opt_kernel_path;
extern char *opt_socks_proxy; extern char *opt_socks_proxy;
#if defined(unix) || defined(__APPLE__)
extern char *opt_stderr_cmd;
#endif // defined(unix)
struct schedtime {
bool enable;
struct tm tm;
};
extern struct schedtime schedstart;
extern struct schedtime schedstop;
extern char *sgminer_path; extern char *sgminer_path;
extern int opt_shares;
extern bool opt_fail_only; extern bool opt_fail_only;
extern bool opt_autofan; extern bool opt_autofan;
extern bool opt_autoengine; extern bool opt_autoengine;
@ -1023,11 +1041,12 @@ extern void api(int thr_id);
extern struct pool *current_pool(void); extern struct pool *current_pool(void);
extern int enabled_pools; extern int enabled_pools;
extern void get_intrange(char *arg, int *val1, int *val2); extern void get_intrange(char *arg, int *val1, int *val2);
extern char *set_devices(char *arg);
extern bool detect_stratum(struct pool *pool, char *url); extern bool detect_stratum(struct pool *pool, char *url);
extern void print_summary(void); extern void print_summary(void);
extern void adjust_quota_gcd(void); extern void adjust_quota_gcd(void);
extern struct pool *add_pool(void); extern struct pool *add_pool(void);
extern bool add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass, char *name, char *desc, char *algo); extern bool add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass, char *name, char *desc, char *profile, char *algo);
#define MAX_GPUDEVICES 16 #define MAX_GPUDEVICES 16
#define MAX_DEVICES 4096 #define MAX_DEVICES 4096
@ -1056,6 +1075,9 @@ extern struct cgpu_info gpus[MAX_GPUDEVICES];
extern double total_secs; extern double total_secs;
extern int mining_threads; extern int mining_threads;
extern int total_devices; extern int total_devices;
extern bool devices_enabled[MAX_DEVICES];
extern int opt_devs_enabled;
extern bool opt_removedisabled;
extern struct cgpu_info **devices; extern struct cgpu_info **devices;
extern int total_pools; extern int total_pools;
extern struct pool **pools; extern struct pool **pools;
@ -1081,6 +1103,9 @@ extern double best_diff;
extern struct timeval block_timeval; extern struct timeval block_timeval;
extern char *workpadding; extern char *workpadding;
//config options table
extern struct opt_table opt_config_table[];
typedef struct _dev_blk_ctx { typedef struct _dev_blk_ctx {
cl_uint ctx_a; cl_uint ctx_b; cl_uint ctx_c; cl_uint ctx_d; cl_uint ctx_a; cl_uint ctx_b; cl_uint ctx_c; cl_uint ctx_d;
cl_uint ctx_e; cl_uint ctx_f; cl_uint ctx_g; cl_uint ctx_h; cl_uint ctx_e; cl_uint ctx_f; cl_uint ctx_g; cl_uint ctx_h;
@ -1192,15 +1217,22 @@ struct pool {
proxytypes_t rpc_proxytype; proxytypes_t rpc_proxytype;
char *rpc_proxy; char *rpc_proxy;
char *profile;
algorithm_t algorithm; algorithm_t algorithm;
const char *devices;
const char *intensity; const char *intensity;
const char *xintensity; const char *xintensity;
const char *rawintensity; const char *rawintensity;
const char *thread_concurrency; const char *lookup_gap;
const char *gpu_engine; const char *gpu_engine;
const char *gpu_memclock; const char *gpu_memclock;
const char *gpu_threads; const char *gpu_threads;
const char *gpu_fan; const char *gpu_fan;
const char *gpu_powertune;
const char *gpu_vddc;
const char *shaders;
const char *thread_concurrency;
const char *worksize;
pthread_mutex_t pool_lock; pthread_mutex_t pool_lock;
cglock_t data_lock; cglock_t data_lock;
@ -1374,7 +1406,7 @@ extern void kill_work(void);
extern void switch_pools(struct pool *selected); extern void switch_pools(struct pool *selected);
extern void discard_work(struct work *work); extern void discard_work(struct work *work);
extern void remove_pool(struct pool *pool); extern void remove_pool(struct pool *pool);
extern void write_config(FILE *fcfg); //extern void write_config(FILE *fcfg);
extern void zero_bestshare(void); extern void zero_bestshare(void);
extern void zero_stats(void); extern void zero_stats(void);
extern void default_save_file(char *filename); extern void default_save_file(char *filename);
@ -1398,6 +1430,11 @@ extern struct work *copy_work_noffset(struct work *base_work, int noffset);
#define copy_work(work_in) copy_work_noffset(work_in, 0) #define copy_work(work_in) copy_work_noffset(work_in, 0)
extern struct cgpu_info *get_devices(int id); extern struct cgpu_info *get_devices(int id);
extern char *set_int_0_to_9999(const char *arg, int *i);
extern char *set_int_1_to_65535(const char *arg, int *i);
extern char *set_int_0_to_10(const char *arg, int *i);
extern char *set_int_1_to_10(const char *arg, int *i);
enum api_data_type { enum api_data_type {
API_ESCAPE, API_ESCAPE,
API_STRING, API_STRING,

987
sgminer.c

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save