mirror of https://github.com/SChernykh/p2pool
Console: read commands via localhost TCP
parent
ce192670a3
commit
196b27f3b2
|
@ -28,19 +28,40 @@
|
||||||
|
|
||||||
static constexpr char log_category_prefix[] = "ConsoleCommands ";
|
static constexpr char log_category_prefix[] = "ConsoleCommands ";
|
||||||
|
|
||||||
|
static constexpr int DEFAULT_BACKLOG = 1;
|
||||||
|
|
||||||
|
#include "tcp_server.inl"
|
||||||
|
|
||||||
namespace p2pool {
|
namespace p2pool {
|
||||||
|
|
||||||
ConsoleCommands::ConsoleCommands(p2pool* pool)
|
ConsoleCommands::ConsoleCommands(p2pool* pool)
|
||||||
: m_pool(pool)
|
: TCPServer(ConsoleClient::allocate)
|
||||||
, m_loop{}
|
, m_pool(pool)
|
||||||
, m_shutdownAsync{}
|
|
||||||
, m_tty{}
|
, m_tty{}
|
||||||
, m_stdin_pipe{}
|
, m_stdin_pipe{}
|
||||||
, m_stdin_handle(nullptr)
|
, m_stdin_handle(nullptr)
|
||||||
, m_loopThread{}
|
|
||||||
, m_readBuf{}
|
, m_readBuf{}
|
||||||
, m_readBufInUse(false)
|
, m_readBufInUse(false)
|
||||||
{
|
{
|
||||||
|
std::random_device rd;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
if (start_listening(false, "127.0.0.1", 49152 + (rd() % 16384))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_listenPort < 0) {
|
||||||
|
LOGERR(1, "failed to listen on TCP port");
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = uv_thread_create(&m_loopThread, loop, this);
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
|
||||||
|
PANIC_STOP();
|
||||||
|
}
|
||||||
|
|
||||||
const uv_handle_type stdin_type = uv_guess_handle(0);
|
const uv_handle_type stdin_type = uv_guess_handle(0);
|
||||||
LOGINFO(3, "uv_guess_handle returned " << static_cast<int>(stdin_type));
|
LOGINFO(3, "uv_guess_handle returned " << static_cast<int>(stdin_type));
|
||||||
if (stdin_type != UV_TTY && stdin_type != UV_NAMED_PIPE) {
|
if (stdin_type != UV_TTY && stdin_type != UV_NAMED_PIPE) {
|
||||||
|
@ -48,19 +69,6 @@ ConsoleCommands::ConsoleCommands(p2pool* pool)
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = uv_loop_init(&m_loop);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to create event loop, error " << uv_err_name(err));
|
|
||||||
throw std::exception();
|
|
||||||
}
|
|
||||||
|
|
||||||
err = uv_async_init(&m_loop, &m_shutdownAsync, on_shutdown);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
|
|
||||||
throw std::exception();
|
|
||||||
}
|
|
||||||
m_shutdownAsync.data = this;
|
|
||||||
|
|
||||||
if (stdin_type == UV_TTY) {
|
if (stdin_type == UV_TTY) {
|
||||||
LOGINFO(3, "processing stdin as UV_TTY");
|
LOGINFO(3, "processing stdin as UV_TTY");
|
||||||
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
|
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
|
||||||
|
@ -91,19 +99,16 @@ ConsoleCommands::ConsoleCommands(p2pool* pool)
|
||||||
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
|
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
|
||||||
throw std::exception();
|
throw std::exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
err = uv_thread_create(&m_loopThread, loop, this);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
|
|
||||||
throw std::exception();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleCommands::~ConsoleCommands()
|
ConsoleCommands::~ConsoleCommands()
|
||||||
{
|
{
|
||||||
uv_async_send(&m_shutdownAsync);
|
shutdown_tcp();
|
||||||
uv_thread_join(&m_loopThread);
|
}
|
||||||
LOGINFO(1, "stopped");
|
|
||||||
|
void ConsoleCommands::on_shutdown()
|
||||||
|
{
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(m_stdin_handle), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct strconst {
|
typedef struct strconst {
|
||||||
|
@ -273,46 +278,7 @@ void ConsoleCommands::stdinReadCallback(uv_stream_t* stream, ssize_t nread, cons
|
||||||
ConsoleCommands* pThis = static_cast<ConsoleCommands*>(stream->data);
|
ConsoleCommands* pThis = static_cast<ConsoleCommands*>(stream->data);
|
||||||
|
|
||||||
if (nread > 0) {
|
if (nread > 0) {
|
||||||
std::string& command = pThis->m_command;
|
pThis->process_input(pThis->m_command, buf->base, static_cast<uint32_t>(nread));
|
||||||
command.append(buf->base, nread);
|
|
||||||
|
|
||||||
do {
|
|
||||||
size_t k = command.find_first_of("\r\n");
|
|
||||||
if (k == std::string::npos) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
command[k] = '\0';
|
|
||||||
|
|
||||||
cmd* c = cmds;
|
|
||||||
for (; c->name.len; ++c) {
|
|
||||||
if (!strncmp(command.c_str(), c->name.str, c->name.len)) {
|
|
||||||
const char* args = (c->name.len + 1 <= k) ? (command.c_str() + c->name.len + 1) : "";
|
|
||||||
|
|
||||||
// Skip spaces
|
|
||||||
while ((args[0] == ' ') || (args[0] == '\t')) {
|
|
||||||
++args;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if an argument is required
|
|
||||||
if (strlen(c->arg) && !strlen(args)) {
|
|
||||||
LOGWARN(0, c->name.str << " requires arguments");
|
|
||||||
do_help(nullptr, nullptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->func(pThis->m_pool, args);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c->name.len) {
|
|
||||||
LOGWARN(0, "Unknown command " << command.c_str());
|
|
||||||
do_help(nullptr, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
k = command.find_first_not_of("\r\n", k + 1);
|
|
||||||
command.erase(0, k);
|
|
||||||
} while (true);
|
|
||||||
}
|
}
|
||||||
else if (nread < 0) {
|
else if (nread < 0) {
|
||||||
LOGWARN(4, "read error " << uv_err_name(static_cast<int>(nread)));
|
LOGWARN(4, "read error " << uv_err_name(static_cast<int>(nread)));
|
||||||
|
@ -321,23 +287,48 @@ void ConsoleCommands::stdinReadCallback(uv_stream_t* stream, ssize_t nread, cons
|
||||||
pThis->m_readBufInUse = false;
|
pThis->m_readBufInUse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleCommands::loop(void* data)
|
|
||||||
|
void ConsoleCommands::process_input(std::string& command, char* data, uint32_t size)
|
||||||
{
|
{
|
||||||
LOGINFO(1, "event loop started");
|
command.append(data, size);
|
||||||
|
|
||||||
ConsoleCommands* pThis = static_cast<ConsoleCommands*>(data);
|
do {
|
||||||
|
size_t k = command.find_first_of("\r\n");
|
||||||
|
if (k == std::string::npos) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
command[k] = '\0';
|
||||||
|
|
||||||
int err = uv_run(&pThis->m_loop, UV_RUN_DEFAULT);
|
cmd* c = cmds;
|
||||||
if (err) {
|
for (; c->name.len; ++c) {
|
||||||
LOGWARN(1, "uv_run returned " << err);
|
if (!strncmp(command.c_str(), c->name.str, c->name.len)) {
|
||||||
}
|
const char* args = (c->name.len + 1 <= k) ? (command.c_str() + c->name.len + 1) : "";
|
||||||
|
|
||||||
err = uv_loop_close(&pThis->m_loop);
|
// Skip spaces
|
||||||
if (err) {
|
while ((args[0] == ' ') || (args[0] == '\t')) {
|
||||||
LOGWARN(1, "uv_loop_close returned error " << uv_err_name(err));
|
++args;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGINFO(1, "event loop stopped");
|
// Check if an argument is required
|
||||||
|
if (strlen(c->arg) && !strlen(args)) {
|
||||||
|
LOGWARN(0, c->name.str << " requires arguments");
|
||||||
|
do_help(nullptr, nullptr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->func(m_pool, args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c->name.len) {
|
||||||
|
LOGWARN(0, "Unknown command " << command.c_str());
|
||||||
|
do_help(nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
k = command.find_first_not_of("\r\n", k + 1);
|
||||||
|
command.erase(0, k);
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -18,43 +18,50 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "uv_util.h"
|
#include "uv_util.h"
|
||||||
|
#include "tcp_server.h"
|
||||||
|
|
||||||
namespace p2pool {
|
namespace p2pool {
|
||||||
|
|
||||||
class p2pool;
|
class p2pool;
|
||||||
|
|
||||||
class ConsoleCommands : public nocopy_nomove
|
class ConsoleCommands : public TCPServer<256, 256>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ConsoleCommands(p2pool* pool);
|
explicit ConsoleCommands(p2pool* pool);
|
||||||
~ConsoleCommands();
|
~ConsoleCommands();
|
||||||
|
|
||||||
|
struct ConsoleClient : public Client
|
||||||
|
{
|
||||||
|
~ConsoleClient() {}
|
||||||
|
|
||||||
|
static Client* allocate() { return new ConsoleClient(); }
|
||||||
|
|
||||||
|
size_t size() const override { return sizeof(ConsoleClient); }
|
||||||
|
|
||||||
|
bool on_connect() override { return true; };
|
||||||
|
bool on_read(char* data, uint32_t size) override { static_cast<ConsoleCommands*>(m_owner)->process_input(m_command, data, size); return true; };
|
||||||
|
|
||||||
|
std::string m_command;
|
||||||
|
};
|
||||||
|
|
||||||
|
void on_shutdown() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
p2pool* m_pool;
|
p2pool* m_pool;
|
||||||
|
|
||||||
uv_loop_t m_loop;
|
|
||||||
uv_async_t m_shutdownAsync;
|
|
||||||
uv_tty_t m_tty;
|
uv_tty_t m_tty;
|
||||||
uv_pipe_t m_stdin_pipe;
|
uv_pipe_t m_stdin_pipe;
|
||||||
uv_stream_t* m_stdin_handle;
|
uv_stream_t* m_stdin_handle;
|
||||||
uv_thread_t m_loopThread;
|
|
||||||
|
|
||||||
char m_readBuf[64];
|
char m_readBuf[64];
|
||||||
bool m_readBufInUse;
|
bool m_readBufInUse;
|
||||||
|
|
||||||
std::string m_command;
|
std::string m_command;
|
||||||
|
|
||||||
static void loop(void* data);
|
|
||||||
|
|
||||||
static void on_shutdown(uv_async_t* async)
|
|
||||||
{
|
|
||||||
ConsoleCommands* pThis = reinterpret_cast<ConsoleCommands*>(async->data);
|
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&pThis->m_shutdownAsync), nullptr);
|
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(pThis->m_stdin_handle), nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void allocCallback(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
static void allocCallback(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
|
||||||
static void stdinReadCallback(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
|
static void stdinReadCallback(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
|
||||||
|
|
||||||
|
void process_input(std::string& command, char* data, uint32_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace p2pool
|
} // namespace p2pool
|
||||||
|
|
|
@ -138,7 +138,6 @@ public:
|
||||||
FORCEINLINE bool send(Client* client, T&& callback) { return send_internal(client, SendCallback<T>(std::move(callback))); }
|
FORCEINLINE bool send(Client* client, T&& callback) { return send_internal(client, SendCallback<T>(std::move(callback))); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void loop(void* data);
|
|
||||||
static void on_new_connection(uv_stream_t* server, int status);
|
static void on_new_connection(uv_stream_t* server, int status);
|
||||||
static void on_connection_close(uv_handle_t* handle);
|
static void on_connection_close(uv_handle_t* handle);
|
||||||
static void on_connection_error(uv_handle_t* handle);
|
static void on_connection_error(uv_handle_t* handle);
|
||||||
|
@ -156,10 +155,14 @@ private:
|
||||||
|
|
||||||
std::vector<uv_tcp_t*> m_listenSockets6;
|
std::vector<uv_tcp_t*> m_listenSockets6;
|
||||||
std::vector<uv_tcp_t*> m_listenSockets;
|
std::vector<uv_tcp_t*> m_listenSockets;
|
||||||
uv_thread_t m_loopThread;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
uv_thread_t m_loopThread;
|
||||||
|
|
||||||
|
static void loop(void* data);
|
||||||
|
|
||||||
void start_listening(const std::string& listen_addresses, bool upnp);
|
void start_listening(const std::string& listen_addresses, bool upnp);
|
||||||
|
bool start_listening(bool is_v6, const std::string& ip, int port, std::string address = std::string());
|
||||||
|
|
||||||
#ifdef WITH_UPNP
|
#ifdef WITH_UPNP
|
||||||
int m_portMapping;
|
int m_portMapping;
|
||||||
|
|
|
@ -130,6 +130,102 @@ void TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::parse_address_list(const std::str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<size_t READ_BUF_SIZE, size_t WRITE_BUF_SIZE>
|
||||||
|
bool TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::start_listening(bool is_v6, const std::string& ip, int port, std::string address)
|
||||||
|
{
|
||||||
|
if ((m_listenPort >= 0) && (m_listenPort != port)) {
|
||||||
|
LOGERR(1, "all sockets must be listening on the same port number, fix the command line");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv_tcp_t* socket = new uv_tcp_t();
|
||||||
|
|
||||||
|
int err = uv_tcp_init(&m_loop, socket);
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "failed to create tcp server handle, error " << uv_err_name(err));
|
||||||
|
delete socket;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
socket->data = this;
|
||||||
|
|
||||||
|
ON_SCOPE_LEAVE([is_v6, this, socket]()
|
||||||
|
{
|
||||||
|
const std::vector<uv_tcp_t*>& v = is_v6 ? m_listenSockets6 : m_listenSockets;
|
||||||
|
if (std::find(v.begin(), v.end(), socket) == v.end()) {
|
||||||
|
uv_close(reinterpret_cast<uv_handle_t*>(socket), [](uv_handle_t* h) { delete reinterpret_cast<uv_tcp_t*>(h); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
err = uv_tcp_nodelay(socket, 1);
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "failed to set tcp_nodelay on tcp server handle, error " << uv_err_name(err));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_v6) {
|
||||||
|
if (address.empty()) {
|
||||||
|
char buf[64] = {};
|
||||||
|
log::Stream s(buf);
|
||||||
|
s << '[' << ip << "]:" << port;
|
||||||
|
address = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_in6 addr6;
|
||||||
|
err = uv_ip6_addr(ip.c_str(), port, &addr6);
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "failed to parse IPv6 address " << ip << ", error " << uv_err_name(err));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uv_tcp_bind(socket, reinterpret_cast<sockaddr*>(&addr6), UV_TCP_IPV6ONLY);
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "failed to bind tcp server IPv6 socket " << address << ", error " << uv_err_name(err));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (address.empty()) {
|
||||||
|
char buf[64] = {};
|
||||||
|
log::Stream s(buf);
|
||||||
|
s << ip << ':' << port;
|
||||||
|
address = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_in addr;
|
||||||
|
err = uv_ip4_addr(ip.c_str(), port, &addr);
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "failed to parse IPv4 address " << ip << ", error " << uv_err_name(err));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uv_tcp_bind(socket, reinterpret_cast<sockaddr*>(&addr), 0);
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "failed to bind tcp server IPv4 socket " << address << ", error " << uv_err_name(err));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = uv_listen(reinterpret_cast<uv_stream_t*>(socket), DEFAULT_BACKLOG, on_new_connection);
|
||||||
|
if (err) {
|
||||||
|
LOGERR(1, "failed to listen on tcp server socket " << address << ", error " << uv_err_name(err));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_v6) {
|
||||||
|
m_listenSockets6.push_back(socket);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_listenSockets.push_back(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_listenPort < 0) {
|
||||||
|
m_listenPort = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGINFO(1, "listening on " << log::Gray() << address);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<size_t READ_BUF_SIZE, size_t WRITE_BUF_SIZE>
|
template<size_t READ_BUF_SIZE, size_t WRITE_BUF_SIZE>
|
||||||
void TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::start_listening(const std::string& listen_addresses, bool upnp)
|
void TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::start_listening(const std::string& listen_addresses, bool upnp)
|
||||||
{
|
{
|
||||||
|
@ -139,74 +235,11 @@ void TCPServer<READ_BUF_SIZE, WRITE_BUF_SIZE>::start_listening(const std::string
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_address_list(listen_addresses,
|
parse_address_list(listen_addresses,
|
||||||
[this](bool is_v6, const std::string& address, const std::string& ip, int port)
|
[this](bool is_v6, const std::string& /*address*/, const std::string& ip, int port)
|
||||||
{
|
{
|
||||||
if (m_listenPort < 0) {
|
if (!start_listening(is_v6, ip, port)) {
|
||||||
m_listenPort = port;
|
|
||||||
}
|
|
||||||
else if (m_listenPort != port) {
|
|
||||||
LOGERR(1, "all sockets must be listening on the same port number, fix the command line");
|
|
||||||
PANIC_STOP();
|
PANIC_STOP();
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_tcp_t* socket = new uv_tcp_t();
|
|
||||||
|
|
||||||
if (is_v6) {
|
|
||||||
m_listenSockets6.push_back(socket);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_listenSockets.push_back(socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
int err = uv_tcp_init(&m_loop, socket);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to create tcp server handle, error " << uv_err_name(err));
|
|
||||||
PANIC_STOP();
|
|
||||||
}
|
|
||||||
socket->data = this;
|
|
||||||
|
|
||||||
err = uv_tcp_nodelay(socket, 1);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to set tcp_nodelay on tcp server handle, error " << uv_err_name(err));
|
|
||||||
PANIC_STOP();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_v6) {
|
|
||||||
sockaddr_in6 addr6;
|
|
||||||
err = uv_ip6_addr(ip.c_str(), port, &addr6);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to parse IPv6 address " << ip << ", error " << uv_err_name(err));
|
|
||||||
PANIC_STOP();
|
|
||||||
}
|
|
||||||
|
|
||||||
err = uv_tcp_bind(socket, reinterpret_cast<sockaddr*>(&addr6), UV_TCP_IPV6ONLY);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to bind tcp server IPv6 socket " << address << ", error " << uv_err_name(err));
|
|
||||||
PANIC_STOP();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sockaddr_in addr;
|
|
||||||
err = uv_ip4_addr(ip.c_str(), port, &addr);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to parse IPv4 address " << ip << ", error " << uv_err_name(err));
|
|
||||||
PANIC_STOP();
|
|
||||||
}
|
|
||||||
|
|
||||||
err = uv_tcp_bind(socket, reinterpret_cast<sockaddr*>(&addr), 0);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to bind tcp server IPv4 socket " << address << ", error " << uv_err_name(err));
|
|
||||||
PANIC_STOP();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = uv_listen(reinterpret_cast<uv_stream_t*>(socket), DEFAULT_BACKLOG, on_new_connection);
|
|
||||||
if (err) {
|
|
||||||
LOGERR(1, "failed to listen on tcp server socket " << address << ", error " << uv_err_name(err));
|
|
||||||
PANIC_STOP();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGINFO(1, "listening on " << log::Gray() << address);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef WITH_UPNP
|
#ifdef WITH_UPNP
|
||||||
|
|
Loading…
Reference in New Issue