From b1733bc0070cba5a82efb65f4857119ada934671 Mon Sep 17 00:00:00 2001 From: BodgeMaster <> Date: Wed, 20 Jul 2022 08:06:04 +0200 Subject: [PATCH] tools/hexnet: initial implementation of TCP receive only server --- src/tools/hexnet.cpp | 65 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/src/tools/hexnet.cpp b/src/tools/hexnet.cpp index 06125db..80e4230 100644 --- a/src/tools/hexnet.cpp +++ b/src/tools/hexnet.cpp @@ -14,9 +14,11 @@ //If not, see https://www.gnu.org/licenses/agpl-3.0.en.html #include +#include #include #include #include +#include #include "../lib/error.h++" #include "../lib/cli.h++" @@ -34,8 +36,9 @@ int main(int argc, char* argv[]){ bool tcp = true; bool udp = true; bool listen = false; + int64_t mtu = 1500; std::string host; - uint16_t port; + in_port_t port; std::vector flags; flags.push_back(CLI::Flag('4', "ipv4", "use IPv4, defaults to both when -4 and -6 are omitted, otherwise uses what is specified")); @@ -45,6 +48,7 @@ int main(int argc, char* argv[]){ std::vector unpositionalArguments; unpositionalArguments.push_back(CLI::UnpositionalArgument('c', "connect", "HOST", "connect to HOST, listen for incoming connections if omitted")); + unpositionalArguments.push_back(CLI::UnpositionalArgument('m', "mtu-optimize", "MTU", "Optimize for a specific maximum transfer unit by reading MTU bytes at a time.")); std::vector positionalArguments; positionalArguments.push_back(CLI::PositionalArgument("PORT", "the port to use")); @@ -66,15 +70,56 @@ int main(int argc, char* argv[]){ if (cliParser.getUnpositionalArgument('c').errorCode == ErrorCodes::NOT_PRESENT) { listen = true; } + if (cliParser.getUnpositionalArgument('m').errorCode == ErrorCodes::SUCCESS) { + mtu = std::stol(cliParser.getUnpositionalArgument('m').value); + } host = cliParser.getUnpositionalArgument('c').value; - //FIXME: use a function that returns a fixed-width data type instead - port = (uint16_t) std::stoi(cliParser.getPositionalArgument(0).value); + //FIXME: use a function that returns a fixed-width data type instead, + // ensure that the given value is a valid port + port = (in_port_t) std::stoi(cliParser.getPositionalArgument(0).value); - std::cerr << "Port: " << (int) port << std::endl; - std::cerr << (listen? "Listening" : "Host: ") << host << std::endl; - std::cerr << "IPv4: " << (ipv4? "yes" : "no") << std::endl; - std::cerr << "IPv6: " << (ipv6? "yes" : "no") << std::endl; - std::cerr << "TCP: " << ( tcp? "yes" : "no") << std::endl; - std::cerr << "UDP: " << ( udp? "yes" : "no") << std::endl; - return EXIT_UNIMPLEMENTED; + if (listen) { + if (ipv6) { + std::cerr << "IPv6 support is not implented yet." << std::endl; + return EXIT_UNIMPLEMENTED; + } + if (udp) { + std::cerr << "UDP support is not implemented yet." << std::endl; + return EXIT_UNIMPLEMENTED; + } + std::cerr << "Listening on port " << port << "." << std::endl; + + sockpp::socket_initializer socketInitializer; + sockpp::tcp_acceptor tcpAcceptor(port); + + if (!tcpAcceptor) { + std::cerr << "Error while creating TCP acceptor: " << tcpAcceptor.last_error_str() << std::endl; + return EXIT_RUNTIME; + } + + sockpp::inet_address peer; + sockpp::tcp_socket tcpSocket = tcpAcceptor.accept(&peer); + std::cerr << "Incoming connection from " << peer << std::endl; + + if (!tcpSocket) { + std::cerr << "Error on incoming connection: " << tcpAcceptor.last_error_str() << std::endl; + return EXIT_RUNTIME; + } + + ssize_t numBytes; + uint8_t buffer[mtu]; + while ((numBytes = tcpSocket.read(buffer, sizeof(buffer))) > 0) { + for (ssize_t i=0; i