PageRenderTime 32ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/mordor/socket.cpp

https://github.com/llvm-djk/mordor
C++ | 2001 lines | 1846 code | 121 blank | 34 comment | 415 complexity | b8ee32b4c0b6e78b27938283a2ba9ed3 MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. // Copyright (c) 2009 - Mozy, Inc.
  2. #include "socket.h"
  3. #include <boost/bind.hpp>
  4. #include <boost/thread/once.hpp>
  5. #include "assert.h"
  6. #include "fiber.h"
  7. #include "iomanager.h"
  8. #include "string.h"
  9. #include "version.h"
  10. #include "mordor/config.h"
  11. #ifdef WINDOWS
  12. #include <mswsock.h>
  13. #include <IPHlpApi.h>
  14. #include "runtime_linking.h"
  15. #pragma comment(lib, "ws2_32")
  16. #pragma comment(lib, "mswsock")
  17. #pragma comment(lib, "iphlpapi")
  18. #else
  19. #include <arpa/inet.h>
  20. #include <fcntl.h>
  21. #include <ifaddrs.h>
  22. #include <netdb.h>
  23. #define closesocket close
  24. #endif
  25. namespace Mordor {
  26. #ifdef WINDOWS
  27. static ConfigVar<bool>::ptr g_useConnectEx =
  28. Config::lookup("socket.useconnectex", true, "Use WinSock2 ConnectEx API when available");
  29. static ConfigVar<bool>::ptr g_useAcceptEx =
  30. Config::lookup("socket.useacceptex", true, "Use WinSock2 AcceptEx API when available");
  31. #endif
  32. namespace {
  33. enum Family
  34. {
  35. UNSPECIFIED = AF_UNSPEC,
  36. IP4 = AF_INET,
  37. IP6 = AF_INET6
  38. };
  39. enum Type
  40. {
  41. STREAM = SOCK_STREAM,
  42. DATAGRAM = SOCK_DGRAM
  43. };
  44. enum Protocol
  45. {
  46. ANY = 0,
  47. TCP = IPPROTO_TCP,
  48. UDP = IPPROTO_UDP
  49. };
  50. std::ostream &operator <<(std::ostream &os, Family family)
  51. {
  52. switch (family)
  53. {
  54. case UNSPECIFIED:
  55. return os << "AF_UNSPEC";
  56. case IP4:
  57. return os << "AF_INET";
  58. case IP6:
  59. return os << "AF_INET6";
  60. default:
  61. return os << (int)family;
  62. }
  63. }
  64. std::ostream &operator <<(std::ostream &os, Type type)
  65. {
  66. switch (type)
  67. {
  68. case STREAM:
  69. return os << "SOCK_STREAM";
  70. case DATAGRAM:
  71. return os << "SOCK_DGRAM";
  72. default:
  73. return os << (int)type;
  74. }
  75. }
  76. std::ostream &operator <<(std::ostream &os, Protocol protocol)
  77. {
  78. switch (protocol)
  79. {
  80. case TCP:
  81. return os << "IPPROTO_TCP";
  82. case UDP:
  83. return os << "IPPROTO_UDP";
  84. default:
  85. return os << (int)protocol;
  86. }
  87. }
  88. }
  89. #ifdef WINDOWS
  90. static LPFN_ACCEPTEX pAcceptEx = 0;
  91. static LPFN_GETACCEPTEXSOCKADDRS pGetAcceptExSockaddrs = 0;
  92. static LPFN_CONNECTEX ConnectEx = 0;
  93. namespace {
  94. static struct Initializer {
  95. Initializer()
  96. {
  97. WSADATA wd;
  98. WSAStartup(MAKEWORD(2,2), &wd);
  99. socket_t sock = socket(AF_INET, SOCK_STREAM, 0);
  100. DWORD bytes = 0;
  101. GUID acceptExGuid = WSAID_ACCEPTEX;
  102. WSAIoctl(sock,
  103. SIO_GET_EXTENSION_FUNCTION_POINTER,
  104. &acceptExGuid,
  105. sizeof(GUID),
  106. &pAcceptEx,
  107. sizeof(LPFN_ACCEPTEX),
  108. &bytes,
  109. NULL,
  110. NULL);
  111. GUID getAcceptExSockaddrsGuid = WSAID_GETACCEPTEXSOCKADDRS;
  112. WSAIoctl(sock,
  113. SIO_GET_EXTENSION_FUNCTION_POINTER,
  114. &getAcceptExSockaddrsGuid,
  115. sizeof(GUID),
  116. &pGetAcceptExSockaddrs,
  117. sizeof(LPFN_GETACCEPTEXSOCKADDRS),
  118. &bytes,
  119. NULL,
  120. NULL);
  121. GUID connectExGuid = WSAID_CONNECTEX;
  122. WSAIoctl(sock,
  123. SIO_GET_EXTENSION_FUNCTION_POINTER,
  124. &connectExGuid,
  125. sizeof(GUID),
  126. &ConnectEx,
  127. sizeof(LPFN_CONNECTEX),
  128. &bytes,
  129. NULL,
  130. NULL);
  131. closesocket(sock);
  132. }
  133. ~Initializer()
  134. {
  135. WSACleanup();
  136. }
  137. } g_init;
  138. }
  139. #endif
  140. static Logger::ptr g_log = Log::lookup("mordor:socket");
  141. static int g_iosPortIndex;
  142. namespace {
  143. static struct IOSInitializer {
  144. IOSInitializer()
  145. {
  146. g_iosPortIndex = std::ios_base::xalloc();
  147. }
  148. } g_iosInit;
  149. }
  150. Socket::Socket(IOManager *ioManager, int family, int type, int protocol, int initialize)
  151. : m_sock(-1),
  152. m_family(family),
  153. m_protocol(protocol),
  154. m_ioManager(ioManager),
  155. m_receiveTimeout(~0ull),
  156. m_sendTimeout(~0ull),
  157. m_cancelledSend(0),
  158. m_cancelledReceive(0),
  159. #ifdef WINDOWS
  160. m_hEvent(NULL),
  161. m_scheduler(NULL),
  162. #endif
  163. m_isConnected(false),
  164. m_isRegisteredForRemoteClose(false)
  165. {
  166. // Windows accepts type == 0 as implying SOCK_STREAM; other OS's aren't so
  167. // lenient
  168. MORDOR_ASSERT(type != 0);
  169. #ifdef WINDOWS
  170. m_useAcceptEx = g_useAcceptEx->val(); //remember the setting for the entire life of the socket
  171. m_useConnectEx = g_useConnectEx->val(); //in case it is changed in the registry
  172. if (m_useAcceptEx && pAcceptEx && m_ioManager) {
  173. m_sock = socket(family, type, protocol);
  174. MORDOR_LOG_LEVEL(g_log, m_sock == -1 ? Log::ERROR : Log::DEBUG) << this
  175. << " socket(" << (Family)family << ", " << (Type)type << ", "
  176. << (Protocol)protocol << "): " << m_sock << " (" << lastError()
  177. << ")";
  178. if (m_sock == -1)
  179. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("socket");
  180. }
  181. #endif
  182. }
  183. Socket::Socket(int family, int type, int protocol)
  184. : m_sock(-1),
  185. m_family(family),
  186. m_protocol(protocol),
  187. m_ioManager(NULL),
  188. m_isConnected(false),
  189. m_isRegisteredForRemoteClose(false)
  190. {
  191. #ifdef WINDOWS
  192. m_useAcceptEx = g_useAcceptEx->val(); //remember the setting for the entire life of the socket
  193. m_useConnectEx = g_useConnectEx->val(); //in case it is changed in the registry
  194. #endif
  195. // Windows accepts type == 0 as implying SOCK_STREAM; other OS's aren't so
  196. // lenient
  197. MORDOR_ASSERT(type != 0);
  198. m_sock = socket(family, type, protocol);
  199. MORDOR_LOG_DEBUG(g_log) << this << " socket(" << (Family)family << ", "
  200. << (Type)type << ", " << (Protocol)protocol << "): " << m_sock << " ("
  201. << lastError() << ")";
  202. if (m_sock == -1)
  203. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("socket");
  204. #ifdef OSX
  205. unsigned int opt = 1;
  206. if (setsockopt(m_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)) == -1) {
  207. ::closesocket(m_sock);
  208. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("setsockopt");
  209. }
  210. #endif
  211. }
  212. Socket::Socket(IOManager &ioManager, int family, int type, int protocol)
  213. : m_sock(-1),
  214. m_family(family),
  215. m_protocol(protocol),
  216. m_ioManager(&ioManager),
  217. m_receiveTimeout(~0ull),
  218. m_sendTimeout(~0ull),
  219. m_cancelledSend(0),
  220. m_cancelledReceive(0),
  221. #ifdef WINDOWS
  222. m_hEvent(NULL),
  223. m_scheduler(NULL),
  224. #endif
  225. m_isConnected(false),
  226. m_isRegisteredForRemoteClose(false)
  227. {
  228. #ifdef WINDOWS
  229. m_useAcceptEx = g_useAcceptEx->val(); //remember the setting for the entire life of the socket
  230. m_useConnectEx = g_useConnectEx->val(); //in case it is changed in the registry
  231. #endif
  232. // Windows accepts type == 0 as implying SOCK_STREAM; other OS's aren't so
  233. // lenient
  234. MORDOR_ASSERT(type != 0);
  235. m_sock = socket(family, type, protocol);
  236. MORDOR_LOG_DEBUG(g_log) << this << " socket(" << (Family)family << ", "
  237. << (Type)type << ", " << (Protocol)protocol << "): " << m_sock << " ("
  238. << lastError() << ")";
  239. if (m_sock == -1)
  240. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("socket");
  241. #ifdef WINDOWS
  242. try {
  243. m_ioManager->registerFile((HANDLE)m_sock);
  244. m_skipCompletionPortOnSuccess =
  245. !!pSetFileCompletionNotificationModes((HANDLE)m_sock,
  246. FILE_SKIP_COMPLETION_PORT_ON_SUCCESS |
  247. FILE_SKIP_SET_EVENT_ON_HANDLE);
  248. } catch(...) {
  249. closesocket(m_sock);
  250. throw;
  251. }
  252. #else
  253. if (fcntl(m_sock, F_SETFL, O_NONBLOCK) == -1) {
  254. ::closesocket(m_sock);
  255. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("fcntl");
  256. }
  257. #endif
  258. #ifdef OSX
  259. unsigned int opt = 1;
  260. if (setsockopt(m_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)) == -1) {
  261. ::closesocket(m_sock);
  262. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("setsockopt");
  263. }
  264. #endif
  265. }
  266. Socket::~Socket()
  267. {
  268. #ifdef WINDOWS
  269. if (m_ioManager && m_hEvent) {
  270. if (m_isRegisteredForRemoteClose) {
  271. m_ioManager->unregisterEvent(m_hEvent);
  272. WSAEventSelect(m_sock, m_hEvent, 0);
  273. }
  274. CloseHandle(m_hEvent);
  275. }
  276. #else
  277. if (m_isRegisteredForRemoteClose)
  278. m_ioManager->unregisterEvent(m_sock, IOManager::CLOSE);
  279. #endif
  280. if (m_sock != -1) {
  281. int rc = ::closesocket(m_sock);
  282. if (rc) {
  283. MORDOR_LOG_ERROR(g_log) << this << " close(" << m_sock << "): ("
  284. << lastError() << ")";
  285. } else {
  286. MORDOR_LOG_INFO(g_log) << this << " close(" << m_sock << ")";
  287. }
  288. }
  289. }
  290. void
  291. Socket::bind(const Address &addr)
  292. {
  293. MORDOR_ASSERT(addr.family() == m_family);
  294. if (::bind(m_sock, addr.name(), addr.nameLen())) {
  295. error_t error = lastError();
  296. MORDOR_LOG_ERROR(g_log) << this << " bind(" << m_sock << ", " << addr
  297. << "): (" << error << ")";
  298. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "bind");
  299. }
  300. MORDOR_LOG_DEBUG(g_log) << this << " bind(" << m_sock << ", " << addr << ")";
  301. localAddress();
  302. }
  303. void
  304. Socket::bind(Address::ptr addr)
  305. {
  306. bind(*addr);
  307. }
  308. void
  309. Socket::connect(const Address &to)
  310. {
  311. MORDOR_ASSERT(to.family() == m_family);
  312. if (!m_ioManager) {
  313. if (::connect(m_sock, to.name(), to.nameLen())) {
  314. MORDOR_LOG_ERROR(g_log) << this << " connect(" << m_sock << ", "
  315. << to << "): (" << lastError() << ")";
  316. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("connect");
  317. }
  318. MORDOR_LOG_INFO(g_log) << this << " connect(" << m_sock << ", "
  319. << to << ") local: " << *(localAddress());
  320. } else {
  321. #ifdef WINDOWS
  322. if (m_useConnectEx && ConnectEx) {
  323. if (!m_localAddress) {
  324. // need to be bound, even to ADDR_ANY, before calling ConnectEx
  325. switch (m_family) {
  326. case AF_INET:
  327. {
  328. sockaddr_in addr;
  329. addr.sin_family = AF_INET;
  330. addr.sin_port = 0;
  331. addr.sin_addr.s_addr = ADDR_ANY;
  332. if(::bind(m_sock, (sockaddr*)&addr, sizeof(sockaddr_in))) {
  333. MORDOR_LOG_ERROR(g_log) << this << " bind(" << m_sock
  334. << ", 0.0.0.0:0): (" << lastError() << ")";
  335. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("bind");
  336. }
  337. MORDOR_LOG_DEBUG(g_log) << this << " bind(" << m_sock
  338. << ", 0.0.0.0:0)";
  339. break;
  340. }
  341. case AF_INET6:
  342. {
  343. sockaddr_in6 addr;
  344. memset(&addr, 0, sizeof(sockaddr_in6));
  345. addr.sin6_family = AF_INET6;
  346. addr.sin6_port = 0;
  347. in6_addr anyaddr = IN6ADDR_ANY_INIT;
  348. addr.sin6_addr = anyaddr;
  349. if(::bind(m_sock, (sockaddr*)&addr, sizeof(sockaddr_in6))) {
  350. MORDOR_LOG_ERROR(g_log) << this << " bind(" << m_sock
  351. << ", [::]:0): (" << lastError() << ")";
  352. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("bind");
  353. }
  354. MORDOR_LOG_DEBUG(g_log) << this << " bind(" << m_sock
  355. << ", [::]:0)";
  356. break;
  357. }
  358. default:
  359. MORDOR_NOTREACHED();
  360. }
  361. }
  362. m_ioManager->registerEvent(&m_sendEvent);
  363. BOOL bRet = ConnectEx(m_sock, to.name(), to.nameLen(), NULL, 0, NULL, &m_sendEvent.overlapped);
  364. if (!bRet && lastError() != WSA_IO_PENDING) {
  365. if (lastError() == WSAEINVAL) {
  366. m_ioManager->unregisterEvent(&m_sendEvent);
  367. // Some LSPs are *borken* (I'm looking at you, bmnet.dll),
  368. // and don't properly support ConnectEx (and AcceptEx). In
  369. // that case, go to how we work on Windows 2000 without
  370. // ConnectEx at all
  371. goto suckylsp;
  372. }
  373. MORDOR_LOG_ERROR(g_log) << this << " ConnectEx(" << m_sock
  374. << ", " << to << "): (" << lastError() << ")";
  375. m_ioManager->unregisterEvent(&m_sendEvent);
  376. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("ConnectEx");
  377. }
  378. if (m_skipCompletionPortOnSuccess && bRet) {
  379. m_ioManager->unregisterEvent(&m_sendEvent);
  380. m_sendEvent.overlapped.Internal = STATUS_SUCCESS;
  381. } else {
  382. if (m_cancelledSend) {
  383. MORDOR_LOG_ERROR(g_log) << this << " ConnectEx(" << m_sock << ", " << to
  384. << "): (" << m_cancelledSend << ")";
  385. m_ioManager->cancelEvent((HANDLE)m_sock, &m_sendEvent);
  386. Scheduler::yieldTo();
  387. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledSend, "ConnectEx");
  388. }
  389. Timer::ptr timeout;
  390. if (m_sendTimeout != ~0ull)
  391. timeout = m_ioManager->registerTimer(m_sendTimeout, boost::bind(
  392. &IOManager::cancelEvent, m_ioManager, (HANDLE)m_sock, &m_sendEvent));
  393. Scheduler::yieldTo();
  394. if (timeout)
  395. timeout->cancel();
  396. }
  397. error_t error = pRtlNtStatusToDosError((NTSTATUS)m_sendEvent.overlapped.Internal);
  398. if (error == ERROR_OPERATION_ABORTED &&
  399. m_cancelledSend != ERROR_OPERATION_ABORTED)
  400. error = WSAETIMEDOUT;
  401. // WTF, Windows!?
  402. if (error == ERROR_SEM_TIMEOUT)
  403. error = WSAETIMEDOUT;
  404. if (error) {
  405. MORDOR_LOG_ERROR(g_log) << this << " ConnectEx(" << m_sock
  406. << ", " << to << "): (" << error << ")";
  407. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "ConnectEx");
  408. }
  409. MORDOR_LOG_INFO(g_log) << this << " connectEX(" << m_sock << ", "
  410. << to << ") local: " << *(localAddress());
  411. setOption(SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
  412. } else {
  413. suckylsp:
  414. if (!m_hEvent) {
  415. m_hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
  416. if (!m_hEvent)
  417. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CreateEventW");
  418. }
  419. if (WSAEventSelect(m_sock, m_hEvent, FD_CONNECT))
  420. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WSAEventSelect");
  421. if (!::connect(m_sock, to.name(), to.nameLen())) {
  422. MORDOR_LOG_INFO(g_log) << this << " connectEX(" << m_sock << ", "
  423. << to << ") local: " << *(localAddress());
  424. // Worked first time
  425. return;
  426. }
  427. if (lastError() == WSAEWOULDBLOCK) {
  428. m_ioManager->registerEvent(m_hEvent);
  429. m_fiber = Fiber::getThis();
  430. m_scheduler = Scheduler::getThis();
  431. m_unregistered = false;
  432. if (m_cancelledSend) {
  433. MORDOR_LOG_ERROR(g_log) << this << " connect(" << m_sock << ", " << to
  434. << "): (" << m_cancelledSend << ")";
  435. if (!m_ioManager->unregisterEvent(m_hEvent))
  436. Scheduler::yieldTo();
  437. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledSend, "connect");
  438. }
  439. Timer::ptr timeout;
  440. if (m_sendTimeout != ~0ull)
  441. timeout = m_ioManager->registerConditionTimer(m_sendTimeout,
  442. boost::bind(&Socket::cancelIo, this,
  443. boost::ref(m_cancelledSend), WSAETIMEDOUT),
  444. weak_ptr(shared_from_this()));
  445. Scheduler::yieldTo();
  446. m_fiber.reset();
  447. m_scheduler = NULL;
  448. if (timeout)
  449. timeout->cancel();
  450. // The timeout expired, but the event fired before we could
  451. // cancel it, so we got scheduled twice
  452. if (m_cancelledSend && !m_unregistered)
  453. Scheduler::yieldTo();
  454. if (m_cancelledSend) {
  455. MORDOR_LOG_ERROR(g_log) << this << " connect(" << m_sock
  456. << ", " << to << "): (" << m_cancelledSend << ")";
  457. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledSend, "connect");
  458. }
  459. // get the result of the connect operation
  460. WSANETWORKEVENTS events;
  461. if (0 != WSAEnumNetworkEvents(m_sock, NULL, &events))
  462. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WSAEnumNetworkEvents");
  463. // fall back to general socket error if no connect error recorded
  464. error_t error = (events.lNetworkEvents & FD_CONNECT) ?
  465. events.iErrorCode[FD_CONNECT_BIT] :
  466. getOption<int>(SOL_SOCKET, SO_ERROR);
  467. MORDOR_LOG_LEVEL(g_log, error ? Log::ERROR : Log::INFO)
  468. << this << " connect(" << m_sock << ", " << to
  469. << "): (" << error << ")";
  470. if (error)
  471. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "connect");
  472. } else {
  473. MORDOR_LOG_ERROR(g_log) << this << " connect(" << m_sock << ", "
  474. << to << "): (" << lastError() << ")";
  475. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("connect");
  476. }
  477. }
  478. #else
  479. if (!::connect(m_sock, to.name(), to.nameLen())) {
  480. MORDOR_LOG_INFO(g_log) << this << " connect(" << m_sock << ", "
  481. << to << ") local: " << *(localAddress());
  482. // Worked first time
  483. return;
  484. }
  485. if (errno == EINPROGRESS) {
  486. m_ioManager->registerEvent(m_sock, IOManager::WRITE);
  487. if (m_cancelledSend) {
  488. MORDOR_LOG_ERROR(g_log) << this << " connect(" << m_sock << ", " << to
  489. << "): (" << m_cancelledSend << ")";
  490. m_ioManager->cancelEvent(m_sock, IOManager::WRITE);
  491. Scheduler::yieldTo();
  492. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledSend, "connect");
  493. }
  494. Timer::ptr timeout;
  495. if (m_sendTimeout != ~0ull)
  496. timeout = m_ioManager->registerConditionTimer(m_sendTimeout,
  497. boost::bind(&Socket::cancelIo, this, IOManager::WRITE,
  498. boost::ref(m_cancelledSend), ETIMEDOUT),
  499. weak_ptr(shared_from_this()));
  500. Scheduler::yieldTo();
  501. if (timeout)
  502. timeout->cancel();
  503. if (m_cancelledSend) {
  504. MORDOR_LOG_ERROR(g_log) << this << " connect(" << m_sock << ", " << to
  505. << "): (" << m_cancelledSend << ")";
  506. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledSend, "connect");
  507. }
  508. int err;
  509. size_t size = sizeof(int);
  510. getOption(SOL_SOCKET, SO_ERROR, &err, &size);
  511. if (err != 0) {
  512. MORDOR_LOG_ERROR(g_log) << this << " connect(" << m_sock << ", " << to
  513. << "): (" << err << ")";
  514. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(err, "connect");
  515. }
  516. MORDOR_LOG_INFO(g_log) << this << " connect(" << m_sock << ", "
  517. << to << ") local: " << *(localAddress());
  518. } else {
  519. MORDOR_LOG_ERROR(g_log) << this << " connect(" << m_sock << ", " << to
  520. << "): (" << lastError() << ")";
  521. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("connect");
  522. }
  523. #endif
  524. m_isConnected = true;
  525. if (!m_onRemoteClose.empty())
  526. registerForRemoteClose();
  527. }
  528. }
  529. void
  530. Socket::listen(int backlog)
  531. {
  532. int rc = ::listen(m_sock, backlog);
  533. MORDOR_LOG_LEVEL(g_log, rc ? Log::ERROR : Log::DEBUG) << this << " listen("
  534. << m_sock << ", " << backlog << "): " << rc << " (" << lastError()
  535. << ")";
  536. if (rc)
  537. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("listen");
  538. }
  539. Socket::ptr
  540. Socket::accept()
  541. {
  542. Socket::ptr sock(new Socket(m_ioManager, m_family, type(), m_protocol, 0));
  543. accept(*sock.get());
  544. return sock;
  545. }
  546. void
  547. Socket::accept(Socket &target)
  548. {
  549. #ifdef WINDOWS
  550. if (m_useAcceptEx && pAcceptEx && m_ioManager) {
  551. MORDOR_ASSERT(target.m_sock != -1);
  552. } else {
  553. MORDOR_ASSERT(target.m_sock == -1);
  554. }
  555. #else
  556. MORDOR_ASSERT(target.m_sock == -1);
  557. #endif
  558. MORDOR_ASSERT(target.m_family == m_family);
  559. MORDOR_ASSERT(target.m_protocol == m_protocol);
  560. if (!m_ioManager) {
  561. socket_t newsock = ::accept(m_sock, NULL, NULL);
  562. if (newsock == -1) {
  563. MORDOR_LOG_ERROR(g_log) << this << " accept(" << m_sock << "): "
  564. << newsock << " (" << lastError() << ")";
  565. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("accept");
  566. }
  567. target.m_sock = newsock;
  568. MORDOR_LOG_INFO(g_log) << this << " accept(" << m_sock << "): "
  569. << newsock << " (" << *target.remoteAddress() << ", " << &target << ')';
  570. } else {
  571. #ifdef WINDOWS
  572. if (m_useAcceptEx && pAcceptEx) {
  573. m_ioManager->registerEvent(&m_receiveEvent);
  574. unsigned char addrs[sizeof(SOCKADDR_STORAGE) * 2 + 16];
  575. DWORD bytes;
  576. BOOL ret = pAcceptEx(m_sock, target.m_sock, addrs, 0, sizeof(SOCKADDR_STORAGE) + 16, sizeof(SOCKADDR_STORAGE) + 16, &bytes,
  577. &m_receiveEvent.overlapped);
  578. if (!ret && lastError() != WSA_IO_PENDING) {
  579. if (lastError() == WSAENOTSOCK) {
  580. m_ioManager->unregisterEvent(&m_receiveEvent);
  581. // See comment in similar line in connect()
  582. goto suckylsp;
  583. }
  584. MORDOR_LOG_ERROR(g_log) << this << " AcceptEx(" << m_sock << "): ("
  585. << lastError() << ")";
  586. m_ioManager->unregisterEvent(&m_receiveEvent);
  587. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("AcceptEx");
  588. }
  589. if (m_skipCompletionPortOnSuccess && ret) {
  590. m_ioManager->unregisterEvent(&m_receiveEvent);
  591. m_receiveEvent.overlapped.Internal = STATUS_SUCCESS;
  592. } else {
  593. if (m_cancelledReceive) {
  594. MORDOR_LOG_ERROR(g_log) << this << " AcceptEx(" << m_sock << "): ("
  595. << m_cancelledReceive << ")";
  596. m_ioManager->cancelEvent((HANDLE)m_sock, &m_receiveEvent);
  597. Scheduler::yieldTo();
  598. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledReceive, "AcceptEx");
  599. }
  600. Timer::ptr timeout;
  601. if (m_receiveTimeout != ~0ull)
  602. timeout = m_ioManager->registerTimer(m_receiveTimeout, boost::bind(
  603. &IOManager::cancelEvent, m_ioManager, (HANDLE)m_sock, &m_receiveEvent));
  604. Scheduler::yieldTo();
  605. if (timeout)
  606. timeout->cancel();
  607. }
  608. error_t error = pRtlNtStatusToDosError((NTSTATUS)m_receiveEvent.overlapped.Internal);
  609. if (error && error != ERROR_MORE_DATA) {
  610. if (error == ERROR_OPERATION_ABORTED &&
  611. m_cancelledReceive != ERROR_OPERATION_ABORTED)
  612. error = WSAETIMEDOUT;
  613. MORDOR_LOG_ERROR(g_log) << this << " AcceptEx(" << m_sock << "): ("
  614. << error << ")";
  615. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, "AcceptEx");
  616. }
  617. sockaddr *localAddr = NULL, *remoteAddr = NULL;
  618. INT localAddrLen, remoteAddrLen;
  619. if (m_useAcceptEx && pGetAcceptExSockaddrs)
  620. pGetAcceptExSockaddrs(addrs, 0, sizeof(SOCKADDR_STORAGE) + 16,
  621. sizeof(SOCKADDR_STORAGE) + 16, &localAddr, &localAddrLen,
  622. &remoteAddr, &remoteAddrLen);
  623. if (remoteAddr)
  624. target.m_remoteAddress = Address::create(remoteAddr, remoteAddrLen);
  625. std::ostringstream os;
  626. MORDOR_LOG_INFO(g_log) << this << " AcceptEx(" << m_sock << "): "
  627. << target.m_sock << " (" << *target.remoteAddress() << ", " << &target << ')';
  628. target.setOption(SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, &m_sock, sizeof(m_sock));
  629. target.m_ioManager->registerFile((HANDLE)target.m_sock);
  630. target.m_skipCompletionPortOnSuccess =
  631. !!pSetFileCompletionNotificationModes((HANDLE)target.m_sock,
  632. FILE_SKIP_COMPLETION_PORT_ON_SUCCESS |
  633. FILE_SKIP_SET_EVENT_ON_HANDLE);
  634. } else {
  635. suckylsp:
  636. if (!m_hEvent) {
  637. m_hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
  638. if (!m_hEvent)
  639. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CreateEventW");
  640. }
  641. if (!ResetEvent(m_hEvent))
  642. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("ResetEvent");
  643. if (WSAEventSelect(m_sock, m_hEvent, FD_ACCEPT))
  644. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WSAEventSelect");
  645. socket_t newsock = ::accept(m_sock, NULL, NULL);
  646. if (newsock != -1) {
  647. // Worked first time
  648. } else if (lastError() == WSAEWOULDBLOCK) {
  649. m_ioManager->registerEvent(m_hEvent);
  650. m_fiber = Fiber::getThis();
  651. m_scheduler = Scheduler::getThis();
  652. if (m_cancelledReceive) {
  653. MORDOR_LOG_ERROR(g_log) << this << " accept(" << m_sock << "): ("
  654. << m_cancelledReceive << ")";
  655. if (!m_ioManager->unregisterEvent(m_hEvent))
  656. Scheduler::yieldTo();
  657. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledReceive, "accept");
  658. }
  659. m_unregistered = false;
  660. Timer::ptr timeout;
  661. if (m_receiveTimeout != ~0ull)
  662. timeout = m_ioManager->registerConditionTimer(m_sendTimeout,
  663. boost::bind(&Socket::cancelIo, this,
  664. boost::ref(m_cancelledReceive), WSAETIMEDOUT),
  665. weak_ptr(shared_from_this()));
  666. Scheduler::yieldTo();
  667. m_fiber.reset();
  668. m_scheduler = NULL;
  669. if (timeout)
  670. timeout->cancel();
  671. // The timeout expired, but the event fired before we could
  672. // cancel it, so we got scheduled twice
  673. if (m_cancelledReceive && !m_unregistered)
  674. Scheduler::yieldTo();
  675. if (m_cancelledReceive) {
  676. MORDOR_LOG_ERROR(g_log) << this << " accept(" << m_sock
  677. << "): (" << m_cancelledReceive << ")";
  678. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledReceive, "accept");
  679. }
  680. newsock = ::accept(m_sock, NULL, NULL);
  681. if (newsock == -1) {
  682. MORDOR_LOG_ERROR(g_log) << this << " accept(" << m_sock
  683. << "): " << newsock << " (" << lastError() << ")";
  684. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("accept");
  685. }
  686. } else {
  687. MORDOR_LOG_ERROR(g_log) << this << " accept(" << m_sock << "): ("
  688. << lastError() << ")";
  689. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("accept");
  690. }
  691. try {
  692. m_ioManager->registerFile((HANDLE)newsock);
  693. } catch(...) {
  694. closesocket(newsock);
  695. throw;
  696. }
  697. if (target.m_sock != -1)
  698. ::closesocket(target.m_sock);
  699. target.m_sock = newsock;
  700. MORDOR_LOG_INFO(g_log) << this << " accept(" << m_sock << "): "
  701. << newsock << " (" << *target.remoteAddress() << ", " << &target << ')';
  702. target.m_skipCompletionPortOnSuccess =
  703. !!pSetFileCompletionNotificationModes((HANDLE)newsock,
  704. FILE_SKIP_COMPLETION_PORT_ON_SUCCESS |
  705. FILE_SKIP_SET_EVENT_ON_HANDLE);
  706. }
  707. #else
  708. int newsock;
  709. error_t error;
  710. do {
  711. newsock = ::accept(m_sock, NULL, NULL);
  712. error = errno;
  713. } while (newsock == -1 && error == EINTR);
  714. while (newsock == -1 && error == EAGAIN) {
  715. m_ioManager->registerEvent(m_sock, IOManager::READ);
  716. if (m_cancelledReceive) {
  717. MORDOR_LOG_ERROR(g_log) << this << " accept(" << m_sock << "): ("
  718. << m_cancelledReceive << ")";
  719. m_ioManager->cancelEvent(m_sock, IOManager::READ);
  720. Scheduler::yieldTo();
  721. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledReceive, "accept");
  722. }
  723. Timer::ptr timeout;
  724. if (m_receiveTimeout != ~0ull)
  725. timeout = m_ioManager->registerConditionTimer(m_receiveTimeout,
  726. boost::bind(&Socket::cancelIo, this, IOManager::READ,
  727. boost::ref(m_cancelledReceive), ETIMEDOUT),
  728. weak_ptr(shared_from_this()));
  729. Scheduler::yieldTo();
  730. if (timeout)
  731. timeout->cancel();
  732. if (m_cancelledReceive) {
  733. MORDOR_LOG_ERROR(g_log) << this << " accept(" << m_sock
  734. << "): (" << m_cancelledReceive << ")";
  735. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(m_cancelledReceive, "accept");
  736. }
  737. do {
  738. newsock = ::accept(m_sock, NULL, NULL);
  739. error = errno;
  740. } while (newsock == -1 && error == EINTR);
  741. }
  742. if (newsock == -1) {
  743. MORDOR_LOG_ERROR(g_log) << this << " accept(" << m_sock << "): "
  744. << newsock << " (" << error << ")";
  745. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("accept");
  746. }
  747. if (fcntl(newsock, F_SETFL, O_NONBLOCK) == -1) {
  748. ::close(newsock);
  749. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("fcntl");
  750. }
  751. target.m_sock = newsock;
  752. MORDOR_LOG_INFO(g_log) << this << " accept(" << m_sock << "): "
  753. << newsock << " (" << *target.remoteAddress() << ", " << &target << ')';
  754. #endif
  755. target.m_isConnected = true;
  756. if (!target.m_onRemoteClose.empty())
  757. target.registerForRemoteClose();
  758. }
  759. }
  760. void
  761. Socket::shutdown(int how)
  762. {
  763. if(::shutdown(m_sock, how)) {
  764. MORDOR_LOG_ERROR(g_log) << this << " shutdown(" << m_sock << ", "
  765. << how << "): (" << lastError() << ")";
  766. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("shutdown");
  767. }
  768. if (m_isRegisteredForRemoteClose) {
  769. #ifdef WINDOWS
  770. m_ioManager->unregisterEvent(m_hEvent);
  771. WSAEventSelect(m_sock, m_hEvent, 0);
  772. #else
  773. if (m_isRegisteredForRemoteClose)
  774. m_ioManager->unregisterEvent(m_sock, IOManager::CLOSE);
  775. #endif
  776. m_isRegisteredForRemoteClose = false;
  777. }
  778. m_isConnected = false;
  779. MORDOR_LOG_VERBOSE(g_log) << this << " shutdown(" << m_sock << ", "
  780. << how << ")";
  781. }
  782. #define MORDOR_SOCKET_LOG(result, error) \
  783. if (g_log->enabled(result == -1 ? Log::ERROR : Log::DEBUG)) { \
  784. LogEvent event = g_log->log(result == -1 ? Log::ERROR : Log::DEBUG, \
  785. __FILE__, __LINE__); \
  786. event.os() << this << " " << api << "(" << m_sock << ", " \
  787. << length; \
  788. if (isSend && address) \
  789. event.os() << ", " << *address; \
  790. event.os() << "): "; \
  791. if (result == -1) \
  792. event.os() << "(" << error << ")"; \
  793. else \
  794. event.os() << result; \
  795. if (result != -1 && !isSend && address) \
  796. event.os() << ", " << *address; \
  797. }
  798. template <bool isSend>
  799. size_t
  800. Socket::doIO(iovec *buffers, size_t length, int &flags, Address *address)
  801. {
  802. #if !defined(WINDOWS) && !defined(OSX)
  803. flags |= MSG_NOSIGNAL;
  804. #endif
  805. #ifdef WINDOWS
  806. const char *api = isSend ? (address ? "WSASendTo" : "WSASend") :
  807. (address ? "WSARecvFrom" : "WSARecv");
  808. #else
  809. const char *api = isSend ? "sendmsg" : "recvmsg";
  810. #endif
  811. error_t &cancelled = isSend ? m_cancelledSend : m_cancelledReceive;
  812. unsigned long long &timeout = isSend ? m_sendTimeout : m_receiveTimeout;
  813. #ifdef WINDOWS
  814. DWORD bufferCount = (DWORD)std::min<size_t>(length, 0xffffffff);
  815. AsyncEvent &event = isSend ? m_sendEvent : m_receiveEvent;
  816. OVERLAPPED *overlapped = m_ioManager ? &event.overlapped : NULL;
  817. if (m_ioManager) {
  818. if (cancelled) {
  819. MORDOR_SOCKET_LOG(-1, cancelled);
  820. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(cancelled, api);
  821. }
  822. m_ioManager->registerEvent(&event);
  823. }
  824. DWORD transferred;
  825. int result;
  826. INT addrLen;
  827. if (address) {
  828. addrLen = address->nameLen();
  829. result = isSend ? WSASendTo(m_sock,
  830. (LPWSABUF)buffers,
  831. bufferCount,
  832. &transferred,
  833. flags,
  834. address->name(),
  835. address->nameLen(),
  836. overlapped,
  837. NULL) : WSARecvFrom(m_sock,
  838. (LPWSABUF)buffers,
  839. bufferCount,
  840. &transferred,
  841. (LPDWORD)&flags,
  842. address->name(),
  843. &addrLen,
  844. overlapped,
  845. NULL);
  846. } else {
  847. result = isSend ? WSASend(m_sock,
  848. (LPWSABUF)buffers,
  849. bufferCount,
  850. &transferred,
  851. flags,
  852. overlapped,
  853. NULL) : WSARecv(m_sock,
  854. (LPWSABUF)buffers,
  855. bufferCount,
  856. &transferred,
  857. (LPDWORD)&flags,
  858. overlapped,
  859. NULL);
  860. }
  861. if (result) {
  862. if (!m_ioManager || lastError() != WSA_IO_PENDING) {
  863. MORDOR_SOCKET_LOG(-1, lastError());
  864. if (m_ioManager)
  865. m_ioManager->unregisterEvent(&event);
  866. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API(api);
  867. }
  868. }
  869. if (m_ioManager) {
  870. if (m_skipCompletionPortOnSuccess && result == 0) {
  871. m_ioManager->unregisterEvent(&event);
  872. } else {
  873. Timer::ptr timer;
  874. if (timeout != ~0ull)
  875. timer = m_ioManager->registerTimer(timeout, boost::bind(
  876. &IOManager::cancelEvent, m_ioManager, (HANDLE)m_sock,
  877. &event));
  878. Scheduler::yieldTo();
  879. if (timer)
  880. timer->cancel();
  881. }
  882. error_t error = pRtlNtStatusToDosError(
  883. (NTSTATUS)event.overlapped.Internal);
  884. if (error == ERROR_OPERATION_ABORTED &&
  885. cancelled != ERROR_OPERATION_ABORTED)
  886. error = WSAETIMEDOUT;
  887. if (error == ERROR_SEM_TIMEOUT)
  888. error = WSAETIMEDOUT;
  889. result = error ? -1 : (int)event.overlapped.InternalHigh;
  890. MORDOR_SOCKET_LOG(result, error);
  891. if (error)
  892. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(error, api);
  893. return result;
  894. }
  895. MORDOR_SOCKET_LOG(transferred, lastError());
  896. return transferred;
  897. #else
  898. msghdr msg;
  899. memset(&msg, 0, sizeof(msghdr));
  900. msg.msg_iov = buffers;
  901. msg.msg_iovlen = std::min(length, (size_t)IOV_MAX);
  902. if (address) {
  903. msg.msg_name = (sockaddr *)address->name();
  904. msg.msg_namelen = address->nameLen();
  905. }
  906. IOManager::Event event = isSend ? IOManager::WRITE : IOManager::READ;
  907. if (m_ioManager) {
  908. if (cancelled) {
  909. MORDOR_SOCKET_LOG(-1, cancelled);
  910. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(cancelled, api);
  911. }
  912. }
  913. int rc;
  914. error_t error;
  915. do {
  916. rc = isSend ? sendmsg(m_sock, &msg, flags) : recvmsg(m_sock, &msg, flags);
  917. error = errno;
  918. } while (rc == -1 && error == EINTR);
  919. while (m_ioManager && rc == -1 && error == EAGAIN) {
  920. m_ioManager->registerEvent(m_sock, event);
  921. Timer::ptr timer;
  922. if (timeout != ~0ull)
  923. timer = m_ioManager->registerConditionTimer(timeout,
  924. boost::bind(&Socket::cancelIo, this, event, boost::ref(cancelled), ETIMEDOUT),
  925. weak_ptr(shared_from_this()));
  926. Scheduler::yieldTo();
  927. if (timer)
  928. timer->cancel();
  929. if (cancelled) {
  930. MORDOR_SOCKET_LOG(-1, cancelled);
  931. MORDOR_THROW_EXCEPTION_FROM_ERROR_API(cancelled, api);
  932. }
  933. do {
  934. rc = isSend ? sendmsg(m_sock, &msg, flags) : recvmsg(m_sock, &msg, flags);
  935. error = errno;
  936. } while (rc == -1 && error == EINTR);
  937. }
  938. MORDOR_SOCKET_LOG(rc, error);
  939. if (rc == -1)
  940. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API(api);
  941. if (!isSend)
  942. flags = msg.msg_flags;
  943. return rc;
  944. #endif
  945. }
  946. size_t
  947. Socket::send(const void *buffer, size_t length, int flags)
  948. {
  949. iovec buffers;
  950. buffers.iov_base = (void *)buffer;
  951. buffers.iov_len = (u_long)std::min<size_t>(length, 0xffffffff);
  952. return doIO<true>(&buffers, 1, flags);
  953. }
  954. size_t
  955. Socket::send(const iovec *buffers, size_t length, int flags)
  956. {
  957. return doIO<true>((iovec *)buffers, length, flags);
  958. }
  959. size_t
  960. Socket::sendTo(const void *buffer, size_t length, int flags, const Address &to)
  961. {
  962. iovec buffers;
  963. buffers.iov_base = (void *)buffer;
  964. buffers.iov_len = (u_long)std::min<size_t>(length, 0xffffffff);
  965. return doIO<true>(&buffers, 1, flags, (Address *)&to);
  966. }
  967. size_t
  968. Socket::sendTo(const iovec *buffers, size_t length, int flags,
  969. const Address &to)
  970. {
  971. return doIO<true>((iovec *)buffers, length, flags, (Address *)&to);
  972. }
  973. size_t
  974. Socket::receive(void *buffer, size_t length, int *flags)
  975. {
  976. iovec buffers;
  977. buffers.iov_base = buffer;
  978. buffers.iov_len = (u_long)std::min<size_t>(length, 0xffffffff);
  979. int flagStorage = 0;
  980. if (!flags)
  981. flags = &flagStorage;
  982. return doIO<false>(&buffers, 1, *flags);
  983. }
  984. size_t
  985. Socket::receive(iovec *buffers, size_t length, int *flags)
  986. {
  987. int flagStorage = 0;
  988. if (!flags)
  989. flags = &flagStorage;
  990. return doIO<false>(buffers, length, *flags);
  991. }
  992. size_t
  993. Socket::receiveFrom(void *buffer, size_t length, Address &from, int *flags)
  994. {
  995. iovec buffers;
  996. buffers.iov_base = buffer;
  997. buffers.iov_len = (u_long)std::min<size_t>(length, 0xffffffff);
  998. int flagStorage = 0;
  999. if (!flags)
  1000. flags = &flagStorage;
  1001. return doIO<false>(&buffers, 1, *flags, &from);
  1002. }
  1003. size_t
  1004. Socket::receiveFrom(iovec *buffers, size_t length, Address &from, int *flags)
  1005. {
  1006. int flagStorage = 0;
  1007. if (!flags)
  1008. flags = &flagStorage;
  1009. return doIO<false>(buffers, length, *flags, &from);
  1010. }
  1011. void
  1012. Socket::getOption(int level, int option, void *result, size_t *len)
  1013. {
  1014. int ret = getsockopt(m_sock, level, option, (char*)result, (socklen_t*)len);
  1015. if (ret) {
  1016. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("getsockopt");
  1017. }
  1018. }
  1019. void
  1020. Socket::setOption(int level, int option, const void *value, size_t len)
  1021. {
  1022. if (setsockopt(m_sock, level, option, (const char*)value, (socklen_t)len)) {
  1023. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("setsockopt");
  1024. }
  1025. }
  1026. void
  1027. Socket::cancelAccept()
  1028. {
  1029. MORDOR_ASSERT(m_ioManager);
  1030. #ifdef WINDOWS
  1031. if (m_cancelledReceive)
  1032. return;
  1033. m_cancelledReceive = ERROR_OPERATION_ABORTED;
  1034. if (m_useAcceptEx && pAcceptEx) {
  1035. m_ioManager->cancelEvent((HANDLE)m_sock, &m_receiveEvent);
  1036. }
  1037. if (m_hEvent && m_scheduler && m_fiber) {
  1038. m_unregistered = !!m_ioManager->unregisterEvent(m_hEvent);
  1039. m_scheduler->schedule(m_fiber);
  1040. }
  1041. #else
  1042. cancelIo(IOManager::READ, m_cancelledReceive, ECANCELED);
  1043. #endif
  1044. }
  1045. void
  1046. Socket::cancelConnect()
  1047. {
  1048. MORDOR_ASSERT(m_ioManager);
  1049. #ifdef WINDOWS
  1050. if (m_cancelledSend)
  1051. return;
  1052. MORDOR_LOG_VERBOSE(g_log) << this << " cancelConnect(" << m_sock << ")";
  1053. m_cancelledSend = ERROR_OPERATION_ABORTED;
  1054. if (m_useConnectEx && ConnectEx) {
  1055. m_ioManager->cancelEvent((HANDLE)m_sock, &m_sendEvent);
  1056. }
  1057. if (m_hEvent && m_scheduler && m_fiber) {
  1058. m_unregistered = !!m_ioManager->unregisterEvent(m_hEvent);
  1059. m_scheduler->schedule(m_fiber);
  1060. }
  1061. #else
  1062. cancelIo(IOManager::WRITE, m_cancelledSend, ECANCELED);
  1063. #endif
  1064. }
  1065. void
  1066. Socket::cancelSend()
  1067. {
  1068. MORDOR_ASSERT(m_ioManager);
  1069. #ifdef WINDOWS
  1070. if (m_cancelledSend)
  1071. return;
  1072. MORDOR_LOG_VERBOSE(g_log) << this << " cancelSend(" << m_sock << ")";
  1073. m_cancelledSend = ERROR_OPERATION_ABORTED;
  1074. m_ioManager->cancelEvent((HANDLE)m_sock, &m_sendEvent);
  1075. #else
  1076. cancelIo(IOManager::WRITE, m_cancelledSend, ECANCELED);
  1077. #endif
  1078. }
  1079. void
  1080. Socket::cancelReceive()
  1081. {
  1082. MORDOR_ASSERT(m_ioManager);
  1083. #ifdef WINDOWS
  1084. if (m_cancelledReceive)
  1085. return;
  1086. MORDOR_LOG_VERBOSE(g_log) << this << "cancelReceive(" << m_sock << ")";
  1087. m_cancelledReceive = ERROR_OPERATION_ABORTED;
  1088. m_ioManager->cancelEvent((HANDLE)m_sock, &m_receiveEvent);
  1089. #else
  1090. cancelIo(IOManager::READ, m_cancelledReceive, ECANCELED);
  1091. #endif
  1092. }
  1093. #ifdef WINDOWS
  1094. void
  1095. Socket::cancelIo(error_t &cancelled, error_t error)
  1096. {
  1097. MORDOR_ASSERT(error);
  1098. if (cancelled)
  1099. return;
  1100. MORDOR_LOG_VERBOSE(g_log) << this << " cancelIo(" << m_sock << ")";
  1101. cancelled = error;
  1102. if (m_hEvent && m_scheduler && m_fiber) {
  1103. m_unregistered = !!m_ioManager->unregisterEvent(m_hEvent);
  1104. m_scheduler->schedule(m_fiber);
  1105. }
  1106. }
  1107. #else
  1108. void
  1109. Socket::cancelIo(int event, error_t &cancelled, error_t error)
  1110. {
  1111. MORDOR_ASSERT(error);
  1112. if (cancelled)
  1113. return;
  1114. MORDOR_LOG_VERBOSE(g_log) << this
  1115. << ((event == IOManager::READ) ? " cancelReceive(" : " cancelSend(")
  1116. << m_sock << ")";
  1117. cancelled = error;
  1118. m_ioManager->cancelEvent(m_sock, (IOManager::Event)event);
  1119. }
  1120. #endif
  1121. Address::ptr
  1122. Socket::emptyAddress()
  1123. {
  1124. switch (m_family) {
  1125. case AF_INET:
  1126. return Address::ptr(new IPv4Address());
  1127. case AF_INET6:
  1128. return Address::ptr(new IPv6Address());
  1129. default:
  1130. return Address::ptr(new UnknownAddress(m_family));
  1131. }
  1132. }
  1133. Address::ptr
  1134. Socket::remoteAddress()
  1135. {
  1136. if (m_remoteAddress)
  1137. return m_remoteAddress;
  1138. Address::ptr result;
  1139. switch (m_family) {
  1140. case AF_INET:
  1141. result.reset(new IPv4Address());
  1142. break;
  1143. case AF_INET6:
  1144. result.reset(new IPv6Address());
  1145. break;
  1146. #ifndef WINDOWS
  1147. case AF_UNIX:
  1148. result.reset(new UnixAddress());
  1149. break;
  1150. #endif
  1151. default:
  1152. result.reset(new UnknownAddress(m_family));
  1153. break;
  1154. }
  1155. socklen_t namelen = result->nameLen();
  1156. if (getpeername(m_sock, result->name(), &namelen))
  1157. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("getpeername");
  1158. MORDOR_ASSERT(namelen <= result->nameLen());
  1159. #ifndef WINDOWS
  1160. if (m_family == AF_UNIX) {
  1161. boost::shared_ptr<UnixAddress> addr = boost::dynamic_pointer_cast<UnixAddress>(result);
  1162. addr->nameLen(namelen);
  1163. }
  1164. #endif
  1165. return m_remoteAddress = result;
  1166. }
  1167. Address::ptr
  1168. Socket::localAddress()
  1169. {
  1170. if (m_localAddress)
  1171. return m_localAddress;
  1172. Address::ptr result;
  1173. switch (m_family) {
  1174. case AF_INET:
  1175. result.reset(new IPv4Address());
  1176. break;
  1177. case AF_INET6:
  1178. result.reset(new IPv6Address());
  1179. break;
  1180. #ifndef WINDOWS
  1181. case AF_UNIX:
  1182. result.reset(new UnixAddress());
  1183. break;
  1184. #endif
  1185. default:
  1186. result.reset(new UnknownAddress(m_family));
  1187. break;
  1188. }
  1189. socklen_t namelen = result->nameLen();
  1190. if (getsockname(m_sock, result->name(), &namelen))
  1191. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("getsockname");
  1192. MORDOR_ASSERT(namelen <= result->nameLen());
  1193. #ifndef WINDOWS
  1194. // set the result->nameLen() right
  1195. if (m_family == AF_UNIX) {
  1196. boost::shared_ptr<UnixAddress> addr = boost::dynamic_pointer_cast<UnixAddress>(result);
  1197. addr->nameLen(namelen);
  1198. }
  1199. #endif
  1200. return m_localAddress = result;
  1201. }
  1202. int
  1203. Socket::type()
  1204. {
  1205. int result;
  1206. size_t len = sizeof(int);
  1207. getOption(SOL_SOCKET, SO_TYPE, &result, &len);
  1208. return result;
  1209. }
  1210. boost::signals2::connection
  1211. Socket::onRemoteClose(const boost::signals2::slot<void ()> &slot)
  1212. {
  1213. boost::signals2::connection result = m_onRemoteClose.connect(slot);
  1214. if (m_isConnected && !m_isRegisteredForRemoteClose)
  1215. registerForRemoteClose();
  1216. return result;
  1217. }
  1218. void
  1219. Socket::callOnRemoteClose(weak_ptr self)
  1220. {
  1221. ptr strongSelf = self.lock();
  1222. if (strongSelf)
  1223. strongSelf->m_onRemoteClose();
  1224. }
  1225. void
  1226. Socket::registerForRemoteClose()
  1227. {
  1228. #ifdef WINDOWS
  1229. // listen for the close event
  1230. if (!m_hEvent) {
  1231. m_hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
  1232. if (!m_hEvent)
  1233. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("CreateEventW");
  1234. }
  1235. if (!ResetEvent(m_hEvent))
  1236. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("ResetEvent");
  1237. if (WSAEventSelect(m_sock, m_hEvent, FD_CLOSE))
  1238. MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("WSAEventSelect");
  1239. m_ioManager->registerEvent(m_hEvent, boost::bind(&Socket::callOnRemoteClose,
  1240. weak_ptr(shared_from_this())));
  1241. #else
  1242. m_ioManager->registerEvent(m_sock, IOManager::CLOSE,
  1243. boost::bind(&Socket::callOnRemoteClose, weak_ptr(shared_from_this())));
  1244. #endif
  1245. m_isRegisteredForRemoteClose = true;
  1246. }
  1247. static void throwGaiException(int error)
  1248. {
  1249. switch (error) {
  1250. case EAI_AGAIN:
  1251. MORDOR_THROW_EXCEPTION(TemporaryNameServerFailureException()
  1252. << errinfo_gaierror(error)
  1253. << boost::errinfo_api_function("getaddrinfo"));
  1254. case EAI_FAIL:
  1255. MORDOR_THROW_EXCEPTION(PermanentNameServerFailureException()
  1256. << errinfo_gaierror(error)
  1257. << boost::errinfo_api_function("getaddrinfo"));
  1258. #if defined(WSANO_DATA) || defined(EAI_NODATA)
  1259. case MORDOR_NATIVE(WSANO_DATA, EAI_NODATA):
  1260. MORDOR_THROW_EXCEPTION(NoNameServerDataException()
  1261. << errinfo_gaierror(error)
  1262. << boost::errinfo_api_function("getaddrinfo"));
  1263. #endif
  1264. case EAI_NONAME:
  1265. MORDOR_THROW_EXCEPTION(HostNotFoundException()
  1266. << errinfo_gaierror(error)
  1267. << boost::errinfo_api_function("getaddrinfo"));
  1268. #ifdef EAI_ADDRFAMILY
  1269. case EAI_ADDRFAMILY:
  1270. #endif
  1271. case EAI_FAMILY:
  1272. MORDOR_THROW_EXCEPTION(OperationNotSupportedException()
  1273. << errinfo_gaierror(error)
  1274. << boost::errinfo_api_function("getaddrinfo"));
  1275. case EAI_BADFLAGS:
  1276. case EAI_MEMORY:
  1277. case EAI_SERVICE:
  1278. case EAI_SOCKTYPE:
  1279. #ifdef EAI_SYSTEM
  1280. case EAI_SYSTEM:
  1281. #endif
  1282. default:
  1283. MORDOR_THROW_EXCEPTION(NameLookupException()
  1284. << errinfo_gaierror(error)
  1285. << boost::errinfo_api_function("getaddrinfo"));
  1286. }
  1287. }
  1288. std::vector<Address::ptr>
  1289. Address::lookup(const std::string &host, int family, int type, int protocol)
  1290. {
  1291. #ifdef WINDOWS
  1292. addrinfoW hints, *results, *next;
  1293. #else
  1294. addrinfo hints, *results, *next;
  1295. #endif
  1296. hints.ai_flags = 0;
  1297. hints.ai_family = family;
  1298. hints.ai_socktype = type;
  1299. hints.ai_protocol = protocol;
  1300. hints.ai_addrlen = 0;
  1301. hints.ai_canonname = NULL;
  1302. hints.ai_addr = NULL;
  1303. hints.ai_next = NULL;
  1304. std::string node;
  1305. const char *service = NULL;
  1306. // Check for [ipv6addr] (with optional :service)
  1307. if (!host.empty() && host[0] == '[') {
  1308. const char *endipv6 = (const char *)memchr(host.c_str() + 1, ']', host.size() - 1);
  1309. if (endipv6) {
  1310. if (*(endipv6 + 1) == ':') {
  1311. service = endipv6 + 2;
  1312. }
  1313. node = host.substr(1, endipv6 - host.c_str() - 1);
  1314. }
  1315. }
  1316. // Check for node:service
  1317. if (node.empty()) {
  1318. service = (const char*)memchr(host.c_str(), ':', host.size());
  1319. if (service) {
  1320. // More than 1 : means it's not node:service
  1321. if (!memchr(service + 1, ':', host.c_str() + host.size() - service - 1)) {
  1322. node = host.substr(0, service - host.c_str());
  1323. ++service;
  1324. } else {
  1325. service = NULL;
  1326. }
  1327. }
  1328. }
  1329. if (node.empty())
  1330. node = host;
  1331. int error;
  1332. #ifdef WINDOWS
  1333. std::wstring serviceWStorage;
  1334. const wchar_t *serviceW = NULL;
  1335. if (service) {
  1336. if (stricmp(service, "socks") == 0)
  1337. serviceWStorage = L"1080";
  1338. else
  1339. serviceWStorage = toUtf16(service);
  1340. serviceW = serviceWStorage.c_str();
  1341. }
  1342. error = pGetAddrInfoW(toUtf16(node).c_str(), serviceW, &hints, &results);
  1343. #else
  1344. error = getaddrinfo(node.c_str(), service, &hints, &results);
  1345. #endif
  1346. if (error) {
  1347. MORDOR_LOG_ERROR(g_log) << "…

Large files files are truncated, but you can click here to view the full file