PageRenderTime 138ms CodeModel.GetById 51ms RepoModel.GetById 0ms app.codeStats 1ms

/os/posix/Socket.cc

https://github.com/my4ndr0id/android_external_alljoyn_common
C++ | 1105 lines | 835 code | 168 blank | 102 comment | 206 complexity | a87a370285add690439369a05f26ebb5 MD5 | raw file
  1. /**
  2. * @file
  3. *
  4. * Define the abstracted socket interface for Linux
  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. #include <algorithm>
  23. #include <arpa/inet.h>
  24. #include <netinet/tcp.h>
  25. #include <net/if.h>
  26. #include <errno.h>
  27. #include <fcntl.h>
  28. #include <netdb.h>
  29. #include <stddef.h>
  30. #include <string.h>
  31. #include <sys/socket.h>
  32. #include <sys/types.h>
  33. #include <sys/un.h>
  34. #include <sys/ioctl.h>
  35. #include <unistd.h>
  36. #if defined(QCC_OS_DARWIN)
  37. #include <sys/ucred.h>
  38. #endif
  39. #include <qcc/IPAddress.h>
  40. #include <qcc/ScatterGatherList.h>
  41. #include <qcc/Util.h>
  42. #include <qcc/Thread.h>
  43. #include <Status.h>
  44. #define QCC_MODULE "NETWORK"
  45. namespace qcc {
  46. const SocketFd INVALID_SOCKET_FD = -1;
  47. #if defined(QCC_OS_DARWIN)
  48. #define MSG_NOSIGNAL 0
  49. static void DisableSigPipe(SocketFd socket)
  50. {
  51. int disableSigPipe = 1;
  52. setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &disableSigPipe, sizeof(disableSigPipe));
  53. }
  54. #endif
  55. static QStatus MakeSockAddr(const char* path,
  56. struct sockaddr_storage* addrBuf, socklen_t& addrSize)
  57. {
  58. size_t pathLen = strlen(path);
  59. struct sockaddr_un sa;
  60. assert((size_t)addrSize >= sizeof(sa));
  61. memset(&sa, 0, sizeof(sa));
  62. sa.sun_family = AF_UNIX;
  63. memcpy(sa.sun_path, path, (std::min)(pathLen, sizeof(sa.sun_path) - 1));
  64. /*
  65. * We use an @ in the first character position to indicate an abstract socket. Abstract sockets
  66. * start with a NUL character on Linux.
  67. */
  68. if (sa.sun_path[0] == '@') {
  69. #if defined(QCC_OS_LINUX) || defined (QCC_OS_ANDROID)
  70. sa.sun_path[0] = 0;
  71. addrSize = offsetof(struct sockaddr_un, sun_path) + pathLen;
  72. #else /* Non-linux platforms */
  73. QCC_LogError(ER_NOT_IMPLEMENTED, ("Abstract socket paths are not supported"));
  74. return ER_NOT_IMPLEMENTED;
  75. #endif
  76. } else {
  77. addrSize = sizeof(sa);
  78. }
  79. memcpy(addrBuf, &sa, sizeof(sa));
  80. return ER_OK;
  81. }
  82. static QStatus MakeSockAddr(const IPAddress& addr, uint16_t port,
  83. struct sockaddr_storage* addrBuf, socklen_t& addrSize)
  84. {
  85. if (addr.IsIPv4()) {
  86. struct sockaddr_in sa;
  87. assert((size_t)addrSize >= sizeof(sa));
  88. memset(&sa, 0, sizeof(sa));
  89. sa.sin_family = AF_INET;
  90. sa.sin_port = htons(port);
  91. sa.sin_addr.s_addr = addr.GetIPv4AddressNetOrder();
  92. addrSize = sizeof(sa);
  93. memcpy(addrBuf, &sa, sizeof(sa));
  94. } else {
  95. struct sockaddr_in6 sa;
  96. assert((size_t)addrSize >= sizeof(sa));
  97. memset(&sa, 0, sizeof(sa));
  98. sa.sin6_family = AF_INET6;
  99. sa.sin6_port = htons(port);
  100. sa.sin6_flowinfo = 0; // TODO: What should go here???
  101. addr.RenderIPv6Binary(sa.sin6_addr.s6_addr, sizeof(sa.sin6_addr.s6_addr));
  102. sa.sin6_scope_id = 0; // TODO: What should go here???
  103. addrSize = sizeof(sa);
  104. memcpy(addrBuf, &sa, sizeof(sa));
  105. }
  106. return ER_OK;
  107. }
  108. static QStatus GetSockAddr(const sockaddr_storage* addrBuf, socklen_t addrSize,
  109. IPAddress& addr, uint16_t& port)
  110. {
  111. QStatus status = ER_OK;
  112. char hostname[NI_MAXHOST];
  113. char servInfo[NI_MAXSERV];
  114. int s = getnameinfo((struct sockaddr*) addrBuf,
  115. addrSize,
  116. hostname,
  117. NI_MAXHOST, servInfo,
  118. NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
  119. if (s != 0) {
  120. status = ER_OS_ERROR;
  121. QCC_LogError(status, ("GetSockAddr: %d - %s", s, gai_strerror(s)));
  122. } else {
  123. /*
  124. * In the case of IPv6, the hostname will have the interface name
  125. * tacked on the end, as in "fe80::20c:29ff:fe7b:6f10%eth1". We
  126. * need to chop that off since nobody expects either the Spanish
  127. * Inquisition or the interface.
  128. */
  129. char* p = strchr(hostname, '%');
  130. if (p) *p = 0;
  131. addr = IPAddress(hostname);
  132. port = atoi(servInfo);
  133. }
  134. return status;
  135. }
  136. uint32_t GetLastError()
  137. {
  138. return errno;
  139. }
  140. qcc::String GetLastErrorString()
  141. {
  142. return strerror(errno);
  143. }
  144. QStatus Socket(AddressFamily addrFamily, SocketType type, SocketFd& sockfd)
  145. {
  146. QStatus status = ER_OK;
  147. int ret;
  148. QCC_DbgTrace(("Socket(addrFamily = %d, type = %d, sockfd = <>)", addrFamily, type));
  149. ret = socket(static_cast<int>(addrFamily), static_cast<int>(type), 0);
  150. if (ret == -1) {
  151. status = ER_OS_ERROR;
  152. QCC_LogError(status, ("Opening socket: %d - %s", errno, strerror(errno)));
  153. } else {
  154. sockfd = static_cast<SocketFd>(ret);
  155. #if defined(QCC_OS_DARWIN)
  156. DisableSigPipe(sockfd);
  157. #endif
  158. }
  159. return status;
  160. }
  161. QStatus Connect(SocketFd sockfd, const IPAddress& remoteAddr, uint16_t remotePort)
  162. {
  163. QStatus status = ER_OK;
  164. int ret;
  165. struct sockaddr_storage addr;
  166. socklen_t addrLen = sizeof(addr);
  167. QCC_DbgTrace(("Connect(sockfd = %d, remoteAddr = %s, remotePort = %hu)",
  168. sockfd, remoteAddr.ToString().c_str(), remotePort));
  169. status = MakeSockAddr(remoteAddr, remotePort, &addr, addrLen);
  170. if (status != ER_OK) {
  171. return status;
  172. }
  173. ret = connect(static_cast<int>(sockfd), reinterpret_cast<struct sockaddr*>(&addr), addrLen);
  174. if (ret == -1) {
  175. if ((errno == EINPROGRESS) || (errno == EALREADY)) {
  176. status = ER_WOULDBLOCK;
  177. } else if (errno == EISCONN) {
  178. status = ER_OK;
  179. } else if (errno == ECONNREFUSED) {
  180. status = ER_CONN_REFUSED;
  181. } else {
  182. status = ER_OS_ERROR;
  183. QCC_LogError(status, ("Connecting (sockfd = %u) to %s %d: %d - %s", sockfd,
  184. remoteAddr.ToString().c_str(), remotePort,
  185. errno, strerror(errno)));
  186. }
  187. } else {
  188. int flags = fcntl(sockfd, F_GETFL, 0);
  189. ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
  190. if (ret == -1) {
  191. status = ER_OS_ERROR;
  192. QCC_LogError(status, ("Connect fcntl (sockfd = %u) to O_NONBLOCK: %d - %s", sockfd, errno, strerror(errno)));
  193. /* better to close and error out than to leave in unexpected state */
  194. close(sockfd);
  195. }
  196. }
  197. return status;
  198. }
  199. QStatus Connect(SocketFd sockfd, const char* pathName)
  200. {
  201. QStatus status = ER_OK;
  202. int ret;
  203. struct sockaddr_storage addr;
  204. socklen_t addrLen = sizeof(addr);
  205. QCC_DbgTrace(("Connect(sockfd = %u, path = %s)", sockfd, pathName));
  206. status = MakeSockAddr(pathName, &addr, addrLen);
  207. if (status != ER_OK) {
  208. return status;
  209. }
  210. ret = connect(static_cast<int>(sockfd), reinterpret_cast<struct sockaddr*>(&addr), addrLen);
  211. if (ret == -1) {
  212. status = ER_OS_ERROR;
  213. QCC_LogError(status, ("Connecting (sockfd = %u) to %s : %d - %s", sockfd,
  214. pathName,
  215. errno, strerror(errno)));
  216. } else {
  217. int flags = fcntl(sockfd, F_GETFL, 0);
  218. ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
  219. if (ret == -1) {
  220. status = ER_OS_ERROR;
  221. QCC_LogError(status, ("Connect fcntl (sockfd = %u) to O_NONBLOCK: %d - %s", sockfd, errno, strerror(errno)));
  222. /* better to close and error out than to leave in unexpected state */
  223. close(sockfd);
  224. }
  225. }
  226. return status;
  227. }
  228. QStatus Bind(SocketFd sockfd, const IPAddress& localAddr, uint16_t localPort)
  229. {
  230. QStatus status = ER_OK;
  231. int ret;
  232. struct sockaddr_storage addr;
  233. socklen_t addrLen = sizeof(addr);
  234. QCC_DbgTrace(("Bind(sockfd = %d, localAddr = %s, localPort = %hu)",
  235. sockfd, localAddr.ToString().c_str(), localPort));
  236. status = MakeSockAddr(localAddr, localPort, &addr, addrLen);
  237. if (status != ER_OK) {
  238. return status;
  239. }
  240. ret = bind(static_cast<int>(sockfd), reinterpret_cast<struct sockaddr*>(&addr), addrLen);
  241. if (ret != 0) {
  242. status = (errno == EADDRNOTAVAIL ? ER_SOCKET_BIND_ERROR : ER_OS_ERROR);
  243. QCC_LogError(status, ("Binding (sockfd = %u) to %s %d: %d - %s", sockfd,
  244. localAddr.ToString().c_str(), localPort, errno, strerror(errno)));
  245. }
  246. return status;
  247. }
  248. QStatus Bind(SocketFd sockfd, const char* pathName)
  249. {
  250. QStatus status = ER_OK;
  251. int ret;
  252. struct sockaddr_storage addr;
  253. socklen_t addrLen = sizeof(addr);
  254. QCC_DbgTrace(("Bind(sockfd = %d, pathName = %s)", sockfd, pathName));
  255. status = MakeSockAddr(pathName, &addr, addrLen);
  256. if (status != ER_OK) {
  257. return status;
  258. }
  259. ret = bind(static_cast<int>(sockfd), reinterpret_cast<struct sockaddr*>(&addr), addrLen);
  260. if (ret != 0) {
  261. status = (errno == EADDRNOTAVAIL ? ER_SOCKET_BIND_ERROR : ER_OS_ERROR);
  262. QCC_LogError(status, ("Binding (sockfd = %u) to %s: %d - %s", sockfd,
  263. pathName, errno, strerror(errno)));
  264. }
  265. return status;
  266. }
  267. QStatus Listen(SocketFd sockfd, int backlog)
  268. {
  269. QStatus status = ER_OK;
  270. int ret;
  271. QCC_DbgTrace(("Listen(sockfd = %d, backlog = %d)", sockfd, backlog));
  272. ret = listen(static_cast<int>(sockfd), backlog);
  273. if (ret != 0) {
  274. status = ER_OS_ERROR;
  275. QCC_LogError(status, ("Listening (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  276. }
  277. return status;
  278. }
  279. QStatus Accept(SocketFd sockfd, IPAddress& remoteAddr, uint16_t& remotePort, SocketFd& newSockfd)
  280. {
  281. QStatus status = ER_OK;
  282. int ret;
  283. struct sockaddr_storage addr;
  284. socklen_t addrLen = sizeof(addr);
  285. QCC_DbgTrace(("Accept(sockfd = %d, remoteAddr = <>, remotePort = <>)", sockfd));
  286. ret = accept(static_cast<int>(sockfd), reinterpret_cast<struct sockaddr*>(&addr), &addrLen);
  287. if (ret == -1) {
  288. if (errno == EWOULDBLOCK) {
  289. status = ER_WOULDBLOCK;
  290. } else {
  291. status = ER_OS_ERROR;
  292. QCC_LogError(status, ("Accept (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  293. }
  294. } else {
  295. if (addr.ss_family == AF_INET) {
  296. struct sockaddr_in* sa = reinterpret_cast<struct sockaddr_in*>(&addr);
  297. uint8_t* portBuf = reinterpret_cast<uint8_t*>(&sa->sin_port);
  298. remoteAddr = IPAddress(reinterpret_cast<uint8_t*>(&sa->sin_addr.s_addr),
  299. IPAddress::IPv4_SIZE);
  300. remotePort = (static_cast<uint16_t>(portBuf[0]) << 8) | static_cast<uint16_t>(portBuf[1]);
  301. } else if (addr.ss_family == AF_INET6) {
  302. struct sockaddr_in6* sa = reinterpret_cast<struct sockaddr_in6*>(&addr);
  303. uint8_t* portBuf = reinterpret_cast<uint8_t*>(&sa->sin6_port);
  304. remoteAddr = IPAddress(reinterpret_cast<uint8_t*>(&sa->sin6_addr.s6_addr),
  305. IPAddress::IPv6_SIZE);
  306. remotePort = (static_cast<uint16_t>(portBuf[0]) << 8) | static_cast<uint16_t>(portBuf[1]);
  307. } else {
  308. remotePort = 0;
  309. }
  310. newSockfd = static_cast<SocketFd>(ret);
  311. #if defined(QCC_OS_DARWIN)
  312. DisableSigPipe(newSockfd);
  313. #endif
  314. QCC_DbgPrintf(("New socket FD: %d", newSockfd));
  315. int flags = fcntl(newSockfd, F_GETFL, 0);
  316. ret = fcntl(newSockfd, F_SETFL, flags | O_NONBLOCK);
  317. if (ret == -1) {
  318. status = ER_OS_ERROR;
  319. QCC_LogError(status, ("Accept fcntl (newSockfd = %u) to O_NONBLOCK: %d - %s", newSockfd, errno, strerror(errno)));
  320. /* better to close and error out than to leave in unexpected state */
  321. close(newSockfd);
  322. }
  323. }
  324. return status;
  325. }
  326. QStatus Accept(SocketFd sockfd, SocketFd& newSockfd)
  327. {
  328. IPAddress addr;
  329. uint16_t port;
  330. return Accept(sockfd, addr, port, newSockfd);
  331. }
  332. QStatus Shutdown(SocketFd sockfd)
  333. {
  334. QStatus status = ER_OK;
  335. int ret;
  336. QCC_DbgTrace(("Shutdown(sockfd = %d)", sockfd));
  337. ret = shutdown(static_cast<int>(sockfd), SHUT_RDWR);
  338. if (ret != 0) {
  339. status = ER_OS_ERROR;
  340. QCC_LogError(status, ("Shutdown socket (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  341. }
  342. return status;
  343. }
  344. void Close(SocketFd sockfd)
  345. {
  346. close(static_cast<int>(sockfd));
  347. }
  348. QStatus SocketDup(SocketFd sockfd, SocketFd& dupSock)
  349. {
  350. QStatus status = ER_OK;
  351. dupSock = dup(sockfd);
  352. if (dupSock < 0) {
  353. status = ER_OS_ERROR;
  354. QCC_LogError(status, ("SocketDup of %d failed %d - %s", sockfd, errno, strerror(errno)));
  355. }
  356. return status;
  357. }
  358. QStatus GetLocalAddress(SocketFd sockfd, IPAddress& addr, uint16_t& port)
  359. {
  360. QStatus status = ER_OK;
  361. struct sockaddr_storage addrBuf;
  362. socklen_t addrLen = sizeof(addrBuf);
  363. int ret;
  364. QCC_DbgTrace(("GetLocalAddress(sockfd = %d, addr = <>, port = <>)", sockfd));
  365. memset(&addrBuf, 0, addrLen);
  366. ret = getsockname(static_cast<int>(sockfd), reinterpret_cast<struct sockaddr*>(&addrBuf), &addrLen);
  367. if (ret == -1) {
  368. status = ER_OS_ERROR;
  369. QCC_LogError(status, ("Geting Local Address (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  370. } else {
  371. if (addrBuf.ss_family == AF_INET) {
  372. struct sockaddr_in* sa = reinterpret_cast<struct sockaddr_in*>(&addrBuf);
  373. uint8_t* portBuf = reinterpret_cast<uint8_t*>(&sa->sin_port);
  374. QCC_DbgLocalData(&addrBuf, sizeof(*sa));
  375. addr = IPAddress(reinterpret_cast<uint8_t*>(&sa->sin_addr.s_addr), IPAddress::IPv4_SIZE);
  376. port = (static_cast<uint16_t>(portBuf[0]) << 8) | static_cast<uint16_t>(portBuf[1]);
  377. } else {
  378. struct sockaddr_in6* sa = reinterpret_cast<struct sockaddr_in6*>(&addrBuf);
  379. uint8_t* portBuf = reinterpret_cast<uint8_t*>(&sa->sin6_port);
  380. addr = IPAddress(reinterpret_cast<uint8_t*>(&sa->sin6_addr.s6_addr), IPAddress::IPv6_SIZE);
  381. port = (static_cast<uint16_t>(portBuf[0]) << 8) | static_cast<uint16_t>(portBuf[1]);
  382. }
  383. QCC_DbgPrintf(("Local Address (sockfd = %u): %s - %u", sockfd, addr.ToString().c_str(), port));
  384. }
  385. return status;
  386. }
  387. QStatus Send(SocketFd sockfd, const void* buf, size_t len, size_t& sent, uint32_t timeout)
  388. {
  389. QStatus status = ER_OK;
  390. ssize_t ret;
  391. QCC_DbgTrace(("Send(sockfd = %d, *buf = <>, len = %lu, sent = <>)",
  392. sockfd, len));
  393. assert(buf != NULL);
  394. QCC_DbgLocalData(buf, len);
  395. while (status == ER_OK) {
  396. ret = send(static_cast<int>(sockfd), buf, len, MSG_NOSIGNAL);
  397. if (ret == -1) {
  398. if (errno == EAGAIN) {
  399. status = ER_WOULDBLOCK;
  400. } else {
  401. status = ER_OS_ERROR;
  402. QCC_DbgHLPrintf(("Send (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  403. }
  404. } else {
  405. sent = static_cast<size_t>(ret);
  406. }
  407. break;
  408. }
  409. return status;
  410. }
  411. QStatus SendTo(SocketFd sockfd, IPAddress& remoteAddr, uint16_t remotePort,
  412. const void* buf, size_t len, size_t& sent)
  413. {
  414. QStatus status = ER_OK;
  415. struct sockaddr_storage addr;
  416. socklen_t addrLen = sizeof(addr);
  417. ssize_t ret;
  418. QCC_DbgTrace(("SendTo(sockfd = %d, remoteAddr = %s, remotePort = %u, *buf = <>, len = %lu, sent = <>)",
  419. sockfd, remoteAddr.ToString().c_str(), remotePort, len));
  420. assert(buf != NULL);
  421. QCC_DbgLocalData(buf, len);
  422. status = MakeSockAddr(remoteAddr, remotePort, &addr, addrLen);
  423. if (status != ER_OK) {
  424. return status;
  425. }
  426. ret = sendto(static_cast<int>(sockfd), buf, len, MSG_NOSIGNAL,
  427. reinterpret_cast<struct sockaddr*>(&addr), addrLen);
  428. if (ret == -1) {
  429. status = ER_OS_ERROR;
  430. QCC_LogError(status, ("SendTo (sockfd = %u addr = %s port = %u): %d - %s",
  431. sockfd, remoteAddr.ToString().c_str(), remotePort, errno, strerror(errno)));
  432. } else {
  433. sent = static_cast<size_t>(ret);
  434. }
  435. return status;
  436. }
  437. static QStatus SendSGCommon(SocketFd sockfd, struct sockaddr_storage* addr, socklen_t addrLen,
  438. const ScatterGatherList& sg, size_t& sent)
  439. {
  440. QStatus status = ER_OK;
  441. ssize_t ret;
  442. struct msghdr msg;
  443. size_t index;
  444. struct iovec* iov;
  445. ScatterGatherList::const_iterator iter;
  446. QCC_DbgTrace(("SendSGCommon(sockfd = %d, *addr, addrLen, sg[%u:%u/%u], sent = <>)",
  447. sockfd, sg.Size(), sg.DataSize(), sg.MaxDataSize()));
  448. iov = new struct iovec[sg.Size()];
  449. for (index = 0, iter = sg.Begin(); iter != sg.End(); ++index, ++iter) {
  450. iov[index].iov_base = iter->buf;
  451. iov[index].iov_len = iter->len;
  452. QCC_DbgLocalData(iov[index].iov_base, iov[index].iov_len);
  453. }
  454. msg.msg_name = addr;
  455. msg.msg_namelen = addrLen;
  456. msg.msg_iov = iov;
  457. msg.msg_iovlen = sg.Size();
  458. msg.msg_control = NULL;
  459. msg.msg_controllen = 0;
  460. msg.msg_flags = 0;
  461. ret = sendmsg(static_cast<int>(sockfd), &msg, MSG_NOSIGNAL);
  462. if (ret == -1) {
  463. status = ER_OS_ERROR;
  464. QCC_LogError(status, ("SendSGCommon (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  465. } else {
  466. sent = static_cast<size_t>(ret);
  467. }
  468. delete[] iov;
  469. return status;
  470. }
  471. QStatus SendSG(SocketFd sockfd, const ScatterGatherList& sg, size_t& sent)
  472. {
  473. QCC_DbgTrace(("SendSG(sockfd = %d, sg[%u:%u/%u], sent = <>)",
  474. sockfd, sg.Size(), sg.DataSize(), sg.MaxDataSize()));
  475. return SendSGCommon(sockfd, NULL, 0, sg, sent);
  476. }
  477. QStatus SendToSG(SocketFd sockfd, IPAddress& remoteAddr, uint16_t remotePort,
  478. const ScatterGatherList& sg, size_t& sent)
  479. {
  480. struct sockaddr_storage addr;
  481. socklen_t addrLen = sizeof(addr);
  482. QCC_DbgTrace(("SendToSG(sockfd = %d, remoteAddr = %s, remotePort = %u, sg[%u:%u/%u], sent = <>)",
  483. sockfd, remoteAddr.ToString().c_str(), remotePort,
  484. sg.Size(), sg.DataSize(), sg.MaxDataSize()));
  485. QStatus status = MakeSockAddr(remoteAddr, remotePort, &addr, addrLen);
  486. if (status != ER_OK) {
  487. return status;
  488. }
  489. return SendSGCommon(sockfd, &addr, addrLen, sg, sent);
  490. }
  491. QStatus Recv(SocketFd sockfd, void* buf, size_t len, size_t& received)
  492. {
  493. QStatus status = ER_OK;
  494. ssize_t ret;
  495. QCC_DbgTrace(("Recv(sockfd = %d, buf = <>, len = %lu, received = <>)", sockfd, len));
  496. assert(buf != NULL);
  497. ret = recv(static_cast<int>(sockfd), buf, len, 0);
  498. if ((ret == -1) && (errno == EWOULDBLOCK)) {
  499. return ER_WOULDBLOCK;
  500. }
  501. if (ret == -1) {
  502. status = ER_OS_ERROR;
  503. QCC_DbgHLPrintf(("Recv (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  504. } else {
  505. received = static_cast<size_t>(ret);
  506. QCC_DbgRemoteData(buf, received);
  507. }
  508. return status;
  509. }
  510. QStatus RecvFrom(SocketFd sockfd, IPAddress& remoteAddr, uint16_t& remotePort,
  511. void* buf, size_t len, size_t& received)
  512. {
  513. QStatus status = ER_OK;
  514. struct sockaddr_storage addr;
  515. socklen_t addrLen = sizeof(addr);
  516. ssize_t ret;
  517. received = 0;
  518. QCC_DbgTrace(("RecvFrom(sockfd = %d, remoteAddr = %s, remotePort = %u, buf = <>, len = %lu, received = <>)",
  519. sockfd, remoteAddr.ToString().c_str(), remotePort, len));
  520. assert(buf != NULL);
  521. ret = recvfrom(static_cast<int>(sockfd), buf, len, 0,
  522. reinterpret_cast<struct sockaddr*>(&addr), &addrLen);
  523. if (ret == -1) {
  524. status = ER_OS_ERROR;
  525. QCC_DbgHLPrintf(("RecvFrom (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  526. } else {
  527. received = static_cast<size_t>(ret);
  528. GetSockAddr(&addr, addrLen, remoteAddr, remotePort);
  529. QCC_DbgPrintf(("Received %u bytes, remoteAddr = %s, remotePort = %u",
  530. received, remoteAddr.ToString().c_str(), remotePort));
  531. }
  532. QCC_DbgRemoteData(buf, received);
  533. return status;
  534. }
  535. static QStatus RecvSGCommon(SocketFd sockfd, struct sockaddr_storage* addr, socklen_t* addrLen,
  536. ScatterGatherList& sg, size_t& received)
  537. {
  538. QStatus status = ER_OK;
  539. ssize_t ret;
  540. struct msghdr msg;
  541. size_t index;
  542. struct iovec* iov;
  543. ScatterGatherList::const_iterator iter;
  544. QCC_DbgTrace(("RecvSGCommon(sockfd = &d, addr, addrLen, sg = <>, received = <>)",
  545. sockfd));
  546. iov = new struct iovec[sg.Size()];
  547. for (index = 0, iter = sg.Begin(); iter != sg.End(); ++index, ++iter) {
  548. iov[index].iov_base = iter->buf;
  549. iov[index].iov_len = iter->len;
  550. }
  551. msg.msg_name = addr;
  552. msg.msg_namelen = *addrLen;
  553. msg.msg_iov = iov;
  554. msg.msg_iovlen = sg.Size();
  555. msg.msg_control = NULL;
  556. msg.msg_controllen = 0;
  557. msg.msg_flags = 0;
  558. ret = recvmsg(static_cast<int>(sockfd), &msg, 0);
  559. if (ret == -1) {
  560. status = ER_OS_ERROR;
  561. QCC_DbgHLPrintf(("RecvSGCommon (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  562. } else {
  563. received = static_cast<size_t>(ret);
  564. sg.SetDataSize(static_cast<size_t>(ret));
  565. *addrLen = msg.msg_namelen;
  566. }
  567. delete[] iov;
  568. #if !defined(NDEBUG)
  569. if (1) {
  570. size_t rxcnt = received;
  571. QCC_DbgPrintf(("Received %u bytes", received));
  572. for (iter = sg.Begin(); rxcnt > 0 && iter != sg.End(); ++iter) {
  573. QCC_DbgRemoteData(iter->buf, std::min(rxcnt, iter->len));
  574. rxcnt -= std::min(rxcnt, iter->len);
  575. }
  576. }
  577. #endif
  578. return status;
  579. }
  580. QStatus RecvSG(SocketFd sockfd, ScatterGatherList& sg, size_t& received)
  581. {
  582. socklen_t addrLen = 0;
  583. QCC_DbgTrace(("RecvSG(sockfd = %d, sg = <>, received = <>)", sockfd));
  584. return RecvSGCommon(sockfd, NULL, &addrLen, sg, received);
  585. }
  586. QStatus RecvFromSG(SocketFd sockfd, IPAddress& remoteAddr, uint16_t& remotePort,
  587. ScatterGatherList& sg, size_t& received)
  588. {
  589. QStatus status;
  590. struct sockaddr_storage addr;
  591. socklen_t addrLen = sizeof(addr);
  592. status = RecvSGCommon(sockfd, &addr, &addrLen, sg, received);
  593. if (ER_OK == status) {
  594. GetSockAddr(&addr, addrLen, remoteAddr, remotePort);
  595. QCC_DbgTrace(("RecvFromSG(sockfd = %d, remoteAddr = %s, remotePort = %u, sg = <>, sent = <>)",
  596. sockfd, remoteAddr.ToString().c_str(), remotePort));
  597. }
  598. return status;
  599. }
  600. QStatus RecvWithFds(SocketFd sockfd, void* buf, size_t len, size_t& received, SocketFd* fdList, size_t maxFds, size_t& recvdFds)
  601. {
  602. QStatus status = ER_OK;
  603. if (!fdList) {
  604. return ER_BAD_ARG_5;
  605. }
  606. if (!maxFds) {
  607. return ER_BAD_ARG_6;
  608. }
  609. QCC_DbgHLPrintf(("RecvWithFds"));
  610. recvdFds = 0;
  611. maxFds = std::min(maxFds, SOCKET_MAX_FILE_DESCRIPTORS);
  612. struct iovec iov[] = { { buf, len } };
  613. static const size_t sz = CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(SOCKET_MAX_FILE_DESCRIPTORS * sizeof(SocketFd));
  614. char cbuf[sz];
  615. struct msghdr msg;
  616. memset(&msg, 0, sizeof(msg));
  617. msg.msg_iov = iov;
  618. msg.msg_iovlen = ArraySize(iov);
  619. msg.msg_control = cbuf;
  620. msg.msg_controllen = CMSG_LEN(sz);
  621. ssize_t ret = recvmsg(sockfd, &msg, 0);
  622. if (ret == -1) {
  623. if (errno == EWOULDBLOCK) {
  624. status = ER_WOULDBLOCK;
  625. } else {
  626. status = ER_OS_ERROR;
  627. QCC_DbgHLPrintf(("RecvWithFds (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  628. }
  629. } else {
  630. struct cmsghdr* cmsg;
  631. for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
  632. if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) {
  633. recvdFds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(SocketFd);
  634. /*
  635. * Check we have enough room to return the file descriptors.
  636. */
  637. if (recvdFds > maxFds) {
  638. status = ER_OS_ERROR;
  639. QCC_LogError(status, ("Too many handles: %d implementation limit is %d", recvdFds, maxFds));
  640. } else {
  641. memcpy(fdList, CMSG_DATA(cmsg), recvdFds * sizeof(SocketFd));
  642. QCC_DbgHLPrintf(("Received %d handles %d...", recvdFds, fdList[0]));
  643. }
  644. break;
  645. }
  646. }
  647. received = static_cast<size_t>(ret);
  648. }
  649. return status;
  650. }
  651. QStatus SendWithFds(SocketFd sockfd, const void* buf, size_t len, size_t& sent, SocketFd* fdList, size_t numFds, uint32_t pid)
  652. {
  653. QStatus status = ER_OK;
  654. if (!fdList) {
  655. return ER_BAD_ARG_5;
  656. }
  657. if (!numFds || (numFds > SOCKET_MAX_FILE_DESCRIPTORS)) {
  658. return ER_BAD_ARG_6;
  659. }
  660. QCC_DbgHLPrintf(("SendWithFds"));
  661. struct iovec iov[] = { { const_cast<void*>(buf), len } };
  662. size_t sz = numFds * sizeof(SocketFd);
  663. char* cbuf = new char[CMSG_SPACE(sz)];
  664. memset(cbuf, 0, CMSG_SPACE(sz));
  665. struct msghdr msg;
  666. memset(&msg, 0, sizeof(msg));
  667. msg.msg_iov = iov;
  668. msg.msg_iovlen = ArraySize(iov);
  669. msg.msg_control = cbuf;
  670. msg.msg_controllen = CMSG_SPACE(sz);
  671. struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
  672. cmsg->cmsg_level = SOL_SOCKET;
  673. cmsg->cmsg_type = SCM_RIGHTS;
  674. cmsg->cmsg_len = CMSG_LEN(sz);
  675. QCC_DbgHLPrintf(("Sending %d file descriptors %d...", numFds, fdList[0]));
  676. memcpy(CMSG_DATA(cmsg), fdList, sz);
  677. ssize_t ret = sendmsg(sockfd, &msg, 0);
  678. if (ret == -1) {
  679. status = ER_OS_ERROR;
  680. QCC_DbgHLPrintf(("SendWithFds (sockfd = %u): %d - %s", sockfd, errno, strerror(errno)));
  681. } else {
  682. sent = static_cast<size_t>(ret);
  683. }
  684. delete [] cbuf;
  685. return status;
  686. }
  687. QStatus SocketPair(SocketFd(&sockets)[2])
  688. {
  689. int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
  690. return (ret == 0) ? ER_OK : ER_FAIL;
  691. }
  692. QStatus SetBlocking(SocketFd sockfd, bool blocking)
  693. {
  694. int flags = fcntl(sockfd, F_GETFL, 0);
  695. ssize_t ret;
  696. if (blocking) {
  697. ret = fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK);
  698. } else {
  699. ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
  700. }
  701. if (ret == -1) {
  702. return ER_OS_ERROR;
  703. } else {
  704. return ER_OK;
  705. }
  706. }
  707. QStatus SetNagle(SocketFd sockfd, bool useNagle)
  708. {
  709. QStatus status = ER_OK;
  710. int arg = useNagle ? 1 : -0;
  711. int r = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void*)&arg, sizeof(int));
  712. if (r != 0) {
  713. status = ER_OS_ERROR;
  714. QCC_LogError(status, ("Setting TCP_NODELAY failed: (%d) %s", errno, strerror(errno)));
  715. }
  716. return status;
  717. }
  718. QStatus SetReuseAddress(SocketFd sockfd, bool reuse)
  719. {
  720. QStatus status = ER_OK;
  721. int arg = reuse ? 1 : -0;
  722. int r = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&arg, sizeof(arg));
  723. if (r != 0) {
  724. status = ER_OS_ERROR;
  725. QCC_LogError(status, ("Setting SO_REUSEADDR failed: (%d) %s", errno, strerror(errno)));
  726. }
  727. return status;
  728. }
  729. /*
  730. * Some systems do not define SO_REUSEPORT (which is a BSD-ism from the first
  731. * days of multicast support). In this case they special case SO_REUSEADDR in
  732. * the presence of multicast addresses to perform the same function, which is to
  733. * allow multiple processes to bind to the same multicast address/port. In this
  734. * case, SO_REUSEADDR provides the equivalent functionality of SO_REUSEPORT, so
  735. * it is quite safe to substitute them. Interestingly, Darwin which is actually
  736. * BSD-derived does not define SO_REUSEPORT, but Linux which is supposedly not
  737. * BSD does. Go figure.
  738. */
  739. #ifndef SO_REUSEPORT
  740. #define SO_REUSEPORT SO_REUSEADDR
  741. #endif
  742. QStatus SetReusePort(SocketFd sockfd, bool reuse)
  743. {
  744. QStatus status = ER_OK;
  745. int arg = reuse ? 1 : -0;
  746. int r = setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (void*)&arg, sizeof(arg));
  747. if (r != 0) {
  748. status = ER_OS_ERROR;
  749. QCC_LogError(status, ("Setting SO_REUSEPORT failed: (%d) %s", errno, strerror(errno)));
  750. }
  751. return status;
  752. }
  753. #ifndef IPV6_ADD_MEMBERSHIP
  754. #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
  755. #endif
  756. #ifndef IPV6_DROP_MEMBERSHIP
  757. #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
  758. #endif
  759. /*
  760. * Getting set to do a multicast join or drop is straightforward but not
  761. * completely trivial, and the process is identical for both socket options, so
  762. * we only do the work in one place and select one of the followin oeprations.
  763. */
  764. enum GroupOp {JOIN, LEAVE};
  765. QStatus MulticastGroupOpInternal(SocketFd sockFd, AddressFamily family, String multicastGroup, String iface, GroupOp op)
  766. {
  767. /*
  768. * We assume that No external API will be trying to call here and so asserts
  769. * are appropriate when checking for completely bogus parameters.
  770. */
  771. assert(sockFd);
  772. assert(family == AF_INET || family == AF_INET6);
  773. assert(multicastGroup.size());
  774. assert(iface.size());
  775. assert(op == JOIN || op == LEAVE);
  776. /*
  777. * Joining a multicast group requires a different approach based on the
  778. * address family of the socket. There's no way to get this information
  779. * from an unbound socket, and it is not unreasonable to join a multicast
  780. * group before binding; so to avoid an inscrutable initialization order
  781. * requirement we force the caller to provide this tidbit.
  782. */
  783. if (family == QCC_AF_INET) {
  784. /*
  785. * Group memberships are associated with both the multicast group itself
  786. * and also an interface. In the IPv4 version, we need to provide an
  787. * interface address. We borrow the socket passed in to do the required
  788. * call to find the address from the interface name.
  789. */
  790. struct ifreq ifr;
  791. ifr.ifr_addr.sa_family = AF_INET;
  792. strncpy(ifr.ifr_name, iface.c_str(), IFNAMSIZ);
  793. ifr.ifr_name[IFNAMSIZ - 1] = '\0';
  794. int rc = ioctl(sockFd, SIOCGIFADDR, &ifr);
  795. if (rc == -1) {
  796. QCC_LogError(ER_OS_ERROR, ("ioctl(SIOCGIFADDR) failed: (%d) %s", errno, strerror(errno)));
  797. return ER_OS_ERROR;
  798. }
  799. struct ip_mreq mreq;
  800. mreq.imr_interface.s_addr = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr;
  801. rc = inet_pton(AF_INET, multicastGroup.c_str(), &mreq.imr_multiaddr);
  802. if (rc != 1) {
  803. QCC_LogError(ER_OS_ERROR, ("inet_pton() failed: %d - %s", errno, strerror(errno)));
  804. return ER_OS_ERROR;
  805. }
  806. int opt = op == JOIN ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
  807. rc = setsockopt(sockFd, IPPROTO_IP, opt, reinterpret_cast<const char*>(&mreq), sizeof(mreq));
  808. if (rc == -1) {
  809. QCC_LogError(ER_OS_ERROR, ("setsockopt(%s) failed: %d - %s", op == JOIN ? "IP_ADD_MEMBERSHIP" : "IP_DROP_MEMBERSHIP", errno, strerror(errno)));
  810. return ER_OS_ERROR;
  811. }
  812. } else if (family == QCC_AF_INET6) {
  813. /*
  814. * Group memberships are associated with both the multicast group itself
  815. * and also an interface. In the IPv6 version, we need to provide an
  816. * interface index instead of an IP address associated with the
  817. * interface.
  818. */
  819. struct ipv6_mreq mreq;
  820. mreq.ipv6mr_interface = if_nametoindex(iface.c_str());
  821. if (mreq.ipv6mr_interface == 0) {
  822. QCC_LogError(ER_OS_ERROR, ("if_nametoindex() failed: unknown interface"));
  823. return ER_OS_ERROR;
  824. }
  825. int rc = inet_pton(AF_INET6, multicastGroup.c_str(), &mreq.ipv6mr_multiaddr);
  826. if (rc != 1) {
  827. QCC_LogError(ER_OS_ERROR, ("inet_pton() failed: %d - %s", errno, strerror(errno)));
  828. return ER_OS_ERROR;
  829. }
  830. int opt = op == JOIN ? IPV6_ADD_MEMBERSHIP : IPV6_DROP_MEMBERSHIP;
  831. rc = setsockopt(sockFd, IPPROTO_IPV6, opt, reinterpret_cast<const char*>(&mreq), sizeof(mreq));
  832. if (rc == -1) {
  833. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_ADD_MEMBERSHIP) failed: %d - %s", errno, strerror(errno)));
  834. return ER_OS_ERROR;
  835. }
  836. }
  837. return ER_OK;
  838. }
  839. QStatus JoinMulticastGroup(SocketFd sockFd, AddressFamily family, String multicastGroup, String iface)
  840. {
  841. return MulticastGroupOpInternal(sockFd, family, multicastGroup, iface, JOIN);
  842. }
  843. QStatus LeaveMulticastGroup(SocketFd sockFd, AddressFamily family, String multicastGroup, String iface)
  844. {
  845. return MulticastGroupOpInternal(sockFd, family, multicastGroup, iface, LEAVE);
  846. }
  847. QStatus SetMulticastInterface(SocketFd sockFd, AddressFamily family, qcc::String iface)
  848. {
  849. /*
  850. * We assume that No external API will be trying to call here and so asserts
  851. * are appropriate when checking for completely bogus parameters.
  852. */
  853. assert(sockFd);
  854. assert(family == AF_INET || family == AF_INET6);
  855. assert(iface.size());
  856. /*
  857. * Associating the multicast interface with a socket requires a different
  858. * approach based on the address family of the socket. There's no way to
  859. * get this information from an unbound socket, and it is not unreasonable
  860. * to set the interface before binding; so to avoid an inscrutable
  861. * initialization order requirement we force the caller to provide this
  862. * tidbit.
  863. */
  864. if (family == QCC_AF_INET) {
  865. /*
  866. * In the IPv4 version, we need to provide an interface address. We
  867. * borrow the socket passed in to do the required call to find the
  868. * address from the interface name.
  869. */
  870. struct ifreq ifr;
  871. ifr.ifr_addr.sa_family = AF_INET;
  872. strncpy(ifr.ifr_name, iface.c_str(), IFNAMSIZ);
  873. ifr.ifr_name[IFNAMSIZ - 1] = '\0';
  874. int rc = ioctl(sockFd, SIOCGIFADDR, &ifr);
  875. if (rc == -1) {
  876. QCC_LogError(ER_OS_ERROR, ("ioctl(SIOCGIFADDR) failed: (%d) %s", errno, strerror(errno)));
  877. return ER_OS_ERROR;
  878. }
  879. struct in_addr addr;
  880. addr.s_addr = ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr.s_addr;
  881. rc = setsockopt(sockFd, IPPROTO_IP, IP_MULTICAST_IF, reinterpret_cast<const char*>(&addr), sizeof(addr));
  882. if (rc == -1) {
  883. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_MULTICAST_IF) failed: %d - %s", errno, strerror(errno)));
  884. return ER_OS_ERROR;
  885. }
  886. } else if (family == QCC_AF_INET6) {
  887. /*
  888. * In the IPv6 version, we need to provide an interface index instead of
  889. * an IP address associated with the interface.
  890. */
  891. uint32_t index = if_nametoindex(iface.c_str());
  892. int rc = setsockopt(sockFd, IPPROTO_IPV6, IPV6_MULTICAST_IF, reinterpret_cast<const char*>(&index), sizeof(index));
  893. if (rc == -1) {
  894. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_MULTICAST_IF) failed: %d - %s", errno, strerror(errno)));
  895. return ER_OS_ERROR;
  896. }
  897. }
  898. return ER_OK;
  899. }
  900. QStatus SetMulticastHops(SocketFd sockFd, AddressFamily family, uint32_t hops)
  901. {
  902. /*
  903. * We assume that No external API will be trying to call here and so asserts
  904. * are appropriate when checking for completely bogus parameters.
  905. */
  906. assert(sockFd);
  907. assert(family == AF_INET || family == AF_INET6);
  908. /*
  909. * IPv4 and IPv6 are almost the same. Of course, not quite, though.
  910. */
  911. if (family == QCC_AF_INET) {
  912. int rc = setsockopt(sockFd, IPPROTO_IP, IP_MULTICAST_TTL, reinterpret_cast<const char*>(&hops), sizeof(hops));
  913. if (rc == -1) {
  914. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_MULTICAST_TTL) failed: %d - %s", errno, strerror(errno)));
  915. return ER_OS_ERROR;
  916. }
  917. } else if (family == QCC_AF_INET6) {
  918. int rc = setsockopt(sockFd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, reinterpret_cast<const char*>(&hops), sizeof(hops));
  919. if (rc == -1) {
  920. QCC_LogError(ER_OS_ERROR, ("setsockopt(IP_MULTICAST_HOPS) failed: %d - %s", errno, strerror(errno)));
  921. return ER_OS_ERROR;
  922. }
  923. }
  924. return ER_OK;
  925. }
  926. QStatus SetBroadcast(SocketFd sockfd, bool broadcast)
  927. {
  928. QStatus status = ER_OK;
  929. int arg = broadcast ? 1 : -0;
  930. int r = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (void*)&arg, sizeof(arg));
  931. if (r != 0) {
  932. status = ER_OS_ERROR;
  933. QCC_LogError(status, ("Setting SO_BROADCAST failed: (%d) %s", errno, strerror(errno)));
  934. }
  935. return status;
  936. }
  937. } // namespace qcc