diff --git a/connect_code.cpp b/connect_code.cpp index 67c6292..98228f1 100644 --- a/connect_code.cpp +++ b/connect_code.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -82,9 +83,12 @@ namespace connect_code { std::string encode(std::string address, std::string port) { - std::string addr_coded; - /* Convert the address to decimal, and convert that to hex */ + std::string addr_coded = ""; if (check_ip_ver(address.data()) == 4) { + /* First, convert the address into a decimal format. Then convert this decimal format + into base-32, and also convert the port number into base-32. Join these together with + a "_". */ + /* I don't really have a reason to use my own function (dotted_dec_to_dec() and dec_to_dotted_dec()), to convert the IP address from text to binary. The inet_pton() and inet_ntop() functions can do this just fine, and also @@ -101,10 +105,9 @@ namespace connect_code { Then, tokenize the string, using colons as the delimiters. Finally, take each token in the string, and convert it from base-16 to base-32, appending a '-' as a delimiter. */ std::string addr_expanded = expand_ip6_addr(address); - std::string addr_coded = ""; std::vector addr_tokenized = tokenize_str(addr_expanded, ":"); - for (int i = 0; i < addr_tokenized.size()-1; i++ ) { + for (size_t i = 0; i < addr_tokenized.size()-1; i++ ) { addr_coded += base_convert(addr_tokenized[i], 16, 32); addr_coded += "-"; } @@ -113,9 +116,6 @@ namespace connect_code { /* TODO - Check if the IP address is actually converted properly, and test if the server socket is created correctly. Also do the same for client side, and check client-server connection. */ - std::cout << addr_coded << std::endl; - abort(); - } /* Convert the port to hex */ @@ -127,32 +127,62 @@ namespace connect_code { } std::vector decode(std::string connect_code) { - // + if (connect_code.find("_") == std::string::npos) { + throw std::invalid_argument("Invalid code entered."); // There must be an underscore, to separate the address part from the port part + } + int ip_ver = 0; - if (connect_code.find("-") == connect_code.npos) { + if (connect_code.find("-") != std::string::npos) { ip_ver = 6; // If the string contains hyphens, it must be an IPv6 address encoding. } else { ip_ver = 4; } - // - if (connect_code.find("_") == std::string::npos) { - throw std::invalid_argument("Invalid code entered."); - } std::vector result = tokenize_str(connect_code, "_"); /* Split the string into address and port */ - std::string address = result[0]; /* Address (in base 16) */ - std::string port = result[1]; /* Port (in base 16) */ + std::string address = result[0]; /* Address (in base 32) */ + std::string port = result[1]; /* Port (in base 32) */ + + std::vector ret_val; + + /* The IPv6 and IPv4 encodings are slightly different - I use a hyphen as a delimiter + for IPv6, while there is no delimiter for IPv4. This is why I need to check if the address + is IPv4 or IPv6. */ + if (ip_ver == 4) { + /* Base 32 to base 10 - These lines convert the string to a base 10 number, and convert the result back into a string */ + address = std::to_string(std::stoul(address, 0, 32)); + port = std::to_string(std::stoul(port, 0, 32)); + + /* Convert decimal address to dotted decimal */ + address = dec_to_dotted_dec(address); + + /* Create a vector containing the address and the port, which will be returned */ + ret_val.push_back(address); + ret_val.push_back(port); + } else { + /* IPv6 */ + /* There are three main steps to decoding for IPv6: + 1. Tokenize the address using the delimiter set while encoding ('-', in my case). + 2. Convert each token from base-32 to base-16. + 3. Join the string vector back together into a string, this time using ':' as a delimiter. This will give us our IP address. */ + + std::string conv_addr = ""; // Stores the final address + std::vector address_tokenized = tokenize_str(address, "-"); // Step 1 + + for (size_t i = 0; i < address_tokenized.size()-1; i++) { + address_tokenized[i] = base_convert(address_tokenized[i], 32, 16); // Step 2 + conv_addr += address_tokenized[i] + ":"; // Step 3 + } + conv_addr += base_convert(address_tokenized[address_tokenized.size()-1], 32, 16); // Add the last token - /* Base 16 to base 10 - These lines convert the string to a base 10 number, and convert the result back into a string */ - address = std::to_string(std::stoul(address, 0, 32)); - port = std::to_string(std::stoul(port, 0, 32)); + port = std::to_string(std::stoul(port, 0, 32)); - /* Convert decimal address to dotted decimal */ - address = dec_to_dotted_dec(address); + std::cout << conv_addr << std::endl; + abort(); - std::vector ret_val; - ret_val.push_back(address); - ret_val.push_back(port); + ret_val.push_back(conv_addr); + ret_val.push_back(port); + } + return ret_val; } }