Logo
~Sockets~
~Examples~
~Contact~


ResolvSocket Class Reference
[Asynchronous DNS]

Async DNS resolver socket. More...

#include <ResolvSocket.h>

Inheritance diagram for ResolvSocket:
Collaboration diagram for ResolvSocket:

List of all members.


Public Member Functions

 ResolvSocket (ISocketHandler &)
 ResolvSocket (ISocketHandler &, Socket *parent, const std::string &host, port_t port, bool ipv6=false)
 ResolvSocket (ISocketHandler &, Socket *parent, ipaddr_t)
 ~ResolvSocket ()
void OnAccept ()
 Called when an incoming connection has been completed.
void OnLine (const std::string &line)
 Callback fires when a socket in line protocol has read one full line.
void OnDetached ()
 Callback fires when a new socket thread has started and this socket is ready for operation again.
void OnDelete ()
 Called before a socket class is deleted by the ISocketHandler.
void SetId (int x)
int GetId ()
void OnConnect ()
 Called when a connection has completed.

Private Types

typedef std::map< std::string,
std::map< std::string,
std::string > > 
cache_t
typedef std::map< std::string,
std::map< std::string, time_t > > 
timeout_t

Private Member Functions

 ResolvSocket (const ResolvSocket &s)
ResolvSocketoperator= (const ResolvSocket &)

Private Attributes

std::string m_query
std::string m_data
bool m_bServer
Socketm_parent
 Pointer to ListenSocket class, valid for incoming sockets.
int m_resolv_id
std::string m_resolv_host
port_t m_resolv_port
ipaddr_t m_resolv_address
bool m_cached

Static Private Attributes

static cache_t m_cache
static timeout_t m_cache_to
static Mutex m_cache_mutex

Detailed Description

Async DNS resolver socket.

Definition at line 45 of file ResolvSocket.h.


Member Typedef Documentation

typedef std::map<std::string, std::map<std::string, std::string> > ResolvSocket::cache_t [private]

Definition at line 48 of file ResolvSocket.h.

typedef std::map<std::string, std::map<std::string, time_t> > ResolvSocket::timeout_t [private]

Definition at line 50 of file ResolvSocket.h.


Constructor & Destructor Documentation

ResolvSocket::ResolvSocket ( ISocketHandler h  ) 

Definition at line 63 of file ResolvSocket.cpp.

References TcpSocket::SetLineProtocol().

00064 :TcpSocket(h)
00065 ,m_bServer(false)
00066 ,m_parent(NULL)
00067 #ifdef ENABLE_IPV6
00068 ,m_resolve_ipv6(false)
00069 #endif
00070 ,m_cached(false)
00071 {
00072         SetLineProtocol();
00073 }

ResolvSocket::ResolvSocket ( ISocketHandler h,
Socket parent,
const std::string &  host,
port_t  port,
bool  ipv6 = false 
)

Definition at line 76 of file ResolvSocket.cpp.

References TcpSocket::SetLineProtocol().

00077 :TcpSocket(h)
00078 ,m_bServer(false)
00079 ,m_parent(parent)
00080 ,m_resolv_host(host)
00081 ,m_resolv_port(port)
00082 #ifdef ENABLE_IPV6
00083 ,m_resolve_ipv6(ipv6)
00084 #endif
00085 ,m_cached(false)
00086 {
00087         SetLineProtocol();
00088 }

ResolvSocket::ResolvSocket ( ISocketHandler h,
Socket parent,
ipaddr_t  a 
)

Definition at line 91 of file ResolvSocket.cpp.

References TcpSocket::SetLineProtocol().

00092 :TcpSocket(h)
00093 ,m_bServer(false)
00094 ,m_parent(parent)
00095 ,m_resolv_port(0)
00096 ,m_resolv_address(a)
00097 #ifdef ENABLE_IPV6
00098 ,m_resolve_ipv6(false)
00099 #endif
00100 ,m_cached(false)
00101 {
00102         SetLineProtocol();
00103 }

ResolvSocket::~ResolvSocket (  ) 

Definition at line 121 of file ResolvSocket.cpp.

00122 {
00123 }

ResolvSocket::ResolvSocket ( const ResolvSocket s  )  [inline, private]

Definition at line 76 of file ResolvSocket.h.

00076 : TcpSocket(s) {} // copy constructor


Member Function Documentation

void ResolvSocket::OnAccept (  )  [inline, virtual]

Called when an incoming connection has been completed.

Reimplemented from Socket.

Definition at line 61 of file ResolvSocket.h.

