A bit of refactoring before SSL conversion

This commit is contained in:
2022-01-05 13:14:44 -05:00
parent c733023823
commit 0833662539

View File

@@ -16,6 +16,8 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/types.h> #include <sys/types.h>
#include <netdb.h> #include <netdb.h>
using SOCKET=int;
const int INVALID_SOCKET = -1;
struct termios orig_termios; struct termios orig_termios;
@@ -45,16 +47,91 @@ static void enableRawMode() {
assert(status >= 0); assert(status >= 0);
} }
SOCKET open_connection(const std::string &target, std::string &err) {
struct addrinfo *addrs = nullptr;
struct addrinfo *goodaddr = nullptr;
struct addrinfo hints;
SOCKET sock = INVALID_SOCKET;
std::string host, port;
char errbuf[1024];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_NUMERICSERV;
err = "";
util::split_host_port(target, host, port);
int status = getaddrinfo(host.c_str(), port.c_str(), &hints, &addrs);
if (status != 0) {
err = gai_strerror(status);
goto error;
}
if (addrs == nullptr) {
err = "no such host found";
goto error;
}
goodaddr = addrs;
assert(goodaddr->ai_family == AF_INET);
assert(goodaddr->ai_socktype == SOCK_STREAM);
assert(goodaddr->ai_protocol == IPPROTO_TCP);
sock = socket(goodaddr->ai_family, goodaddr->ai_socktype, goodaddr->ai_protocol);
assert(sock > 0);
set_nonblocking(sock);
status = connect(sock, goodaddr->ai_addr, goodaddr->ai_addrlen);
if ((status != 0) && (errno != EINPROGRESS)) {
goto error_errno;
}
freeaddrinfo(addrs);
return sock;
error_errno:
err = strerror_r(errno, errbuf, 1024);
error:
if (sock != INVALID_SOCKET) close(sock);
if (addrs != nullptr) freeaddrinfo(addrs);
return INVALID_SOCKET;
}
SOCKET listen_on_port(int port, std::string &err) {
int status;
err = "";
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
assert(sock > 0);
int enable = 1;
status = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
assert(status == 0);
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;
}
class Driver { class Driver {
public: public:
using PollVec = std::vector<struct pollfd>; enum ChanState {
using SOCKET=int; CHAN_INACTIVE,
const int INVALID_SOCKET = -1; CHAN_CONNECTING,
CHAN_OPEN,
};
struct ChanInfo {
ChanState state;
SOCKET socket;
};
static const int MAX_CHAN = DrivenEngine::MAX_CHAN; static const int MAX_CHAN = DrivenEngine::MAX_CHAN;
DrivenEngine *driven_; DrivenEngine *driven_;
SOCKET socket_[MAX_CHAN]; ChanInfo channels_[MAX_CHAN];
bool connected_[MAX_CHAN];
bool short_sleep_; bool short_sleep_;
std::map<int, SOCKET> listen_sockets_; std::map<int, SOCKET> listen_sockets_;
std::unique_ptr<char[]> chbuf; std::unique_ptr<char[]> chbuf;
@@ -68,81 +145,11 @@ public:
return tv_sec * 1000000 + tv_usec; return tv_sec * 1000000 + tv_usec;
} }
SOCKET open_connection(const std::string &target, std::string &err) {
struct addrinfo *addrs = nullptr;
struct addrinfo *goodaddr = nullptr;
struct addrinfo hints;
SOCKET sock = INVALID_SOCKET;
std::string host, port;
char errbuf[1024];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_NUMERICSERV;
err = "";
util::split_host_port(target, host, port);
int status = getaddrinfo(host.c_str(), port.c_str(), &hints, &addrs);
if (status != 0) {
err = gai_strerror(status);
goto error;
}
if (addrs == nullptr) {
err = "no such host found";
goto error;
}
goodaddr = addrs;
assert(goodaddr->ai_family == AF_INET);
assert(goodaddr->ai_socktype == SOCK_STREAM);
assert(goodaddr->ai_protocol == IPPROTO_TCP);
sock = socket(goodaddr->ai_family, goodaddr->ai_socktype, goodaddr->ai_protocol);
assert(sock > 0);
set_nonblocking(sock);
status = connect(sock, goodaddr->ai_addr, goodaddr->ai_addrlen);
if ((status != 0) && (errno != EINPROGRESS)) {
goto error_errno;
}
freeaddrinfo(addrs);
return sock;
error_errno:
err = strerror_r(errno, errbuf, 1024);
error:
if (sock != INVALID_SOCKET) close(sock);
if (addrs != nullptr) freeaddrinfo(addrs);
return INVALID_SOCKET;
}
SOCKET listen_on_port(int port, std::string &err) {
int status;
err = "";
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
assert(sock > 0);
int enable = 1;
status = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
assert(status == 0);
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) { void init(DrivenEngine *de) {
driven_ = de; driven_ = de;
for (int i = 0; i < MAX_CHAN; i++) { for (int i = 0; i < MAX_CHAN; i++) {
socket_[i] = INVALID_SOCKET; channels_[i].state = CHAN_INACTIVE;
connected_[i] = false; channels_[i].socket = INVALID_SOCKET;
} }
short_sleep_ = false; short_sleep_ = false;
chbuf.reset(new char[65536]); chbuf.reset(new char[65536]);
@@ -172,10 +179,10 @@ public:
void handle_new_closed_sockets() { void handle_new_closed_sockets() {
for (int chid = 1; chid < MAX_CHAN; chid++) { for (int chid = 1; chid < MAX_CHAN; chid++) {
if (driven_->drv_get_channel_released(chid)) { if (driven_->drv_get_channel_released(chid)) {
if (socket_[chid] != INVALID_SOCKET) { if (channels_[chid].state != CHAN_INACTIVE) {
assert(close(socket_[chid]) == 0); assert(close(channels_[chid].socket) == 0);
socket_[chid] = INVALID_SOCKET; channels_[chid].state = CHAN_INACTIVE;
connected_[chid] = false; channels_[chid].socket = INVALID_SOCKET;
} }
driven_->drv_notify_close(chid, ""); driven_->drv_notify_close(chid, "");
} }
@@ -186,15 +193,15 @@ public:
std::set<int> chans; std::set<int> chans;
driven_->drv_get_new_outgoing(chans); driven_->drv_get_new_outgoing(chans);
for (int chid : chans) { for (int chid : chans) {
assert(socket_[chid] == INVALID_SOCKET); assert(channels_[chid].state == CHAN_INACTIVE);
std::string err; std::string err;
SOCKET sock = open_connection(driven_->drv_get_target(chid), err); SOCKET sock = open_connection(driven_->drv_get_target(chid), err);
if (sock == INVALID_SOCKET) { if (sock == INVALID_SOCKET) {
driven_->drv_notify_close(chid, err); driven_->drv_notify_close(chid, err);
short_sleep_ = true; short_sleep_ = true;
} else { } else {
socket_[chid] = sock; channels_[chid].state = CHAN_CONNECTING;
connected_[chid] = false; channels_[chid].socket = sock;
} }
} }
} }
@@ -225,12 +232,12 @@ public:
driven_->drv_set_clock(double(now) / 1000000.0); driven_->drv_set_clock(double(now) / 1000000.0);
} }
void close_socket(int chid, const std::string err) { void close_channel(int chid, const std::string err) {
assert(socket_[chid] != INVALID_SOCKET); assert(channels_[chid].state != CHAN_INACTIVE);
assert(close(socket_[chid]) == 0); assert(close(channels_[chid].socket) == 0);
driven_->drv_notify_close(chid, err); driven_->drv_notify_close(chid, err);
socket_[chid] = INVALID_SOCKET; channels_[chid].state = CHAN_INACTIVE;
connected_[chid] = false; channels_[chid].socket = INVALID_SOCKET;
short_sleep_ = true; short_sleep_ = true;
} }
@@ -239,8 +246,9 @@ public:
SOCKET chsock = accept(sock, nullptr, nullptr); SOCKET chsock = accept(sock, nullptr, nullptr);
if (chsock > 0) { if (chsock > 0) {
int chid = driven_->drv_notify_accept(port); int chid = driven_->drv_notify_accept(port);
socket_[chid] = chsock; assert(channels_[chid].state == CHAN_INACTIVE);
connected_[chid] = true; channels_[chid].state = CHAN_OPEN;
channels_[chid].socket = chsock;
short_sleep_ = true; short_sleep_ = true;
continue; continue;
} }
@@ -270,7 +278,7 @@ public:
if (p.second > largest) largest = p.second; if (p.second > largest) largest = p.second;
} }
for (int chid = 1; chid < MAX_CHAN; chid++) { for (int chid = 1; chid < MAX_CHAN; chid++) {
SOCKET sock = socket_[chid]; SOCKET sock = channels_[chid].socket;
if (sock == INVALID_SOCKET) continue; if (sock == INVALID_SOCKET) continue;
FD_SET(sock, &rfds); FD_SET(sock, &rfds);
FD_SET(sock, &efds); FD_SET(sock, &efds);
@@ -299,15 +307,16 @@ public:
} }
for (int chid = 1; chid < MAX_CHAN; chid++) { for (int chid = 1; chid < MAX_CHAN; chid++) {
SOCKET sock = socket_[chid]; ChanInfo *chan = channels_ + chid;
SOCKET sock = chan->socket;
if (sock == INVALID_SOCKET) continue; if (sock == INVALID_SOCKET) continue;
if (FD_ISSET(sock, &wfds)) { if (FD_ISSET(sock, &wfds)) {
connected_[chid] = true; chan->state = CHAN_OPEN;
driven_->drv_peek_outgoing(chid, &nbytes, &bytes); driven_->drv_peek_outgoing(chid, &nbytes, &bytes);
if (nbytes > 0) { if (nbytes > 0) {
int wbytes = send(sock, bytes, nbytes, 0); int wbytes = send(sock, bytes, nbytes, 0);
if (wbytes < 0) { if (wbytes < 0) {
close_socket(chid, "send failure"); close_channel(chid, "send failure");
continue; continue;
} else { } else {
driven_->drv_sent_outgoing(chid, wbytes); driven_->drv_sent_outgoing(chid, wbytes);
@@ -317,7 +326,7 @@ public:
if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &efds)) { if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &efds)) {
int nrecv = recv(sock, chbuf.get(), 65536, 0); int nrecv = recv(sock, chbuf.get(), 65536, 0);
if (nrecv <= 0) { if (nrecv <= 0) {
close_socket(chid, "recv failure"); close_channel(chid, "recv failure");
continue; continue;
} else { } else {
driven_->drv_recv_incoming(chid, nrecv, chbuf.get()); driven_->drv_recv_incoming(chid, nrecv, chbuf.get());