socket_ops.hpp 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913
  1. //
  2. // socket_ops.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_DETAIL_SOCKET_OPS_HPP
  11. #define BOOST_ASIO_DETAIL_SOCKET_OPS_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/push_options.hpp>
  16. #include <boost/asio/detail/push_options.hpp>
  17. #include <boost/config.hpp>
  18. #include <boost/assert.hpp>
  19. #include <cstdio>
  20. #include <cstdlib>
  21. #include <cstring>
  22. #include <cerrno>
  23. #include <boost/detail/workaround.hpp>
  24. #include <new>
  25. #include <boost/asio/detail/pop_options.hpp>
  26. #include <boost/asio/error.hpp>
  27. #include <boost/asio/detail/socket_types.hpp>
  28. namespace boost {
  29. namespace asio {
  30. namespace detail {
  31. namespace socket_ops {
  32. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  33. struct msghdr { int msg_namelen; };
  34. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  35. #if defined(__hpux)
  36. // HP-UX doesn't declare these functions extern "C", so they are declared again
  37. // here to avoid linker errors about undefined symbols.
  38. extern "C" char* if_indextoname(unsigned int, char*);
  39. extern "C" unsigned int if_nametoindex(const char*);
  40. #endif // defined(__hpux)
  41. inline void clear_error(boost::system::error_code& ec)
  42. {
  43. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  44. WSASetLastError(0);
  45. #else
  46. errno = 0;
  47. #endif
  48. ec = boost::system::error_code();
  49. }
  50. template <typename ReturnType>
  51. inline ReturnType error_wrapper(ReturnType return_value,
  52. boost::system::error_code& ec)
  53. {
  54. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  55. ec = boost::system::error_code(WSAGetLastError(),
  56. boost::asio::error::get_system_category());
  57. #else
  58. ec = boost::system::error_code(errno,
  59. boost::asio::error::get_system_category());
  60. #endif
  61. return return_value;
  62. }
  63. template <typename SockLenType>
  64. inline socket_type call_accept(SockLenType msghdr::*,
  65. socket_type s, socket_addr_type* addr, std::size_t* addrlen)
  66. {
  67. SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
  68. socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
  69. if (addrlen)
  70. *addrlen = (std::size_t)tmp_addrlen;
  71. return result;
  72. }
  73. inline socket_type accept(socket_type s, socket_addr_type* addr,
  74. std::size_t* addrlen, boost::system::error_code& ec)
  75. {
  76. clear_error(ec);
  77. socket_type new_s = error_wrapper(call_accept(
  78. &msghdr::msg_namelen, s, addr, addrlen), ec);
  79. if (new_s == invalid_socket)
  80. return new_s;
  81. #if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
  82. int optval = 1;
  83. int result = error_wrapper(::setsockopt(new_s,
  84. SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
  85. if (result != 0)
  86. {
  87. ::close(new_s);
  88. return invalid_socket;
  89. }
  90. #endif
  91. clear_error(ec);
  92. return new_s;
  93. }
  94. template <typename SockLenType>
  95. inline int call_bind(SockLenType msghdr::*,
  96. socket_type s, const socket_addr_type* addr, std::size_t addrlen)
  97. {
  98. return ::bind(s, addr, (SockLenType)addrlen);
  99. }
  100. inline int bind(socket_type s, const socket_addr_type* addr,
  101. std::size_t addrlen, boost::system::error_code& ec)
  102. {
  103. clear_error(ec);
  104. int result = error_wrapper(call_bind(
  105. &msghdr::msg_namelen, s, addr, addrlen), ec);
  106. if (result == 0)
  107. clear_error(ec);
  108. return result;
  109. }
  110. inline int close(socket_type s, boost::system::error_code& ec)
  111. {
  112. clear_error(ec);
  113. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  114. int result = error_wrapper(::closesocket(s), ec);
  115. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  116. int result = error_wrapper(::close(s), ec);
  117. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  118. if (result == 0)
  119. clear_error(ec);
  120. return result;
  121. }
  122. inline int shutdown(socket_type s, int what, boost::system::error_code& ec)
  123. {
  124. clear_error(ec);
  125. int result = error_wrapper(::shutdown(s, what), ec);
  126. if (result == 0)
  127. clear_error(ec);
  128. return result;
  129. }
  130. template <typename SockLenType>
  131. inline int call_connect(SockLenType msghdr::*,
  132. socket_type s, const socket_addr_type* addr, std::size_t addrlen)
  133. {
  134. return ::connect(s, addr, (SockLenType)addrlen);
  135. }
  136. inline int connect(socket_type s, const socket_addr_type* addr,
  137. std::size_t addrlen, boost::system::error_code& ec)
  138. {
  139. clear_error(ec);
  140. int result = error_wrapper(call_connect(
  141. &msghdr::msg_namelen, s, addr, addrlen), ec);
  142. if (result == 0)
  143. clear_error(ec);
  144. return result;
  145. }
  146. inline int socketpair(int af, int type, int protocol,
  147. socket_type sv[2], boost::system::error_code& ec)
  148. {
  149. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  150. (void)(af);
  151. (void)(type);
  152. (void)(protocol);
  153. (void)(sv);
  154. ec = boost::asio::error::operation_not_supported;
  155. return -1;
  156. #else
  157. clear_error(ec);
  158. int result = error_wrapper(::socketpair(af, type, protocol, sv), ec);
  159. if (result == 0)
  160. clear_error(ec);
  161. return result;
  162. #endif
  163. }
  164. inline int listen(socket_type s, int backlog, boost::system::error_code& ec)
  165. {
  166. clear_error(ec);
  167. int result = error_wrapper(::listen(s, backlog), ec);
  168. if (result == 0)
  169. clear_error(ec);
  170. return result;
  171. }
  172. inline void init_buf_iov_base(void*& base, void* addr)
  173. {
  174. base = addr;
  175. }
  176. template <typename T>
  177. inline void init_buf_iov_base(T& base, void* addr)
  178. {
  179. base = static_cast<T>(addr);
  180. }
  181. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  182. typedef WSABUF buf;
  183. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  184. typedef iovec buf;
  185. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  186. inline void init_buf(buf& b, void* data, size_t size)
  187. {
  188. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  189. b.buf = static_cast<char*>(data);
  190. b.len = static_cast<u_long>(size);
  191. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  192. init_buf_iov_base(b.iov_base, data);
  193. b.iov_len = size;
  194. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  195. }
  196. inline void init_buf(buf& b, const void* data, size_t size)
  197. {
  198. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  199. b.buf = static_cast<char*>(const_cast<void*>(data));
  200. b.len = static_cast<u_long>(size);
  201. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  202. init_buf_iov_base(b.iov_base, const_cast<void*>(data));
  203. b.iov_len = size;
  204. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  205. }
  206. inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
  207. {
  208. name = addr;
  209. }
  210. inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
  211. {
  212. name = const_cast<socket_addr_type*>(addr);
  213. }
  214. template <typename T>
  215. inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
  216. {
  217. name = reinterpret_cast<T>(addr);
  218. }
  219. template <typename T>
  220. inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
  221. {
  222. name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
  223. }
  224. inline int recv(socket_type s, buf* bufs, size_t count, int flags,
  225. boost::system::error_code& ec)
  226. {
  227. clear_error(ec);
  228. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  229. // Receive some data.
  230. DWORD recv_buf_count = static_cast<DWORD>(count);
  231. DWORD bytes_transferred = 0;
  232. DWORD recv_flags = flags;
  233. int result = error_wrapper(::WSARecv(s, bufs,
  234. recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
  235. if (result != 0)
  236. return -1;
  237. clear_error(ec);
  238. return bytes_transferred;
  239. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  240. msghdr msg = msghdr();
  241. msg.msg_iov = bufs;
  242. msg.msg_iovlen = count;
  243. int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
  244. if (result >= 0)
  245. clear_error(ec);
  246. return result;
  247. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  248. }
  249. inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
  250. socket_addr_type* addr, std::size_t* addrlen,
  251. boost::system::error_code& ec)
  252. {
  253. clear_error(ec);
  254. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  255. // Receive some data.
  256. DWORD recv_buf_count = static_cast<DWORD>(count);
  257. DWORD bytes_transferred = 0;
  258. DWORD recv_flags = flags;
  259. int tmp_addrlen = (int)*addrlen;
  260. int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
  261. &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
  262. *addrlen = (std::size_t)tmp_addrlen;
  263. if (result != 0)
  264. return -1;
  265. clear_error(ec);
  266. return bytes_transferred;
  267. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  268. msghdr msg = msghdr();
  269. init_msghdr_msg_name(msg.msg_name, addr);
  270. msg.msg_namelen = *addrlen;
  271. msg.msg_iov = bufs;
  272. msg.msg_iovlen = count;
  273. int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
  274. *addrlen = msg.msg_namelen;
  275. if (result >= 0)
  276. clear_error(ec);
  277. return result;
  278. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  279. }
  280. inline int send(socket_type s, const buf* bufs, size_t count, int flags,
  281. boost::system::error_code& ec)
  282. {
  283. clear_error(ec);
  284. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  285. // Send the data.
  286. DWORD send_buf_count = static_cast<DWORD>(count);
  287. DWORD bytes_transferred = 0;
  288. DWORD send_flags = flags;
  289. int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs),
  290. send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
  291. if (result != 0)
  292. return -1;
  293. clear_error(ec);
  294. return bytes_transferred;
  295. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  296. msghdr msg = msghdr();
  297. msg.msg_iov = const_cast<buf*>(bufs);
  298. msg.msg_iovlen = count;
  299. #if defined(__linux__)
  300. flags |= MSG_NOSIGNAL;
  301. #endif // defined(__linux__)
  302. int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
  303. if (result >= 0)
  304. clear_error(ec);
  305. return result;
  306. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  307. }
  308. inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
  309. const socket_addr_type* addr, std::size_t addrlen,
  310. boost::system::error_code& ec)
  311. {
  312. clear_error(ec);
  313. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  314. // Send the data.
  315. DWORD send_buf_count = static_cast<DWORD>(count);
  316. DWORD bytes_transferred = 0;
  317. int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
  318. send_buf_count, &bytes_transferred, flags, addr,
  319. static_cast<int>(addrlen), 0, 0), ec);
  320. if (result != 0)
  321. return -1;
  322. clear_error(ec);
  323. return bytes_transferred;
  324. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  325. msghdr msg = msghdr();
  326. init_msghdr_msg_name(msg.msg_name, addr);
  327. msg.msg_namelen = addrlen;
  328. msg.msg_iov = const_cast<buf*>(bufs);
  329. msg.msg_iovlen = count;
  330. #if defined(__linux__)
  331. flags |= MSG_NOSIGNAL;
  332. #endif // defined(__linux__)
  333. int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
  334. if (result >= 0)
  335. clear_error(ec);
  336. return result;
  337. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  338. }
  339. inline socket_type socket(int af, int type, int protocol,
  340. boost::system::error_code& ec)
  341. {
  342. clear_error(ec);
  343. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  344. socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0,
  345. WSA_FLAG_OVERLAPPED), ec);
  346. if (s == invalid_socket)
  347. return s;
  348. if (af == AF_INET6)
  349. {
  350. // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
  351. // false. This will only succeed on Windows Vista and later versions of
  352. // Windows, where a dual-stack IPv4/v6 implementation is available.
  353. DWORD optval = 0;
  354. ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
  355. reinterpret_cast<const char*>(&optval), sizeof(optval));
  356. }
  357. clear_error(ec);
  358. return s;
  359. #elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
  360. socket_type s = error_wrapper(::socket(af, type, protocol), ec);
  361. if (s == invalid_socket)
  362. return s;
  363. int optval = 1;
  364. int result = error_wrapper(::setsockopt(s,
  365. SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
  366. if (result != 0)
  367. {
  368. ::close(s);
  369. return invalid_socket;
  370. }
  371. return s;
  372. #else
  373. int s = error_wrapper(::socket(af, type, protocol), ec);
  374. if (s >= 0)
  375. clear_error(ec);
  376. return s;
  377. #endif
  378. }
  379. template <typename SockLenType>
  380. inline int call_setsockopt(SockLenType msghdr::*,
  381. socket_type s, int level, int optname,
  382. const void* optval, std::size_t optlen)
  383. {
  384. return ::setsockopt(s, level, optname,
  385. (const char*)optval, (SockLenType)optlen);
  386. }
  387. inline int setsockopt(socket_type s, int level, int optname,
  388. const void* optval, std::size_t optlen, boost::system::error_code& ec)
  389. {
  390. if (level == custom_socket_option_level && optname == always_fail_option)
  391. {
  392. ec = boost::asio::error::invalid_argument;
  393. return -1;
  394. }
  395. #if defined(__BORLANDC__)
  396. // Mysteriously, using the getsockopt and setsockopt functions directly with
  397. // Borland C++ results in incorrect values being set and read. The bug can be
  398. // worked around by using function addresses resolved with GetProcAddress.
  399. if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
  400. {
  401. typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);
  402. if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))
  403. {
  404. clear_error(ec);
  405. return error_wrapper(sso(s, level, optname,
  406. reinterpret_cast<const char*>(optval),
  407. static_cast<int>(optlen)), ec);
  408. }
  409. }
  410. ec = boost::asio::error::fault;
  411. return -1;
  412. #else // defined(__BORLANDC__)
  413. clear_error(ec);
  414. int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
  415. s, level, optname, optval, optlen), ec);
  416. if (result == 0)
  417. clear_error(ec);
  418. return result;
  419. #endif // defined(__BORLANDC__)
  420. }
  421. template <typename SockLenType>
  422. inline int call_getsockopt(SockLenType msghdr::*,
  423. socket_type s, int level, int optname,
  424. void* optval, std::size_t* optlen)
  425. {
  426. SockLenType tmp_optlen = (SockLenType)*optlen;
  427. int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
  428. *optlen = (std::size_t)tmp_optlen;
  429. return result;
  430. }
  431. inline int getsockopt(socket_type s, int level, int optname, void* optval,
  432. size_t* optlen, boost::system::error_code& ec)
  433. {
  434. if (level == custom_socket_option_level && optname == always_fail_option)
  435. {
  436. ec = boost::asio::error::invalid_argument;
  437. return -1;
  438. }
  439. #if defined(__BORLANDC__)
  440. // Mysteriously, using the getsockopt and setsockopt functions directly with
  441. // Borland C++ results in incorrect values being set and read. The bug can be
  442. // worked around by using function addresses resolved with GetProcAddress.
  443. if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
  444. {
  445. typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);
  446. if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))
  447. {
  448. clear_error(ec);
  449. int tmp_optlen = static_cast<int>(*optlen);
  450. int result = error_wrapper(gso(s, level, optname,
  451. reinterpret_cast<char*>(optval), &tmp_optlen), ec);
  452. *optlen = static_cast<size_t>(tmp_optlen);
  453. if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
  454. && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
  455. {
  456. // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
  457. // only supported on Windows Vista and later. To simplify program logic
  458. // we will fake success of getting this option and specify that the
  459. // value is non-zero (i.e. true). This corresponds to the behavior of
  460. // IPv6 sockets on Windows platforms pre-Vista.
  461. *static_cast<DWORD*>(optval) = 1;
  462. clear_error(ec);
  463. }
  464. return result;
  465. }
  466. }
  467. ec = boost::asio::error::fault;
  468. return -1;
  469. #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  470. clear_error(ec);
  471. int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
  472. s, level, optname, optval, optlen), ec);
  473. if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
  474. && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
  475. {
  476. // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
  477. // supported on Windows Vista and later. To simplify program logic we will
  478. // fake success of getting this option and specify that the value is
  479. // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
  480. // on Windows platforms pre-Vista.
  481. *static_cast<DWORD*>(optval) = 1;
  482. clear_error(ec);
  483. }
  484. if (result == 0)
  485. clear_error(ec);
  486. return result;
  487. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  488. clear_error(ec);
  489. int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
  490. s, level, optname, optval, optlen), ec);
  491. #if defined(__linux__)
  492. if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
  493. && (optname == SO_SNDBUF || optname == SO_RCVBUF))
  494. {
  495. // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
  496. // to set the buffer size to N*2. Linux puts additional stuff into the
  497. // buffers so that only about half is actually available to the application.
  498. // The retrieved value is divided by 2 here to make it appear as though the
  499. // correct value has been set.
  500. *static_cast<int*>(optval) /= 2;
  501. }
  502. #endif // defined(__linux__)
  503. if (result == 0)
  504. clear_error(ec);
  505. return result;
  506. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  507. }
  508. template <typename SockLenType>
  509. inline int call_getpeername(SockLenType msghdr::*,
  510. socket_type s, socket_addr_type* addr, std::size_t* addrlen)
  511. {
  512. SockLenType tmp_addrlen = (SockLenType)*addrlen;
  513. int result = ::getpeername(s, addr, &tmp_addrlen);
  514. *addrlen = (std::size_t)tmp_addrlen;
  515. return result;
  516. }
  517. inline int getpeername(socket_type s, socket_addr_type* addr,
  518. std::size_t* addrlen, boost::system::error_code& ec)
  519. {
  520. clear_error(ec);
  521. int result = error_wrapper(call_getpeername(
  522. &msghdr::msg_namelen, s, addr, addrlen), ec);
  523. if (result == 0)
  524. clear_error(ec);
  525. return result;
  526. }
  527. template <typename SockLenType>
  528. inline int call_getsockname(SockLenType msghdr::*,
  529. socket_type s, socket_addr_type* addr, std::size_t* addrlen)
  530. {
  531. SockLenType tmp_addrlen = (SockLenType)*addrlen;
  532. int result = ::getsockname(s, addr, &tmp_addrlen);
  533. *addrlen = (std::size_t)tmp_addrlen;
  534. return result;
  535. }
  536. inline int getsockname(socket_type s, socket_addr_type* addr,
  537. std::size_t* addrlen, boost::system::error_code& ec)
  538. {
  539. clear_error(ec);
  540. int result = error_wrapper(call_getsockname(
  541. &msghdr::msg_namelen, s, addr, addrlen), ec);
  542. if (result == 0)
  543. clear_error(ec);
  544. return result;
  545. }
  546. inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
  547. boost::system::error_code& ec)
  548. {
  549. clear_error(ec);
  550. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  551. int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
  552. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  553. int result = error_wrapper(::ioctl(s, cmd, arg), ec);
  554. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  555. if (result >= 0)
  556. clear_error(ec);
  557. return result;
  558. }
  559. inline int select(int nfds, fd_set* readfds, fd_set* writefds,
  560. fd_set* exceptfds, timeval* timeout, boost::system::error_code& ec)
  561. {
  562. clear_error(ec);
  563. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  564. if (!readfds && !writefds && !exceptfds && timeout)
  565. {
  566. DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
  567. if (milliseconds == 0)
  568. milliseconds = 1; // Force context switch.
  569. ::Sleep(milliseconds);
  570. ec = boost::system::error_code();
  571. return 0;
  572. }
  573. // The select() call allows timeout values measured in microseconds, but the
  574. // system clock (as wrapped by boost::posix_time::microsec_clock) typically
  575. // has a resolution of 10 milliseconds. This can lead to a spinning select
  576. // reactor, meaning increased CPU usage, when waiting for the earliest
  577. // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
  578. // spin we'll use a minimum timeout of 1 millisecond.
  579. if (timeout && timeout->tv_sec == 0
  580. && timeout->tv_usec > 0 && timeout->tv_usec < 1000)
  581. timeout->tv_usec = 1000;
  582. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  583. #if defined(__hpux) && defined(__HP_aCC)
  584. timespec ts;
  585. ts.tv_sec = timeout ? timeout->tv_sec : 0;
  586. ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
  587. return error_wrapper(::pselect(nfds, readfds,
  588. writefds, exceptfds, timeout ? &ts : 0, 0), ec);
  589. #else
  590. int result = error_wrapper(::select(nfds, readfds,
  591. writefds, exceptfds, timeout), ec);
  592. if (result >= 0)
  593. clear_error(ec);
  594. return result;
  595. #endif
  596. }
  597. inline int poll_read(socket_type s, boost::system::error_code& ec)
  598. {
  599. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  600. FD_SET fds;
  601. FD_ZERO(&fds);
  602. FD_SET(s, &fds);
  603. clear_error(ec);
  604. int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
  605. if (result >= 0)
  606. clear_error(ec);
  607. return result;
  608. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  609. pollfd fds;
  610. fds.fd = s;
  611. fds.events = POLLIN;
  612. fds.revents = 0;
  613. clear_error(ec);
  614. int result = error_wrapper(::poll(&fds, 1, -1), ec);
  615. if (result >= 0)
  616. clear_error(ec);
  617. return result;
  618. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  619. }
  620. inline int poll_write(socket_type s, boost::system::error_code& ec)
  621. {
  622. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  623. FD_SET fds;
  624. FD_ZERO(&fds);
  625. FD_SET(s, &fds);
  626. clear_error(ec);
  627. int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
  628. if (result >= 0)
  629. clear_error(ec);
  630. return result;
  631. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  632. pollfd fds;
  633. fds.fd = s;
  634. fds.events = POLLOUT;
  635. fds.revents = 0;
  636. clear_error(ec);
  637. int result = error_wrapper(::poll(&fds, 1, -1), ec);
  638. if (result >= 0)
  639. clear_error(ec);
  640. return result;
  641. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  642. }
  643. inline int poll_connect(socket_type s, boost::system::error_code& ec)
  644. {
  645. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  646. FD_SET write_fds;
  647. FD_ZERO(&write_fds);
  648. FD_SET(s, &write_fds);
  649. FD_SET except_fds;
  650. FD_ZERO(&except_fds);
  651. FD_SET(s, &except_fds);
  652. clear_error(ec);
  653. int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec);
  654. if (result >= 0)
  655. clear_error(ec);
  656. return result;
  657. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  658. pollfd fds;
  659. fds.fd = s;
  660. fds.events = POLLOUT;
  661. fds.revents = 0;
  662. clear_error(ec);
  663. int result = error_wrapper(::poll(&fds, 1, -1), ec);
  664. if (result >= 0)
  665. clear_error(ec);
  666. return result;
  667. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  668. }
  669. inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,
  670. unsigned long scope_id, boost::system::error_code& ec)
  671. {
  672. clear_error(ec);
  673. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  674. using namespace std; // For memcpy.
  675. if (af != AF_INET && af != AF_INET6)
  676. {
  677. ec = boost::asio::error::address_family_not_supported;
  678. return 0;
  679. }
  680. union
  681. {
  682. socket_addr_type base;
  683. sockaddr_storage_type storage;
  684. sockaddr_in4_type v4;
  685. sockaddr_in6_type v6;
  686. } address;
  687. DWORD address_length;
  688. if (af == AF_INET)
  689. {
  690. address_length = sizeof(sockaddr_in4_type);
  691. address.v4.sin_family = AF_INET;
  692. address.v4.sin_port = 0;
  693. memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
  694. }
  695. else // AF_INET6
  696. {
  697. address_length = sizeof(sockaddr_in6_type);
  698. address.v6.sin6_family = AF_INET6;
  699. address.v6.sin6_port = 0;
  700. address.v6.sin6_flowinfo = 0;
  701. address.v6.sin6_scope_id = scope_id;
  702. memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
  703. }
  704. DWORD string_length = static_cast<DWORD>(length);
  705. #if defined(BOOST_NO_ANSI_APIS)
  706. LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
  707. int result = error_wrapper(::WSAAddressToStringW(&address.base,
  708. address_length, 0, string_buffer, &string_length), ec);
  709. ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
  710. #else
  711. int result = error_wrapper(::WSAAddressToStringA(
  712. &address.base, address_length, 0, dest, &string_length), ec);
  713. #endif
  714. // Windows may set error code on success.
  715. if (result != socket_error_retval)
  716. clear_error(ec);
  717. // Windows may not set an error code on failure.
  718. else if (result == socket_error_retval && !ec)
  719. ec = boost::asio::error::invalid_argument;
  720. return result == socket_error_retval ? 0 : dest;
  721. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  722. const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec);
  723. if (result == 0 && !ec)
  724. ec = boost::asio::error::invalid_argument;
  725. if (result != 0 && af == AF_INET6 && scope_id != 0)
  726. {
  727. using namespace std; // For strcat and sprintf.
  728. char if_name[IF_NAMESIZE + 1] = "%";
  729. const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
  730. bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
  731. if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
  732. sprintf(if_name + 1, "%lu", scope_id);
  733. strcat(dest, if_name);
  734. }
  735. return result;
  736. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  737. }
  738. inline int inet_pton(int af, const char* src, void* dest,
  739. unsigned long* scope_id, boost::system::error_code& ec)
  740. {
  741. clear_error(ec);
  742. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  743. using namespace std; // For memcpy and strcmp.
  744. if (af != AF_INET && af != AF_INET6)
  745. {
  746. ec = boost::asio::error::address_family_not_supported;
  747. return -1;
  748. }
  749. union
  750. {
  751. socket_addr_type base;
  752. sockaddr_storage_type storage;
  753. sockaddr_in4_type v4;
  754. sockaddr_in6_type v6;
  755. } address;
  756. int address_length = sizeof(sockaddr_storage_type);
  757. #if defined(BOOST_NO_ANSI_APIS)
  758. int num_wide_chars = strlen(src) + 1;
  759. LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
  760. ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
  761. int result = error_wrapper(::WSAStringToAddressW(
  762. wide_buffer, af, 0, &address.base, &address_length), ec);
  763. #else
  764. int result = error_wrapper(::WSAStringToAddressA(
  765. const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
  766. #endif
  767. if (af == AF_INET)
  768. {
  769. if (result != socket_error_retval)
  770. {
  771. memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
  772. clear_error(ec);
  773. }
  774. else if (strcmp(src, "255.255.255.255") == 0)
  775. {
  776. static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;
  777. clear_error(ec);
  778. }
  779. }
  780. else // AF_INET6
  781. {
  782. if (result != socket_error_retval)
  783. {
  784. memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
  785. if (scope_id)
  786. *scope_id = address.v6.sin6_scope_id;
  787. clear_error(ec);
  788. }
  789. }
  790. // Windows may not set an error code on failure.
  791. if (result == socket_error_retval && !ec)
  792. ec = boost::asio::error::invalid_argument;
  793. if (result != socket_error_retval)
  794. clear_error(ec);
  795. return result == socket_error_retval ? -1 : 1;
  796. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  797. int result = error_wrapper(::inet_pton(af, src, dest), ec);
  798. if (result <= 0 && !ec)
  799. ec = boost::asio::error::invalid_argument;
  800. if (result > 0 && af == AF_INET6 && scope_id)
  801. {
  802. using namespace std; // For strchr and atoi.
  803. *scope_id = 0;
  804. if (const char* if_name = strchr(src, '%'))
  805. {
  806. in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);
  807. bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
  808. if (is_link_local)
  809. *scope_id = if_nametoindex(if_name + 1);
  810. if (*scope_id == 0)
  811. *scope_id = atoi(if_name + 1);
  812. }
  813. }
  814. return result;
  815. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  816. }
  817. inline int gethostname(char* name, int namelen, boost::system::error_code& ec)
  818. {
  819. clear_error(ec);
  820. int result = error_wrapper(::gethostname(name, namelen), ec);
  821. #if defined(BOOST_WINDOWS)
  822. if (result == 0)
  823. clear_error(ec);
  824. #endif
  825. return result;
  826. }
  827. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
  828. || defined(__MACH__) && defined(__APPLE__)
  829. // The following functions are only needed for emulation of getaddrinfo and
  830. // getnameinfo.
  831. inline boost::system::error_code translate_netdb_error(int error)
  832. {
  833. switch (error)
  834. {
  835. case 0:
  836. return boost::system::error_code();
  837. case HOST_NOT_FOUND:
  838. return boost::asio::error::host_not_found;
  839. case TRY_AGAIN:
  840. return boost::asio::error::host_not_found_try_again;
  841. case NO_RECOVERY:
  842. return boost::asio::error::no_recovery;
  843. case NO_DATA:
  844. return boost::asio::error::no_data;
  845. default:
  846. BOOST_ASSERT(false);
  847. return boost::asio::error::invalid_argument;
  848. }
  849. }
  850. inline hostent* gethostbyaddr(const char* addr, int length, int af,
  851. hostent* result, char* buffer, int buflength, boost::system::error_code& ec)
  852. {
  853. clear_error(ec);
  854. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  855. (void)(buffer);
  856. (void)(buflength);
  857. hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
  858. if (!retval)
  859. return 0;
  860. clear_error(ec);
  861. *result = *retval;
  862. return retval;
  863. #elif defined(__sun) || defined(__QNX__)
  864. int error = 0;
  865. hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result,
  866. buffer, buflength, &error), ec);
  867. if (error)
  868. ec = translate_netdb_error(error);
  869. return retval;
  870. #elif defined(__MACH__) && defined(__APPLE__)
  871. (void)(buffer);
  872. (void)(buflength);
  873. int error = 0;
  874. hostent* retval = error_wrapper(::getipnodebyaddr(
  875. addr, length, af, &error), ec);
  876. if (error)
  877. ec = translate_netdb_error(error);
  878. if (!retval)
  879. return 0;
  880. *result = *retval;
  881. return retval;
  882. #else
  883. hostent* retval = 0;
  884. int error = 0;
  885. error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer,
  886. buflength, &retval, &error), ec);
  887. if (error)
  888. ec = translate_netdb_error(error);
  889. return retval;
  890. #endif
  891. }
  892. inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
  893. char* buffer, int buflength, int ai_flags, boost::system::error_code& ec)
  894. {
  895. clear_error(ec);
  896. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  897. (void)(buffer);
  898. (void)(buflength);
  899. (void)(ai_flags);
  900. if (af != AF_INET)
  901. {
  902. ec = boost::asio::error::address_family_not_supported;
  903. return 0;
  904. }
  905. hostent* retval = error_wrapper(::gethostbyname(name), ec);
  906. if (!retval)
  907. return 0;
  908. clear_error(ec);
  909. *result = *retval;
  910. return result;
  911. #elif defined(__sun) || defined(__QNX__)
  912. (void)(ai_flags);
  913. if (af != AF_INET)
  914. {
  915. ec = boost::asio::error::address_family_not_supported;
  916. return 0;
  917. }
  918. int error = 0;
  919. hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer,
  920. buflength, &error), ec);
  921. if (error)
  922. ec = translate_netdb_error(error);
  923. return retval;
  924. #elif defined(__MACH__) && defined(__APPLE__)
  925. (void)(buffer);
  926. (void)(buflength);
  927. int error = 0;
  928. hostent* retval = error_wrapper(::getipnodebyname(
  929. name, af, ai_flags, &error), ec);
  930. if (error)
  931. ec = translate_netdb_error(error);
  932. if (!retval)
  933. return 0;
  934. *result = *retval;
  935. return retval;
  936. #else
  937. (void)(ai_flags);
  938. if (af != AF_INET)
  939. {
  940. ec = boost::asio::error::address_family_not_supported;
  941. return 0;
  942. }
  943. hostent* retval = 0;
  944. int error = 0;
  945. error_wrapper(::gethostbyname_r(name, result,
  946. buffer, buflength, &retval, &error), ec);
  947. if (error)
  948. ec = translate_netdb_error(error);
  949. return retval;
  950. #endif
  951. }
  952. inline void freehostent(hostent* h)
  953. {
  954. #if defined(__MACH__) && defined(__APPLE__)
  955. if (h)
  956. ::freehostent(h);
  957. #else
  958. (void)(h);
  959. #endif
  960. }
  961. // Emulation of getaddrinfo based on implementation in:
  962. // Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
  963. struct gai_search
  964. {
  965. const char* host;
  966. int family;
  967. };
  968. inline int gai_nsearch(const char* host,
  969. const addrinfo_type* hints, gai_search (&search)[2])
  970. {
  971. int search_count = 0;
  972. if (host == 0 || host[0] == '\0')
  973. {
  974. if (hints->ai_flags & AI_PASSIVE)
  975. {
  976. // No host and AI_PASSIVE implies wildcard bind.
  977. switch (hints->ai_family)
  978. {
  979. case AF_INET:
  980. search[search_count].host = "0.0.0.0";
  981. search[search_count].family = AF_INET;
  982. ++search_count;
  983. break;
  984. case AF_INET6:
  985. search[search_count].host = "0::0";
  986. search[search_count].family = AF_INET6;
  987. ++search_count;
  988. break;
  989. case AF_UNSPEC:
  990. search[search_count].host = "0::0";
  991. search[search_count].family = AF_INET6;
  992. ++search_count;
  993. search[search_count].host = "0.0.0.0";
  994. search[search_count].family = AF_INET;
  995. ++search_count;
  996. break;
  997. default:
  998. break;
  999. }
  1000. }
  1001. else
  1002. {
  1003. // No host and not AI_PASSIVE means connect to local host.
  1004. switch (hints->ai_family)
  1005. {
  1006. case AF_INET:
  1007. search[search_count].host = "localhost";
  1008. search[search_count].family = AF_INET;
  1009. ++search_count;
  1010. break;
  1011. case AF_INET6:
  1012. search[search_count].host = "localhost";
  1013. search[search_count].family = AF_INET6;
  1014. ++search_count;
  1015. break;
  1016. case AF_UNSPEC:
  1017. search[search_count].host = "localhost";
  1018. search[search_count].family = AF_INET6;
  1019. ++search_count;
  1020. search[search_count].host = "localhost";
  1021. search[search_count].family = AF_INET;
  1022. ++search_count;
  1023. break;
  1024. default:
  1025. break;
  1026. }
  1027. }
  1028. }
  1029. else
  1030. {
  1031. // Host is specified.
  1032. switch (hints->ai_family)
  1033. {
  1034. case AF_INET:
  1035. search[search_count].host = host;
  1036. search[search_count].family = AF_INET;
  1037. ++search_count;
  1038. break;
  1039. case AF_INET6:
  1040. search[search_count].host = host;
  1041. search[search_count].family = AF_INET6;
  1042. ++search_count;
  1043. break;
  1044. case AF_UNSPEC:
  1045. search[search_count].host = host;
  1046. search[search_count].family = AF_INET6;
  1047. ++search_count;
  1048. search[search_count].host = host;
  1049. search[search_count].family = AF_INET;
  1050. ++search_count;
  1051. break;
  1052. default:
  1053. break;
  1054. }
  1055. }
  1056. return search_count;
  1057. }
  1058. template <typename T>
  1059. inline T* gai_alloc(std::size_t size = sizeof(T))
  1060. {
  1061. using namespace std;
  1062. T* p = static_cast<T*>(::operator new(size, std::nothrow));
  1063. if (p)
  1064. memset(p, 0, size);
  1065. return p;
  1066. }
  1067. inline void gai_free(void* p)
  1068. {
  1069. ::operator delete(p);
  1070. }
  1071. inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
  1072. {
  1073. using namespace std;
  1074. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
  1075. strcpy_s(target, max_size, source);
  1076. #else
  1077. *target = 0;
  1078. strncat(target, source, max_size);
  1079. #endif
  1080. }
  1081. enum { gai_clone_flag = 1 << 30 };
  1082. inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
  1083. const void* addr, int family)
  1084. {
  1085. using namespace std;
  1086. addrinfo_type* ai = gai_alloc<addrinfo_type>();
  1087. if (ai == 0)
  1088. return EAI_MEMORY;
  1089. ai->ai_next = 0;
  1090. **next = ai;
  1091. *next = &ai->ai_next;
  1092. ai->ai_canonname = 0;
  1093. ai->ai_socktype = hints->ai_socktype;
  1094. if (ai->ai_socktype == 0)
  1095. ai->ai_flags |= gai_clone_flag;
  1096. ai->ai_protocol = hints->ai_protocol;
  1097. ai->ai_family = family;
  1098. switch (ai->ai_family)
  1099. {
  1100. case AF_INET:
  1101. {
  1102. sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();
  1103. if (sinptr == 0)
  1104. return EAI_MEMORY;
  1105. sinptr->sin_family = AF_INET;
  1106. memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));
  1107. ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);
  1108. ai->ai_addrlen = sizeof(sockaddr_in4_type);
  1109. break;
  1110. }
  1111. case AF_INET6:
  1112. {
  1113. sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();
  1114. if (sin6ptr == 0)
  1115. return EAI_MEMORY;
  1116. sin6ptr->sin6_family = AF_INET6;
  1117. memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));
  1118. ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);
  1119. ai->ai_addrlen = sizeof(sockaddr_in6_type);
  1120. break;
  1121. }
  1122. default:
  1123. break;
  1124. }
  1125. return 0;
  1126. }
  1127. inline addrinfo_type* gai_clone(addrinfo_type* ai)
  1128. {
  1129. using namespace std;
  1130. addrinfo_type* new_ai = gai_alloc<addrinfo_type>();
  1131. if (new_ai == 0)
  1132. return new_ai;
  1133. new_ai->ai_next = ai->ai_next;
  1134. ai->ai_next = new_ai;
  1135. new_ai->ai_flags = 0;
  1136. new_ai->ai_family = ai->ai_family;
  1137. new_ai->ai_socktype = ai->ai_socktype;
  1138. new_ai->ai_protocol = ai->ai_protocol;
  1139. new_ai->ai_canonname = 0;
  1140. new_ai->ai_addrlen = ai->ai_addrlen;
  1141. new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);
  1142. memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);
  1143. return new_ai;
  1144. }
  1145. inline int gai_port(addrinfo_type* aihead, int port, int socktype)
  1146. {
  1147. int num_found = 0;
  1148. for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)
  1149. {
  1150. if (ai->ai_flags & gai_clone_flag)
  1151. {
  1152. if (ai->ai_socktype != 0)
  1153. {
  1154. ai = gai_clone(ai);
  1155. if (ai == 0)
  1156. return -1;
  1157. // ai now points to newly cloned entry.
  1158. }
  1159. }
  1160. else if (ai->ai_socktype != socktype)
  1161. {
  1162. // Ignore if mismatch on socket type.
  1163. continue;
  1164. }
  1165. ai->ai_socktype = socktype;
  1166. switch (ai->ai_family)
  1167. {
  1168. case AF_INET:
  1169. {
  1170. sockaddr_in4_type* sinptr =
  1171. reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
  1172. sinptr->sin_port = port;
  1173. ++num_found;
  1174. break;
  1175. }
  1176. case AF_INET6:
  1177. {
  1178. sockaddr_in6_type* sin6ptr =
  1179. reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
  1180. sin6ptr->sin6_port = port;
  1181. ++num_found;
  1182. break;
  1183. }
  1184. default:
  1185. break;
  1186. }
  1187. }
  1188. return num_found;
  1189. }
  1190. inline int gai_serv(addrinfo_type* aihead,
  1191. const addrinfo_type* hints, const char* serv)
  1192. {
  1193. using namespace std;
  1194. int num_found = 0;
  1195. if (
  1196. #if defined(AI_NUMERICSERV)
  1197. (hints->ai_flags & AI_NUMERICSERV) ||
  1198. #endif
  1199. isdigit(serv[0]))
  1200. {
  1201. int port = htons(atoi(serv));
  1202. if (hints->ai_socktype)
  1203. {
  1204. // Caller specifies socket type.
  1205. int rc = gai_port(aihead, port, hints->ai_socktype);
  1206. if (rc < 0)
  1207. return EAI_MEMORY;
  1208. num_found += rc;
  1209. }
  1210. else
  1211. {
  1212. // Caller does not specify socket type.
  1213. int rc = gai_port(aihead, port, SOCK_STREAM);
  1214. if (rc < 0)
  1215. return EAI_MEMORY;
  1216. num_found += rc;
  1217. rc = gai_port(aihead, port, SOCK_DGRAM);
  1218. if (rc < 0)
  1219. return EAI_MEMORY;
  1220. num_found += rc;
  1221. }
  1222. }
  1223. else
  1224. {
  1225. // Try service name with TCP first, then UDP.
  1226. if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)
  1227. {
  1228. servent* sptr = getservbyname(serv, "tcp");
  1229. if (sptr != 0)
  1230. {
  1231. int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);
  1232. if (rc < 0)
  1233. return EAI_MEMORY;
  1234. num_found += rc;
  1235. }
  1236. }
  1237. if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)
  1238. {
  1239. servent* sptr = getservbyname(serv, "udp");
  1240. if (sptr != 0)
  1241. {
  1242. int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);
  1243. if (rc < 0)
  1244. return EAI_MEMORY;
  1245. num_found += rc;
  1246. }
  1247. }
  1248. }
  1249. if (num_found == 0)
  1250. {
  1251. if (hints->ai_socktype == 0)
  1252. {
  1253. // All calls to getservbyname() failed.
  1254. return EAI_NONAME;
  1255. }
  1256. else
  1257. {
  1258. // Service not supported for socket type.
  1259. return EAI_SERVICE;
  1260. }
  1261. }
  1262. return 0;
  1263. }
  1264. inline int gai_echeck(const char* host, const char* service,
  1265. int flags, int family, int socktype, int protocol)
  1266. {
  1267. (void)(flags);
  1268. (void)(protocol);
  1269. // Host or service must be specified.
  1270. if (host == 0 || host[0] == '\0')
  1271. if (service == 0 || service[0] == '\0')
  1272. return EAI_NONAME;
  1273. // Check combination of family and socket type.
  1274. switch (family)
  1275. {
  1276. case AF_UNSPEC:
  1277. break;
  1278. case AF_INET:
  1279. case AF_INET6:
  1280. if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
  1281. return EAI_SOCKTYPE;
  1282. break;
  1283. default:
  1284. return EAI_FAMILY;
  1285. }
  1286. return 0;
  1287. }
  1288. inline void freeaddrinfo_emulation(addrinfo_type* aihead)
  1289. {
  1290. addrinfo_type* ai = aihead;
  1291. while (ai)
  1292. {
  1293. gai_free(ai->ai_addr);
  1294. gai_free(ai->ai_canonname);
  1295. addrinfo_type* ainext = ai->ai_next;
  1296. gai_free(ai);
  1297. ai = ainext;
  1298. }
  1299. }
  1300. inline int getaddrinfo_emulation(const char* host, const char* service,
  1301. const addrinfo_type* hintsp, addrinfo_type** result)
  1302. {
  1303. // Set up linked list of addrinfo structures.
  1304. addrinfo_type* aihead = 0;
  1305. addrinfo_type** ainext = &aihead;
  1306. char* canon = 0;
  1307. // Supply default hints if not specified by caller.
  1308. addrinfo_type hints = addrinfo_type();
  1309. hints.ai_family = AF_UNSPEC;
  1310. if (hintsp)
  1311. hints = *hintsp;
  1312. // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED
  1313. // and AI_ALL flags.
  1314. #if defined(AI_V4MAPPED)
  1315. if (hints.ai_family != AF_INET6)
  1316. hints.ai_flags &= ~AI_V4MAPPED;
  1317. #endif
  1318. #if defined(AI_ALL)
  1319. if (hints.ai_family != AF_INET6)
  1320. hints.ai_flags &= ~AI_ALL;
  1321. #endif
  1322. // Basic error checking.
  1323. int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family,
  1324. hints.ai_socktype, hints.ai_protocol);
  1325. if (rc != 0)
  1326. {
  1327. freeaddrinfo_emulation(aihead);
  1328. return rc;
  1329. }
  1330. gai_search search[2];
  1331. int search_count = gai_nsearch(host, &hints, search);
  1332. for (gai_search* sptr = search; sptr < search + search_count; ++sptr)
  1333. {
  1334. // Check for IPv4 dotted decimal string.
  1335. in4_addr_type inaddr;
  1336. boost::system::error_code ec;
  1337. if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1)
  1338. {
  1339. if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
  1340. {
  1341. freeaddrinfo_emulation(aihead);
  1342. gai_free(canon);
  1343. return EAI_FAMILY;
  1344. }
  1345. if (sptr->family == AF_INET)
  1346. {
  1347. rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET);
  1348. if (rc != 0)
  1349. {
  1350. freeaddrinfo_emulation(aihead);
  1351. gai_free(canon);
  1352. return rc;
  1353. }
  1354. }
  1355. continue;
  1356. }
  1357. // Check for IPv6 hex string.
  1358. in6_addr_type in6addr;
  1359. if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1)
  1360. {
  1361. if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6)
  1362. {
  1363. freeaddrinfo_emulation(aihead);
  1364. gai_free(canon);
  1365. return EAI_FAMILY;
  1366. }
  1367. if (sptr->family == AF_INET6)
  1368. {
  1369. rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6);
  1370. if (rc != 0)
  1371. {
  1372. freeaddrinfo_emulation(aihead);
  1373. gai_free(canon);
  1374. return rc;
  1375. }
  1376. }
  1377. continue;
  1378. }
  1379. // Look up hostname.
  1380. hostent hent;
  1381. char hbuf[8192] = "";
  1382. hostent* hptr = socket_ops::gethostbyname(sptr->host,
  1383. sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec);
  1384. if (hptr == 0)
  1385. {
  1386. if (search_count == 2)
  1387. {
  1388. // Failure is OK if there are multiple searches.
  1389. continue;
  1390. }
  1391. freeaddrinfo_emulation(aihead);
  1392. gai_free(canon);
  1393. if (ec == boost::asio::error::host_not_found)
  1394. return EAI_NONAME;
  1395. if (ec == boost::asio::error::host_not_found_try_again)
  1396. return EAI_AGAIN;
  1397. if (ec == boost::asio::error::no_recovery)
  1398. return EAI_FAIL;
  1399. if (ec == boost::asio::error::no_data)
  1400. return EAI_NONAME;
  1401. return EAI_NONAME;
  1402. }
  1403. // Check for address family mismatch if one was specified.
  1404. if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype)
  1405. {
  1406. freeaddrinfo_emulation(aihead);
  1407. gai_free(canon);
  1408. socket_ops::freehostent(hptr);
  1409. return EAI_FAMILY;
  1410. }
  1411. // Save canonical name first time.
  1412. if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]
  1413. && (hints.ai_flags & AI_CANONNAME) && canon == 0)
  1414. {
  1415. std::size_t canon_len = strlen(hptr->h_name) + 1;
  1416. canon = gai_alloc<char>(canon_len);
  1417. if (canon == 0)
  1418. {
  1419. freeaddrinfo_emulation(aihead);
  1420. socket_ops::freehostent(hptr);
  1421. return EAI_MEMORY;
  1422. }
  1423. gai_strcpy(canon, hptr->h_name, canon_len);
  1424. }
  1425. // Create an addrinfo structure for each returned address.
  1426. for (char** ap = hptr->h_addr_list; *ap; ++ap)
  1427. {
  1428. rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype);
  1429. if (rc != 0)
  1430. {
  1431. freeaddrinfo_emulation(aihead);
  1432. gai_free(canon);
  1433. socket_ops::freehostent(hptr);
  1434. return EAI_FAMILY;
  1435. }
  1436. }
  1437. socket_ops::freehostent(hptr);
  1438. }
  1439. // Check if we found anything.
  1440. if (aihead == 0)
  1441. {
  1442. gai_free(canon);
  1443. return EAI_NONAME;
  1444. }
  1445. // Return canonical name in first entry.
  1446. if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME))
  1447. {
  1448. if (canon)
  1449. {
  1450. aihead->ai_canonname = canon;
  1451. canon = 0;
  1452. }
  1453. else
  1454. {
  1455. std::size_t canonname_len = strlen(search[0].host) + 1;
  1456. aihead->ai_canonname = gai_alloc<char>(canonname_len);
  1457. if (aihead->ai_canonname == 0)
  1458. {
  1459. freeaddrinfo_emulation(aihead);
  1460. return EAI_MEMORY;
  1461. }
  1462. gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len);
  1463. }
  1464. }
  1465. gai_free(canon);
  1466. // Process the service name.
  1467. if (service != 0 && service[0] != '\0')
  1468. {
  1469. rc = gai_serv(aihead, &hints, service);
  1470. if (rc != 0)
  1471. {
  1472. freeaddrinfo_emulation(aihead);
  1473. return rc;
  1474. }
  1475. }
  1476. // Return result to caller.
  1477. *result = aihead;
  1478. return 0;
  1479. }
  1480. inline boost::system::error_code getnameinfo_emulation(
  1481. const socket_addr_type* sa, std::size_t salen, char* host,
  1482. std::size_t hostlen, char* serv, std::size_t servlen, int flags,
  1483. boost::system::error_code& ec)
  1484. {
  1485. using namespace std;
  1486. const char* addr;
  1487. size_t addr_len;
  1488. unsigned short port;
  1489. switch (sa->sa_family)
  1490. {
  1491. case AF_INET:
  1492. if (salen != sizeof(sockaddr_in4_type))
  1493. {
  1494. return ec = boost::asio::error::invalid_argument;
  1495. }
  1496. addr = reinterpret_cast<const char*>(
  1497. &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);
  1498. addr_len = sizeof(in4_addr_type);
  1499. port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;
  1500. break;
  1501. case AF_INET6:
  1502. if (salen != sizeof(sockaddr_in6_type))
  1503. {
  1504. return ec = boost::asio::error::invalid_argument;
  1505. }
  1506. addr = reinterpret_cast<const char*>(
  1507. &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);
  1508. addr_len = sizeof(in6_addr_type);
  1509. port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;
  1510. break;
  1511. default:
  1512. return ec = boost::asio::error::address_family_not_supported;
  1513. }
  1514. if (host && hostlen > 0)
  1515. {
  1516. if (flags & NI_NUMERICHOST)
  1517. {
  1518. if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)
  1519. {
  1520. return ec;
  1521. }
  1522. }
  1523. else
  1524. {
  1525. hostent hent;
  1526. char hbuf[8192] = "";
  1527. hostent* hptr = socket_ops::gethostbyaddr(addr,
  1528. static_cast<int>(addr_len), sa->sa_family,
  1529. &hent, hbuf, sizeof(hbuf), ec);
  1530. if (hptr && hptr->h_name && hptr->h_name[0] != '\0')
  1531. {
  1532. if (flags & NI_NOFQDN)
  1533. {
  1534. char* dot = strchr(hptr->h_name, '.');
  1535. if (dot)
  1536. {
  1537. *dot = 0;
  1538. }
  1539. }
  1540. gai_strcpy(host, hptr->h_name, hostlen);
  1541. socket_ops::freehostent(hptr);
  1542. }
  1543. else
  1544. {
  1545. socket_ops::freehostent(hptr);
  1546. if (flags & NI_NAMEREQD)
  1547. {
  1548. return ec = boost::asio::error::host_not_found;
  1549. }
  1550. if (socket_ops::inet_ntop(sa->sa_family,
  1551. addr, host, hostlen, 0, ec) == 0)
  1552. {
  1553. return ec;
  1554. }
  1555. }
  1556. }
  1557. }
  1558. if (serv && servlen > 0)
  1559. {
  1560. if (flags & NI_NUMERICSERV)
  1561. {
  1562. if (servlen < 6)
  1563. {
  1564. return ec = boost::asio::error::no_buffer_space;
  1565. }
  1566. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
  1567. sprintf_s(serv, servlen, "%u", ntohs(port));
  1568. #else
  1569. sprintf(serv, "%u", ntohs(port));
  1570. #endif
  1571. }
  1572. else
  1573. {
  1574. #if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
  1575. static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  1576. ::pthread_mutex_lock(&mutex);
  1577. #endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
  1578. servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
  1579. if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
  1580. {
  1581. gai_strcpy(serv, sptr->s_name, servlen);
  1582. }
  1583. else
  1584. {
  1585. if (servlen < 6)
  1586. {
  1587. return ec = boost::asio::error::no_buffer_space;
  1588. }
  1589. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
  1590. sprintf_s(serv, servlen, "%u", ntohs(port));
  1591. #else
  1592. sprintf(serv, "%u", ntohs(port));
  1593. #endif
  1594. }
  1595. #if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
  1596. ::pthread_mutex_unlock(&mutex);
  1597. #endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
  1598. }
  1599. }
  1600. clear_error(ec);
  1601. return ec;
  1602. }
  1603. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  1604. // || defined(__MACH__) && defined(__APPLE__)
  1605. inline boost::system::error_code translate_addrinfo_error(int error)
  1606. {
  1607. switch (error)
  1608. {
  1609. case 0:
  1610. return boost::system::error_code();
  1611. case EAI_AGAIN:
  1612. return boost::asio::error::host_not_found_try_again;
  1613. case EAI_BADFLAGS:
  1614. return boost::asio::error::invalid_argument;
  1615. case EAI_FAIL:
  1616. return boost::asio::error::no_recovery;
  1617. case EAI_FAMILY:
  1618. return boost::asio::error::address_family_not_supported;
  1619. case EAI_MEMORY:
  1620. return boost::asio::error::no_memory;
  1621. case EAI_NONAME:
  1622. #if defined(EAI_ADDRFAMILY)
  1623. case EAI_ADDRFAMILY:
  1624. #endif
  1625. #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
  1626. case EAI_NODATA:
  1627. #endif
  1628. return boost::asio::error::host_not_found;
  1629. case EAI_SERVICE:
  1630. return boost::asio::error::service_not_found;
  1631. case EAI_SOCKTYPE:
  1632. return boost::asio::error::socket_type_not_supported;
  1633. default: // Possibly the non-portable EAI_SYSTEM.
  1634. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  1635. return boost::system::error_code(
  1636. WSAGetLastError(), boost::asio::error::get_system_category());
  1637. #else
  1638. return boost::system::error_code(
  1639. errno, boost::asio::error::get_system_category());
  1640. #endif
  1641. }
  1642. }
  1643. inline boost::system::error_code getaddrinfo(const char* host,
  1644. const char* service, const addrinfo_type* hints, addrinfo_type** result,
  1645. boost::system::error_code& ec)
  1646. {
  1647. clear_error(ec);
  1648. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  1649. # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
  1650. // Building for Windows XP, Windows Server 2003, or later.
  1651. int error = ::getaddrinfo(host, service, hints, result);
  1652. return ec = translate_addrinfo_error(error);
  1653. # else
  1654. // Building for Windows 2000 or earlier.
  1655. typedef int (WSAAPI *gai_t)(const char*,
  1656. const char*, const addrinfo_type*, addrinfo_type**);
  1657. if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
  1658. {
  1659. if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo"))
  1660. {
  1661. int error = gai(host, service, hints, result);
  1662. return ec = translate_addrinfo_error(error);
  1663. }
  1664. }
  1665. int error = getaddrinfo_emulation(host, service, hints, result);
  1666. return ec = translate_addrinfo_error(error);
  1667. # endif
  1668. #elif defined(__MACH__) && defined(__APPLE__)
  1669. int error = getaddrinfo_emulation(host, service, hints, result);
  1670. return ec = translate_addrinfo_error(error);
  1671. #else
  1672. int error = ::getaddrinfo(host, service, hints, result);
  1673. return ec = translate_addrinfo_error(error);
  1674. #endif
  1675. }
  1676. inline void freeaddrinfo(addrinfo_type* ai)
  1677. {
  1678. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  1679. # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
  1680. // Building for Windows XP, Windows Server 2003, or later.
  1681. ::freeaddrinfo(ai);
  1682. # else
  1683. // Building for Windows 2000 or earlier.
  1684. typedef int (WSAAPI *fai_t)(addrinfo_type*);
  1685. if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
  1686. {
  1687. if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo"))
  1688. {
  1689. fai(ai);
  1690. return;
  1691. }
  1692. }
  1693. freeaddrinfo_emulation(ai);
  1694. # endif
  1695. #elif defined(__MACH__) && defined(__APPLE__)
  1696. freeaddrinfo_emulation(ai);
  1697. #else
  1698. ::freeaddrinfo(ai);
  1699. #endif
  1700. }
  1701. inline boost::system::error_code getnameinfo(const socket_addr_type* addr,
  1702. std::size_t addrlen, char* host, std::size_t hostlen,
  1703. char* serv, std::size_t servlen, int flags, boost::system::error_code& ec)
  1704. {
  1705. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  1706. # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
  1707. // Building for Windows XP, Windows Server 2003, or later.
  1708. clear_error(ec);
  1709. int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen),
  1710. host, static_cast<DWORD>(hostlen),
  1711. serv, static_cast<DWORD>(servlen), flags);
  1712. return ec = translate_addrinfo_error(error);
  1713. # else
  1714. // Building for Windows 2000 or earlier.
  1715. typedef int (WSAAPI *gni_t)(const socket_addr_type*,
  1716. int, char*, DWORD, char*, DWORD, int);
  1717. if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
  1718. {
  1719. if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
  1720. {
  1721. clear_error(ec);
  1722. int error = gni(addr, static_cast<int>(addrlen),
  1723. host, static_cast<DWORD>(hostlen),
  1724. serv, static_cast<DWORD>(servlen), flags);
  1725. return ec = translate_addrinfo_error(error);
  1726. }
  1727. }
  1728. clear_error(ec);
  1729. return getnameinfo_emulation(addr, addrlen,
  1730. host, hostlen, serv, servlen, flags, ec);
  1731. # endif
  1732. #elif defined(__MACH__) && defined(__APPLE__)
  1733. using namespace std; // For memcpy.
  1734. sockaddr_storage_type tmp_addr;
  1735. memcpy(&tmp_addr, addr, addrlen);
  1736. tmp_addr.ss_len = addrlen;
  1737. addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);
  1738. clear_error(ec);
  1739. return getnameinfo_emulation(addr, addrlen,
  1740. host, hostlen, serv, servlen, flags, ec);
  1741. #else
  1742. clear_error(ec);
  1743. int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);
  1744. return ec = translate_addrinfo_error(error);
  1745. #endif
  1746. }
  1747. inline u_long_type network_to_host_long(u_long_type value)
  1748. {
  1749. return ntohl(value);
  1750. }
  1751. inline u_long_type host_to_network_long(u_long_type value)
  1752. {
  1753. return htonl(value);
  1754. }
  1755. inline u_short_type network_to_host_short(u_short_type value)
  1756. {
  1757. return ntohs(value);
  1758. }
  1759. inline u_short_type host_to_network_short(u_short_type value)
  1760. {
  1761. return htons(value);
  1762. }
  1763. } // namespace socket_ops
  1764. } // namespace detail
  1765. } // namespace asio
  1766. } // namespace boost
  1767. #include <boost/asio/detail/pop_options.hpp>
  1768. #endif // BOOST_ASIO_DETAIL_SOCKET_OPS_HPP