PageRenderTime 57ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/os/windows/Socket.cc

https://github.com/my4ndr0id/android_external_alljoyn_common
C++ | 1354 lines | 1028 code | 182 blank | 144 comment | 269 complexity | f8790f19f17346d654fb3b835945e312 MD5 | raw file
  1. /**
  2. * @file
  3. *
  4. * Define the abstracted socket interface for Windows
  5. */
  6. /******************************************************************************
  7. * Copyright 2009-2011, Qualcomm Innovation Center, Inc.
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License");
  10. * you may not use this file except in compliance with the License.
  11. * You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing, software
  16. * distributed under the License is distributed on an "AS IS" BASIS,
  17. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. * See the License for the specific language governing permissions and
  19. * limitations under the License.
  20. ******************************************************************************/
  21. #include <qcc/platform.h>
  22. // Do not change the order of these includes; they are order dependent.
  23. #include <Winsock2.h>
  24. #include <Mswsock.h>
  25. #include <ws2tcpip.h>
  26. #include <qcc/IPAddress.h>
  27. #include <qcc/ScatterGatherList.h>
  28. #include <qcc/Socket.h>
  29. #include <qcc/IfConfig.h>
  30. #include <qcc/Util.h>
  31. #include <qcc/Thread.h>
  32. #include <qcc/StringUtil.h>
  33. #include <qcc/windows/utility.h>
  34. #include <Status.h>
  35. #define QCC_MODULE "NETWORK"
  36. /* Scatter gather only support on Vista and later */
  37. #if !defined (NTDDI_VERSION) || !defined (NTDDI_VISTA) || (NTDDI_VERSION < NTDDI_VISTA)
  38. #define QCC_USE_SCATTER_GATHER 0
  39. #else
  40. #define QCC_USE_SCATTER_GATHER 1
  41. #endif
  42. namespace qcc {
  43. const SocketFd INVALID_SOCKET_FD = INVALID_SOCKET;
  44. /*
  45. * Called before any operation that might be called before winsock has been started.
  46. */
  47. static void WinsockCheck()
  48. {
  49. static bool initialized = false;
  50. if (!initialized) {
  51. printf("Initialized winsock\n");
  52. WSADATA wsaData;
  53. WORD version = MAKEWORD(2, 0);
  54. int error = WSAStartup(version, &wsaData);
  55. if (error) {
  56. QCC_LogError(ER_OS_ERROR, ("WSAStartup failed with error: %d", error));
  57. } else {
  58. initialized = true;
  59. }
  60. }
  61. }
  62. static qcc::String StrError()
  63. {
  64. WinsockCheck();
  65. int errnum = WSAGetLastError();
  66. char msgbuf[256];
  67. FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
  68. NULL,
  69. errnum,
  70. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  71. (LPSTR) msgbuf,
  72. sizeof(msgbuf),
  73. NULL);
  74. return U32ToString(errnum) + " - " + msgbuf;
  75. }
  76. static void MakeSockAddr(const IPAddress& addr,
  77. uint16_t port,
  78. SOCKADDR_STORAGE* addrBuf,
  79. socklen_t& addrSize)
  80. {
  81. memset(addrBuf, 0, addrSize);
  82. if (addr.IsIPv4()) {
  83. struct sockaddr_in* sa = reinterpret_cast<struct sockaddr_in*>(addrBuf);
  84. sa->sin_family = AF_INET;
  85. sa->sin_port = htons(port);
  86. sa->sin_addr.s_addr = addr.GetIPv4AddressNetOrder();
  87. addrSize = sizeof(*sa);
  88. } else {
  89. struct sockaddr_in6* sa = reinterpret_cast<struct sockaddr_in6*>(addrBuf);
  90. sa->sin6_family = AF_INET6;
  91. sa->sin6_port = htons(port);
  92. addr.RenderIPv6Binary(sa->sin6_addr.s6_addr, sizeof(sa->sin6_addr.s6_addr));
  93. addrSize = sizeof(*sa);
  94. }
  95. }
  96. static QStatus GetSockAddr(const SOCKADDR_STORAGE* addrBuf, socklen_t addrSize,
  97. IPAddress& addr, uint16_t& port)
  98. {
  99. QStatus status = ER_OK;
  100. char hostname[NI_MAXHOST];
  101. char servInfo[NI_MAXSERV];
  102. DWORD dwRetval = getnameinfo((struct sockaddr*)addrBuf,
  103. sizeof (SOCKADDR_STORAGE),
  104. hostname, NI_MAXHOST,
  105. servInfo, NI_MAXSERV,
  106. NI_NUMERICHOST | NI_NUMERICSERV);
  107. if (dwRetval != 0) {
  108. status = ER_OS_ERROR;
  109. QCC_LogError(status, ("GetSockAddr: %s", StrError().c_str()));
  110. } else {
  111. addr = IPAddress(hostname);
  112. port = atoi(servInfo);
  113. }
  114. return status;
  115. }
  116. uint32_t GetLastError()
  117. {
  118. WinsockCheck();
  119. return WSAGetLastError();
  120. }
  121. qcc::String GetLastErrorString()
  122. {
  123. return StrError();
  124. }
  125. QStatus Socket(AddressFamily addrFamily, SocketType type, SocketFd& sockfd)
  126. {
  127. WinsockCheck();
  128. QStatus status = ER_OK;
  129. uint32_t ret;
  130. QCC_DbgTrace(("Socket(addrFamily = %d, type = %d, sockfd = <>)", addrFamily, type));
  131. if (addrFamily == QCC_AF_UNIX) {
  132. return ER_NOT_IMPLEMENTED;
  133. }
  134. ret = socket(static_cast<int>(addrFamily), static_cast<int>(type), 0);
  135. if (ret == SOCKET_ERROR) {
  136. status = ER_OS_ERROR;
  137. QCC_LogError(status, ("Opening socket: %s", StrError().c_str()));
  138. } else {
  139. sockfd = static_cast<SocketFd>(ret);
  140. }
  141. return status;
  142. }
  143. QStatus Connect(SocketFd sockfd, const IPAddress& remoteAddr, uint16_t remotePort)
  144. {
  145. QStatus status = ER_OK;
  146. int ret;
  147. SOCKADDR_STORAGE addr;
  148. socklen_t addrLen = sizeof(addr);
  149. QCC_DbgTrace(("Connect(sockfd = %d, remoteAddr = %s, remotePort = %hu)",
  150. sockfd, remoteAddr.ToString().c_str(), remotePort));
  151. MakeSockAddr(remoteAddr, remotePort, &addr, addrLen);
  152. ret = connect(static_cast<SOCKET>(sockfd), reinterpret_cast<struct sockaddr*>(&addr), addrLen);
  153. if (ret == SOCKET_ERROR) {
  154. switch (WSAGetLastError()) {
  155. case WSAEWOULDBLOCK:
  156. case WSAEALREADY:
  157. status = ER_WOULDBLOCK;
  158. break;
  159. case WSAECONNREFUSED:
  160. status = ER_CONN_REFUSED;
  161. break;
  162. case WSAEISCONN:
  163. status = ER_OK;
  164. break;
  165. default:
  166. status = ER_OS_ERROR;
  167. QCC_LogError(status, ("Connecting to %s %d: %s", remoteAddr.ToString().c_str(), remotePort, StrError().c_str()));
  168. break;
  169. }
  170. } else {
  171. u_long mode = 1; // Non-blocking
  172. ret = ioctlsocket(sockfd, FIONBIO, &mode);
  173. if (ret == SOCKET_ERROR) {
  174. status = ER_OS_ERROR;
  175. QCC_LogError(status, ("Failed to set socket non-blocking ", StrError().c_str()));
  176. }
  177. }
  178. return status;
  179. }
  180. QStatus Connect(SocketFd sockfd, const char* pathName)
  181. {
  182. return ER_NOT_IMPLEMENTED;
  183. }
  184. QStatus Bind(SocketFd sockfd, const IPAddress& localAddr, uint16_t localPort)
  185. {
  186. QStatus status = ER_OK;
  187. int ret;
  188. SOCKADDR_STORAGE addr;
  189. socklen_t addrLen = sizeof(addr);
  190. QCC_DbgTrace(("Bind(sockfd = %d, localAddr = %s, localPort = %hu)",
  191. sockfd, localAddr.ToString().c_str(), localPort));
  192. MakeSockAddr(localAddr, localPort, &addr, addrLen);
  193. ret = bind(static_cast<SOCKET>(sockfd), reinterpret_cast<struct sockaddr*>(&addr), addrLen);
  194. if (ret == SOCKET_ERROR) {
  195. status = (WSAGetLastError() == WSAEADDRNOTAVAIL) ? ER_SOCKET_BIND_ERROR : ER_OS_ERROR;
  196. QCC_LogError(status, ("Binding to %s %d: %s", localAddr.ToString().c_str(), localPort, StrError().c_str()));
  197. }
  198. return status;
  199. }
  200. QStatus Bind(SocketFd sockfd, const char* pathName)
  201. {
  202. return ER_NOT_IMPLEMENTED;
  203. }
  204. QStatus Listen(SocketFd sockfd, int backlog)
  205. {
  206. QStatus status = ER_OK;
  207. int ret;
  208. QCC_DbgTrace(("Listen(sockfd = %d, backlog = %d)", sockfd, backlog));
  209. ret = listen(static_cast<SOCKET>(sockfd), backlog);
  210. if (ret == SOCKET_ERROR) {
  211. status = ER_OS_ERROR;
  212. QCC_LogError(status, ("Listening: %s", StrError().c_str()));
  213. }
  214. return status;
  215. }
  216. QStatus Accept(SocketFd sockfd, IPAddress& remoteAddr, uint16_t& remotePort, SocketFd& newSockfd)
  217. {
  218. QStatus status = ER_OK;
  219. uint32_t ret;
  220. struct sockaddr_storage addr;
  221. socklen_t addrLen = sizeof(addr);
  222. QCC_DbgTrace(("Accept(sockfd = %d, remoteAddr = <>, remotePort = <>)", sockfd));
  223. ret = accept(static_cast<SOCKET>(sockfd), reinterpret_cast<struct sockaddr*>(&addr), &addrLen);
  224. if (ret == SOCKET_ERROR) {
  225. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  226. status = ER_WOULDBLOCK;
  227. } else {
  228. status = ER_OS_ERROR;
  229. QCC_LogError(status, ("Listening: %s", StrError().c_str()));
  230. }
  231. newSockfd = -1;
  232. } else {
  233. if (addr.ss_family == AF_INET) {
  234. struct sockaddr_in* sa = reinterpret_cast<struct sockaddr_in*>(&addr);
  235. uint8_t* portBuf = reinterpret_cast<uint8_t*>(&sa->sin_port);
  236. remoteAddr = IPAddress(reinterpret_cast<uint8_t*>(&sa->sin_addr.s_addr),
  237. IPAddress::IPv4_SIZE);
  238. remotePort = (static_cast<uint16_t>(portBuf[0]) << 8) | static_cast<uint16_t>(portBuf[1]);
  239. } else if (addr.ss_family == AF_INET6) {
  240. struct sockaddr_in6* sa = reinterpret_cast<struct sockaddr_in6*>(&addr);
  241. uint8_t* portBuf = reinterpret_cast<uint8_t*>(&sa->sin6_port);
  242. remoteAddr = IPAddress(reinterpret_cast<uint8_t*>(&sa->sin6_addr.s6_addr),
  243. IPAddress::IPv6_SIZE);
  244. remotePort = (static_cast<uint16_t>(portBuf[0]) << 8) | static_cast<uint16_t>(portBuf[1]);
  245. } else {
  246. remotePort = 0;
  247. }
  248. newSockfd = static_cast<SocketFd>(ret);
  249. u_long mode = 1; // Non-blocking
  250. ret = ioctlsocket(newSockfd, FIONBIO, &mode);
  251. if (ret == SOCKET_ERROR) {
  252. status = ER_OS_ERROR;
  253. QCC_LogError(status, ("Failed to set socket non-blocking %s", StrError().c_str()));
  254. closesocket(newSockfd);
  255. newSockfd = -1;
  256. } else {
  257. QCC_DbgHLPrintf(("Accept(sockfd = %d) newSockfd = %d", sockfd, newSockfd));
  258. }
  259. }
  260. return status;
  261. }
  262. QStatus Accept(SocketFd sockfd, SocketFd& newSockfd)
  263. {
  264. IPAddress addr;
  265. uint16_t port;
  266. return Accept(sockfd, addr, port, newSockfd);
  267. }
  268. QStatus Shutdown(SocketFd sockfd)
  269. {
  270. QStatus status = ER_OK;
  271. int ret;
  272. QCC_DbgHLPrintf(("Shutdown(sockfd = %d)", sockfd));
  273. ret = shutdown(static_cast<SOCKET>(sockfd), SD_BOTH);
  274. if (ret == SOCKET_ERROR) {
  275. status = ER_OS_ERROR;
  276. }
  277. return status;
  278. }
  279. void Close(SocketFd sockfd)
  280. {
  281. uint32_t ret;
  282. QCC_DbgTrace(("Close (sockfd = %d)", sockfd));
  283. ret = closesocket(static_cast<SOCKET>(sockfd));
  284. if (ret == SOCKET_ERROR) {
  285. QCC_LogError(ER_OS_ERROR, ("Close: (sockfd = %d) %s", sockfd, StrError().c_str()));
  286. }
  287. }
  288. QStatus SocketDup(SocketFd sockfd, SocketFd& dupSock)
  289. {
  290. QStatus status = ER_OK;
  291. WSAPROTOCOL_INFO protocolInfo;
  292. int ret = WSADuplicateSocket(sockfd, qcc::GetPid(), &protocolInfo);
  293. if (ret == SOCKET_ERROR) {
  294. QCC_LogError(ER_OS_ERROR, ("SocketDup: %s", StrError().c_str()));
  295. status = ER_OS_ERROR;
  296. } else {
  297. dupSock = WSASocket(protocolInfo.iAddressFamily,
  298. protocolInfo.iSocketType,
  299. protocolInfo.iProtocol,
  300. &protocolInfo,
  301. 0,
  302. WSA_FLAG_OVERLAPPED);
  303. if (dupSock == INVALID_SOCKET) {
  304. status = ER_OS_ERROR;
  305. QCC_LogError(status, ("SocketDup WSASocket: %s", StrError().c_str()));
  306. }
  307. }
  308. return status;
  309. }
  310. QStatus GetLocalAddress(SocketFd sockfd, IPAddress& addr, uint16_t& port)
  311. {
  312. QStatus status = ER_OK;
  313. struct sockaddr_storage addrBuf;
  314. socklen_t addrLen = sizeof(addrBuf);
  315. int ret;
  316. QCC_DbgTrace(("GetLocalAddress(sockfd = %d, addr = <>, port = <>)", sockfd));
  317. memset(&addrBuf, 0, addrLen);
  318. ret = getsockname(static_cast<SOCKET>(sockfd), reinterpret_cast<struct sockaddr*>(&addrBuf), &addrLen);
  319. if (ret == SOCKET_ERROR) {
  320. status = ER_OS_ERROR;
  321. QCC_LogError(status, ("Geting Local Address: %s", StrError().c_str()));
  322. } else {
  323. QCC_DbgPrintf(("ret = %d addrBuf.ss_family = %d addrLen = %d", ret, addrBuf.ss_family, addrLen));
  324. if (addrBuf.ss_family == AF_INET) {
  325. struct sockaddr_in* sa = reinterpret_cast<struct sockaddr_in*>(&addrBuf);
  326. uint8_t* portBuf = reinterpret_cast<uint8_t*>(&sa->sin_port);
  327. addr = IPAddress(reinterpret_cast<uint8_t*>(&sa->sin_addr.s_addr), IPAddress::IPv4_SIZE);
  328. port = (static_cast<uint16_t>(portBuf[0]) << 8) | static_cast<uint16_t>(portBuf[1]);
  329. } else if (addrBuf.ss_family == AF_INET6) {
  330. struct sockaddr_in6* sa = reinterpret_cast<struct sockaddr_in6*>(&addrBuf);
  331. uint8_t* portBuf = reinterpret_cast<uint8_t*>(&sa->sin6_port);
  332. addr = IPAddress(reinterpret_cast<uint8_t*>(&sa->sin6_addr.s6_addr), IPAddress::IPv6_SIZE);
  333. port = (static_cast<uint16_t>(portBuf[0]) << 8) | static_cast<uint16_t>(portBuf[1]);
  334. } else {
  335. port = 0;
  336. }
  337. QCC_DbgPrintf(("Local Address: %s - %u", addr.ToString().c_str(), port));
  338. }
  339. return status;
  340. }
  341. QStatus Send(SocketFd sockfd, const void* buf, size_t len, size_t& sent, uint32_t timeout)
  342. {
  343. QStatus status = ER_OK;
  344. size_t ret;
  345. QCC_DbgTrace(("ERSend(sockfd = %d, *buf = <>, len = %lu, sent = <>)", sockfd, len));
  346. assert(buf != NULL);
  347. QCC_DbgLocalData(buf, len);
  348. ret = send(static_cast<SOCKET>(sockfd), static_cast<const char*>(buf), len, 0);
  349. if (ret == SOCKET_ERROR) {
  350. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  351. sent = 0;
  352. status = ER_WOULDBLOCK;
  353. } else {
  354. status = ER_OS_ERROR;
  355. QCC_LogError(status, ("Send: %s", StrError().c_str()));
  356. }
  357. } else {
  358. sent = static_cast<size_t>(ret);
  359. QCC_DbgPrintf(("Sent %u bytes", sent));
  360. }
  361. return status;
  362. }
  363. QStatus SendTo(SocketFd sockfd, IPAddress& remoteAddr, uint16_t remotePort,
  364. const void* buf, size_t len, size_t& sent)
  365. {
  366. QStatus status = ER_OK;
  367. SOCKADDR_STORAGE addr;
  368. socklen_t addrLen = sizeof(addr);
  369. size_t ret;
  370. QCC_DbgTrace(("SendTo(sockfd = %d, remoteAddr = %s, remotePort = %u, *buf = <>, len = %lu, sent = <>)",
  371. sockfd, remoteAddr.ToString().c_str(), remotePort, len));
  372. assert(buf != NULL);
  373. QCC_DbgLocalData(buf, len);
  374. MakeSockAddr(remoteAddr, remotePort, &addr, addrLen);
  375. ret = sendto(static_cast<SOCKET>(sockfd), static_cast<const char*>(buf), len, 0,
  376. reinterpret_cast<struct sockaddr*>(&addr), addrLen);
  377. if (ret == SOCKET_ERROR) {
  378. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  379. sent = 0;
  380. status = ER_WOULDBLOCK;
  381. } else {
  382. status = ER_OS_ERROR;
  383. QCC_LogError(status, ("Send: %s", StrError().c_str()));
  384. }
  385. } else {
  386. sent = static_cast<size_t>(ret);
  387. QCC_DbgPrintf(("Sent %u bytes", sent));
  388. }
  389. return status;
  390. }
  391. #if QCC_USE_SCATTER_GATHER
  392. static QStatus SendSGCommon(SocketFd sockfd,
  393. SOCKADDR_STORAGE* addr,
  394. socklen_t addrLen,
  395. const ScatterGatherList& sg,
  396. size_t& sent)
  397. {
  398. QStatus status = ER_OK;
  399. QCC_DbgTrace(("SendSGCommon(sockfd = %d, *addr, addrLen, sg, sent = <>)", sockfd));
  400. /*
  401. * We will usually avoid the memory allocation
  402. */
  403. WSABUF iovAuto[8];
  404. WSABUF* iov = sg.Size() <= ArraySize(iovAuto) ? iovAuto : new WSABUF[sg.Size()];
  405. ScatterGatherList::const_iterator iter = sg.Begin();
  406. for (size_t index = 0; iter != sg.End(); ++index, ++iter) {
  407. iov[index].buf = iter->buf;
  408. iov[index].len = iter->len;
  409. QCC_DbgLocalData(iov[index].buf, iov[index].len);
  410. }
  411. WSAMSG msg;
  412. memset(&msg, 0, sizeof(msg));
  413. msg.name = reinterpret_cast<LPSOCKADDR>(addr);
  414. msg.namelen = addrLen;
  415. msg.lpBuffers = iov;
  416. msg.dwBufferCount = sg.Size();
  417. DWORD dwsent;
  418. DWORD ret = WSASendMsg(static_cast<SOCKET>(sockfd), &msg, 0, &dwsent, NULL, NULL);
  419. if (ret == SOCKET_ERROR) {
  420. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  421. status = ER_WOULDBLOCK;
  422. sent = 0;
  423. } else {
  424. status = ER_OS_ERROR;
  425. QCC_LogError(status, ("Send: %s", StrError().c_str()));
  426. }
  427. }
  428. QCC_DbgPrintf(("Sent %u bytes", dwsent));
  429. sent = dwsent;
  430. if (iov != iovAuto) {
  431. delete[] iov;
  432. }
  433. return status;
  434. }
  435. QStatus SendSG(SocketFd sockfd, const ScatterGatherList& sg, size_t& sent)
  436. {
  437. QCC_DbgTrace(("SendSG(sockfd = %d, sg, sent = <>)", sockfd));
  438. return SendSGCommon(sockfd, NULL, 0, sg, sent);
  439. }
  440. QStatus SendToSG(SocketFd sockfd, IPAddress& remoteAddr, uint16_t remotePort,
  441. const ScatterGatherList& sg, size_t& sent)
  442. {
  443. SOCKADDR_STORAGE addr;
  444. socklen_t addrLen = sizeof(addr);
  445. QCC_DbgTrace(("SendToSG(sockfd = %d, remoteAddr = %s, remotePort = %u, sg, sent = <>)",
  446. sockfd, remoteAddr.ToString().c_str(), remotePort));
  447. MakeSockAddr(remoteAddr, remotePort, &addr, addrLen);
  448. return SendSGCommon(sockfd, &addr, addrLen, sg, sent);
  449. }
  450. #else
  451. QStatus SendSG(SocketFd sockfd, const ScatterGatherList& sg, size_t& sent)
  452. {
  453. QStatus status;
  454. uint8_t* tmpBuf = new uint8_t[sg.MaxDataSize()];
  455. sg.CopyToBuffer(tmpBuf, sg.MaxDataSize());
  456. status = Send(sockfd, tmpBuf, sg.DataSize(), sent);
  457. delete[] tmpBuf;
  458. return status;
  459. }
  460. QStatus SendToSG(SocketFd sockfd, IPAddress& remoteAddr, uint16_t remotePort,
  461. const ScatterGatherList& sg, size_t& sent)
  462. {
  463. QStatus status;
  464. uint8_t* tmpBuf = new uint8_t[sg.MaxDataSize()];
  465. sg.CopyToBuffer(tmpBuf, sg.MaxDataSize());
  466. status = SendTo(sockfd, remoteAddr, remotePort, tmpBuf, sg.DataSize(), sent);
  467. delete[] tmpBuf;
  468. return status;
  469. }
  470. #endif
  471. QStatus Recv(SocketFd sockfd, void* buf, size_t len, size_t& received)
  472. {
  473. QStatus status = ER_OK;
  474. size_t ret;
  475. QCC_DbgTrace(("Recv(sockfd = %d, buf = <>, len = %lu, received = <>)", sockfd, len));
  476. assert(buf != NULL);
  477. ret = recv(static_cast<SOCKET>(sockfd), static_cast<char*>(buf), len, 0);
  478. if (ret == SOCKET_ERROR) {
  479. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  480. status = ER_WOULDBLOCK;
  481. } else {
  482. status = ER_OS_ERROR;
  483. }
  484. received = 0;
  485. } else {
  486. received = static_cast<size_t>(ret);
  487. QCC_DbgPrintf(("Received %u bytes", received));
  488. }
  489. QCC_DbgRemoteData(buf, received);
  490. return status;
  491. }
  492. QStatus RecvFrom(SocketFd sockfd, IPAddress& remoteAddr, uint16_t& remotePort,
  493. void* buf, size_t len, size_t& received)
  494. {
  495. QStatus status = ER_OK;
  496. SOCKADDR_STORAGE fromAddr;
  497. socklen_t addrLen = sizeof(fromAddr);
  498. size_t ret;
  499. received = 0;
  500. QCC_DbgTrace(("RecvFrom(sockfd = %d, buf = <>, len = %lu, received = <>)", sockfd, len));
  501. assert(buf != NULL);
  502. ret = recvfrom(static_cast<int>(sockfd), static_cast<char*>(buf), len, 0,
  503. reinterpret_cast<sockaddr*>(&fromAddr), &addrLen);
  504. if (ret == SOCKET_ERROR) {
  505. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  506. status = ER_WOULDBLOCK;
  507. } else {
  508. status = ER_OS_ERROR;
  509. QCC_LogError(status, ("Receive: %d", StrError().c_str()));
  510. }
  511. received = 0;
  512. } else {
  513. received = static_cast<size_t>(ret);
  514. status = GetSockAddr(&fromAddr, addrLen, remoteAddr, remotePort);
  515. QCC_DbgPrintf(("Received %u bytes, remoteAddr = %s, remotePort = %u",
  516. received, remoteAddr.ToString().c_str(), remotePort));
  517. }
  518. QCC_DbgRemoteData(buf, received);
  519. return status;
  520. }
  521. #if QCC_USE_SCATTER_GATHER
  522. static QStatus RecvSGCommon(SocketFd sockfd, SOCKADDR_STORAGE* addr, socklen_t& addrLen,
  523. ScatterGatherList& sg, size_t& received)
  524. {
  525. static LPFN_WSARECVMSG WSARecvMsg = NULL;
  526. QStatus status = ER_OK;
  527. DWORD dwRecv;
  528. DWORD ret;
  529. QCC_DbgTrace(("RecvSGCommon(sockfd = &d, addr, addrLen, sg = <>, received = <>)", sockfd));
  530. /*
  531. * Get extension function pointer
  532. */
  533. if (!WSARecvMsg) {
  534. GUID guid = WSAID_WSARECVMSG;
  535. ret = WSAIoctl(static_cast<SOCKET>(sockfd), SIO_GET_EXTENSION_FUNCTION_POINTER,
  536. &guid, sizeof(guid),
  537. &WSARecvMsg, sizeof(WSARecvMsg),
  538. &dwRecv, NULL, NULL);
  539. if (ret == SOCKET_ERROR) {
  540. status = ER_OS_ERROR;
  541. QCC_LogError(status, ("Receive: %s", StrError().c_str()));
  542. return status;
  543. }
  544. }
  545. /*
  546. * We will usually avoid the memory allocation
  547. */
  548. WSABUF iovAuto[8];
  549. WSABUF* iov = sg.Size() <= ArraySize(iovAuto) ? iovAuto : new WSABUF[sg.Size()];
  550. ScatterGatherList::const_iterator iter = sg.Begin();
  551. for (size_t index = 0; iter != sg.End(); ++index, ++iter) {
  552. iov[index].buf = iter->buf;
  553. iov[index].len = iter->len;
  554. }
  555. WSAMSG msg;
  556. memset(&msg, 0, sizeof(msg));
  557. msg.name = reinterpret_cast<LPSOCKADDR>(addr);
  558. msg.namelen = addrLen;
  559. msg.lpBuffers = iov;
  560. msg.dwBufferCount = sg.Size();
  561. ret = WSARecvMsg(static_cast<SOCKET>(sockfd), &msg, &dwRecv, NULL, NULL);
  562. if (ret == SOCKET_ERROR) {
  563. if (WSAGetLastError() == WSAEWOULDBLOCK) {
  564. received = 0;
  565. status = ER_WOULDBLOCK;
  566. } else {
  567. status = ER_OS_ERROR;
  568. QCC_LogError(status, ("Receive: %s", StrError().c_str()));
  569. }
  570. } else {
  571. sg.SetDataSize(received);
  572. addrLen = msg.namelen;
  573. received = dwRecv;
  574. }
  575. #if !defined(NDEBUG)
  576. QCC_DbgPrintf(("Received %u bytes", received));
  577. for (iter = sg.Begin(); iter != sg.End(); ++iter) {
  578. QCC_DbgRemoteData(iter->buf, iter->len);
  579. }
  580. #endif
  581. if (iov != iovAuto) {
  582. delete[] iov;
  583. }
  584. return status;
  585. }
  586. QStatus RecvSG(SocketFd sockfd, ScatterGatherList& sg, size_t& received)
  587. {
  588. socklen_t addrLen = 0;
  589. QCC_DbgTrace(("RecvSG(sockfd = %d, sg = <>, received = <>)", sockfd));
  590. return RecvSGCommon(sockfd, NULL, addrLen, sg, received);
  591. }
  592. QStatus RecvFromSG(SocketFd sockfd, IPAddress& remoteAddr, uint16_t& remotePort,
  593. ScatterGatherList& sg, size_t& received)
  594. {
  595. QStatus status;
  596. SOCKADDR_STORAGE addr;
  597. socklen_t addrLen = sizeof(addr);
  598. status = RecvSGCommon(sockfd, &addr, addrLen, sg, received);
  599. if (ER_OK == status) {
  600. GetSockAddr(&addr, addrLen, remoteAddr, remotePort);
  601. QCC_DbgTrace(("RecvFromSG(sockfd = %d, remoteAddr = %s, remotePort = %u, sg = <>, rcvd = %u)",
  602. sockfd, remoteAddr.ToString().c_str(), remotePort, received));
  603. }
  604. return status;
  605. }
  606. #else
  607. QStatus RecvSG(SocketFd sockfd, ScatterGatherList& sg, size_t& received)
  608. {
  609. QStatus status = ER_OK;
  610. uint8_t* tmpBuf = new uint8_t[sg.MaxDataSize()];
  611. QCC_DbgTrace(("RecvSG(sockfd = %d, sg = <>, received = <>)", sockfd));
  612. status = Recv(sockfd, tmpBuf, sg.MaxDataSize(), received);
  613. if (ER_OK == status) {
  614. sg.CopyFromBuffer(tmpBuf, received);
  615. }
  616. QCC_DbgPrintf(("Received %u bytes", received));
  617. delete[] tmpBuf;
  618. return status;
  619. }
  620. QStatus RecvFromSG(SocketFd sockfd, IPAddress& remoteAddr, uint16_t& remotePort,
  621. ScatterGatherList& sg, size_t& received)
  622. {
  623. QStatus status = ER_OK;
  624. uint8_t* tmpBuf = new uint8_t[sg.MaxDataSize()];
  625. QCC_DbgTrace(("RecvToSG(sockfd = %d, remoteAddr = %s, remotePort = %u, sg = <>, sent = <>)",
  626. sockfd, remoteAddr.ToString().c_str(), remotePort));
  627. status = RecvFrom(sockfd, remoteAddr, remotePort, tmpBuf, sg.MaxDataSize(), received);
  628. if (ER_OK == status) {
  629. sg.CopyFromBuffer(tmpBuf, received);
  630. }
  631. QCC_DbgPrintf(("Received %u bytes", received));
  632. delete[] tmpBuf;
  633. return status;
  634. }
  635. #endif
  636. int InetPtoN(int af, const char* src, void* dst)
  637. {
  638. WinsockCheck();
  639. int err = -1;
  640. if (af == AF_INET6) {
  641. struct sockaddr_in6 sin6;
  642. int sin6Len = sizeof(sin6);
  643. memset(&sin6, 0, sin6Len);
  644. sin6.sin6_family = AF_INET6;
  645. err = WSAStringToAddressA((LPSTR)src, AF_INET6, NULL, (struct sockaddr*)&sin6, &sin6Len);
  646. if (!err) {
  647. memcpy(dst, &sin6.sin6_addr, sizeof(sin6.sin6_addr));
  648. }
  649. } else if (af == AF_INET) {
  650. struct sockaddr_in sin;
  651. int sinLen = sizeof(sin);
  652. memset(&sin, 0, sinLen);
  653. sin.sin_family = AF_INET;
  654. err = WSAStringToAddressA((LPSTR)src, AF_INET, NULL, (struct sockaddr*)&sin, &sinLen);
  655. if (!err) {
  656. memcpy(dst, &sin.sin_addr, sizeof(sin.sin_addr));
  657. }
  658. }
  659. return err ? -1 : 1;
  660. }
  661. const char* InetNtoP(int af, const void* src, char* dst, socklen_t size)
  662. {
  663. WinsockCheck();
  664. int err = -1;
  665. DWORD sz = (DWORD)size;
  666. if (af == AF_INET6) {
  667. struct sockaddr_in6 sin6;
  668. memset(&sin6, 0, sizeof(sin6));
  669. sin6.sin6_family = AF_INET6;
  670. sin6.sin6_flowinfo = 0;
  671. memcpy(&sin6.sin6_addr, src, sizeof(sin6.sin6_addr));
  672. err = WSAAddressToStringA((struct sockaddr*)&sin6, sizeof(sin6), NULL, dst, &sz);
  673. } else if (af == AF_INET) {
  674. struct sockaddr_in sin;
  675. memset(&sin, 0, sizeof(sin));
  676. sin.sin_family = AF_INET;
  677. memcpy(&sin.sin_addr, src, sizeof(sin.sin_addr));
  678. err = WSAAddressToStringA((struct sockaddr*)&sin, sizeof(sin), NULL, dst, &sz);
  679. }
  680. return err ? NULL : dst;
  681. }
  682. QStatus RecvWithFds(SocketFd sockfd, void* buf, size_t len, size_t& received, SocketFd* fdList, size_t maxFds, size_t& recvdFds)
  683. {
  684. QStatus status = ER_OK;
  685. if (!fdList) {
  686. return ER_BAD_ARG_5;
  687. }
  688. if (!maxFds) {
  689. return ER_BAD_ARG_6;
  690. }
  691. QCC_DbgHLPrintf(("RecvWithFds"));
  692. recvdFds = 0;
  693. maxFds = std::min(maxFds, SOCKET_MAX_FILE_DESCRIPTORS);
  694. /*
  695. * Check if the next read will return OOB data
  696. */
  697. u_long marked = 0;
  698. int ret = ioctlsocket(sockfd, SIOCATMARK, &marked);
  699. if (ret == SOCKET_ERROR) {
  700. status = ER_OS_ERROR;
  701. QCC_LogError(status, ("RecvWithFds ioctlsocket: %s", StrError().c_str()));
  702. }
  703. if ((status == ER_OK) && !marked) {
  704. char fdCount;
  705. ret = recv(sockfd, &fdCount, 1, MSG_OOB);
  706. if (ret == SOCKET_ERROR) {
  707. status = ER_OS_ERROR;
  708. QCC_LogError(status, ("RecvWithFds recv (MSG_OOB): %s", StrError().c_str()));
  709. } else {
  710. recvdFds = fdCount;
  711. QCC_DbgHLPrintf(("RecvWithFds OOB %d handles", recvdFds));
  712. /*
  713. * Check we have enough room to return the file descriptors.
  714. */
  715. if (recvdFds > recvdFds) {
  716. status = ER_OS_ERROR;
  717. QCC_LogError(status, ("Too many handles: %d implementation limit is %d", recvdFds, maxFds));
  718. }
  719. }
  720. /*
  721. * The actual file descriptors are all inband and must be read atomically.
  722. */
  723. for (size_t i = 0; (i < recvdFds) && (status == ER_OK); ++i) {
  724. WSAPROTOCOL_INFO protocolInfo;
  725. uint8_t* buf = reinterpret_cast<uint8_t*>(&protocolInfo);
  726. size_t sz = sizeof(protocolInfo);
  727. uint32_t maxSleeps = 100;
  728. /*
  729. * The poll/sleep loop is a little cheesy but file descriptors are small and
  730. * rare so this is highly unlikely to have any impact on performance.
  731. */
  732. while (sz && (status == ER_OK)) {
  733. size_t recvd;
  734. status = Recv(sockfd, buf, sz, recvd);
  735. if (status == ER_WOULDBLOCK) {
  736. if (--maxSleeps) {
  737. qcc::Sleep(1);
  738. status = ER_OK;
  739. continue;
  740. }
  741. status = ER_TIMEOUT;
  742. }
  743. buf += recvd;
  744. sz -= recvd;
  745. }
  746. if (status == ER_OK) {
  747. SocketFd fd = WSASocket(protocolInfo.iAddressFamily,
  748. protocolInfo.iSocketType,
  749. protocolInfo.iProtocol,
  750. &protocolInfo,
  751. 0,
  752. WSA_FLAG_OVERLAPPED);
  753. if (fd == INVALID_SOCKET) {
  754. status = ER_OS_ERROR;
  755. QCC_LogError(status, ("RecvWithFds WSASocket: %s", StrError().c_str()));
  756. } else {
  757. QCC_DbgHLPrintf(("RecvWithFds got handle %u", fd));
  758. *fdList++ = fd;
  759. }
  760. }
  761. }
  762. }
  763. if (status == ER_OK) {
  764. status = Recv(sockfd, buf, len, received);
  765. }
  766. return status;
  767. }
  768. QStatus SendWithFds(SocketFd sockfd, const void* buf, size_t len, size_t& sent, SocketFd* fdList, size_t numFds, uint32_t pid)
  769. {
  770. QStatus status = ER_OK;
  771. if (!fdList) {
  772. return ER_BAD_ARG_5;
  773. }
  774. if (!numFds || (numFds > SOCKET_MAX_FILE_DESCRIPTORS)) {
  775. return ER_BAD_ARG_6;
  776. }
  777. QCC_DbgHLPrintf(("SendWithFds"));
  778. /*
  779. * We send the file descriptor count as OOB data.
  780. */
  781. char oob = static_cast<char>(numFds);
  782. int ret = send(sockfd, &oob, 1, MSG_OOB);
  783. if (ret == SOCKET_ERROR) {
  784. status = ER_OS_ERROR;
  785. QCC_LogError(status, ("RecvWithFds recv (MSG_OOB): %s", StrError().c_str()));
  786. } else {
  787. QCC_DbgHLPrintf(("SendWithFds OOB %d handles", oob));
  788. }
  789. while (numFds-- && (status == ER_OK)) {
  790. WSAPROTOCOL_INFO protocolInfo;
  791. ret = WSADuplicateSocket(*fdList++, pid, &protocolInfo);
  792. if (ret) {
  793. status = ER_OS_ERROR;
  794. QCC_LogError(status, ("SendFd WSADuplicateSocket: %s", StrError().c_str()));
  795. } else {
  796. uint8_t* buf = reinterpret_cast<uint8_t*>(&protocolInfo);
  797. size_t sz = sizeof(protocolInfo);
  798. uint32_t maxSleeps = 100;
  799. /*
  800. * The poll/sleep loop is a little cheesy but file descriptors are small and
  801. * rare so this is highly unlikely to have any impact on performance.
  802. */
  803. while (sz && (status == ER_OK)) {
  804. status = Send(sockfd, buf, sz, sent);
  805. if (status == ER_WOULDBLOCK) {
  806. if (--maxSleeps) {
  807. qcc::Sleep(1);
  808. status = ER_OK;
  809. continue;
  810. }
  811. status = ER_TIMEOUT;
  812. }
  813. buf += sent;
  814. sz -= sent;
  815. }
  816. }
  817. }
  818. if (status == ER_OK) {
  819. status = Send(sockfd, buf, len, sent);
  820. }
  821. return status;
  822. }
  823. QStatus SocketPair(SocketFd(&sockets)[2])
  824. {
  825. QStatus status = ER_OK;
  826. IPAddress ipAddr("127.0.0.1");
  827. IPAddress remAddr;
  828. uint16_t remPort;
  829. QCC_DbgTrace(("SocketPair()"));
  830. /* Create sockets */
  831. status = Socket(QCC_AF_INET, QCC_SOCK_STREAM, sockets[0]);
  832. if (status != ER_OK) {
  833. return status;
  834. }
  835. status = Socket(QCC_AF_INET, QCC_SOCK_STREAM, sockets[1]);
  836. if (status != ER_OK) {
  837. Close(sockets[0]);
  838. return status;
  839. }
  840. /* Bind fd[0] */
  841. status = Bind(sockets[0], ipAddr, 0);
  842. if (status != ER_OK) {
  843. goto socketPairCleanup;
  844. }
  845. /* Listen fds[0] */
  846. status = Listen(sockets[0], 1);
  847. if (status != ER_OK) {
  848. goto socketPairCleanup;
  849. }
  850. /* Get addr info for fds[0] */
  851. struct sockaddr_in addrInfo;
  852. int len = sizeof(addrInfo);
  853. int ret = getsockname(sockets[0], reinterpret_cast<sockaddr*>(&addrInfo), &len);
  854. if (ret == SOCKET_ERROR) {
  855. status = ER_OS_ERROR;
  856. QCC_LogError(status, ("getsockopt failed: %s", StrError().c_str()));
  857. goto socketPairCleanup;
  858. }
  859. /* Connect fds[1] */
  860. status = Connect(sockets[1], ipAddr, ntohs(addrInfo.sin_port));
  861. if (status != ER_OK) {
  862. QCC_LogError(status, ("SocketPair.Connect failed"));
  863. goto socketPairCleanup;
  864. }
  865. /* Accept fds[0] */
  866. status = Accept(sockets[0], remAddr, remPort, sockets[0]);
  867. if (status != ER_OK) {
  868. QCC_LogError(status, ("SocketPair.Accept failed"));
  869. goto socketPairCleanup;
  870. }
  871. /* Make sockets blocking */
  872. status = SetBlocking(sockets[0], true);
  873. if (status != ER_OK) {
  874. QCC_LogError(status, ("SetBlocking fd[0] failed"));
  875. goto socketPairCleanup;
  876. }
  877. status = SetBlocking(sockets[1], true);
  878. if (status != ER_OK) {
  879. QCC_LogError(status, ("SetBlocking fd[1] failed"));
  880. goto socketPairCleanup;
  881. }
  882. socketPairCleanup:
  883. if (status != ER_OK) {
  884. Close(sockets[0]);
  885. Close(sockets[1]);
  886. }
  887. return status;
  888. }
  889. QStatus SetBlocking(SocketFd sockfd, bool blocking)
  890. {
  891. QStatus status = ER_OK;
  892. u_long mode = blocking ? 0 : 1;
  893. int ret = ioctlsocket(sockfd, FIONBIO, &mode);
  894. if (ret == SOCKET_ERROR) {
  895. status = ER_OS_ERROR;
  896. QCC_LogError(status, ("Failed to set socket non-blocking %s", StrError().c_str()));
  897. }
  898. return status;
  899. }
  900. QStatus SetNagle(SocketFd sockfd, bool useNagle)
  901. {
  902. QStatus status = ER_OK;
  903. int arg = useNagle ? 1 : -0;
  904. int r = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&arg, sizeof(int));
  905. if (r != 0) {
  906. status = ER_OS_ERROR;
  907. QCC_LogError(status, ("Setting TCP_NODELAY failed: (%d) %s", GetLastError(), GetLastErrorString().c_str()));
  908. }
  909. return status;
  910. }
  911. QStatus SetReuseAddress(SocketFd sockfd, bool reuse)
  912. {
  913. QStatus status = ER_OK;
  914. /*
  915. * On Windows SO_REUSEADDR allows an application to bind an steal a port that is already in use.
  916. * This is different than the posix behavior. Setting SO_EXCLUSIVEADDRUSE establishes the
  917. * required behavior.
  918. */
  919. if (status == ER_OK) {
  920. int arg = reuse ? 1 : -0;
  921. int r = setsockopt(sockfd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&arg, sizeof(arg));
  922. if (r != 0) {
  923. QCC_LogError(ER_OS_ERROR, ("Setting SO_EXCLUSIVEADDRUSE failed: (%d) %s", GetLastError(), GetLastErrorString().c_str()));
  924. }
  925. }
  926. return status;
  927. }
  928. /*
  929. * Some systems do not define SO_REUSEPORT (which is a BSD-ism from the first
  930. * days of multicast support). In this case they special case SO_REUSEADDR in
  931. * the presence of multicast addresses to perform the same function, which is to
  932. * allow multiple processes to bind to the same multicast address/port. In this
  933. * case, SO_REUSEADDR provides the equivalent functionality of SO_REUSEPORT, so
  934. * it is quite safe to substitute them. Interestingly, Darwin which is actually
  935. * BSD-derived does not define SO_REUSEPORT, but Linux which is supposedly not
  936. * BSD does. Go figure.
  937. */
  938. #ifndef SO_REUSEPORT
  939. #define SO_REUSEPORT SO_REUSEADDR
  940. #endif
  941. QStatus SetReusePort(SocketFd sockfd, bool reuse)
  942. {
  943. QStatus status = ER_OK;
  944. int arg = reuse ? 1 : -0;
  945. int r = setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&arg, sizeof(arg));
  946. if (r != 0) {
  947. status = ER_OS_ERROR;
  948. QCC_LogError(status, ("Setting SO_REUSEPORT failed: (%d) %s", GetLastError(), GetLastErrorString().c_str()));
  949. }
  950. return status;
  951. }
  952. void IfConfigByFamily(uint32_t family, std::vector<IfConfigEntry>& entries);
  953. /*
  954. * Getting set to do a multicast join or drop is straightforward but not
  955. * completely trivial, and the process is identical for both socket options, so
  956. * we only do the work in one place and select one of the followin oeprations.
  957. */
  958. enum GroupOp {JOIN, LEAVE};
  959. QStatus MulticastGroupOpInternal(SocketFd sockFd, AddressFamily family, String multicastGroup, String iface, GroupOp op)
  960. {
  961. /*
  962. * We assume that No external API will be trying to call here and so asserts
  963. * are appropriate when checking for completely bogus parameters.
  964. */
  965. assert(sockFd);
  966. assert(family == AF_INET || family == AF_INET6);
  967. assert(multicastGroup.size());
  968. assert(iface.size());
  969. assert(op == JOIN || op == LEAVE);
  970. /*
  971. * Joining a multicast group requires a different approach based on the
  972. * address family of the socket. There's no way to get this information
  973. * from an unbound socket, and it is not unreasonable to join a multicast
  974. * group before binding; so to avoid an inscrutable initialization order
  975. * requirement we force the caller to provide this tidbit.
  976. */
  977. if (family == QCC_AF_INET) {
  978. /*
  979. * Group memberships are associated with both the multicast group itself
  980. * and also an interface. In the IPv4 version, we need to provide an
  981. * interface address. There is no convenient socket ioctl in Windows to
  982. * do what we need (SIOCGIFADDR) so we call into IfConfig since it
  983. * already does the surprising amount of dirty work required to get this
  984. * done across the various incarnations of Windows.
  985. */
  986. std::vector<IfConfigEntry> entries;
  987. IfConfigByFamily(AF_INET, entries);
  988. bool found = false;
  989. struct ip_mreq mreq;
  990. for (uint32_t i = 0; i < entries.size(); ++i) {
  991. if (entries[i].m_name == iface) {
  992. IPAddress address(entries[i].m_addr);
  993. mreq.imr_interface.s_addr = address.GetIPv4AddressNetOrder();
  994. found = true;
  995. }
  996. }
  997. if (!found) {
  998. QCC_LogError(ER_OS_ERROR, ("can't find address for interface %s", iface.c_str()));
  999. return ER_OS_ERROR;
  1000. }
  1001. int rc = InetPtoN(AF_INET, multicastGroup.c_str(), &mreq.imr_multiaddr);
  1002. if (rc != 1) {
  1003. QCC_LogError(ER_OS_ERROR, ("InetPtoN() failed: %d - %s", GetLastError(), GetLastErrorString().c_str()));
  1004. return ER_OS_ERROR;
  1005. }
  1006. int opt = op == JOIN ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
  1007. rc = setsockopt(sockFd, IPPROTO_IP, opt, reinterpret_cast<const char*>(&mreq), sizeof(mreq));
  1008. if (rc == -1) {
  1009. QCC_LogError(ER_OS_ERROR, ("setsockopt(%s) failed: %d - %s", op == JOIN ? "IP_ADD_MEMBERSHIP" : "IP_DROP_MEMBERSHIP", GetLastError(), GetLastErrorString().c_str()));
  1010. return ER_OS_ERROR;
  1011. }
  1012. } else if (family == QCC_AF_INET6) {
  1013. /*
  1014. * Group memberships are associated with both the multicast group itself
  1015. * and also an interface. In the IPv6 version, we need to provide an
  1016. * interface index instead of an IP address associated with the
  1017. * interface. There is no convenient call in Windows to do what we need
  1018. * (cf. if_nametoindex) so we call into IfConfig since it already does
  1019. * the surprising amount of dirty work required to get this done across
  1020. * the various incarnations of Windows.
  1021. */
  1022. std::vector<IfConfigEntry> entries;
  1023. IfConfigByFamily(AF_INET6, entries);
  1024. bool found = false;
  1025. struct ipv6_mreq mreq;
  1026. for (uint32_t i = 0; i < entries.size(); ++i) {
  1027. if (entries[i].m_name == iface) {
  1028. mreq.ipv6mr_interface = entries[i].m_index;
  1029. found = true;
  1030. }
  1031. }
  1032. if (!found) {
  1033. QCC_LogError(ER_OS_ERROR, ("can't find interface index for interface %s", iface.c_str()));
  1034. return ER_OS_ERROR;
  1035. }
  1036. int rc = InetPtoN(AF_INET6, multicastGroup.c_str(), &mreq.ipv6mr_multiaddr);
  1037. if (rc != 1) {
  1038. QCC_LogError(ER_OS_ERROR, ("InetPtoN() failed: %d - %s", GetLastError(), GetLastErrorString().c_str()));
  1039. return ER_OS_ERROR;
  1040. }
  1041. int opt = op == JOIN ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
  1042. rc = setsockopt(sockFd, IPPROTO_IPV6, opt, reinterpret_cast<const char*>(&mreq), sizeof(mreq));
  1043. if (rc == -1) {
  1044. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_ADD_MEMBERSHIP) failed: %d - %s", GetLastError(), GetLastErrorString().c_str()));
  1045. return ER_OS_ERROR;
  1046. }
  1047. }
  1048. return ER_OK;
  1049. }
  1050. QStatus JoinMulticastGroup(SocketFd sockFd, AddressFamily family, String multicastGroup, String iface)
  1051. {
  1052. return MulticastGroupOpInternal(sockFd, family, multicastGroup, iface, JOIN);
  1053. }
  1054. QStatus LeaveMulticastGroup(SocketFd sockFd, AddressFamily family, String multicastGroup, String iface)
  1055. {
  1056. return MulticastGroupOpInternal(sockFd, family, multicastGroup, iface, LEAVE);
  1057. }
  1058. QStatus SetMulticastInterface(SocketFd sockFd, AddressFamily family, qcc::String iface)
  1059. {
  1060. /*
  1061. * We assume that No external API will be trying to call here and so asserts
  1062. * are appropriate when checking for completely bogus parameters.
  1063. */
  1064. assert(sockFd);
  1065. assert(family == AF_INET || family == AF_INET6);
  1066. assert(iface.size());
  1067. /*
  1068. * Associating the multicast interface with a socket requires a different
  1069. * approach based on the address family of the socket. There's no way to
  1070. * get this information from an unbound socket, and it is not unreasonable
  1071. * to set the interface before binding; so to avoid an inscrutable
  1072. * initialization order requirement we force the caller to provide this
  1073. * tidbit.
  1074. */
  1075. if (family == QCC_AF_INET) {
  1076. /*
  1077. * In the IPv4 version, we need to provide an interface address. We
  1078. * borrow the socket passed in to do the required call to find the
  1079. * address from the interface name. There is no convenient socket ioctl
  1080. * in Windows to do what we need (SIOCGIFADDR) so we call into IfConfig
  1081. * since it already does the surprising amount of dirty work required to
  1082. * get this done across the various incarnations of Windows.
  1083. */
  1084. std::vector<IfConfigEntry> entries;
  1085. IfConfigByFamily(AF_INET, entries);
  1086. bool found = false;
  1087. struct in_addr addr;
  1088. for (uint32_t i = 0; i < entries.size(); ++i) {
  1089. if (entries[i].m_name == iface) {
  1090. IPAddress address(entries[i].m_addr);
  1091. addr.s_addr = address.GetIPv4AddressNetOrder();
  1092. found = true;
  1093. }
  1094. }
  1095. if (!found) {
  1096. QCC_LogError(ER_OS_ERROR, ("can't find address for interface %s", iface.c_str()));
  1097. return ER_OS_ERROR;
  1098. }
  1099. int rc = setsockopt(sockFd, IPPROTO_IP, IP_MULTICAST_IF, reinterpret_cast<const char*>(&addr), sizeof(addr));
  1100. if (rc == -1) {
  1101. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_MULTICAST_IF) failed: %d - %s", GetLastError(), GetLastErrorString().c_str()));
  1102. return ER_OS_ERROR;
  1103. }
  1104. } else if (family == QCC_AF_INET6) {
  1105. /*
  1106. * In the IPv6 version, we need to provide an interface index instead of
  1107. * an IP address associated with the interface. There is no convenient
  1108. * call in Windows to do what we need (cf. if_nametoindex) so we call
  1109. * into IfConfig since it already does the surprising amount of dirty
  1110. * work required to get this done across the various incarnations of
  1111. * Windows.
  1112. */
  1113. std::vector<IfConfigEntry> entries;
  1114. IfConfigByFamily(AF_INET6, entries);
  1115. bool found = false;
  1116. uint32_t index = 0;
  1117. for (uint32_t i = 0; i < entries.size(); ++i) {
  1118. if (entries[i].m_name == iface) {
  1119. index = entries[i].m_index;
  1120. found = true;
  1121. }
  1122. }
  1123. if (!found) {
  1124. QCC_LogError(ER_OS_ERROR, ("can't find interface index for interface %s", iface.c_str()));
  1125. return ER_OS_ERROR;
  1126. }
  1127. int rc = setsockopt(sockFd, IPPROTO_IPV6, IP_MULTICAST_IF, reinterpret_cast<const char*>(&index), sizeof(index));
  1128. if (rc == -1) {
  1129. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_MULTICAST_IF) failed: %d - %s", GetLastError(), GetLastErrorString().c_str()));
  1130. return ER_OS_ERROR;
  1131. }
  1132. }
  1133. return ER_OK;
  1134. }
  1135. QStatus SetMulticastHops(SocketFd sockFd, AddressFamily family, uint32_t hops)
  1136. {
  1137. /*
  1138. * We assume that No external API will be trying to call here and so asserts
  1139. * are appropriate when checking for completely bogus parameters.
  1140. */
  1141. assert(sockFd);
  1142. assert(family == AF_INET || family == AF_INET6);
  1143. /*
  1144. * IPv4 and IPv6 are almost the same. Of course, not quite, though.
  1145. */
  1146. if (family == QCC_AF_INET) {
  1147. int rc = setsockopt(sockFd, IPPROTO_IP, IP_MULTICAST_TTL, reinterpret_cast<const char*>(&hops), sizeof(hops));
  1148. if (rc == -1) {
  1149. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_MULTICAST_TTL) failed: %d - %s", GetLastError(), GetLastErrorString().c_str()));
  1150. return ER_OS_ERROR;
  1151. }
  1152. } else if (family == QCC_AF_INET6) {
  1153. int rc = setsockopt(sockFd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, reinterpret_cast<const char*>(&hops), sizeof(hops));
  1154. if (rc == -1) {
  1155. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_MULTICAST_HOPS) failed: %d - %s", GetLastError(), GetLastErrorString().c_str()));
  1156. return ER_OS_ERROR;
  1157. }
  1158. }
  1159. return ER_OK;
  1160. }
  1161. QStatus SetBroadcast(SocketFd sockfd, bool broadcast)
  1162. {
  1163. QStatus status = ER_OK;
  1164. int arg = broadcast ? 1 : -0;
  1165. int r = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const char*)&arg, sizeof(arg));
  1166. if (r != 0) {
  1167. status = ER_OS_ERROR;
  1168. QCC_LogError(status, ("Setting SO_BROADCAST failed: (%d) %s", GetLastError(), GetLastErrorString().c_str()));
  1169. }
  1170. return status;
  1171. }
  1172. } /* namespace */