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,25 +62,33 @@ 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) ;
{ DNSResolver::AddrInfo &info = (*dnsr->_addr_map)[next_call];
RsStackMutex mut(dnsr->_rdnsMtx) ;
DNSResolver::AddrInfo &info = (*dnsr->_addr_map)[next_call]; if(succeed)
{
if(pHost) info.state = DNSResolver::DNS_HAVE ;
// IPv4 for the moment.
struct sockaddr_in *addrv4p = (struct sockaddr_in *) &(info.addr);
addrv4p->sin_family = AF_INET;
addrv4p->sin_addr= in ;
addrv4p->sin_port = htons(0);
std::cerr << "LOOKUP succeeded: " << next_call.c_str() << " => " << rs_inet_ntoa(addrv4p->sin_addr) << std::endl;
}
else
{ {
info.state = DNSResolver::DNS_HAVE ;
// IPv4 for the moment.
struct sockaddr_in *addrv4p = (struct sockaddr_in *) &(info.addr);
addrv4p->sin_family = AF_INET;
addrv4p->sin_addr.s_addr = *(unsigned long*) (pHost->h_addr);
addrv4p->sin_port = htons(0);
}
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,29 +21,37 @@
// //
class RsTemporaryMemory class RsTemporaryMemory
{ {
public: public:
RsTemporaryMemory(size_t s) RsTemporaryMemory(size_t s)
{ {
_mem = (unsigned char *)malloc(s) ; _mem = (unsigned char *)malloc(s) ;
}
operator unsigned char *() { return _mem ; } if(_mem)
_size = s ;
else
_size = 0 ;
}
~RsTemporaryMemory() operator unsigned char *() { return _mem ; }
{
if(_mem != NULL) size_t size() const { return _size ; }
{
free(_mem) ;
_mem = NULL ;
}
}
private: ~RsTemporaryMemory()
unsigned char *_mem ; {
if(_mem != NULL)
{
free(_mem) ;
_mem = NULL ;
}
}
// make it noncopyable private:
RsTemporaryMemory& operator=(const RsTemporaryMemory&) { return *this ;} unsigned char *_mem ;
RsTemporaryMemory(const RsTemporaryMemory&) {} size_t _size ;
// make it noncopyable
RsTemporaryMemory& operator=(const RsTemporaryMemory&) { return *this ;}
RsTemporaryMemory(const RsTemporaryMemory&) {}
}; };

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 */