diff --git a/src/tools/hexnet.cpp b/src/tools/hexnet.cpp index ef8324f..963668e 100644 --- a/src/tools/hexnet.cpp +++ b/src/tools/hexnet.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -47,6 +49,10 @@ sockpp::tcp6_socket tcp6Socket; sockpp::tcp6_acceptor tcp6Acceptor; // TCP v6 client sockpp::tcp6_connector tcp6Connector; +// UDP v4 server and client +sockpp::udp_socket udpSocket; +// UDP v6 server and client +sockpp::udp6_socket udp6Socket; bool exitProgram = false; @@ -58,6 +64,12 @@ bool outgoing = false; std::string host; in_port_t port; +// This is probably bigger than the MTU on any given network. +// This should allow us to read entire packets at once when they arrive +// slowly enough to be read individually. +const uint32_t bufferSize = 2048; +uint8_t networkBuffer[bufferSize]; + void signalHandler(int signal) { // shut down gracefully exitProgram = true; @@ -75,10 +87,9 @@ void signalHandler(int signal) { void readFromTCP() { ssize_t byteCount; - uint8_t buffer[1536]; - while (!exitProgram && (outgoing? (byteCount = tcpConnector.read(buffer, sizeof(buffer))) > 0 : (byteCount = tcpSocket.read(buffer, sizeof(buffer))) > 0)) { + while (!exitProgram && (outgoing? (byteCount = tcpConnector.read(networkBuffer, bufferSize)) > 0 : (byteCount = tcpSocket.read(networkBuffer, bufferSize)) > 0)) { for (ssize_t i=0; i 0 : (byteCount = tcp6Socket.read(buffer, sizeof(buffer))) > 0)) { + while (!exitProgram && (outgoing? (byteCount = tcp6Connector.read(networkBuffer, bufferSize)) > 0 : (byteCount = tcp6Socket.read(networkBuffer, bufferSize)) > 0)) { for (ssize_t i=0; i 0) { + std::cout << peer << ": "; + for (ssize_t i=0; i 0) { + std::cout << peer << ": "; + for (ssize_t i=0; i options; options.push_back(CLI::Option('c', "connect", "HOST", "make an outgoing connection to HOST instead of listening for an incoming connection")); + options.push_back(CLI::Option('b', "bind", "ADDRESS", "(UDP only) bind to ADDRESS instead of localhost")); std::vector arguments; arguments.push_back(CLI::Argument("PORT", "the port to lsiten on (or connect to)")); @@ -204,10 +239,42 @@ int main(int argc, char* argv[]) { std::cerr << "Talking to " << host << " on port " << (int) port << " (UDP)..." << std::endl; if (ipv4) { // UDP v4 out - return EXIT_UNIMPLEMENTED; + if (!udpSocket) { + std::cerr << "Error creating UDP socket: " << udpSocket.last_error_str() << std::endl; + } + // Btw: Did you know that UDP has no concept of a connection? + if (!udpSocket.connect(sockpp::inet_address(host, port))) { + std::cerr << "Error associating socket with " << host << " port " << port << std::endl; + std::cerr << udpSocket.last_error_str() << std::endl; + } + + std::thread threadReadFromUDP = std::thread(readFromUDP); + //std::thread threadWriteToUDP = std::thread(writeToUDP); + + threadReadFromUDP.join(); + //threadWriteToUDP.join(); + + std::cout << std::endl; + return EXIT_SUCCESS; } else { // UDP v6 out - return EXIT_UNIMPLEMENTED; + if (!udp6Socket) { + std::cerr << "Error creating UDP socket: " << udp6Socket.last_error_str() << std::endl; + } + // Btw: Did you know that UDP has no concept of a connection? + if (!udp6Socket.connect(sockpp::inet6_address(host, port))) { + std::cerr << "Error associating socket with " << host << " port " << port << std::endl; + std::cerr << udp6Socket.last_error_str() << std::endl; + } + + std::thread threadReadFromUDP6 = std::thread(readFromUDP6); + //std::thread threadWriteToUDP6 = std::thread(writeToUDP6); + + threadReadFromUDP6.join(); + //threadWriteToUDP6.join(); + + std::cout << std::endl; + return EXIT_SUCCESS; } } } else { @@ -263,13 +330,45 @@ int main(int argc, char* argv[]) { return EXIT_SUCCESS; } } else { - std::cerr << "Listening on port " << (int) port << " (UDP)..." << std::endl; + std::string address = "localhost"; + if (cliParser.getOption("bind").errorCode != ErrorCodes::NOT_PRESENT) { + address = cliParser.getOption("bind").value; + } + std::cerr << "Listening on " << address << " port " << (int) port << " (UDP)..." << std::endl; if (ipv4) { // UDP v4 in - return EXIT_UNIMPLEMENTED; + if (!udpSocket) { + std::cerr << "Error creating UDP socket: " << udpSocket.last_error_str() << std::endl; + } + if (!udpSocket.bind(sockpp::inet_address(address, port))) { + std::cerr << "Error binding UDP socket to " << address << " port " << port << ": " << udpSocket.last_error_str() << std::endl; + } + + std::thread threadReadFromUDP = std::thread(readFromUDP); + //std::thread threadWriteToUDP = std::thread(writeToUDP); + + threadReadFromUDP.join(); + //threadWriteToUDP.join(); + + std::cout << std::endl; + return EXIT_SUCCESS; } else { // UDP v6 in - return EXIT_UNIMPLEMENTED; + if (!udp6Socket) { + std::cerr << "Error creating UDP socket: " << udp6Socket.last_error_str() << std::endl; + } + if (!udp6Socket.bind(sockpp::inet6_address(address, port))) { + std::cerr << "Error binding UDP socket to " << address << " port " << port << ": " << udp6Socket.last_error_str() << std::endl; + } + + std::thread threadReadFromUDP6 = std::thread(readFromUDP6); + //std::thread threadWriteToUDP6 = std::thread(writeToUDP6); + + threadReadFromUDP6.join(); + //threadWriteToUDP6.join(); + + std::cout << std::endl; + return EXIT_SUCCESS; } } }