You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
netpong/includes/connect-helpers.hpp

87 lines
3.1 KiB
C++

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <cstdint>
#include <iomanip>
namespace code {
namespace { /* Since these are internal function, I have wrapped them in an anonymous namespace, to prevent outside access to them */
/* Tokenizes a string, based on the given delimiter */
std::vector<std::string> tokenize_str(std::string str, std::string delim) {
std::vector<std::string> result;
char* c_str = str.data();
char* c_delim = delim.data();
char* tok = strtok(c_str, c_delim);
while (tok != NULL) {
result.push_back(std::string(tok));
tok = strtok(NULL, c_delim);
}
return result;
}
/* Convert an IPv4 address from decimal to dotted decimal notation */
std::string dec_to_dotted_dec(std::string addr) {
uint32_t addr_val = std::stoul(addr); /* 32 bit address */
uint8_t addr_1 = (addr_val & (0xFF << 24)) >> 24; /* First octet (Bitwise AND the address with 255.0.0.0, and shift it to the right to obtain the first octet) */
uint8_t addr_2 = (addr_val & (0xFF << 16)) >> 16;
uint8_t addr_3 = (addr_val & (0xFF << 8)) >> 8;
uint8_t addr_4 = (addr_val & 0xFF);
std::string ret_val = std::string(std::to_string(addr_1) + "." + std::to_string(addr_2) + "." + std::to_string(addr_3) + "." + std::to_string(addr_4));
return ret_val;
}
/* Convert an IPv4 address from dotted deecimal to decimal */
std::string dotted_dec_to_dec(std::string addr) {
std::vector<std::string> octets = tokenize_str(addr, ".");
uint32_t addr_val = (std::stoul(octets[0]) << 24) + (std::stoul(octets[1]) << 16) + (std::stoul(octets[2]) << 8) + (std::stoul(octets[3]));
return std::to_string(addr_val);
}
}
/* Given an address and a port, return a 'code' which has the address and port encoded in it */
std::string encode(std::string address, std::string port) {
/* Convert the address to decimal, and convert that to hex */
std::string addr_coded = dotted_dec_to_dec(address);
std::stringstream stream;
stream << std::hex << std::stoul(addr_coded, 0, 10);
addr_coded = stream.str();
stream.str("");
/* Convert the port to hex */
stream << std::hex << std::stoul(port, 0, 10);
std::string port_coded = stream.str();
std::string ret_val = addr_coded + "_" + port_coded;
return ret_val;
}
/* Given a code, decode it and return a vector with the address and port */
std::vector<std::string> decode(std::string connect_code) {
std::vector<std::string> 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) */
/* 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, 16));
port = std::to_string(std::stoul(address, 0, 10));
/* Convert decimal address to dotted decimal */
address = dec_to_dotted_dec(address);
std::vector<std::string> ret_val;
ret_val.push_back(address);
ret_val.push_back(port);
return ret_val;
}
}