00061 { m_bServer = true; }

void ResolvSocket::OnLine ( const std::string &  line  )  [virtual]

Callback fires when a socket in line protocol has read one full line.

Parameters:
line Line read

Reimplemented from TcpSocket.

Definition at line 126 of file ResolvSocket.cpp.

References DEB, Socket::Detach(), Parse::getrest(), Parse::getword(), Socket::Handler(), m_bServer, m_cache, m_cache_mutex, m_cache_to, m_cached, m_data, m_parent, m_query, m_resolv_host, m_resolv_id, m_resolv_port, TcpSocket::OnResolved(), Socket::OnResolveFailed(), Socket::OnReverseResolved(), ISocketHandler::Resolving(), TcpSocket::Send(), Socket::SetCloseAndDelete(), Utility::u2ip(), and ISocketHandler::Valid().

00127 {
00128         Parse pa(line, ":");
00129         if (m_bServer)
00130         {
00131                 m_query = pa.getword();
00132                 m_data = pa.getrest();
00133 DEB(            fprintf(stderr, " *** ResolvSocket server; query=%s, data=%s\n", m_query.c_str(), m_data.c_str());)
00134                 // %! check cache
00135                 {
00136                         Lock lock(m_cache_mutex);
00137                         if (m_cache[m_query].find(m_data) != m_cache[m_query].end())
00138                         {
00139                                 if (time(NULL) - m_cache_to[m_query][m_data] < 3600) // ttl
00140                                 {
00141                                         std::string result = m_cache[m_query][m_data];
00142 DEB(fprintf(stderr, " *** Returning cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), result.c_str());)
00143                                         Send("Cached\n");
00144                                         if (!result.size()) /* failed */
00145                                         {
00146                                                 Send("Failed\n\n");
00147                                                 SetCloseAndDelete();
00148                                                 return;
00149                                         }
00150                                         else
00151                                         if (m_query == "gethostbyname")
00152                                         {
00153                                                 Send("A: " + result + "\n\n");
00154                                                 SetCloseAndDelete();
00155                                                 return;
00156                                         }
00157                                         else
00158 #ifdef ENABLE_IPV6
00159 #ifdef IPPROTO_IPV6
00160                                         if (m_query == "gethostbyname2")
00161                                         {
00162                                                 Send("AAAA: " + result + "\n\n");
00163                                                 SetCloseAndDelete();
00164                                                 return;
00165                                         }
00166                                         else
00167 #endif
00168 #endif
00169                                         if (m_query == "gethostbyaddr")
00170                                         {
00171                                                 Send("Name: " + result + "\n\n");
00172                                                 SetCloseAndDelete();
00173                                                 return;
00174                                         }
00175                                 }
00176                         }
00177                 }
00178                 if (!Detach()) // detach failed?
00179                 {
00180                         SetCloseAndDelete();
00181                 }
00182                 return;
00183         }
00184         std::string key = pa.getword();
00185         std::string value = pa.getrest();
00186 DEB(    fprintf(stderr, " *** ResolvSocket response;  %s: %s\n", key.c_str(), value.c_str());)
00187 
00188         if (key == "Cached")
00189         {
00190                 m_cached = true;
00191         }
00192         else
00193         if (key == "Failed" && m_parent)
00194         {
00195 DEB(            fprintf(stderr, " ************ Resolve failed\n");)
00196                 if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
00197                 {
00198                         m_parent -> OnResolveFailed(m_resolv_id);
00199                 }
00200                 // update cache
00201                 if (!m_cached)
00202                 {
00203                         Lock lock(m_cache_mutex);
00204 DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
00205                         m_cache[m_query][m_data] = value;
00206                         m_cache_to[m_query][m_data] = time(NULL);
00207                 }
00208                 m_parent = NULL;
00209         }
00210         else
00211         if (key == "Name" && !m_resolv_host.size() && m_parent)
00212         {
00213                 if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
00214                 {
00215                         m_parent -> OnReverseResolved(m_resolv_id, value);
00216                 }
00217                 // update cache
00218                 if (!m_cached)
00219                 {
00220                         Lock lock(m_cache_mutex);
00221 DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
00222                         m_cache[m_query][m_data] = value;
00223                         m_cache_to[m_query][m_data] = time(NULL);
00224                 }
00225                 m_parent = NULL;
00226         }
00227         else
00228         if (key == "A" && m_parent)
00229         {
00230                 if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
00231                 {
00232                         ipaddr_t l;
00233                         Utility::u2ip(value, l); // ip2ipaddr_t
00234                         m_parent -> OnResolved(m_resolv_id, l, m_resolv_port);
00235                 }
00236                 // update cache
00237                 if (!m_cached)
00238                 {
00239                         Lock lock(m_cache_mutex);
00240 DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
00241                         m_cache[m_query][m_data] = value;
00242                         m_cache_to[m_query][m_data] = time(NULL);
00243                 }
00244                 m_parent = NULL; // always use first ip in case there are several
00245         }
00246 #ifdef ENABLE_IPV6
00247 #ifdef IPPROTO_IPV6
00248         else
00249         if (key == "AAAA" && m_parent)
00250         {
00251                 if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
00252                 {
00253                         in6_addr a;
00254                         Utility::u2ip(value, a);
00255                         m_parent -> OnResolved(m_resolv_id, a, m_resolv_port);
00256                 }
00257                 // update cache
00258                 if (!m_cached)
00259                 {
00260                         Lock lock(m_cache_mutex);
00261 DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
00262                         m_cache[m_query][m_data] = value;
00263                         m_cache_to[m_query][m_data] = time(NULL);
00264                 }
00265                 m_parent = NULL;
00266         }
00267 #endif
00268 #endif
00269 }

void ResolvSocket::OnDetached (  )  [virtual]

Callback fires when a new socket thread has started and this socket is ready for operation again.

See also:
ResolvSocket

Reimplemented from Socket.

Definition at line 272 of file ResolvSocket.cpp.

References AI_NUMERICHOST, DEB, Socket::Handler(), Utility::isipv4(), Utility::isipv6(), Utility::l2ip(), ISocketHandler::LogError(), m_data, m_query, Utility::reverse(), TcpSocket::Send(), Socket::SetCloseAndDelete(), and Utility::u2ip().

00273 {
00274 DEB(    fprintf(stderr, " *** ResolvSocket::OnDetached(); query=%s, data=%s\n", m_query.c_str(), m_data.c_str());)
00275         if (m_query == "gethostbyname")
00276         {
00277                 struct sockaddr_in sa;
00278                 if (Utility::u2ip(m_data, sa))
00279                 {
00280                         std::string ip;
00281                         Utility::l2ip(sa.sin_addr, ip);
00282                         Send("A: " + ip + "\n");
00283                 }
00284                 else
00285                 {
00286                         Send("Failed\n");
00287                 }
00288                 Send("\n");
00289         }
00290         else
00291 #ifdef ENABLE_IPV6
00292 #ifdef IPPROTO_IPV6
00293         if (m_query == "gethostbyname2")
00294         {
00295                 struct sockaddr_in6 sa;
00296                 if (Utility::u2ip(m_data, sa))
00297                 {
00298                         std::string ip;
00299                         Utility::l2ip(sa.sin6_addr, ip);
00300                         Send("AAAA: " + ip + "\n");
00301                 }
00302                 else
00303                 {
00304                         Send("Failed\n");
00305                 }
00306                 Send("\n");
00307         }
00308         else
00309 #endif
00310 #endif
00311         if (m_query == "gethostbyaddr")
00312         {
00313                 if (Utility::isipv4( m_data ))
00314                 {
00315                         struct sockaddr_in sa;
00316                         if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST))
00317                         {
00318                                 Send("Failed: convert to sockaddr_in failed\n");
00319                         }
00320                         else
00321                         {
00322                                 std::string name;
00323                                 if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name))
00324                                 {
00325                                         Send("Failed: ipv4 reverse lookup of " + m_data + "\n");
00326                                 }
00327                                 else
00328                                 {
00329                                         Send("Name: " + name + "\n");
00330                                 }
00331                         }
00332                 }
00333                 else
00334 #ifdef ENABLE_IPV6
00335 #ifdef IPPROTO_IPV6
00336                 if (Utility::isipv6( m_data ))
00337                 {
00338                         struct sockaddr_in6 sa;
00339                         if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST))
00340                         {
00341                                 Send("Failed: convert to sockaddr_in6 failed\n");
00342                         }
00343                         else
00344                         {
00345                                 std::string name;
00346                                 if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name))
00347                                 {
00348                                         Send("Failed: ipv6 reverse lookup of " + m_data + "\n");
00349                                 }
00350                                 else
00351                                 {
00352                                         Send("Name: " + name + "\n");
00353                                 }
00354                         }
00355                 }
00356                 else
00357 #endif
00358 #endif
00359                 {
00360                         Send("Failed: malformed address\n");
00361                 }
00362                 Send("\n");
00363         }
00364         else
00365         {
00366                 std::string msg = "Unknown query type: " + m_query;
00367                 Handler().LogError(this, "OnDetached", 0, msg);
00368                 Send("Unknown\n\n");
00369         }
00370         SetCloseAndDelete();
00371 }

