forked from Ocean/datum_gateway
Merge remote-tracking branch 'github-pull/77/head'
This commit is contained in:
commit
9166d3c835
@ -1163,7 +1163,7 @@ enum MHD_Result datum_api_answer(void *cls, struct MHD_Connection *connection, c
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct MHD_Daemon *datum_api_try_start(unsigned int flags) {
|
static struct MHD_Daemon *datum_api_try_start(unsigned int flags, const int sock) {
|
||||||
flags |= MHD_USE_AUTO; // event loop API
|
flags |= MHD_USE_AUTO; // event loop API
|
||||||
flags |= MHD_USE_INTERNAL_POLLING_THREAD;
|
flags |= MHD_USE_INTERNAL_POLLING_THREAD;
|
||||||
return MHD_start_daemon(
|
return MHD_start_daemon(
|
||||||
@ -1171,6 +1171,7 @@ static struct MHD_Daemon *datum_api_try_start(unsigned int flags) {
|
|||||||
datum_config.api_listen_port,
|
datum_config.api_listen_port,
|
||||||
NULL, NULL, // accept policy filter
|
NULL, NULL, // accept policy filter
|
||||||
&datum_api_answer, NULL, // default URI handler
|
&datum_api_answer, NULL, // default URI handler
|
||||||
|
MHD_OPTION_LISTEN_SOCKET, sock,
|
||||||
MHD_OPTION_CONNECTION_LIMIT, 128,
|
MHD_OPTION_CONNECTION_LIMIT, 128,
|
||||||
MHD_OPTION_NOTIFY_COMPLETED, datum_api_request_completed, NULL,
|
MHD_OPTION_NOTIFY_COMPLETED, datum_api_request_completed, NULL,
|
||||||
MHD_OPTION_LISTENING_ADDRESS_REUSE, (unsigned int)1,
|
MHD_OPTION_LISTENING_ADDRESS_REUSE, (unsigned int)1,
|
||||||
@ -1185,8 +1186,13 @@ void *datum_api_thread(void *ptr) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
daemon = datum_api_try_start(MHD_USE_DUAL_STACK);
|
int listen_socks[1];
|
||||||
if (!daemon) daemon = datum_api_try_start(0);
|
size_t listen_socks_len = 1;
|
||||||
|
if (!datum_sockets_setup_listening_sockets("API", datum_config.api_listen_addr, datum_config.api_listen_port, listen_socks, &listen_socks_len)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
daemon = datum_api_try_start(0, listen_socks[0]);
|
||||||
|
|
||||||
if (!daemon) {
|
if (!daemon) {
|
||||||
DLOG_FATAL("Unable to start daemon for API");
|
DLOG_FATAL("Unable to start daemon for API");
|
||||||
@ -1194,7 +1200,7 @@ void *datum_api_thread(void *ptr) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DLOG_INFO("API listening on port %d", datum_config.api_listen_port);
|
DLOG_INFO("API listening on address %s port %d", datum_config.api_listen_addr[0] ? datum_config.api_listen_addr : "(any)", datum_config.api_listen_port);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
sleep(3);
|
sleep(3);
|
||||||
|
@ -67,6 +67,8 @@ const T_DATUM_CONFIG_ITEM datum_config_options[] = {
|
|||||||
.required = false, .ptr = &datum_config.bitcoind_notify_fallback, .default_bool = true },
|
.required = false, .ptr = &datum_config.bitcoind_notify_fallback, .default_bool = true },
|
||||||
|
|
||||||
// stratum v1 server configs
|
// stratum v1 server configs
|
||||||
|
{ .var_type = DATUM_CONF_STRING, .category = "stratum", .name = "listen_addr", .description = "IP address to listen for Stratum Gateway connections",
|
||||||
|
.required = false, .ptr = datum_config.stratum_v1_listen_addr, .default_string[0] = "", .max_string_len = sizeof(datum_config.stratum_v1_listen_addr) },
|
||||||
{ .var_type = DATUM_CONF_INT, .category = "stratum", .name = "listen_port", .description = "Listening port for Stratum Gateway",
|
{ .var_type = DATUM_CONF_INT, .category = "stratum", .name = "listen_port", .description = "Listening port for Stratum Gateway",
|
||||||
.required = false, .ptr = &datum_config.stratum_v1_listen_port, .default_int = 23334 },
|
.required = false, .ptr = &datum_config.stratum_v1_listen_port, .default_int = 23334 },
|
||||||
{ .var_type = DATUM_CONF_INT, .category = "stratum", .name = "max_clients_per_thread", .description = "Maximum clients per Stratum server thread",
|
{ .var_type = DATUM_CONF_INT, .category = "stratum", .name = "max_clients_per_thread", .description = "Maximum clients per Stratum server thread",
|
||||||
@ -109,6 +111,8 @@ const T_DATUM_CONFIG_ITEM datum_config_options[] = {
|
|||||||
// API/dashboard
|
// API/dashboard
|
||||||
{ .var_type = DATUM_CONF_STRING, .category = "api", .name = "admin_password", .description = "API password for actions/changes (username 'admin'; disabled if blank)",
|
{ .var_type = DATUM_CONF_STRING, .category = "api", .name = "admin_password", .description = "API password for actions/changes (username 'admin'; disabled if blank)",
|
||||||
.required = false, .ptr = datum_config.api_admin_password, .default_string[0] = "", .max_string_len = sizeof(datum_config.api_admin_password) },
|
.required = false, .ptr = datum_config.api_admin_password, .default_string[0] = "", .max_string_len = sizeof(datum_config.api_admin_password) },
|
||||||
|
{ .var_type = DATUM_CONF_STRING, .category = "api", .name = "listen_addr", .description = "IP address to listen for API/dashboard requests",
|
||||||
|
.required = false, .ptr = datum_config.api_listen_addr, .default_string[0] = "", .max_string_len = sizeof(datum_config.api_listen_addr) },
|
||||||
{ .var_type = DATUM_CONF_INT, .category = "api", .name = "listen_port", .description = "Port to listen for API/dashboard requests (0=disabled)",
|
{ .var_type = DATUM_CONF_INT, .category = "api", .name = "listen_port", .description = "Port to listen for API/dashboard requests (0=disabled)",
|
||||||
.required = false, .ptr = &datum_config.api_listen_port, .default_int = 0 },
|
.required = false, .ptr = &datum_config.api_listen_port, .default_int = 0 },
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ typedef struct {
|
|||||||
int bitcoind_work_update_seconds;
|
int bitcoind_work_update_seconds;
|
||||||
bool bitcoind_notify_fallback;
|
bool bitcoind_notify_fallback;
|
||||||
|
|
||||||
|
char stratum_v1_listen_addr[128];
|
||||||
int stratum_v1_listen_port;
|
int stratum_v1_listen_port;
|
||||||
int stratum_v1_max_clients;
|
int stratum_v1_max_clients;
|
||||||
int stratum_v1_max_threads;
|
int stratum_v1_max_threads;
|
||||||
@ -102,6 +103,7 @@ typedef struct {
|
|||||||
char api_admin_password[64];
|
char api_admin_password[64];
|
||||||
size_t api_admin_password_len;
|
size_t api_admin_password_len;
|
||||||
char api_csrf_token[65];
|
char api_csrf_token[65];
|
||||||
|
char api_listen_addr[128];
|
||||||
int api_listen_port;
|
int api_listen_port;
|
||||||
|
|
||||||
int extra_block_submissions_count;
|
int extra_block_submissions_count;
|
||||||
|
@ -33,11 +33,14 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
@ -560,6 +563,84 @@ const char *datum_sockets_setup_listen_sock(const int listen_sock, const struct
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool datum_sockets_setup_listening_sockets(const char * const purpose, const char * const addr, const uint16_t port, int * const out_socks, size_t * const inout_socks_n) {
|
||||||
|
assert(*inout_socks_n > 0);
|
||||||
|
if (addr && addr[0]) {
|
||||||
|
char port_str[6];
|
||||||
|
snprintf(port_str, sizeof(port_str), "%u", (unsigned int)port);
|
||||||
|
const struct addrinfo hints = {
|
||||||
|
.ai_family = AF_UNSPEC,
|
||||||
|
.ai_socktype = SOCK_STREAM,
|
||||||
|
.ai_protocol = 0,
|
||||||
|
.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV,
|
||||||
|
};
|
||||||
|
struct addrinfo *res;
|
||||||
|
int err = getaddrinfo(addr, port_str, &hints, &res);
|
||||||
|
if (err) {
|
||||||
|
DLOG_FATAL("Failed to resolve listen address '%s' (%s): %s", purpose, addr, gai_strerror(err));
|
||||||
|
panic_from_thread(__LINE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_socks = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
|
||||||
|
const char *errstr = datum_sockets_setup_listen_sock(*out_socks, res->ai_addr, res->ai_addrlen);
|
||||||
|
const int errno_saved = errno;
|
||||||
|
freeaddrinfo(res);
|
||||||
|
if (errstr) {
|
||||||
|
DLOG_FATAL("%s (%s): %s", errstr, purpose, strerror(errno_saved));
|
||||||
|
panic_from_thread(__LINE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*inout_socks_n = 1;
|
||||||
|
} else {
|
||||||
|
const struct sockaddr_in6 anyaddr6 = {
|
||||||
|
.sin6_family = AF_INET6,
|
||||||
|
.sin6_port = htons(port),
|
||||||
|
.sin6_addr = IN6ADDR_ANY_INIT,
|
||||||
|
};
|
||||||
|
out_socks[0] = socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
|
#if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
|
||||||
|
if (out_socks[0] != -1) {
|
||||||
|
static const int zero = 0;
|
||||||
|
setsockopt(out_socks[0], IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(zero));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
const char * const errstr6 = datum_sockets_setup_listen_sock(out_socks[0], (const struct sockaddr *)&anyaddr6, sizeof(anyaddr6));
|
||||||
|
const int errno6 = errno;
|
||||||
|
unsigned int socks_n = 1;
|
||||||
|
if (errstr6 && out_socks[0] != -1) {
|
||||||
|
close(out_socks[0]);
|
||||||
|
out_socks[0] = -1;
|
||||||
|
--socks_n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*inout_socks_n > socks_n) {
|
||||||
|
const struct sockaddr_in anyaddr4 = {
|
||||||
|
.sin_family = AF_INET,
|
||||||
|
.sin_port = htons(port),
|
||||||
|
.sin_addr.s_addr = INADDR_ANY,
|
||||||
|
};
|
||||||
|
out_socks[socks_n] = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
const char *errstr = datum_sockets_setup_listen_sock(out_socks[socks_n], (const struct sockaddr *)&anyaddr4, sizeof(anyaddr4));
|
||||||
|
if (errstr && errstr6) {
|
||||||
|
const int errno4 = errno;
|
||||||
|
DLOG_FATAL("%s (IPv6): %s", errstr6, strerror(errno6));
|
||||||
|
DLOG_FATAL("%s (IPv4): %s", errstr, strerror(errno4));
|
||||||
|
panic_from_thread(__LINE__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (errstr && out_socks[socks_n] != -1) {
|
||||||
|
close(out_socks[socks_n]);
|
||||||
|
out_socks[socks_n] = -1;
|
||||||
|
} else {
|
||||||
|
++socks_n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*inout_socks_n = socks_n;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void *datum_gateway_listener_thread(void *arg) {
|
void *datum_gateway_listener_thread(void *arg) {
|
||||||
int i, ret;
|
int i, ret;
|
||||||
bool rejecting_now = false;
|
bool rejecting_now = false;
|
||||||
@ -577,7 +658,7 @@ void *datum_gateway_listener_thread(void *arg) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DLOG_DEBUG("Setting up app '%s' on port %d. (T:%d/TC:%d/C:%d)", app->name, app->listen_port, app->max_threads, app->max_clients_thread, app->max_clients);
|
DLOG_DEBUG("Setting up app '%s' on address %s port %d. (T:%d/TC:%d/C:%d)", app->name, datum_config.stratum_v1_listen_addr[0] ? datum_config.stratum_v1_listen_addr : "(any)", app->listen_port, app->max_threads, app->max_clients_thread, app->max_clients);
|
||||||
|
|
||||||
// we assume the caller sets up the thread data in some way
|
// we assume the caller sets up the thread data in some way
|
||||||
// don't clobber those pointers
|
// don't clobber those pointers
|
||||||
@ -598,37 +679,10 @@ void *datum_gateway_listener_thread(void *arg) {
|
|||||||
|
|
||||||
app->datum_active_threads = 0;
|
app->datum_active_threads = 0;
|
||||||
|
|
||||||
const struct sockaddr_in6 anyaddr6 = {
|
size_t listen_socks_len = 2;
|
||||||
.sin6_family = AF_INET6,
|
if (!datum_sockets_setup_listening_sockets("stratum", datum_config.stratum_v1_listen_addr, app->listen_port, listen_socks, &listen_socks_len)) {
|
||||||
.sin6_port = htons(app->listen_port),
|
|
||||||
.sin6_addr = IN6ADDR_ANY_INIT,
|
|
||||||
};
|
|
||||||
listen_socks[0] = socket(AF_INET6, SOCK_STREAM, 0);
|
|
||||||
const char * const errstr6 = datum_sockets_setup_listen_sock(listen_socks[0], (const struct sockaddr *)&anyaddr6, sizeof(anyaddr6));
|
|
||||||
const int errno6 = errno;
|
|
||||||
if (errstr6 && listen_socks[0] != -1) {
|
|
||||||
close(listen_socks[0]);
|
|
||||||
listen_socks[0] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const struct sockaddr_in anyaddr4 = {
|
|
||||||
.sin_family = AF_INET,
|
|
||||||
.sin_port = htons(app->listen_port),
|
|
||||||
.sin_addr.s_addr = INADDR_ANY,
|
|
||||||
};
|
|
||||||
listen_socks[1] = socket(AF_INET, SOCK_STREAM, 0);
|
|
||||||
const char *errstr = datum_sockets_setup_listen_sock(listen_socks[1], (const struct sockaddr *)&anyaddr4, sizeof(anyaddr4));
|
|
||||||
if (errstr && errstr6) {
|
|
||||||
const int errno4 = errno;
|
|
||||||
DLOG_FATAL("%s (IPv6): %s", errstr6, strerror(errno6));
|
|
||||||
DLOG_FATAL("%s (IPv4): %s", errstr, strerror(errno4));
|
|
||||||
panic_from_thread(__LINE__);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (errstr && listen_socks[1] != -1) {
|
|
||||||
close(listen_socks[1]);
|
|
||||||
listen_socks[1] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
epollfd = epoll_create1(0);
|
epollfd = epoll_create1(0);
|
||||||
if (epollfd < 0) {
|
if (epollfd < 0) {
|
||||||
|
@ -161,6 +161,7 @@ typedef struct T_DATUM_THREAD_DATA {
|
|||||||
void *app_thread_data;
|
void *app_thread_data;
|
||||||
} T_DATUM_THREAD_DATA;
|
} T_DATUM_THREAD_DATA;
|
||||||
|
|
||||||
|
bool datum_sockets_setup_listening_sockets(const char *purpose, const char *addr, uint16_t port, int *out_socks, size_t *inout_socks_n);
|
||||||
void *datum_gateway_listener_thread(void *arg);
|
void *datum_gateway_listener_thread(void *arg);
|
||||||
void datum_socket_setoptions(int sock);
|
void datum_socket_setoptions(int sock);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user