added new method rsGetHostByName to use gethostbyname_r for re-entrant calls. Updated dnsresolver and extaddrfinder to use it. Suggestion by GuessWho #125

This commit is contained in:
csoler 2015-10-07 21:24:31 -04:00
parent f1f722a767
commit e776effc0d
5 changed files with 90 additions and 39 deletions

View File

@ -62,24 +62,32 @@ void *solveDNSEntries(void *p)
if(!next_call.empty()) if(!next_call.empty())
{ {
hostent *pHost = gethostbyname(next_call.c_str()); in_addr in ;
bool succeed = rsGetHostByName(next_call.c_str(),in);
{ {
RsStackMutex mut(dnsr->_rdnsMtx) ; RsStackMutex mut(dnsr->_rdnsMtx) ;
DNSResolver::AddrInfo &info = (*dnsr->_addr_map)[next_call]; DNSResolver::AddrInfo &info = (*dnsr->_addr_map)[next_call];
if(pHost) if(succeed)
{ {
info.state = DNSResolver::DNS_HAVE ; info.state = DNSResolver::DNS_HAVE ;
// IPv4 for the moment. // IPv4 for the moment.
struct sockaddr_in *addrv4p = (struct sockaddr_in *) &(info.addr); struct sockaddr_in *addrv4p = (struct sockaddr_in *) &(info.addr);
addrv4p->sin_family = AF_INET; addrv4p->sin_family = AF_INET;
addrv4p->sin_addr.s_addr = *(unsigned long*) (pHost->h_addr); addrv4p->sin_addr= in ;
addrv4p->sin_port = htons(0); addrv4p->sin_port = htons(0);
std::cerr << "LOOKUP succeeded: " << next_call.c_str() << " => " << rs_inet_ntoa(addrv4p->sin_addr) << std::endl;
} }
else else
{
info.state = DNSResolver::DNS_LOOKUP_ERROR ; info.state = DNSResolver::DNS_LOOKUP_ERROR ;
std::cerr << "DNSResolver: lookup error for address \"" << next_call.c_str() << "\"" << std::endl;
}
} }
} }
} }

View File

@ -2,6 +2,7 @@
#include "pqi/pqinetwork.h" #include "pqi/pqinetwork.h"
#include "util/rsstring.h" #include "util/rsstring.h"
#include "util/rsmemory.h"
#ifndef WIN32 #ifndef WIN32
#include <netdb.h> #include <netdb.h>
@ -58,7 +59,6 @@ static void getPage(const std::string& server_name,std::string& page)
int sockfd,n=0; // socket descriptor int sockfd,n=0; // socket descriptor
struct sockaddr_in serveur; // server's parameters struct sockaddr_in serveur; // server's parameters
memset(&serveur.sin_zero, 0, sizeof(serveur.sin_zero)); memset(&serveur.sin_zero, 0, sizeof(serveur.sin_zero));
struct hostent *hostinfo=NULL; // structure for storing the server's ip
char buf[1024]; char buf[1024];
char request[1024]; char request[1024];
@ -78,20 +78,21 @@ static void getPage(const std::string& server_name,std::string& page)
// get server's ipv4 adress // get server's ipv4 adress
hostinfo = gethostbyname(server_name.c_str()); in_addr in ;
if (hostinfo == NULL) /* l'hôte n'existe pas */ if(!rsGetHostByName(server_name.c_str(),in)) /* l'hôte n'existe pas */
{ {
std::cerr << "ExtAddrFinder: Unknown host " << server_name << std::endl; std::cerr << "ExtAddrFinder: Unknown host " << server_name << std::endl;
unix_close(sockfd); unix_close(sockfd);
return ; return ;
} }
serveur.sin_addr = *(struct in_addr*) hostinfo->h_addr; serveur.sin_addr = in ;
serveur.sin_port = htons(80); serveur.sin_port = htons(80);
#ifdef EXTADDRSEARCH_DEBUG #ifdef EXTADDRSEARCH_DEBUG
printf("Connection attempt\n"); printf("Connection attempt\n");
#endif #endif
std::cerr << "ExtAddrFinder: resolved hostname " << server_name << " to " << rs_inet_ntoa(in) << std::endl;
if(unix_connect(sockfd,(struct sockaddr *)&serveur, sizeof(serveur)) == -1) if(unix_connect(sockfd,(struct sockaddr *)&serveur, sizeof(serveur)) == -1)
{ {

View File

@ -21,14 +21,21 @@
// //
class RsTemporaryMemory class RsTemporaryMemory
{ {
public: public:
RsTemporaryMemory(size_t s) RsTemporaryMemory(size_t s)
{ {
_mem = (unsigned char *)malloc(s) ; _mem = (unsigned char *)malloc(s) ;
if(_mem)
_size = s ;
else
_size = 0 ;
} }
operator unsigned char *() { return _mem ; } operator unsigned char *() { return _mem ; }
size_t size() const { return _size ; }
~RsTemporaryMemory() ~RsTemporaryMemory()
{ {
if(_mem != NULL) if(_mem != NULL)
@ -38,8 +45,9 @@ class RsTemporaryMemory
} }
} }
private: private:
unsigned char *_mem ; unsigned char *_mem ;
size_t _size ;
// make it noncopyable // make it noncopyable
RsTemporaryMemory& operator=(const RsTemporaryMemory&) { return *this ;} RsTemporaryMemory& operator=(const RsTemporaryMemory&) { return *this ;}

View File

@ -26,6 +26,7 @@
#include "util/rsnet.h" #include "util/rsnet.h"
#include "util/rsthreads.h" #include "util/rsthreads.h"
#include "util/rsstring.h" #include "util/rsstring.h"
#include "util/rsmemory.h"
#ifdef WINDOWS_SYS #ifdef WINDOWS_SYS
#else #else
@ -72,6 +73,36 @@ void sockaddr_clear(struct sockaddr_in *addr)
addr->sin_family = AF_INET; addr->sin_family = AF_INET;
} }
bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr)
{
RsTemporaryMemory mem(8192) ;
if(!mem)
{
std::cerr << __PRETTY_FUNCTION__ << ": Cannot allocate memory!" << std::endl;
return false; // Do something.
}
int error = 0;
struct hostent pHost;
struct hostent *result;
if(gethostbyname_r(hostname.c_str(), &pHost, (char*)(unsigned char*)mem, mem.size(), &result, &error) != 0)
{
std::cerr << __PRETTY_FUNCTION__ << ": cannot call gethostname_r. Internal error reported. Check buffer size." << std::endl;
return false ;
}
if(!result)
{
std::cerr << __PRETTY_FUNCTION__ << ": gethostname_r returned null result." << std::endl;
return false ;
}
// Use contents of result.
returned_addr.s_addr = *(unsigned long*) (result->h_addr);
return true ;
}
bool isValidNet(const struct in_addr *addr) bool isValidNet(const struct in_addr *addr)
{ {

View File

@ -70,6 +70,9 @@ bool isLoopbackNet(const struct in_addr *addr);
bool isPrivateNet(const struct in_addr *addr); bool isPrivateNet(const struct in_addr *addr);
bool isExternalNet(const struct in_addr *addr); bool isExternalNet(const struct in_addr *addr);
// uses a re-entrant version of gethostbyname
bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) ;
std::ostream& operator<<(std::ostream& o,const struct sockaddr_in&) ; std::ostream& operator<<(std::ostream& o,const struct sockaddr_in&) ;
/* thread-safe version of inet_ntoa */ /* thread-safe version of inet_ntoa */