void ResolvSocket::OnDelete (  )  [virtual]

Called before a socket class is deleted by the ISocketHandler.

Reimplemented from Socket.

Definition at line 409 of file ResolvSocket.cpp.

References DEB, Socket::Handler(), m_cache, m_cache_mutex, m_cache_to, m_cached, m_data, m_parent, m_query, m_resolv_id, and Socket::OnResolveFailed().

00410 {
00411         if (m_parent)
00412         {
00413                 if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
00414                 {
00415                         m_parent -> OnResolveFailed(m_resolv_id);
00416                 }
00417                 // update cache
00418                 if (!m_cached)
00419                 {
00420                         Lock lock(m_cache_mutex);
00421                         std::string value;
00422 DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
00423                         m_cache[m_query][m_data] = value;
00424                         m_cache_to[m_query][m_data] = time(NULL);
00425                 }
00426                 m_parent = NULL;
00427         }
00428 }

void ResolvSocket::SetId ( int  x  )  [inline]

Definition at line 66 of file ResolvSocket.h.

00066 { m_resolv_id = x; }

int ResolvSocket::GetId (  )  [inline]

Definition at line 67 of file ResolvSocket.h.

00067 { return m_resolv_id; }

void ResolvSocket::OnConnect (  )  [virtual]

Called when a connection has completed.

