PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/dep/src/sockets/ResolvSocket.cpp

https://bitbucket.org/oregon/oregoncore/
C++ | 437 lines | 369 code | 28 blank | 40 comment | 59 complexity | e43ae0dbc9f906d767797daafba2399e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, CC-BY-SA-3.0, BSD-2-Clause
  1. /** \file ResolvSocket.cpp
  2. ** \date 2005-03-24
  3. ** \author grymse@alhem.net
  4. **/
  5. /*
  6. Copyright (C) 2004-2007 Anders Hedstrom
  7. This library is made available under the terms of the GNU GPL.
  8. If you would like to use this library in a closed-source application,
  9. a separate license agreement is available. For information about
  10. the closed-source license agreement for the C++ sockets library,
  11. please visit http://www.alhem.net/Sockets/license.html and/or
  12. email license@alhem.net.
  13. This program is free software; you can redistribute it and/or
  14. modify it under the terms of the GNU General Public License
  15. as published by the Free Software Foundation; either version 2
  16. of the License, or (at your option) any later version.
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. GNU General Public License for more details.
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24. */
  25. #ifdef _WIN32
  26. #ifdef _MSC_VER
  27. #pragma warning(disable:4786)
  28. #pragma warning(disable:4503)
  29. #endif
  30. #else
  31. #include <netdb.h>
  32. #endif
  33. #include "ResolvSocket.h"
  34. #ifdef ENABLE_RESOLVER
  35. #include "Utility.h"
  36. #include "Parse.h"
  37. #include "ISocketHandler.h"
  38. #include "Lock.h"
  39. #include "Mutex.h"
  40. #ifdef SOCKETS_NAMESPACE
  41. namespace SOCKETS_NAMESPACE {
  42. #endif
  43. //#ifdef _DEBUG
  44. //#define DEB(x) x
  45. //#else
  46. #define DEB(x)
  47. //#endif
  48. // static
  49. ResolvSocket::cache_t ResolvSocket::m_cache;
  50. ResolvSocket::timeout_t ResolvSocket::m_cache_to;
  51. Mutex ResolvSocket::m_cache_mutex;
  52. ResolvSocket::ResolvSocket(ISocketHandler& h)
  53. :TcpSocket(h)
  54. ,m_bServer(false)
  55. ,m_parent(NULL)
  56. #ifdef ENABLE_IPV6
  57. ,m_resolve_ipv6(false)
  58. #endif
  59. ,m_cached(false)
  60. {
  61. SetLineProtocol();
  62. }
  63. ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, const std::string& host, port_t port, bool ipv6)
  64. :TcpSocket(h)
  65. ,m_bServer(false)
  66. ,m_parent(parent)
  67. ,m_resolv_host(host)
  68. ,m_resolv_port(port)
  69. #ifdef ENABLE_IPV6
  70. ,m_resolve_ipv6(ipv6)
  71. #endif
  72. ,m_cached(false)
  73. {
  74. SetLineProtocol();
  75. }
  76. ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, ipaddr_t a)
  77. :TcpSocket(h)
  78. ,m_bServer(false)
  79. ,m_parent(parent)
  80. ,m_resolv_port(0)
  81. ,m_resolv_address(a)
  82. #ifdef ENABLE_IPV6
  83. ,m_resolve_ipv6(false)
  84. #endif
  85. ,m_cached(false)
  86. {
  87. SetLineProtocol();
  88. }
  89. #ifdef ENABLE_IPV6
  90. ResolvSocket::ResolvSocket(ISocketHandler& h, Socket *parent, in6_addr& a)
  91. :TcpSocket(h)
  92. ,m_bServer(false)
  93. ,m_parent(parent)
  94. ,m_resolv_port(0)
  95. ,m_resolve_ipv6(true)
  96. ,m_resolv_address6(a)
  97. ,m_cached(false)
  98. {
  99. SetLineProtocol();
  100. }
  101. #endif
  102. ResolvSocket::~ResolvSocket()
  103. {
  104. }
  105. void ResolvSocket::OnLine(const std::string& line)
  106. {
  107. Parse pa(line, ":");
  108. if (m_bServer)
  109. {
  110. m_query = pa.getword();
  111. m_data = pa.getrest();
  112. DEB( fprintf(stderr, " *** ResolvSocket server; query=%s, data=%s\n", m_query.c_str(), m_data.c_str());)
  113. // %! check cache
  114. {
  115. Lock lock(m_cache_mutex);
  116. if (m_cache[m_query].find(m_data) != m_cache[m_query].end())
  117. {
  118. if (time(NULL) - m_cache_to[m_query][m_data] < 3600) // ttl
  119. {
  120. std::string result = m_cache[m_query][m_data];
  121. DEB(fprintf(stderr, " *** Returning cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), result.c_str());)
  122. Send("Cached\n");
  123. if (!result.size()) /* failed */
  124. {
  125. Send("Failed\n\n");
  126. SetCloseAndDelete();
  127. return;
  128. }
  129. else
  130. if (m_query == "gethostbyname")
  131. {
  132. Send("A: " + result + "\n\n");
  133. SetCloseAndDelete();
  134. return;
  135. }
  136. else
  137. #ifdef ENABLE_IPV6
  138. #ifdef IPPROTO_IPV6
  139. if (m_query == "gethostbyname2")
  140. {
  141. Send("AAAA: " + result + "\n\n");
  142. SetCloseAndDelete();
  143. return;
  144. }
  145. else
  146. #endif
  147. #endif
  148. if (m_query == "gethostbyaddr")
  149. {
  150. Send("Name: " + result + "\n\n");
  151. SetCloseAndDelete();
  152. return;
  153. }
  154. }
  155. }
  156. }
  157. if (!Detach()) // detach failed?
  158. {
  159. SetCloseAndDelete();
  160. }
  161. return;
  162. }
  163. std::string key = pa.getword();
  164. std::string value = pa.getrest();
  165. DEB( fprintf(stderr, " *** ResolvSocket response; %s: %s\n", key.c_str(), value.c_str());)
  166. if (key == "Cached")
  167. {
  168. m_cached = true;
  169. }
  170. else
  171. if (key == "Failed" && m_parent)
  172. {
  173. DEB( fprintf(stderr, " ************ Resolve failed\n");)
  174. if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
  175. {
  176. m_parent -> OnResolveFailed(m_resolv_id);
  177. }
  178. // update cache
  179. if (!m_cached)
  180. {
  181. Lock lock(m_cache_mutex);
  182. DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
  183. m_cache[m_query][m_data] = value;
  184. m_cache_to[m_query][m_data] = time(NULL);
  185. }
  186. m_parent = NULL;
  187. }
  188. else
  189. if (key == "Name" && !m_resolv_host.size() && m_parent)
  190. {
  191. if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
  192. {
  193. m_parent -> OnReverseResolved(m_resolv_id, value);
  194. }
  195. // update cache
  196. if (!m_cached)
  197. {
  198. Lock lock(m_cache_mutex);
  199. DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
  200. m_cache[m_query][m_data] = value;
  201. m_cache_to[m_query][m_data] = time(NULL);
  202. }
  203. m_parent = NULL;
  204. }
  205. else
  206. if (key == "A" && m_parent)
  207. {
  208. if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
  209. {
  210. ipaddr_t l;
  211. Utility::u2ip(value, l); // ip2ipaddr_t
  212. m_parent -> OnResolved(m_resolv_id, l, m_resolv_port);
  213. }
  214. // update cache
  215. if (!m_cached)
  216. {
  217. Lock lock(m_cache_mutex);
  218. DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
  219. m_cache[m_query][m_data] = value;
  220. m_cache_to[m_query][m_data] = time(NULL);
  221. }
  222. m_parent = NULL; // always use first ip in case there are several
  223. }
  224. #ifdef ENABLE_IPV6
  225. #ifdef IPPROTO_IPV6
  226. else
  227. if (key == "AAAA" && m_parent)
  228. {
  229. if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
  230. {
  231. in6_addr a;
  232. Utility::u2ip(value, a);
  233. m_parent -> OnResolved(m_resolv_id, a, m_resolv_port);
  234. }
  235. // update cache
  236. if (!m_cached)
  237. {
  238. Lock lock(m_cache_mutex);
  239. DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
  240. m_cache[m_query][m_data] = value;
  241. m_cache_to[m_query][m_data] = time(NULL);
  242. }
  243. m_parent = NULL;
  244. }
  245. #endif
  246. #endif
  247. }
  248. void ResolvSocket::OnDetached()
  249. {
  250. DEB( fprintf(stderr, " *** ResolvSocket::OnDetached(); query=%s, data=%s\n", m_query.c_str(), m_data.c_str());)
  251. if (m_query == "gethostbyname")
  252. {
  253. struct sockaddr_in sa;
  254. if (Utility::u2ip(m_data, sa))
  255. {
  256. std::string ip;
  257. Utility::l2ip(sa.sin_addr, ip);
  258. Send("A: " + ip + "\n");
  259. }
  260. else
  261. {
  262. Send("Failed\n");
  263. }
  264. Send("\n");
  265. }
  266. else
  267. #ifdef ENABLE_IPV6
  268. #ifdef IPPROTO_IPV6
  269. if (m_query == "gethostbyname2")
  270. {
  271. struct sockaddr_in6 sa;
  272. if (Utility::u2ip(m_data, sa))
  273. {
  274. std::string ip;
  275. Utility::l2ip(sa.sin6_addr, ip);
  276. Send("AAAA: " + ip + "\n");
  277. }
  278. else
  279. {
  280. Send("Failed\n");
  281. }
  282. Send("\n");
  283. }
  284. else
  285. #endif
  286. #endif
  287. if (m_query == "gethostbyaddr")
  288. {
  289. if (Utility::isipv4( m_data ))
  290. {
  291. struct sockaddr_in sa;
  292. if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST))
  293. {
  294. Send("Failed: convert to sockaddr_in failed\n");
  295. }
  296. else
  297. {
  298. std::string name;
  299. if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name))
  300. {
  301. Send("Failed: ipv4 reverse lookup of " + m_data + "\n");
  302. }
  303. else
  304. {
  305. Send("Name: " + name + "\n");
  306. }
  307. }
  308. }
  309. else
  310. #ifdef ENABLE_IPV6
  311. #ifdef IPPROTO_IPV6
  312. if (Utility::isipv6( m_data ))
  313. {
  314. struct sockaddr_in6 sa;
  315. if (!Utility::u2ip(m_data, sa, AI_NUMERICHOST))
  316. {
  317. Send("Failed: convert to sockaddr_in6 failed\n");
  318. }
  319. else
  320. {
  321. std::string name;
  322. if (!Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), name))
  323. {
  324. Send("Failed: ipv6 reverse lookup of " + m_data + "\n");
  325. }
  326. else
  327. {
  328. Send("Name: " + name + "\n");
  329. }
  330. }
  331. }
  332. else
  333. #endif
  334. #endif
  335. {
  336. Send("Failed: malformed address\n");
  337. }
  338. Send("\n");
  339. }
  340. else
  341. {
  342. std::string msg = "Unknown query type: " + m_query;
  343. Handler().LogError(this, "OnDetached", 0, msg);
  344. Send("Unknown\n\n");
  345. }
  346. SetCloseAndDelete();
  347. }
  348. void ResolvSocket::OnConnect()
  349. {
  350. if (!m_resolv_host.empty())
  351. {
  352. #ifdef ENABLE_IPV6
  353. std::string msg = (m_resolve_ipv6 ? "gethostbyname2 " : "gethostbyname ") + m_resolv_host + "\n";
  354. m_query = m_resolve_ipv6 ? "gethostbyname2" : "gethostbyname";
  355. #else
  356. std::string msg = "gethostbyname " + m_resolv_host + "\n";
  357. m_query = "gethostbyname";
  358. #endif
  359. m_data = m_resolv_host;
  360. Send( msg );
  361. return;
  362. }
  363. #ifdef ENABLE_IPV6
  364. if (m_resolve_ipv6)
  365. {
  366. std::string tmp;
  367. Utility::l2ip(m_resolv_address6, tmp);
  368. m_query = "gethostbyaddr";
  369. m_data = tmp;
  370. std::string msg = "gethostbyaddr " + tmp + "\n";
  371. Send( msg );
  372. }
  373. #endif
  374. std::string tmp;
  375. Utility::l2ip(m_resolv_address, tmp);
  376. m_query = "gethostbyaddr";
  377. m_data = tmp;
  378. std::string msg = "gethostbyaddr " + tmp + "\n";
  379. Send( msg );
  380. }
  381. void ResolvSocket::OnDelete()
  382. {
  383. if (m_parent)
  384. {
  385. if (Handler().Resolving(m_parent) || Handler().Valid(m_parent))
  386. {
  387. m_parent -> OnResolveFailed(m_resolv_id);
  388. }
  389. // update cache
  390. if (!m_cached)
  391. {
  392. Lock lock(m_cache_mutex);
  393. std::string value;
  394. DEB(fprintf(stderr, " *** Update cache for [%s][%s] = '%s'\n", m_query.c_str(), m_data.c_str(), value.c_str());)
  395. m_cache[m_query][m_data] = value;
  396. m_cache_to[m_query][m_data] = time(NULL);
  397. }
  398. m_parent = NULL;
  399. }
  400. }
  401. #ifdef SOCKETS_NAMESPACE
  402. }
  403. #endif
  404. #endif // ENABLE_RESOLVER