Listening channels implemented

This commit is contained in:
2021-10-08 21:03:52 -04:00
parent 760bd22874
commit 315bf6e3b1
4 changed files with 151 additions and 32 deletions

View File

@@ -22,6 +22,7 @@ public:
bool engine_wakeup_;
char console_line_[CONSOLE_MAX + 1];
int console_len_;
std::map<int, SOCKET> listen_sockets_;
std::unique_ptr<char> chbuf;
static PADDRINFOA find_good_addr(PADDRINFOA addrinfo) {
@@ -33,12 +34,17 @@ public:
return nullptr;
}
void set_nonblocking(SOCKET sock) {
u_long mode = 1; // 1 to enable non-blocking socket
int status = ioctlsocket(sock, FIONBIO, &mode);
assert(status == 0);
}
SOCKET open_connection(const std::string &target, std::string &err) {
PADDRINFOA addrs = nullptr;
PADDRINFOA goodaddr = nullptr;
SOCKET sock = INVALID_SOCKET;
std::string host, port;
u_long mode = 1; // 1 to enable non-blocking socket
err = "";
util::split_host_port(target, host, port);
@@ -62,8 +68,7 @@ public:
}
sock = socket(goodaddr->ai_family, SOCK_STREAM, IPPROTO_TCP);
assert(sock != INVALID_SOCKET);
status = ioctlsocket(sock, FIONBIO, &mode);
assert(status == 0);
set_nonblocking(sock);
status = connect(sock, goodaddr->ai_addr, goodaddr->ai_addrlen);
if (status != 0) {
int errcode = WSAGetLastError();
@@ -83,6 +88,25 @@ public:
return SOCKET_ERROR;
}
SOCKET listen_on_port(int port, std::string &err) {
int status;
err = "";
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
assert(sock != INVALID_SOCKET);
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
status = bind(sock, (struct sockaddr *)&server, sizeof(server));
assert(status == 0);
status = listen(sock, 10);
assert(status == 0);
set_nonblocking(sock);
return sock;
}
void init(DrivenEngine *de) {
driven_ = de;
for (int i = 0; i < MAX_CHAN; i++) {
@@ -94,6 +118,20 @@ public:
chbuf.reset(new char[65536]);
}
void handle_listen_ports() {
std::set<int> listenports;
driven_->drv_get_listen_ports(listenports);
for (int port : listenports) {
if (listen_sockets_.find(port) == listen_sockets_.end()) {
std::string err;
SOCKET sock = listen_on_port(port, err);
if (sock != INVALID_SOCKET) {
listen_sockets_[port] = sock;
}
}
}
}
void handle_lua_source() {
if (driven_->drv_get_rescan_lua_source()) {
driven_->drv_set_lua_source(util::read_lua_source("lua"));
@@ -190,11 +228,24 @@ public:
void handle_clock() {
}
void close_socket(int chid) {
assert(socket_[chid] != INVALID_SOCKET);
assert(closesocket(socket_[chid]) == 0);
driven_->drv_notify_close(chid);
socket_[chid] = INVALID_SOCKET;
connected_[chid] = false;
engine_wakeup_ = true;
}
bool calc_select_sets(fd_set &rfds, fd_set &wfds, fd_set &efds) const {
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
bool any = false;
for (const auto &p : listen_sockets_) {
FD_SET(p.second, &rfds);
any = true;
}
for (int chid = 1; chid < MAX_CHAN; chid++) {
SOCKET sock = socket_[chid];
if (sock == INVALID_SOCKET) continue;
@@ -207,13 +258,30 @@ public:
return any;
}
void close_socket(int chid) {
assert(socket_[chid] != INVALID_SOCKET);
assert(closesocket(socket_[chid]) == 0);
driven_->drv_notify_close(chid);
socket_[chid] = INVALID_SOCKET;
connected_[chid] = false;
engine_wakeup_ = true;
void accept_connections(int port, SOCKET sock) {
while (true) {
SOCKET chsock = accept(sock, nullptr, nullptr);
if (chsock != INVALID_SOCKET) {
int chid = driven_->drv_notify_accept(port);
socket_[chid] = chsock;
connected_[chid] = true;
engine_wakeup_ = true;
continue;
}
int errcode = WSAGetLastError();
if (errcode == WSAEWOULDBLOCK) {
return;
}
if (errcode == WSAECONNRESET) {
// The remote disconnected before we had a chance to accept.
// Just pretend it never happened.
continue;
}
// If a listening port fails in a non-transient way,
// we don't really have any good way of handling
// that.
assert(false);
}
}
void handle_socket_input_output(int mstimeout) {
@@ -229,6 +297,13 @@ public:
timeout.tv_usec = (mstimeout - (timeout.tv_sec*1000)) * 1000;
int status = select(1, &rfds, &wfds, &efds, &timeout);
assert(status != SOCKET_ERROR);
for (auto &p : listen_sockets_) {
if (FD_ISSET(p.second, &rfds)) {
accept_connections(p.first, p.second);
}
}
for (int chid = 1; chid < MAX_CHAN; chid++) {
SOCKET sock = socket_[chid];
if (sock == INVALID_SOCKET) continue;
@@ -267,6 +342,7 @@ public:
DrivenEngine::set(de);
driven_->drv_set_lua_source(util::read_lua_source("lua"));
driven_->drv_invoke_event_init();
handle_listen_ports();
while (!de->drv_get_stop_driver()) {
engine_wakeup_ = false;
handle_lua_source();