From 0833662539b46c5bd558734cec003441442f3e29 Mon Sep 17 00:00:00 2001 From: jyelon Date: Wed, 5 Jan 2022 13:14:44 -0500 Subject: [PATCH] A bit of refactoring before SSL conversion --- luprex/core/cpp/driver-linux.cpp | 201 ++++++++++++++++--------------- 1 file changed, 105 insertions(+), 96 deletions(-) diff --git a/luprex/core/cpp/driver-linux.cpp b/luprex/core/cpp/driver-linux.cpp index 16e52bf2..8bcd12bb 100644 --- a/luprex/core/cpp/driver-linux.cpp +++ b/luprex/core/cpp/driver-linux.cpp @@ -16,6 +16,8 @@ #include #include #include +using SOCKET=int; +const int INVALID_SOCKET = -1; struct termios orig_termios; @@ -45,16 +47,91 @@ static void enableRawMode() { 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 { public: - using PollVec = std::vector; - using SOCKET=int; - const int INVALID_SOCKET = -1; + enum ChanState { + CHAN_INACTIVE, + CHAN_CONNECTING, + CHAN_OPEN, + }; + struct ChanInfo { + ChanState state; + SOCKET socket; + }; + static const int MAX_CHAN = DrivenEngine::MAX_CHAN; DrivenEngine *driven_; - SOCKET socket_[MAX_CHAN]; - bool connected_[MAX_CHAN]; + ChanInfo channels_[MAX_CHAN]; bool short_sleep_; std::map listen_sockets_; std::unique_ptr chbuf; @@ -68,81 +145,11 @@ public: 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) { driven_ = de; for (int i = 0; i < MAX_CHAN; i++) { - socket_[i] = INVALID_SOCKET; - connected_[i] = false; + channels_[i].state = CHAN_INACTIVE; + channels_[i].socket = INVALID_SOCKET; } short_sleep_ = false; chbuf.reset(new char[65536]); @@ -172,10 +179,10 @@ public: void handle_new_closed_sockets() { for (int chid = 1; chid < MAX_CHAN; chid++) { if (driven_->drv_get_channel_released(chid)) { - if (socket_[chid] != INVALID_SOCKET) { - assert(close(socket_[chid]) == 0); - socket_[chid] = INVALID_SOCKET; - connected_[chid] = false; + if (channels_[chid].state != CHAN_INACTIVE) { + assert(close(channels_[chid].socket) == 0); + channels_[chid].state = CHAN_INACTIVE; + channels_[chid].socket = INVALID_SOCKET; } driven_->drv_notify_close(chid, ""); } @@ -186,15 +193,15 @@ public: std::set chans; driven_->drv_get_new_outgoing(chans); for (int chid : chans) { - assert(socket_[chid] == INVALID_SOCKET); + assert(channels_[chid].state == CHAN_INACTIVE); std::string err; SOCKET sock = open_connection(driven_->drv_get_target(chid), err); if (sock == INVALID_SOCKET) { driven_->drv_notify_close(chid, err); short_sleep_ = true; } else { - socket_[chid] = sock; - connected_[chid] = false; + channels_[chid].state = CHAN_CONNECTING; + channels_[chid].socket = sock; } } } @@ -225,12 +232,12 @@ public: driven_->drv_set_clock(double(now) / 1000000.0); } - void close_socket(int chid, const std::string err) { - assert(socket_[chid] != INVALID_SOCKET); - assert(close(socket_[chid]) == 0); + void close_channel(int chid, const std::string err) { + assert(channels_[chid].state != CHAN_INACTIVE); + assert(close(channels_[chid].socket) == 0); driven_->drv_notify_close(chid, err); - socket_[chid] = INVALID_SOCKET; - connected_[chid] = false; + channels_[chid].state = CHAN_INACTIVE; + channels_[chid].socket = INVALID_SOCKET; short_sleep_ = true; } @@ -239,8 +246,9 @@ public: SOCKET chsock = accept(sock, nullptr, nullptr); if (chsock > 0) { int chid = driven_->drv_notify_accept(port); - socket_[chid] = chsock; - connected_[chid] = true; + assert(channels_[chid].state == CHAN_INACTIVE); + channels_[chid].state = CHAN_OPEN; + channels_[chid].socket = chsock; short_sleep_ = true; continue; } @@ -270,7 +278,7 @@ public: if (p.second > largest) largest = p.second; } for (int chid = 1; chid < MAX_CHAN; chid++) { - SOCKET sock = socket_[chid]; + SOCKET sock = channels_[chid].socket; if (sock == INVALID_SOCKET) continue; FD_SET(sock, &rfds); FD_SET(sock, &efds); @@ -299,15 +307,16 @@ public: } 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 (FD_ISSET(sock, &wfds)) { - connected_[chid] = true; + chan->state = CHAN_OPEN; driven_->drv_peek_outgoing(chid, &nbytes, &bytes); if (nbytes > 0) { int wbytes = send(sock, bytes, nbytes, 0); if (wbytes < 0) { - close_socket(chid, "send failure"); + close_channel(chid, "send failure"); continue; } else { driven_->drv_sent_outgoing(chid, wbytes); @@ -317,7 +326,7 @@ public: if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &efds)) { int nrecv = recv(sock, chbuf.get(), 65536, 0); if (nrecv <= 0) { - close_socket(chid, "recv failure"); + close_channel(chid, "recv failure"); continue; } else { driven_->drv_recv_incoming(chid, nrecv, chbuf.get());