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.
socketuid_t m_parent_uid
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 47 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 50 of file ResolvSocket.h.

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

Definition at line 52 of file ResolvSocket.h.


Constructor & Destructor Documentation

ResolvSocket::ResolvSocket ( ISocketHandler h  ) 

Definition at line 65 of file ResolvSocket.cpp.

References TcpSocket::SetLineProtocol().

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

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

Definition at line 79 of file ResolvSocket.cpp.

References TcpSocket::SetLineProtocol().

00080 :TcpSocket(h)
00081 ,m_bServer(false)
00082 ,m_parent(parent)
00083 ,m_parent_uid(parent -> UniqueIdentifier())
00084 ,m_resolv_host(host)
00085 ,m_resolv_port(port)
00086 #ifdef ENABLE_IPV6
00087 ,m_resolve_ipv6(ipv6)
00088 #endif
00089 ,m_cached(false)
00090 {
00091         SetLineProtocol();
00092 }

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

Definition at line 95 of file ResolvSocket.cpp.

References TcpSocket::SetLineProtocol().

00096 :TcpSocket(h)
00097 ,m_bServer(false)
00098 ,m_parent(parent)
00099 ,m_parent_uid(parent -> UniqueIdentifier())
00100 ,m_resolv_port(0)
00101 ,m_resolv_address(a)
00102 #ifdef ENABLE_IPV6
00103 ,m_resolve_ipv6(false)
00104 #endif
00105 ,m_cached(false)
00106 {
00107         SetLineProtocol();
00108 }

ResolvSocket::~ResolvSocket (  ) 

Definition at line 127 of file ResolvSocket.cpp.

00128 {
00129 }

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

Definition at line 78 of file ResolvSocket.h.

00078 : 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 63 of file ResolvSocket.h.

00063 { 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 132 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_parent_uid, 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().

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

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 278 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().

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

void ResolvSocket::OnDelete (  )  [virtual]

Called before a socket class is deleted by the ISocketHandler.

Reimplemented from Socket.

Definition at line 415 of file ResolvSocket.cpp.

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

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

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

Definition at line 68 of file ResolvSocket.h.

00068 { m_resolv_id = x; }

int ResolvSocket::GetId (  )  [inline]

Definition at line 69 of file ResolvSocket.h.

00069 { return m_resolv_id; }

void ResolvSocket::OnConnect (  )  [virtual]

Called when a connection has completed.

Reimplemented from Socket.

Definition at line 380 of file ResolvSocket.cpp.

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

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

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

Definition at line 79 of file ResolvSocket.h.

00079 { return *this; } // assignment operator


Member Data Documentation

std::string ResolvSocket::m_query [private]

Definition at line 81 of file ResolvSocket.h.

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

std::string ResolvSocket::m_data [private]

Definition at line 82 of file ResolvSocket.h.

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

bool ResolvSocket::m_bServer [private]

Definition at line 83 of file ResolvSocket.h.

Referenced by OnLine().

Pointer to ListenSocket class, valid for incoming sockets.

Reimplemented from Socket.

Definition at line 84 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

Definition at line 85 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

Definition at line 86 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

std::string ResolvSocket::m_resolv_host [private]

Definition at line 87 of file ResolvSocket.h.

Referenced by OnConnect(), and OnLine().

Definition at line 88 of file ResolvSocket.h.

Referenced by OnLine().

Definition at line 89 of file ResolvSocket.h.

Referenced by OnConnect().

Definition at line 94 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

Definition at line 95 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

Definition at line 96 of file ResolvSocket.h.

Referenced by OnDelete(), and OnLine().

bool ResolvSocket::m_cached [private]

Definition at line 97 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