Reimplemented from Socket.

Definition at line 374 of file ResolvSocket.cpp.

References Utility::l2ip(), m_data, m_query, m_resolv_address, m_resolv_host, and TcpSocket::Send().

00375 {
00376         if (m_resolv_host.size())
00377         {
00378 #ifdef ENABLE_IPV6
00379                 std::string msg = (m_resolve_ipv6 ? "gethostbyname2 " : "gethostbyname ") + m_resolv_host + "\n";
00380                 m_query = m_resolve_ipv6 ? "gethostbyname2" : "gethostbyname";
00381 #else
00382                 std::string msg = "gethostbyname " + m_resolv_host + "\n";
00383                 m_query = "gethostbyname";
00384 #endif
00385                 m_data = m_resolv_host;
00386                 Send( msg );
00387                 return;
00388         }
00389 #ifdef ENABLE_IPV6
00390         if (m_resolve_ipv6)
00391         {
00392                 std::string tmp;
00393                 Utility::l2ip(m_resolv_address6, tmp);
00394                 m_query = "gethostbyaddr";
00395                 m_data = tmp;
00396                 std::string msg = "gethostbyaddr " + tmp + "\n";
00397                 Send( msg );
00398         }
00399 #endif
00400         std::string tmp;
00401         Utility::l2ip(m_resolv_address, tmp);
00402         m_query = "gethostbyaddr";
00403         m_data = tmp;
00404         std::string msg = "gethostbyaddr " + tmp + "\n";
00405         Send( msg );
00406 }

ResolvSocket& ResolvSocket::operator= ( const ResolvSocket  )  [inline, private]

Definition at line 77 of file ResolvSocket.h.

00077 { return *this; } // assignment operator


Member Data Documentation

std::string ResolvSocket::m_query [private]

Definition at line 79 of file ResolvSocket.h.

Referenced by OnConnect(), OnDelete(), OnDetached(), and OnLine().

std::string ResolvSocket::m_data [private]

Definition at line 80 of file ResolvSocket.h.

Referenced by OnConnect(), OnDelete(), OnDetached(), and OnLine().

bool ResolvSocket::m_bServer [private]

Definition at line 81 of file ResolvSocket.h.

Referenced by OnLine().

Pointer to ListenSocket class, valid for incoming sockets.

Reimplemented from Socket.

Definition at line 82 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

Definition at line 83 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

std::string ResolvSocket::m_resolv_host [private]

Definition at line 84 of file ResolvSocket.h.

Referenced by OnConnect(), and OnLine().

Definition at line 85 of file ResolvSocket.h.

Referenced by OnLine().

Definition at line 86 of file ResolvSocket.h.

Referenced by OnConnect().

Definition at line 91 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

Definition at line 92 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

Definition at line 93 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

bool ResolvSocket::m_cached [private]

Definition at line 94 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().


The documentation for this class was generated from the following files:
Page, code, and content Copyright (C) 2007 by Anders Hedström
Generated for C++ Sockets by  doxygen 1.4.4