diff --git a/src/tools/hexnet.cpp b/src/tools/hexnet.cpp index 412bf96..06125db 100644 --- a/src/tools/hexnet.cpp +++ b/src/tools/hexnet.cpp @@ -18,7 +18,8 @@ #include #include -#define usage std::cerr << "Usage: " << argv[0] << " [-4|-6] [-t|-u] < | -l >" << std::endl << " may be hexadecimal (prefixed with 0x) or binary (prefixed with 0b)." << std::endl +#include "../lib/error.h++" +#include "../lib/cli.h++" #define EXIT_SUCCESS 0 #define EXIT_RUNTIME 1 @@ -33,117 +34,47 @@ int main(int argc, char* argv[]){ bool tcp = true; bool udp = true; bool listen = false; - std::string host = ""; + std::string host; uint16_t port; - if (argc<2) { - usage; - return EXIT_USAGE; - } - for (int i=1; i18) { - std::cerr << argument << " is too big for a valid port." << std::endl; - usage; - return EXIT_USAGE; - } - port = (uint16_t) std::stoul(argument.substr(2, argument.length()), nullptr, 2); - } else if (argument.substr(0, 2)=="0x" || argument.substr(0, 2)=="0X") { - // check for four digit hex number - for (char const &digit : argument.substr(2,argument.length())) { - if (std::isxdigit(digit)==0) { - std::cerr << argument << " is not a valid port." << digit << std::endl; - usage; - return EXIT_USAGE; - } - } - if (argument.length()>6) { - std::cerr << argument << " is too big for a valid port." << std::endl; - usage; - return EXIT_USAGE; - } - port = (uint16_t) std::stoul(argument.substr(2, argument.length()), nullptr, 16); - } else { - // check for decimal number between 0 and 65536 exclusively - for (char const &digit : argument) { - if (std::isdigit(digit)==0) { - std::cerr << argument << " is not a valid port." << std::endl; - usage; - return EXIT_USAGE; - } - } - // using unsigned long here because that's how stoul() - // is defined - unsigned long argumentNumber = std::stoul(argument, nullptr, 10); - if (argumentNumber > 65535) { - std::cerr << argument << " is too big for a valid port." << std::endl; - usage; - return EXIT_USAGE; - } - port = (uint16_t) argumentNumber; - } - break; // last argument anyway - } - usage; - return EXIT_USAGE; - } - // Argument parsing end ############################################ - if (!listen) { - //TODO: verify that host is possibly a valid host (or usage error) - //TODO: look up host if necessary, determine IPv4 or IPv6 mode if necessary - std::cerr << "Client mode not implemented" << std::endl; - return EXIT_UNIMPLEMENTED; + 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")); + flags.push_back(CLI::Flag('6', "ipv6", "use IPv6, defaults to both when -4 and -6 are omitted, otherwise uses what is specified")); + flags.push_back(CLI::Flag('t', "tcp", "use TCP, defaults to both when -t and -u are omitted, otherwise uses what is specified")); + flags.push_back(CLI::Flag('u', "udp", "use UDP, defaults to both when -t and -u are omitted, otherwise uses what is specified")); + + std::vector unpositionalArguments; + unpositionalArguments.push_back(CLI::UnpositionalArgument('c', "connect", "HOST", "connect to HOST, listen for incoming connections if omitted")); + + std::vector positionalArguments; + positionalArguments.push_back(CLI::PositionalArgument("PORT", "the port to use")); + + CLI::ArgumentsParser cliParser = CLI::ArgumentsParser(argc, argv, flags, unpositionalArguments, positionalArguments); + + if (cliParser.wrongUsage) { + //TODO: spit out usage information generated by the parser + return EXIT_USAGE; } + if (cliParser.getFlag('4').value || cliParser.getFlag('6').value) { + ipv4 = cliParser.getFlag('4').value; + ipv6 = cliParser.getFlag('6').value; + } + if (cliParser.getFlag('t').value || cliParser.getFlag('u').value) { + tcp = cliParser.getFlag('t').value; + udp = cliParser.getFlag('u').value; + } + if (cliParser.getUnpositionalArgument('c').errorCode == ErrorCodes::NOT_PRESENT) { + listen = true; + } + 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); + + 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; }