mirror of https://github.com/GOSTSec/sgminer
Kano
13 years ago
2 changed files with 413 additions and 0 deletions
@ -0,0 +1,117 @@ |
|||||||
|
<?php |
||||||
|
# |
||||||
|
# Sample Socket I/O to CGMiner API |
||||||
|
# |
||||||
|
function getsock($port) |
||||||
|
{ |
||||||
|
$socket = null; |
||||||
|
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); |
||||||
|
if ($socket === false || $socket === null) |
||||||
|
{ |
||||||
|
$error = socket_strerror(socket_last_error()); |
||||||
|
$msg = "socket create($port) failed"; |
||||||
|
echo "ERR: $msg '$error'\n"; |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
$res = socket_connect($socket, '127.0.0.1', $port); |
||||||
|
if ($res === false) |
||||||
|
{ |
||||||
|
$error = socket_strerror(socket_last_error()); |
||||||
|
$msg = "socket connect($port) failed"; |
||||||
|
echo "ERR: $msg '$error'\n"; |
||||||
|
socket_close($socket); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
return $socket; |
||||||
|
} |
||||||
|
# |
||||||
|
# Slow ... |
||||||
|
function readsockline($socket) |
||||||
|
{ |
||||||
|
$line = ''; |
||||||
|
while (true) |
||||||
|
{ |
||||||
|
$byte = socket_read($socket, 1); |
||||||
|
if ($byte === false || $byte === '') |
||||||
|
break; |
||||||
|
if ($byte === "\0") |
||||||
|
break; |
||||||
|
$line .= $byte; |
||||||
|
} |
||||||
|
return $line; |
||||||
|
} |
||||||
|
# |
||||||
|
function request($cmd) |
||||||
|
{ |
||||||
|
$socket = getsock(4028); |
||||||
|
if ($socket != null) |
||||||
|
{ |
||||||
|
socket_write($socket, $cmd, strlen($cmd)); |
||||||
|
$line = readsockline($socket); |
||||||
|
socket_close($socket); |
||||||
|
|
||||||
|
if (strlen($line) == 0) |
||||||
|
{ |
||||||
|
echo "WARN: '$cmd' returned nothing\n"; |
||||||
|
return $line; |
||||||
|
} |
||||||
|
|
||||||
|
print "$cmd returned '$line'\n"; |
||||||
|
|
||||||
|
$data = array(); |
||||||
|
|
||||||
|
$objs = explode('|', $line); |
||||||
|
foreach ($objs as $obj) |
||||||
|
{ |
||||||
|
if (strlen($obj) > 0) |
||||||
|
{ |
||||||
|
$items = explode(',', $obj); |
||||||
|
$item = $items[0]; |
||||||
|
$id = explode('=', $items[0], 2); |
||||||
|
if (count($id) == 1) |
||||||
|
$name = $id[0]; |
||||||
|
else |
||||||
|
$name = $id[0].$id[1]; |
||||||
|
|
||||||
|
if (strlen($name) == 0) |
||||||
|
$name = 'null'; |
||||||
|
|
||||||
|
if (isset($data[$name])) |
||||||
|
{ |
||||||
|
$num = 1; |
||||||
|
while (isset($data[$name.$num])) |
||||||
|
$num++; |
||||||
|
$name .= $num; |
||||||
|
} |
||||||
|
|
||||||
|
$counter = 0; |
||||||
|
foreach ($items as $item) |
||||||
|
{ |
||||||
|
$id = explode('=', $item, 2); |
||||||
|
if (count($id) == 2) |
||||||
|
$data[$name][$id[0]] = $id[1]; |
||||||
|
else |
||||||
|
$data[$name][$counter] = $id[0]; |
||||||
|
|
||||||
|
$counter++; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return $data; |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
# |
||||||
|
$ver = request('apiversion'); |
||||||
|
echo print_r($ver, true)."\n"; |
||||||
|
# |
||||||
|
$dev = request('dev'); |
||||||
|
echo print_r($dev, true)."\n"; |
||||||
|
# |
||||||
|
$pool = request('pool'); |
||||||
|
echo print_r($pool, true)."\n"; |
||||||
|
# |
||||||
|
?> |
@ -0,0 +1,296 @@ |
|||||||
|
/*
|
||||||
|
* Copyright 2011 Kano |
||||||
|
* Copyright 2011 Con Kolivas |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify it |
||||||
|
* under the terms of the GNU General Public License as published by the Free |
||||||
|
* Software Foundation; either version 2 of the License, or (at your option) |
||||||
|
* any later version. See COPYING for more details. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "config.h" |
||||||
|
|
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <sys/time.h> |
||||||
|
#include <time.h> |
||||||
|
#include <math.h> |
||||||
|
#include <stdarg.h> |
||||||
|
#include <assert.h> |
||||||
|
|
||||||
|
#include <sys/stat.h> |
||||||
|
#include <sys/types.h> |
||||||
|
|
||||||
|
#include "compat.h" |
||||||
|
#include "miner.h" |
||||||
|
|
||||||
|
#if defined(unix) |
||||||
|
#include <errno.h> |
||||||
|
// #include <fcntl.h>
|
||||||
|
// #include <sys/wait.h>
|
||||||
|
#endif |
||||||
|
|
||||||
|
// Big enough for largest API request
|
||||||
|
// though a PC with 100s of CPUs may exceed the size ...
|
||||||
|
// Current code assumes it can socket send this size also
|
||||||
|
#define MYBUFSIZ 16384 |
||||||
|
|
||||||
|
static char *buffer = NULL; |
||||||
|
|
||||||
|
static const char *UNAVAILABLE = " - API will not be available"; |
||||||
|
|
||||||
|
static const char *BLANK = ""; |
||||||
|
|
||||||
|
static const char *VERSION = "0.1"; |
||||||
|
static const char *DEAD = "DEAD"; |
||||||
|
static const char *SICK = "SICK"; |
||||||
|
static const char *DISABLED = "DISABLED"; |
||||||
|
static const char * = ""; |
||||||
|
zzz -> other pool status |
||||||
|
|
||||||
|
static int bye = 0; |
||||||
|
|
||||||
|
char *apiversion(char *params) |
||||||
|
{ |
||||||
|
return VERSION; |
||||||
|
} |
||||||
|
|
||||||
|
void gpustatus(int thr_id) |
||||||
|
{ |
||||||
|
char buf[BUFSIZ]; |
||||||
|
char status_buf[BUFSIZ]; |
||||||
|
char *status; |
||||||
|
float gt; |
||||||
|
int gf, gp; |
||||||
|
|
||||||
|
if (thr_id >= 0 && thr_id < gpu_threads) { |
||||||
|
int gpu = dev_from_id(thr_id); |
||||||
|
struct cgpu_info *cgpu = &gpus[gpu]; |
||||||
|
|
||||||
|
cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60; |
||||||
|
|
||||||
|
#ifdef HAVE_ADL |
||||||
|
if (cgpu->has_adl) { |
||||||
|
gt = gpu_temp(gpu); |
||||||
|
gf = gpu_fanspeed(gpu); |
||||||
|
gp = gpu_fanpercent(gpu); |
||||||
|
} |
||||||
|
else |
||||||
|
#endif |
||||||
|
gt = gf = gp = 0; |
||||||
|
|
||||||
|
if (cgpu->status == LIFE_DEAD) |
||||||
|
status = DEAD; |
||||||
|
else if (cgpu->status == LIFE_SICK) |
||||||
|
status = SICK; |
||||||
|
else if (!gpu_devices[gpu]) |
||||||
|
status = DISABLED; |
||||||
|
else { |
||||||
|
sprintf(status_buf, "%.1f", cgpu->rolling); |
||||||
|
status = status_buf; |
||||||
|
} |
||||||
|
|
||||||
|
sprintf(buf, "G%d=%.2f,%d,%d,%s,%.2f,%d,%d,%d,%.2f,%d|", |
||||||
|
gpu, gt, gf, gp, status, |
||||||
|
cgpu->total_mhashes / total_secs, |
||||||
|
cgpu->accepted, cgpu->rejected, cgpu->hw_errors, |
||||||
|
cgpu->utility, gpus[gpu].intensity); |
||||||
|
|
||||||
|
strcat(buffer, buf); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void cpustatus(int thr_id) |
||||||
|
{ |
||||||
|
char buf[BUFSIZ]; |
||||||
|
|
||||||
|
if (thr_id >= gpu_threads) { |
||||||
|
int cpu = dev_from_id(thr_id); |
||||||
|
struct cgpu_info *cgpu = &cpus[cpu]; |
||||||
|
|
||||||
|
cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60; |
||||||
|
|
||||||
|
sprintf(buf, "C%d=%.2f,%.2f,%d,%d,%d,%.2f,%d|", |
||||||
|
cpu, cgpu->rolling, |
||||||
|
cgpu->total_mhashes / total_secs, |
||||||
|
cgpu->accepted, cgpu->rejected, cgpu->hw_errors, |
||||||
|
cgpu->utility, gpus[gpu].intensity); |
||||||
|
|
||||||
|
strcat(buffer, buf); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
char *devstatus(char *params) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
|
||||||
|
*buffer = '\0'; |
||||||
|
|
||||||
|
for (i = 0; i < gpu_threads; i++) |
||||||
|
gpustatus(i); |
||||||
|
|
||||||
|
for (i = gpu_threads; i < mining_threads; i++) |
||||||
|
cpustatus(i); |
||||||
|
|
||||||
|
return buffer; |
||||||
|
} |
||||||
|
|
||||||
|
char *poolstatus(char *params) |
||||||
|
{ |
||||||
|
char buf[BUFSIZ]; |
||||||
|
char *status; |
||||||
|
int i; |
||||||
|
|
||||||
|
*buffer = '\0'; |
||||||
|
|
||||||
|
for (i = 0; i < total_pools; i++) { |
||||||
|
struct pool *pool = pools[i]; |
||||||
|
|
||||||
|
if (!pool->enabled) |
||||||
|
status = DISABLED; |
||||||
|
else |
||||||
|
status = OK; |
||||||
|
|
||||||
|
sprintf(buf, "P%d=%s,%s,%d,%d,%d,%d,%d,%d,%d|", |
||||||
|
i, pool->rpc_url, status, |
||||||
|
pool->getwork_requested, |
||||||
|
pool->accepted, pool->rejected, |
||||||
|
pool->discarded_work, |
||||||
|
pool->stale_shares, |
||||||
|
pool->getfail_occasions, |
||||||
|
pool->remotefail_occasions); |
||||||
|
|
||||||
|
strcat(buffer, buf); |
||||||
|
} |
||||||
|
|
||||||
|
return buffer; |
||||||
|
} |
||||||
|
|
||||||
|
struct CMDS { |
||||||
|
const char *cmd; |
||||||
|
char (*func)(); |
||||||
|
} cmds[] = { |
||||||
|
{ "apiversion", apiversion }, |
||||||
|
{ "dev", devstatus }, |
||||||
|
{ "pool", poolstatus } |
||||||
|
}; |
||||||
|
|
||||||
|
#define MAXCMD sizeof(cmds)/sizeof(struct CMDS) |
||||||
|
|
||||||
|
void send_result(int c, char *result) |
||||||
|
{ |
||||||
|
int n; |
||||||
|
|
||||||
|
if (result == NULL) |
||||||
|
result = BLANK; |
||||||
|
|
||||||
|
// ignore failure - it's closed immediately anyway
|
||||||
|
n = write(c, result, strlen(result)+1); |
||||||
|
} |
||||||
|
|
||||||
|
static void api() |
||||||
|
{ |
||||||
|
const char *addr; |
||||||
|
int c, sock, n, bound; |
||||||
|
char *binderror; |
||||||
|
time_t bindstart; |
||||||
|
short int port = 4028; |
||||||
|
struct sockaddr_in serv; |
||||||
|
struct sockaddr_in cli; |
||||||
|
socklen_t clisiz; |
||||||
|
long long counter; |
||||||
|
char *result; |
||||||
|
char *params; |
||||||
|
|
||||||
|
addr = "127.0.0.1"; |
||||||
|
|
||||||
|
sock = socket(AF_INET, SOCK_STREAM, 0); |
||||||
|
if (sock < 0) { |
||||||
|
applog(LOG_ERR, "API1 initialisation failed (%s)%s", strerror(errno), UNAVAILABLE); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
memset(&serv, 0, sizeof(serv)); |
||||||
|
|
||||||
|
serv.sin_family = AF_INET; |
||||||
|
if (inet_pton(AF_INET, addr, &(serv.sin_addr)) == 0) { |
||||||
|
applog(LOG_ERR, "API2 initialisation failed (%s)%s", strerror(errno), UNAVAILABLE); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
serv.sin_port = htons(port); |
||||||
|
|
||||||
|
// try for 1 minute ... in case the old one hasn't completely gone yet
|
||||||
|
bound = 0; |
||||||
|
bindstart = time(NULL); |
||||||
|
while (bound == 0) { |
||||||
|
if (bind(sock, (struct sockaddr *)(&serv), sizeof(serv)) < 0) { |
||||||
|
binderror = strerror(errno); |
||||||
|
if ((time(NULL) - bindstart) > 61) |
||||||
|
break; |
||||||
|
else { |
||||||
|
applog(LOG_ERR, "API bind to port %d failed - trying again in 10sec", port); |
||||||
|
sleep(10); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
bound = 1; |
||||||
|
} |
||||||
|
|
||||||
|
if (bound == 0) { |
||||||
|
applog(LOG_ERR, "API bind to port %d failed (%s)%s", port, binderror, UNAVAILABLE); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
if (listen(sock, QUEUE) < 0) { |
||||||
|
applog(LOG_ERR, "API3 initialisation failed (%s)%s", strerror(errno), UNAVAILABLE); |
||||||
|
close(sock); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
buffer = malloc(MYBUFSIZ+1); |
||||||
|
|
||||||
|
counter = 0; |
||||||
|
while (bye == 0) { |
||||||
|
counter++; |
||||||
|
|
||||||
|
clisiz = sizeof(cli); |
||||||
|
if ((c = accept(sock, (struct sockaddr *)(&cli), &clisiz)) < 0) { |
||||||
|
applog(LOG_ERR, "API failed (%s)%s", strerror(errno), UNAVAILABLE); |
||||||
|
close(sock); |
||||||
|
free(buffer); |
||||||
|
return NULL; |
||||||
|
} |
||||||
|
|
||||||
|
inet_ntop(AF_INET, &(cli.sin_addr), &(tmpaddr[0]), sizeof(tmpaddr)-1); |
||||||
|
if (strcmp(tmpaddr, addr) != 0) |
||||||
|
close(c); |
||||||
|
else { |
||||||
|
n = read(c, &buf[0], BUFS); |
||||||
|
if (n < 0) |
||||||
|
close(c); |
||||||
|
else { |
||||||
|
params = strchr(buf, '|'); |
||||||
|
if (params != NULL) |
||||||
|
*(params++) = '\0'; |
||||||
|
|
||||||
|
for (i = 0; i < CMDMAX; i++) { |
||||||
|
if (strcmp(buf, cmds[i].name) == 0) { |
||||||
|
result = cmds[i].func(params); |
||||||
|
send_result(c, result); |
||||||
|
close(c); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
close(sock); |
||||||
|
free(buffer); |
||||||
|
|
||||||
|
return NULL; |
||||||
|
} |
Loading…
Reference in new issue