Backported socket library edits + testing tool from LL branch
This commit is contained in:
parent
5be878bea5
commit
248056e611
4 changed files with 82 additions and 0 deletions
|
@ -704,4 +704,6 @@ add_test(DownloaderTest COMMAND downloadertest)
|
||||||
add_executable(jsontest test/json.cpp ${BINARY_DIR}/mist/.headers)
|
add_executable(jsontest test/json.cpp ${BINARY_DIR}/mist/.headers)
|
||||||
target_link_libraries(jsontest mist)
|
target_link_libraries(jsontest mist)
|
||||||
add_test(JSONTest COMMAND jsontest)
|
add_test(JSONTest COMMAND jsontest)
|
||||||
|
add_executable(resolvetest test/resolve.cpp ${BINARY_DIR}/mist/.headers)
|
||||||
|
target_link_libraries(resolvetest mist)
|
||||||
|
|
||||||
|
|
|
@ -213,6 +213,44 @@ void Socket::hostBytesToStr(const char *bytes, size_t len, std::string &target){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves a hostname into a human-readable address that is the best guess for external address matching this host.
|
||||||
|
/// The optional family can force IPv4/IPv6 resolving, while the optional hint will allow forcing resolving to a
|
||||||
|
/// specific address if it is a match for this host.
|
||||||
|
/// Returns empty string if no reasonable match could be made.
|
||||||
|
std::string Socket::resolveHostToBestExternalAddrGuess(const std::string &host, int family,
|
||||||
|
const std::string &hint){
|
||||||
|
struct addrinfo *result, *rp, hints;
|
||||||
|
std::string newaddr;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
hints.ai_family = family;
|
||||||
|
hints.ai_socktype = 0;
|
||||||
|
hints.ai_flags = AI_ADDRCONFIG;
|
||||||
|
int s = getaddrinfo(host.c_str(), 0, &hints, &result);
|
||||||
|
if (s != 0){
|
||||||
|
FAIL_MSG("Could not resolve %s! Error: %s", host.c_str(), gai_strerror(s));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (rp = result; rp != NULL; rp = rp->ai_next){
|
||||||
|
static char addrconv[INET6_ADDRSTRLEN];
|
||||||
|
if (rp->ai_family == AF_INET6){
|
||||||
|
newaddr = inet_ntop(rp->ai_family, &((const sockaddr_in6 *)rp->ai_addr)->sin6_addr, addrconv, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
if (rp->ai_family == AF_INET){
|
||||||
|
newaddr = inet_ntop(rp->ai_family, &((const sockaddr_in *)rp->ai_addr)->sin_addr, addrconv, INET6_ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
if (newaddr.substr(0, 7) == "::ffff:"){newaddr = newaddr.substr(7);}
|
||||||
|
HIGH_MSG("Resolved to %s addr [%s]", addrFam(rp->ai_family), newaddr.c_str());
|
||||||
|
// if not a local address, we can't bind, so don't bother trying it
|
||||||
|
if (!isLocal(newaddr)){continue;}
|
||||||
|
// we match the hint, done!
|
||||||
|
if (newaddr == hint){break;}
|
||||||
|
}
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return newaddr;
|
||||||
|
}
|
||||||
|
|
||||||
std::string uint2string(unsigned int i){
|
std::string uint2string(unsigned int i){
|
||||||
std::stringstream st;
|
std::stringstream st;
|
||||||
st << i;
|
st << i;
|
||||||
|
@ -1646,6 +1684,25 @@ void Socket::UDPConnection::SendNow(const char *sdata, size_t len){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Socket::UDPConnection::getBoundAddress(){
|
||||||
|
struct sockaddr_in6 tmpaddr;
|
||||||
|
socklen_t len = sizeof(tmpaddr);
|
||||||
|
std::string boundaddr;
|
||||||
|
if (!getsockname(sock, (sockaddr *)&tmpaddr, &len)){
|
||||||
|
static char addrconv[INET6_ADDRSTRLEN];
|
||||||
|
if (tmpaddr.sin6_family == AF_INET6){
|
||||||
|
boundaddr = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
|
||||||
|
if (boundaddr.substr(0, 7) == "::ffff:"){boundaddr = boundaddr.substr(7);}
|
||||||
|
HIGH_MSG("Local IPv6 addr [%s]", boundaddr.c_str());
|
||||||
|
}
|
||||||
|
if (tmpaddr.sin6_family == AF_INET){
|
||||||
|
boundaddr = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
|
||||||
|
HIGH_MSG("Local IPv4 addr [%s]", boundaddr.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return boundaddr;
|
||||||
|
}
|
||||||
|
|
||||||
/// Bind to a port number, returning the bound port.
|
/// Bind to a port number, returning the bound port.
|
||||||
/// If that fails, returns zero.
|
/// If that fails, returns zero.
|
||||||
/// \arg port Port to bind to, required.
|
/// \arg port Port to bind to, required.
|
||||||
|
|
|
@ -42,6 +42,8 @@ namespace Socket{
|
||||||
/// Returns true if given human-readable hostname is a local address.
|
/// Returns true if given human-readable hostname is a local address.
|
||||||
bool isLocalhost(const std::string &host);
|
bool isLocalhost(const std::string &host);
|
||||||
bool checkTrueSocket(int sock);
|
bool checkTrueSocket(int sock);
|
||||||
|
std::string resolveHostToBestExternalAddrGuess(const std::string &host, int family = AF_UNSPEC,
|
||||||
|
const std::string &hint = "");
|
||||||
|
|
||||||
/// A buffer made out of std::string objects that can be efficiently read from and written to.
|
/// A buffer made out of std::string objects that can be efficiently read from and written to.
|
||||||
class Buffer{
|
class Buffer{
|
||||||
|
@ -205,6 +207,7 @@ namespace Socket{
|
||||||
void setBlocking(bool blocking);
|
void setBlocking(bool blocking);
|
||||||
void SetDestination(std::string hostname, uint32_t port);
|
void SetDestination(std::string hostname, uint32_t port);
|
||||||
void GetDestination(std::string &hostname, uint32_t &port);
|
void GetDestination(std::string &hostname, uint32_t &port);
|
||||||
|
std::string getBoundAddress();
|
||||||
uint32_t getDestPort() const;
|
uint32_t getDestPort() const;
|
||||||
bool Receive();
|
bool Receive();
|
||||||
void SendNow(const std::string &data);
|
void SendNow(const std::string &data);
|
||||||
|
|
20
test/resolve.cpp
Normal file
20
test/resolve.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#include "../lib/socket.cpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
if (argc < 2){return 1;}
|
||||||
|
if (argc > 2){
|
||||||
|
std::cout << "Best IPv4 guess:"
|
||||||
|
<< Socket::resolveHostToBestExternalAddrGuess(argv[1], AF_INET, argv[2]) << std::endl;
|
||||||
|
std::cout << "Best IPv6 guess:"
|
||||||
|
<< Socket::resolveHostToBestExternalAddrGuess(argv[1], AF_INET6, argv[2]) << std::endl;
|
||||||
|
}else{
|
||||||
|
std::cout << "Best IPv4 guess:" << Socket::resolveHostToBestExternalAddrGuess(argv[1], AF_INET)
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << "Best IPv6 guess:" << Socket::resolveHostToBestExternalAddrGuess(argv[1], AF_INET6)
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue