socket_ops.hpp 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912
  1. //
  2. // socket_ops.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2010 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 ASIO_DETAIL_SOCKET_OPS_HPP
  11. #define 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 "asio/detail/push_options.hpp"
  16. #include "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 "asio/detail/pop_options.hpp"
  26. #include "asio/error.hpp"
  27. #include "asio/detail/socket_types.hpp"
  28. namespace asio {
  29. namespace detail {
  30. namespace socket_ops {
  31. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  32. struct msghdr { int msg_namelen; };
  33. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  34. #if defined(__hpux)
  35. // HP-UX doesn't declare these functions extern "C", so they are declared again
  36. // here to avoid linker errors about undefined symbols.
  37. extern "C" char* if_indextoname(unsigned int, char*);
  38. extern "C" unsigned int if_nametoindex(const char*);
  39. #endif // defined(__hpux)
  40. inline void clear_error(asio::error_code& ec)
  41. {
  42. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  43. WSASetLastError(0);
  44. #else
  45. errno = 0;
  46. #endif
  47. ec = asio::error_code();
  48. }
  49. template <typename ReturnType>
  50. inline ReturnType error_wrapper(ReturnType return_value,
  51. asio::error_code& ec)
  52. {
  53. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  54. ec = asio::error_code(WSAGetLastError(),
  55. asio::error::get_system_category());
  56. #else
  57. ec = asio::error_code(errno,
  58. asio::error::get_system_category());
  59. #endif
  60. return return_value;
  61. }
  62. template <typename SockLenType>
  63. inline socket_type call_accept(SockLenType msghdr::*,
  64. socket_type s, socket_addr_type* addr, std::size_t* addrlen)
  65. {
  66. SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
  67. socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
  68. if (addrlen)
  69. *addrlen = (std::size_t)tmp_addrlen;
  70. return result;
  71. }
  72. inline socket_type accept(socket_type s, socket_addr_type* addr,
  73. std::size_t* addrlen, asio::error_code& ec)
  74. {
  75. clear_error(ec);
  76. socket_type new_s = error_wrapper(call_accept(
  77. &msghdr::msg_namelen, s, addr, addrlen), ec);
  78. if (new_s == invalid_socket)
  79. return new_s;
  80. #if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
  81. int optval = 1;
  82. int result = error_wrapper(::setsockopt(new_s,
  83. SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
  84. if (result != 0)
  85. {
  86. ::close(new_s);
  87. return invalid_socket;
  88. }
  89. #endif
  90. clear_error(ec);
  91. return new_s;
  92. }
  93. template <typename SockLenType>
  94. inline int call_bind(SockLenType msghdr::*,
  95. socket_type s, const socket_addr_type* addr, std::size_t addrlen)
  96. {
  97. return ::bind(s, addr, (SockLenType)addrlen);
  98. }
  99. inline int bind(socket_type s, const socket_addr_type* addr,
  100. std::size_t addrlen, asio::error_code& ec)
  101. {
  102. clear_error(ec);
  103. int result = error_wrapper(call_bind(
  104. &msghdr::msg_namelen, s, addr, addrlen), ec);
  105. if (result == 0)
  106. clear_error(ec);
  107. return result;
  108. }
  109. inline int close(socket_type s, asio::error_code& ec)
  110. {
  111. clear_error(ec);
  112. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  113. int result = error_wrapper(::closesocket(s), ec);
  114. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  115. int result = error_wrapper(::close(s), ec);
  116. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  117. if (result == 0)
  118. clear_error(ec);
  119. return result;
  120. }
  121. inline int shutdown(socket_type s, int what, asio::error_code& ec)
  122. {
  123. clear_error(ec);
  124. int result = error_wrapper(::shutdown(s, what), ec);
  125. if (result == 0)
  126. clear_error(ec);
  127. return result;
  128. }
  129. template <typename SockLenType>
  130. inline int call_connect(SockLenType msghdr::*,
  131. socket_type s, const socket_addr_type* addr, std::size_t addrlen)
  132. {
  133. return ::connect(s, addr, (SockLenType)addrlen);
  134. }
  135. inline int connect(socket_type s, const socket_addr_type* addr,
  136. std::size_t addrlen, asio::error_code& ec)
  137. {
  138. clear_error(ec);
  139. int result = error_wrapper(call_connect(
  140. &msghdr::msg_namelen, s, addr, addrlen), ec);
  141. if (result == 0)
  142. clear_error(ec);
  143. return result;
  144. }
  145. inline int socketpair(int af, int type, int protocol,
  146. socket_type sv[2], asio::error_code& ec)
  147. {
  148. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  149. (void)(af);
  150. (void)(type);
  151. (void)(protocol);
  152. (void)(sv);
  153. ec = asio::error::operation_not_supported;
  154. return -1;
  155. #else
  156. clear_error(ec);
  157. int result = error_wrapper(::socketpair(af, type, protocol, sv), ec);
  158. if (result == 0)
  159. clear_error(ec);
  160. return result;
  161. #endif
  162. }
  163. inline int listen(socket_type s, int backlog, asio::error_code& ec)
  164. {
  165. clear_error(ec);
  166. int result = error_wrapper(::listen(s, backlog), ec);
  167. if (result == 0)
  168. clear_error(ec);
  169. return result;
  170. }
  171. inline void init_buf_iov_base(void*& base, void* addr)
  172. {
  173. base = addr;
  174. }
  175. template <typename T>
  176. inline void init_buf_iov_base(T& base, void* addr)
  177. {
  178. base = static_cast<T>(addr);
  179. }
  180. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  181. typedef WSABUF buf;
  182. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  183. typedef iovec buf;
  184. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  185. inline void init_buf(buf& b, void* data, size_t size)
  186. {
  187. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  188. b.buf = static_cast<char*>(data);
  189. b.len = static_cast<u_long>(size);
  190. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  191. init_buf_iov_base(b.iov_base, data);
  192. b.iov_len = size;
  193. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  194. }
  195. inline void init_buf(buf& b, const void* data, size_t size)
  196. {
  197. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  198. b.buf = static_cast<char*>(const_cast<void*>(data));
  199. b.len = static_cast<u_long>(size);
  200. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  201. init_buf_iov_base(b.iov_base, const_cast<void*>(data));
  202. b.iov_len = size;
  203. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  204. }
  205. inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
  206. {
  207. name = addr;
  208. }
  209. inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
  210. {
  211. name = const_cast<socket_addr_type*>(addr);
  212. }
  213. template <typename T>
  214. inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
  215. {
  216. name = reinterpret_cast<T>(addr);
  217. }
  218. template <typename T>
  219. inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
  220. {
  221. name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
  222. }
  223. inline int recv(socket_type s, buf* bufs, size_t count, int flags,
  224. asio::error_code& ec)
  225. {
  226. clear_error(ec);
  227. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  228. // Receive some data.
  229. DWORD recv_buf_count = static_cast<DWORD>(count);
  230. DWORD bytes_transferred = 0;
  231. DWORD recv_flags = flags;
  232. int result = error_wrapper(::WSARecv(s, bufs,
  233. recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
  234. if (result != 0)
  235. return -1;
  236. clear_error(ec);
  237. return bytes_transferred;
  238. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  239. msghdr msg = msghdr();
  240. msg.msg_iov = bufs;
  241. msg.msg_iovlen = count;
  242. int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
  243. if (result >= 0)
  244. clear_error(ec);
  245. return result;
  246. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  247. }
  248. inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
  249. socket_addr_type* addr, std::size_t* addrlen,
  250. asio::error_code& ec)
  251. {
  252. clear_error(ec);
  253. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  254. // Receive some data.
  255. DWORD recv_buf_count = static_cast<DWORD>(count);
  256. DWORD bytes_transferred = 0;
  257. DWORD recv_flags = flags;
  258. int tmp_addrlen = (int)*addrlen;
  259. int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
  260. &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
  261. *addrlen = (std::size_t)tmp_addrlen;
  262. if (result != 0)
  263. return -1;
  264. clear_error(ec);
  265. return bytes_transferred;
  266. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  267. msghdr msg = msghdr();
  268. init_msghdr_msg_name(msg.msg_name, addr);
  269. msg.msg_namelen = *addrlen;
  270. msg.msg_iov = bufs;
  271. msg.msg_iovlen = count;
  272. int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
  273. *addrlen = msg.msg_namelen;
  274. if (result >= 0)
  275. clear_error(ec);
  276. return result;
  277. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  278. }
  279. inline int send(socket_type s, const buf* bufs, size_t count, int flags,
  280. asio::error_code& ec)
  281. {
  282. clear_error(ec);
  283. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  284. // Send the data.
  285. DWORD send_buf_count = static_cast<DWORD>(count);
  286. DWORD bytes_transferred = 0;
  287. DWORD send_flags = flags;
  288. int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs),
  289. send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
  290. if (result != 0)
  291. return -1;
  292. clear_error(ec);
  293. return bytes_transferred;
  294. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  295. msghdr msg = msghdr();
  296. msg.msg_iov = const_cast<buf*>(bufs);
  297. msg.msg_iovlen = count;
  298. #if defined(__linux__)
  299. flags |= MSG_NOSIGNAL;
  300. #endif // defined(__linux__)
  301. int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
  302. if (result >= 0)
  303. clear_error(ec);
  304. return result;
  305. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  306. }
  307. inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
  308. const socket_addr_type* addr, std::size_t addrlen,
  309. asio::error_code& ec)
  310. {
  311. clear_error(ec);
  312. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  313. // Send the data.
  314. DWORD send_buf_count = static_cast<DWORD>(count);
  315. DWORD bytes_transferred = 0;
  316. int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
  317. send_buf_count, &bytes_transferred, flags, addr,
  318. static_cast<int>(addrlen), 0, 0), ec);
  319. if (result != 0)
  320. return -1;
  321. clear_error(ec);
  322. return bytes_transferred;
  323. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  324. msghdr msg = msghdr();
  325. init_msghdr_msg_name(msg.msg_name, addr);
  326. msg.msg_namelen = addrlen;
  327. msg.msg_iov = const_cast<buf*>(bufs);
  328. msg.msg_iovlen = count;
  329. #if defined(__linux__)
  330. flags |= MSG_NOSIGNAL;
  331. #endif // defined(__linux__)
  332. int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
  333. if (result >= 0)
  334. clear_error(ec);
  335. return result;
  336. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  337. }
  338. inline socket_type socket(int af, int type, int protocol,
  339. asio::error_code& ec)
  340. {
  341. clear_error(ec);
  342. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  343. socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0,
  344. WSA_FLAG_OVERLAPPED), ec);
  345. if (s == invalid_socket)
  346. return s;
  347. if (af == AF_INET6)
  348. {
  349. // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
  350. // false. This will only succeed on Windows Vista and later versions of
  351. // Windows, where a dual-stack IPv4/v6 implementation is available.
  352. DWORD optval = 0;
  353. ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
  354. reinterpret_cast<const char*>(&optval), sizeof(optval));
  355. }
  356. clear_error(ec);
  357. return s;
  358. #elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
  359. socket_type s = error_wrapper(::socket(af, type, protocol), ec);
  360. if (s == invalid_socket)
  361. return s;
  362. int optval = 1;
  363. int result = error_wrapper(::setsockopt(s,
  364. SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
  365. if (result != 0)
  366. {
  367. ::close(s);
  368. return invalid_socket;
  369. }
  370. return s;
  371. #else
  372. int s = error_wrapper(::socket(af, type, protocol), ec);
  373. if (s >= 0)
  374. clear_error(ec);
  375. return s;
  376. #endif
  377. }
  378. template <typename SockLenType>
  379. inline int call_setsockopt(SockLenType msghdr::*,
  380. socket_type s, int level, int optname,
  381. const void* optval, std::size_t optlen)
  382. {
  383. return ::setsockopt(s, level, optname,
  384. (const char*)optval, (SockLenType)optlen);
  385. }
  386. inline int setsockopt(socket_type s, int level, int optname,
  387. const void* optval, std::size_t optlen, asio::error_code& ec)
  388. {
  389. if (level == custom_socket_option_level && optname == always_fail_option)
  390. {
  391. ec = asio::error::invalid_argument;
  392. return -1;
  393. }
  394. #if defined(__BORLANDC__)
  395. // Mysteriously, using the getsockopt and setsockopt functions directly with
  396. // Borland C++ results in incorrect values being set and read. The bug can be
  397. // worked around by using function addresses resolved with GetProcAddress.
  398. if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
  399. {
  400. typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);
  401. if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))
  402. {
  403. clear_error(ec);
  404. return error_wrapper(sso(s, level, optname,
  405. reinterpret_cast<const char*>(optval),
  406. static_cast<int>(optlen)), ec);
  407. }
  408. }
  409. ec = asio::error::fault;
  410. return -1;
  411. #else // defined(__BORLANDC__)
  412. clear_error(ec);
  413. int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
  414. s, level, optname, optval, optlen), ec);
  415. if (result == 0)
  416. clear_error(ec);
  417. return result;
  418. #endif // defined(__BORLANDC__)
  419. }
  420. template <typename SockLenType>
  421. inline int call_getsockopt(SockLenType msghdr::*,
  422. socket_type s, int level, int optname,
  423. void* optval, std::size_t* optlen)
  424. {
  425. SockLenType tmp_optlen = (SockLenType)*optlen;
  426. int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
  427. *optlen = (std::size_t)tmp_optlen;
  428. return result;
  429. }
  430. inline int getsockopt(socket_type s, int level, int optname, void* optval,
  431. size_t* optlen, asio::error_code& ec)
  432. {
  433. if (level == custom_socket_option_level && optname == always_fail_option)
  434. {
  435. ec = asio::error::invalid_argument;
  436. return -1;
  437. }
  438. #if defined(__BORLANDC__)
  439. // Mysteriously, using the getsockopt and setsockopt functions directly with
  440. // Borland C++ results in incorrect values being set and read. The bug can be
  441. // worked around by using function addresses resolved with GetProcAddress.
  442. if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
  443. {
  444. typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);
  445. if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))
  446. {
  447. clear_error(ec);
  448. int tmp_optlen = static_cast<int>(*optlen);
  449. int result = error_wrapper(gso(s, level, optname,
  450. reinterpret_cast<char*>(optval), &tmp_optlen), ec);
  451. *optlen = static_cast<size_t>(tmp_optlen);
  452. if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
  453. && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
  454. {
  455. // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
  456. // only supported on Windows Vista and later. To simplify program logic
  457. // we will fake success of getting this option and specify that the
  458. // value is non-zero (i.e. true). This corresponds to the behavior of
  459. // IPv6 sockets on Windows platforms pre-Vista.
  460. *static_cast<DWORD*>(optval) = 1;
  461. clear_error(ec);
  462. }
  463. return result;
  464. }
  465. }
  466. ec = asio::error::fault;
  467. return -1;
  468. #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  469. clear_error(ec);
  470. int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
  471. s, level, optname, optval, optlen), ec);
  472. if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
  473. && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
  474. {
  475. // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
  476. // supported on Windows Vista and later. To simplify program logic we will
  477. // fake success of getting this option and specify that the value is
  478. // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
  479. // on Windows platforms pre-Vista.
  480. *static_cast<DWORD*>(optval) = 1;
  481. clear_error(ec);
  482. }
  483. if (result == 0)
  484. clear_error(ec);
  485. return result;
  486. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  487. clear_error(ec);
  488. int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
  489. s, level, optname, optval, optlen), ec);
  490. #if defined(__linux__)
  491. if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
  492. && (optname == SO_SNDBUF || optname == SO_RCVBUF))
  493. {
  494. // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
  495. // to set the buffer size to N*2. Linux puts additional stuff into the
  496. // buffers so that only about half is actually available to the application.
  497. // The retrieved value is divided by 2 here to make it appear as though the
  498. // correct value has been set.
  499. *static_cast<int*>(optval) /= 2;
  500. }
  501. #endif // defined(__linux__)
  502. if (result == 0)
  503. clear_error(ec);
  504. return result;
  505. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  506. }
  507. template <typename SockLenType>
  508. inline int call_getpeername(SockLenType msghdr::*,
  509. socket_type s, socket_addr_type* addr, std::size_t* addrlen)
  510. {
  511. SockLenType tmp_addrlen = (SockLenType)*addrlen;
  512. int result = ::getpeername(s, addr, &tmp_addrlen);
  513. *addrlen = (std::size_t)tmp_addrlen;
  514. return result;
  515. }
  516. inline int getpeername(socket_type s, socket_addr_type* addr,
  517. std::size_t* addrlen, asio::error_code& ec)
  518. {
  519. clear_error(ec);
  520. int result = error_wrapper(call_getpeername(
  521. &msghdr::msg_namelen, s, addr, addrlen), ec);
  522. if (result == 0)
  523. clear_error(ec);
  524. return result;
  525. }
  526. template <typename SockLenType>
  527. inline int call_getsockname(SockLenType msghdr::*,
  528. socket_type s, socket_addr_type* addr, std::size_t* addrlen)
  529. {
  530. SockLenType tmp_addrlen = (SockLenType)*addrlen;
  531. int result = ::getsockname(s, addr, &tmp_addrlen);
  532. *addrlen = (std::size_t)tmp_addrlen;
  533. return result;
  534. }
  535. inline int getsockname(socket_type s, socket_addr_type* addr,
  536. std::size_t* addrlen, asio::error_code& ec)
  537. {
  538. clear_error(ec);
  539. int result = error_wrapper(call_getsockname(
  540. &msghdr::msg_namelen, s, addr, addrlen), ec);
  541. if (result == 0)
  542. clear_error(ec);
  543. return result;
  544. }
  545. inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
  546. asio::error_code& ec)
  547. {
  548. clear_error(ec);
  549. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  550. int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
  551. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  552. int result = error_wrapper(::ioctl(s, cmd, arg), ec);
  553. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  554. if (result >= 0)
  555. clear_error(ec);
  556. return result;
  557. }
  558. inline int select(int nfds, fd_set* readfds, fd_set* writefds,
  559. fd_set* exceptfds, timeval* timeout, asio::error_code& ec)
  560. {
  561. clear_error(ec);
  562. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  563. if (!readfds && !writefds && !exceptfds && timeout)
  564. {
  565. DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
  566. if (milliseconds == 0)
  567. milliseconds = 1; // Force context switch.
  568. ::Sleep(milliseconds);
  569. ec = asio::error_code();
  570. return 0;
  571. }
  572. // The select() call allows timeout values measured in microseconds, but the
  573. // system clock (as wrapped by boost::posix_time::microsec_clock) typically
  574. // has a resolution of 10 milliseconds. This can lead to a spinning select
  575. // reactor, meaning increased CPU usage, when waiting for the earliest
  576. // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
  577. // spin we'll use a minimum timeout of 1 millisecond.
  578. if (timeout && timeout->tv_sec == 0
  579. && timeout->tv_usec > 0 && timeout->tv_usec < 1000)
  580. timeout->tv_usec = 1000;
  581. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  582. #if defined(__hpux) && defined(__HP_aCC)
  583. timespec ts;
  584. ts.tv_sec = timeout ? timeout->tv_sec : 0;
  585. ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
  586. return error_wrapper(::pselect(nfds, readfds,
  587. writefds, exceptfds, timeout ? &ts : 0, 0), ec);
  588. #else
  589. int result = error_wrapper(::select(nfds, readfds,
  590. writefds, exceptfds, timeout), ec);
  591. if (result >= 0)
  592. clear_error(ec);
  593. return result;
  594. #endif
  595. }
  596. inline int poll_read(socket_type s, asio::error_code& ec)
  597. {
  598. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  599. FD_SET fds;
  600. FD_ZERO(&fds);
  601. FD_SET(s, &fds);
  602. clear_error(ec);
  603. int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
  604. if (result >= 0)
  605. clear_error(ec);
  606. return result;
  607. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  608. pollfd fds;
  609. fds.fd = s;
  610. fds.events = POLLIN;
  611. fds.revents = 0;
  612. clear_error(ec);
  613. int result = error_wrapper(::poll(&fds, 1, -1), ec);
  614. if (result >= 0)
  615. clear_error(ec);
  616. return result;
  617. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  618. }
  619. inline int poll_write(socket_type s, asio::error_code& ec)
  620. {
  621. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  622. FD_SET fds;
  623. FD_ZERO(&fds);
  624. FD_SET(s, &fds);
  625. clear_error(ec);
  626. int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
  627. if (result >= 0)
  628. clear_error(ec);
  629. return result;
  630. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  631. pollfd fds;
  632. fds.fd = s;
  633. fds.events = POLLOUT;
  634. fds.revents = 0;
  635. clear_error(ec);
  636. int result = error_wrapper(::poll(&fds, 1, -1), ec);
  637. if (result >= 0)
  638. clear_error(ec);
  639. return result;
  640. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  641. }
  642. inline int poll_connect(socket_type s, asio::error_code& ec)
  643. {
  644. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  645. FD_SET write_fds;
  646. FD_ZERO(&write_fds);
  647. FD_SET(s, &write_fds);
  648. FD_SET except_fds;
  649. FD_ZERO(&except_fds);
  650. FD_SET(s, &except_fds);
  651. clear_error(ec);
  652. int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec);
  653. if (result >= 0)
  654. clear_error(ec);
  655. return result;
  656. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  657. pollfd fds;
  658. fds.fd = s;
  659. fds.events = POLLOUT;
  660. fds.revents = 0;
  661. clear_error(ec);
  662. int result = error_wrapper(::poll(&fds, 1, -1), ec);
  663. if (result >= 0)
  664. clear_error(ec);
  665. return result;
  666. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  667. }
  668. inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,
  669. unsigned long scope_id, asio::error_code& ec)
  670. {
  671. clear_error(ec);
  672. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  673. using namespace std; // For memcpy.
  674. if (af != AF_INET && af != AF_INET6)
  675. {
  676. ec = asio::error::address_family_not_supported;
  677. return 0;
  678. }
  679. union
  680. {
  681. socket_addr_type base;
  682. sockaddr_storage_type storage;
  683. sockaddr_in4_type v4;
  684. sockaddr_in6_type v6;
  685. } address;
  686. DWORD address_length;
  687. if (af == AF_INET)
  688. {
  689. address_length = sizeof(sockaddr_in4_type);
  690. address.v4.sin_family = AF_INET;
  691. address.v4.sin_port = 0;
  692. memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
  693. }
  694. else // AF_INET6
  695. {
  696. address_length = sizeof(sockaddr_in6_type);
  697. address.v6.sin6_family = AF_INET6;
  698. address.v6.sin6_port = 0;
  699. address.v6.sin6_flowinfo = 0;
  700. address.v6.sin6_scope_id = scope_id;
  701. memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
  702. }
  703. DWORD string_length = static_cast<DWORD>(length);
  704. #if defined(BOOST_NO_ANSI_APIS)
  705. LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
  706. int result = error_wrapper(::WSAAddressToStringW(&address.base,
  707. address_length, 0, string_buffer, &string_length), ec);
  708. ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
  709. #else
  710. int result = error_wrapper(::WSAAddressToStringA(
  711. &address.base, address_length, 0, dest, &string_length), ec);
  712. #endif
  713. // Windows may set error code on success.
  714. if (result != socket_error_retval)
  715. clear_error(ec);
  716. // Windows may not set an error code on failure.
  717. else if (result == socket_error_retval && !ec)
  718. ec = asio::error::invalid_argument;
  719. return result == socket_error_retval ? 0 : dest;
  720. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  721. const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec);
  722. if (result == 0 && !ec)
  723. ec = asio::error::invalid_argument;
  724. if (result != 0 && af == AF_INET6 && scope_id != 0)
  725. {
  726. using namespace std; // For strcat and sprintf.
  727. char if_name[IF_NAMESIZE + 1] = "%";
  728. const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
  729. bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
  730. if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
  731. sprintf(if_name + 1, "%lu", scope_id);
  732. strcat(dest, if_name);
  733. }
  734. return result;
  735. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  736. }
  737. inline int inet_pton(int af, const char* src, void* dest,
  738. unsigned long* scope_id, asio::error_code& ec)
  739. {
  740. clear_error(ec);
  741. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  742. using namespace std; // For memcpy and strcmp.
  743. if (af != AF_INET && af != AF_INET6)
  744. {
  745. ec = asio::error::address_family_not_supported;
  746. return -1;
  747. }
  748. union
  749. {
  750. socket_addr_type base;
  751. sockaddr_storage_type storage;
  752. sockaddr_in4_type v4;
  753. sockaddr_in6_type v6;
  754. } address;
  755. int address_length = sizeof(sockaddr_storage_type);
  756. #if defined(BOOST_NO_ANSI_APIS)
  757. int num_wide_chars = strlen(src) + 1;
  758. LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
  759. ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
  760. int result = error_wrapper(::WSAStringToAddressW(
  761. wide_buffer, af, 0, &address.base, &address_length), ec);
  762. #else
  763. int result = error_wrapper(::WSAStringToAddressA(
  764. const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
  765. #endif
  766. if (af == AF_INET)
  767. {
  768. if (result != socket_error_retval)
  769. {
  770. memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
  771. clear_error(ec);
  772. }
  773. else if (strcmp(src, "255.255.255.255") == 0)
  774. {
  775. static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;
  776. clear_error(ec);
  777. }
  778. }
  779. else // AF_INET6
  780. {
  781. if (result != socket_error_retval)
  782. {
  783. memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
  784. if (scope_id)
  785. *scope_id = address.v6.sin6_scope_id;
  786. clear_error(ec);
  787. }
  788. }
  789. // Windows may not set an error code on failure.
  790. if (result == socket_error_retval && !ec)
  791. ec = asio::error::invalid_argument;
  792. if (result != socket_error_retval)
  793. clear_error(ec);
  794. return result == socket_error_retval ? -1 : 1;
  795. #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  796. int result = error_wrapper(::inet_pton(af, src, dest), ec);
  797. if (result <= 0 && !ec)
  798. ec = asio::error::invalid_argument;
  799. if (result > 0 && af == AF_INET6 && scope_id)
  800. {
  801. using namespace std; // For strchr and atoi.
  802. *scope_id = 0;
  803. if (const char* if_name = strchr(src, '%'))
  804. {
  805. in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);
  806. bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
  807. if (is_link_local)
  808. *scope_id = if_nametoindex(if_name + 1);
  809. if (*scope_id == 0)
  810. *scope_id = atoi(if_name + 1);
  811. }
  812. }
  813. return result;
  814. #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  815. }
  816. inline int gethostname(char* name, int namelen, asio::error_code& ec)
  817. {
  818. clear_error(ec);
  819. int result = error_wrapper(::gethostname(name, namelen), ec);
  820. #if defined(BOOST_WINDOWS)
  821. if (result == 0)
  822. clear_error(ec);
  823. #endif
  824. return result;
  825. }
  826. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
  827. || defined(__MACH__) && defined(__APPLE__)
  828. // The following functions are only needed for emulation of getaddrinfo and
  829. // getnameinfo.
  830. inline asio::error_code translate_netdb_error(int error)
  831. {
  832. switch (error)
  833. {
  834. case 0:
  835. return asio::error_code();
  836. case HOST_NOT_FOUND:
  837. return asio::error::host_not_found;
  838. case TRY_AGAIN:
  839. return asio::error::host_not_found_try_again;
  840. case NO_RECOVERY:
  841. return asio::error::no_recovery;
  842. case NO_DATA:
  843. return asio::error::no_data;
  844. default:
  845. BOOST_ASSERT(false);
  846. return asio::error::invalid_argument;
  847. }
  848. }
  849. inline hostent* gethostbyaddr(const char* addr, int length, int af,
  850. hostent* result, char* buffer, int buflength, asio::error_code& ec)
  851. {
  852. clear_error(ec);
  853. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  854. (void)(buffer);
  855. (void)(buflength);
  856. hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
  857. if (!retval)
  858. return 0;
  859. clear_error(ec);
  860. *result = *retval;
  861. return retval;
  862. #elif defined(__sun) || defined(__QNX__)
  863. int error = 0;
  864. hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result,
  865. buffer, buflength, &error), ec);
  866. if (error)
  867. ec = translate_netdb_error(error);
  868. return retval;
  869. #elif defined(__MACH__) && defined(__APPLE__)
  870. (void)(buffer);
  871. (void)(buflength);
  872. int error = 0;
  873. hostent* retval = error_wrapper(::getipnodebyaddr(
  874. addr, length, af, &error), ec);
  875. if (error)
  876. ec = translate_netdb_error(error);
  877. if (!retval)
  878. return 0;
  879. *result = *retval;
  880. return retval;
  881. #else
  882. hostent* retval = 0;
  883. int error = 0;
  884. error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer,
  885. buflength, &retval, &error), ec);
  886. if (error)
  887. ec = translate_netdb_error(error);
  888. return retval;
  889. #endif
  890. }
  891. inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
  892. char* buffer, int buflength, int ai_flags, asio::error_code& ec)
  893. {
  894. clear_error(ec);
  895. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  896. (void)(buffer);
  897. (void)(buflength);
  898. (void)(ai_flags);
  899. if (af != AF_INET)
  900. {
  901. ec = asio::error::address_family_not_supported;
  902. return 0;
  903. }
  904. hostent* retval = error_wrapper(::gethostbyname(name), ec);
  905. if (!retval)
  906. return 0;
  907. clear_error(ec);
  908. *result = *retval;
  909. return result;
  910. #elif defined(__sun) || defined(__QNX__)
  911. (void)(ai_flags);
  912. if (af != AF_INET)
  913. {
  914. ec = asio::error::address_family_not_supported;
  915. return 0;
  916. }
  917. int error = 0;
  918. hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer,
  919. buflength, &error), ec);
  920. if (error)
  921. ec = translate_netdb_error(error);
  922. return retval;
  923. #elif defined(__MACH__) && defined(__APPLE__)
  924. (void)(buffer);
  925. (void)(buflength);
  926. int error = 0;
  927. hostent* retval = error_wrapper(::getipnodebyname(
  928. name, af, ai_flags, &error), ec);
  929. if (error)
  930. ec = translate_netdb_error(error);
  931. if (!retval)
  932. return 0;
  933. *result = *retval;
  934. return retval;
  935. #else
  936. (void)(ai_flags);
  937. if (af != AF_INET)
  938. {
  939. ec = asio::error::address_family_not_supported;
  940. return 0;
  941. }
  942. hostent* retval = 0;
  943. int error = 0;
  944. error_wrapper(::gethostbyname_r(name, result,
  945. buffer, buflength, &retval, &error), ec);
  946. if (error)
  947. ec = translate_netdb_error(error);
  948. return retval;
  949. #endif
  950. }
  951. inline void freehostent(hostent* h)
  952. {
  953. #if defined(__MACH__) && defined(__APPLE__)
  954. if (h)
  955. ::freehostent(h);
  956. #else
  957. (void)(h);
  958. #endif
  959. }
  960. // Emulation of getaddrinfo based on implementation in:
  961. // Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
  962. struct gai_search
  963. {
  964. const char* host;
  965. int family;
  966. };
  967. inline int gai_nsearch(const char* host,
  968. const addrinfo_type* hints, gai_search (&search)[2])
  969. {
  970. int search_count = 0;
  971. if (host == 0 || host[0] == '\0')
  972. {
  973. if (hints->ai_flags & AI_PASSIVE)
  974. {
  975. // No host and AI_PASSIVE implies wildcard bind.
  976. switch (hints->ai_family)
  977. {
  978. case AF_INET:
  979. search[search_count].host = "0.0.0.0";
  980. search[search_count].family = AF_INET;
  981. ++search_count;
  982. break;
  983. case AF_INET6:
  984. search[search_count].host = "0::0";
  985. search[search_count].family = AF_INET6;
  986. ++search_count;
  987. break;
  988. case AF_UNSPEC:
  989. search[search_count].host = "0::0";
  990. search[search_count].family = AF_INET6;
  991. ++search_count;
  992. search[search_count].host = "0.0.0.0";
  993. search[search_count].family = AF_INET;
  994. ++search_count;
  995. break;
  996. default:
  997. break;
  998. }
  999. }
  1000. else
  1001. {
  1002. // No host and not AI_PASSIVE means connect to local host.
  1003. switch (hints->ai_family)
  1004. {
  1005. case AF_INET:
  1006. search[search_count].host = "localhost";
  1007. search[search_count].family = AF_INET;
  1008. ++search_count;
  1009. break;
  1010. case AF_INET6:
  1011. search[search_count].host = "localhost";
  1012. search[search_count].family = AF_INET6;
  1013. ++search_count;
  1014. break;
  1015. case AF_UNSPEC:
  1016. search[search_count].host = "localhost";
  1017. search[search_count].family = AF_INET6;
  1018. ++search_count;
  1019. search[search_count].host = "localhost";
  1020. search[search_count].family = AF_INET;
  1021. ++search_count;
  1022. break;
  1023. default:
  1024. break;
  1025. }
  1026. }
  1027. }
  1028. else
  1029. {
  1030. // Host is specified.
  1031. switch (hints->ai_family)
  1032. {
  1033. case AF_INET:
  1034. search[search_count].host = host;
  1035. search[search_count].family = AF_INET;
  1036. ++search_count;
  1037. break;
  1038. case AF_INET6:
  1039. search[search_count].host = host;
  1040. search[search_count].family = AF_INET6;
  1041. ++search_count;
  1042. break;
  1043. case AF_UNSPEC:
  1044. search[search_count].host = host;
  1045. search[search_count].family = AF_INET6;
  1046. ++search_count;
  1047. search[search_count].host = host;
  1048. search[search_count].family = AF_INET;
  1049. ++search_count;
  1050. break;
  1051. default:
  1052. break;
  1053. }
  1054. }
  1055. return search_count;
  1056. }
  1057. template <typename T>
  1058. inline T* gai_alloc(std::size_t size = sizeof(T))
  1059. {
  1060. using namespace std;
  1061. T* p = static_cast<T*>(::operator new(size, std::nothrow));
  1062. if (p)
  1063. memset(p, 0, size);
  1064. return p;
  1065. }
  1066. inline void gai_free(void* p)
  1067. {
  1068. ::operator delete(p);
  1069. }
  1070. inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
  1071. {
  1072. using namespace std;
  1073. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
  1074. strcpy_s(target, max_size, source);
  1075. #else
  1076. *target = 0;
  1077. strncat(target, source, max_size);
  1078. #endif
  1079. }
  1080. enum { gai_clone_flag = 1 << 30 };
  1081. inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
  1082. const void* addr, int family)
  1083. {
  1084. using namespace std;
  1085. addrinfo_type* ai = gai_alloc<addrinfo_type>();
  1086. if (ai == 0)
  1087. return EAI_MEMORY;
  1088. ai->ai_next = 0;
  1089. **next = ai;
  1090. *next = &ai->ai_next;
  1091. ai->ai_canonname = 0;
  1092. ai->ai_socktype = hints->ai_socktype;
  1093. if (ai->ai_socktype == 0)
  1094. ai->ai_flags |= gai_clone_flag;
  1095. ai->ai_protocol = hints->ai_protocol;
  1096. ai->ai_family = family;
  1097. switch (ai->ai_family)
  1098. {
  1099. case AF_INET:
  1100. {
  1101. sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();
  1102. if (sinptr == 0)
  1103. return EAI_MEMORY;
  1104. sinptr->sin_family = AF_INET;
  1105. memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));
  1106. ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);
  1107. ai->ai_addrlen = sizeof(sockaddr_in4_type);
  1108. break;
  1109. }
  1110. case AF_INET6:
  1111. {
  1112. sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();
  1113. if (sin6ptr == 0)
  1114. return EAI_MEMORY;
  1115. sin6ptr->sin6_family = AF_INET6;
  1116. memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));
  1117. ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);
  1118. ai->ai_addrlen = sizeof(sockaddr_in6_type);
  1119. break;
  1120. }
  1121. default:
  1122. break;
  1123. }
  1124. return 0;
  1125. }
  1126. inline addrinfo_type* gai_clone(addrinfo_type* ai)
  1127. {
  1128. using namespace std;
  1129. addrinfo_type* new_ai = gai_alloc<addrinfo_type>();
  1130. if (new_ai == 0)
  1131. return new_ai;
  1132. new_ai->ai_next = ai->ai_next;
  1133. ai->ai_next = new_ai;
  1134. new_ai->ai_flags = 0;
  1135. new_ai->ai_family = ai->ai_family;
  1136. new_ai->ai_socktype = ai->ai_socktype;
  1137. new_ai->ai_protocol = ai->ai_protocol;
  1138. new_ai->ai_canonname = 0;
  1139. new_ai->ai_addrlen = ai->ai_addrlen;
  1140. new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);
  1141. memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);
  1142. return new_ai;
  1143. }
  1144. inline int gai_port(addrinfo_type* aihead, int port, int socktype)
  1145. {
  1146. int num_found = 0;
  1147. for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)
  1148. {
  1149. if (ai->ai_flags & gai_clone_flag)
  1150. {
  1151. if (ai->ai_socktype != 0)
  1152. {
  1153. ai = gai_clone(ai);
  1154. if (ai == 0)
  1155. return -1;
  1156. // ai now points to newly cloned entry.
  1157. }
  1158. }
  1159. else if (ai->ai_socktype != socktype)
  1160. {
  1161. // Ignore if mismatch on socket type.
  1162. continue;
  1163. }
  1164. ai->ai_socktype = socktype;
  1165. switch (ai->ai_family)
  1166. {
  1167. case AF_INET:
  1168. {
  1169. sockaddr_in4_type* sinptr =
  1170. reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
  1171. sinptr->sin_port = port;
  1172. ++num_found;
  1173. break;
  1174. }
  1175. case AF_INET6:
  1176. {
  1177. sockaddr_in6_type* sin6ptr =
  1178. reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
  1179. sin6ptr->sin6_port = port;
  1180. ++num_found;
  1181. break;
  1182. }
  1183. default:
  1184. break;
  1185. }
  1186. }
  1187. return num_found;
  1188. }
  1189. inline int gai_serv(addrinfo_type* aihead,
  1190. const addrinfo_type* hints, const char* serv)
  1191. {
  1192. using namespace std;
  1193. int num_found = 0;
  1194. if (
  1195. #if defined(AI_NUMERICSERV)
  1196. (hints->ai_flags & AI_NUMERICSERV) ||
  1197. #endif
  1198. isdigit(serv[0]))
  1199. {
  1200. int port = htons(atoi(serv));
  1201. if (hints->ai_socktype)
  1202. {
  1203. // Caller specifies socket type.
  1204. int rc = gai_port(aihead, port, hints->ai_socktype);
  1205. if (rc < 0)
  1206. return EAI_MEMORY;
  1207. num_found += rc;
  1208. }
  1209. else
  1210. {
  1211. // Caller does not specify socket type.
  1212. int rc = gai_port(aihead, port, SOCK_STREAM);
  1213. if (rc < 0)
  1214. return EAI_MEMORY;
  1215. num_found += rc;
  1216. rc = gai_port(aihead, port, SOCK_DGRAM);
  1217. if (rc < 0)
  1218. return EAI_MEMORY;
  1219. num_found += rc;
  1220. }
  1221. }
  1222. else
  1223. {
  1224. // Try service name with TCP first, then UDP.
  1225. if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)
  1226. {
  1227. servent* sptr = getservbyname(serv, "tcp");
  1228. if (sptr != 0)
  1229. {
  1230. int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);
  1231. if (rc < 0)
  1232. return EAI_MEMORY;
  1233. num_found += rc;
  1234. }
  1235. }
  1236. if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)
  1237. {
  1238. servent* sptr = getservbyname(serv, "udp");
  1239. if (sptr != 0)
  1240. {
  1241. int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);
  1242. if (rc < 0)
  1243. return EAI_MEMORY;
  1244. num_found += rc;
  1245. }
  1246. }
  1247. }
  1248. if (num_found == 0)
  1249. {
  1250. if (hints->ai_socktype == 0)
  1251. {
  1252. // All calls to getservbyname() failed.
  1253. return EAI_NONAME;
  1254. }
  1255. else
  1256. {
  1257. // Service not supported for socket type.
  1258. return EAI_SERVICE;
  1259. }
  1260. }
  1261. return 0;
  1262. }
  1263. inline int gai_echeck(const char* host, const char* service,
  1264. int flags, int family, int socktype, int protocol)
  1265. {
  1266. (void)(flags);
  1267. (void)(protocol);
  1268. // Host or service must be specified.
  1269. if (host == 0 || host[0] == '\0')
  1270. if (service == 0 || service[0] == '\0')
  1271. return EAI_NONAME;
  1272. // Check combination of family and socket type.
  1273. switch (family)
  1274. {
  1275. case AF_UNSPEC:
  1276. break;
  1277. case AF_INET:
  1278. case AF_INET6:
  1279. if (service != 0 && service[0] != '\0')
  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. asio::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 == asio::error::host_not_found)
  1394. return EAI_NONAME;
  1395. if (ec == asio::error::host_not_found_try_again)
  1396. return EAI_AGAIN;
  1397. if (ec == asio::error::no_recovery)
  1398. return EAI_FAIL;
  1399. if (ec == 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 asio::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. asio::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 = 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 = 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 = 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 = 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 = 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 = 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 asio::error_code translate_addrinfo_error(int error)
  1606. {
  1607. switch (error)
  1608. {
  1609. case 0:
  1610. return asio::error_code();
  1611. case EAI_AGAIN:
  1612. return asio::error::host_not_found_try_again;
  1613. case EAI_BADFLAGS:
  1614. return asio::error::invalid_argument;
  1615. case EAI_FAIL:
  1616. return asio::error::no_recovery;
  1617. case EAI_FAMILY:
  1618. return asio::error::address_family_not_supported;
  1619. case EAI_MEMORY:
  1620. return 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 asio::error::host_not_found;
  1629. case EAI_SERVICE:
  1630. return asio::error::service_not_found;
  1631. case EAI_SOCKTYPE:
  1632. return asio::error::socket_type_not_supported;
  1633. default: // Possibly the non-portable EAI_SYSTEM.
  1634. #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
  1635. return asio::error_code(
  1636. WSAGetLastError(), asio::error::get_system_category());
  1637. #else
  1638. return asio::error_code(
  1639. errno, asio::error::get_system_category());
  1640. #endif
  1641. }
  1642. }
  1643. inline asio::error_code getaddrinfo(const char* host,
  1644. const char* service, const addrinfo_type* hints, addrinfo_type** result,
  1645. asio::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 asio::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, asio::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. #include "asio/detail/pop_options.hpp"
  1767. #endif // ASIO_DETAIL_SOCKET_OPS_HPP