PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/clients/roscpp/src/libros/io.cpp

https://gitlab.com/F34140r/ros_comm
C++ | 395 lines | 258 code | 26 blank | 111 comment | 91 complexity | c2adb6b782e81b9933adb7be8475a241 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. * Software License Agreement (BSD License)
  3. *
  4. * Copyright (c) 2008, Willow Garage, Inc.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. * * Neither the name of Willow Garage, Inc. nor the names of its
  18. * contributors may be used to endorse or promote products derived
  19. * from this software without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  29. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. /*****************************************************************************
  35. ** Includes
  36. *****************************************************************************/
  37. #include "../../include/ros/io.h"
  38. #include <ros/assert.h> // don't need if we dont call the pipe functions.
  39. #include <errno.h> // for EFAULT and co.
  40. #include <iostream>
  41. #include <sstream>
  42. #ifdef WIN32
  43. #else
  44. #include <cstring> // strerror
  45. #include <fcntl.h> // for non-blocking configuration
  46. #endif
  47. /*****************************************************************************
  48. ** Namespaces
  49. *****************************************************************************/
  50. namespace ros {
  51. int last_socket_error() {
  52. #ifdef WIN32
  53. return WSAGetLastError();
  54. #else
  55. return errno;
  56. #endif
  57. }
  58. const char* last_socket_error_string() {
  59. #ifdef WIN32
  60. // could fix this to use FORMAT_MESSAGE and print a real string later,
  61. // but not high priority.
  62. std::stringstream ostream;
  63. ostream << "WSA Error: " << WSAGetLastError();
  64. return ostream.str().c_str();
  65. #else
  66. return strerror(errno);
  67. #endif
  68. }
  69. bool last_socket_error_is_would_block() {
  70. #if defined(WIN32)
  71. if ( WSAGetLastError() == WSAEWOULDBLOCK ) {
  72. return true;
  73. } else {
  74. return false;
  75. }
  76. #else
  77. if ( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) ) { // posix permits either
  78. return true;
  79. } else {
  80. return false;
  81. }
  82. #endif
  83. }
  84. /*****************************************************************************
  85. ** Service Robotics/Libssh Functions
  86. *****************************************************************************/
  87. /**
  88. * @brief A cross platform polling function for sockets.
  89. *
  90. * Windows doesn't have a polling function until Vista (WSAPoll) and even then
  91. * its implementation is not supposed to be great. This works for a broader
  92. * range of platforms and will suffice.
  93. * @param fds - the socket set (descriptor's and events) to poll for.
  94. * @param nfds - the number of descriptors to poll for.
  95. * @param timeout - timeout in milliseconds.
  96. * @return int : -1 on error, 0 on timeout, +ve number of structures with received events.
  97. */
  98. int poll_sockets(socket_pollfd *fds, nfds_t nfds, int timeout) {
  99. #if defined(WIN32)
  100. fd_set readfds, writefds, exceptfds;
  101. struct timeval tv, *ptv;
  102. socket_fd_t max_fd;
  103. int rc;
  104. nfds_t i;
  105. if (fds == NULL) {
  106. errno = EFAULT;
  107. return -1;
  108. }
  109. FD_ZERO (&readfds);
  110. FD_ZERO (&writefds);
  111. FD_ZERO (&exceptfds);
  112. /*********************
  113. ** Compute fd sets
  114. **********************/
  115. // also find the largest descriptor.
  116. for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
  117. if (fds[i].fd == INVALID_SOCKET) {
  118. continue;
  119. }
  120. if (fds[i].events & (POLLIN | POLLRDNORM)) {
  121. FD_SET (fds[i].fd, &readfds);
  122. }
  123. if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
  124. FD_SET (fds[i].fd, &writefds);
  125. }
  126. if (fds[i].events & (POLLPRI | POLLRDBAND)) {
  127. FD_SET (fds[i].fd, &exceptfds);
  128. }
  129. if (fds[i].fd > max_fd &&
  130. (fds[i].events & (POLLIN | POLLOUT | POLLPRI |
  131. POLLRDNORM | POLLRDBAND |
  132. POLLWRNORM | POLLWRBAND))) {
  133. max_fd = fds[i].fd;
  134. rc = 0;
  135. }
  136. }
  137. if (rc == -1) {
  138. errno = EINVAL;
  139. return -1;
  140. }
  141. /*********************
  142. ** Setting the timeout
  143. **********************/
  144. if (timeout < 0) {
  145. ptv = NULL;
  146. } else {
  147. ptv = &tv;
  148. if (timeout == 0) {
  149. tv.tv_sec = 0;
  150. tv.tv_usec = 0;
  151. } else {
  152. tv.tv_sec = timeout / 1000;
  153. tv.tv_usec = (timeout % 1000) * 1000;
  154. }
  155. }
  156. rc = select (max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
  157. if (rc < 0) {
  158. return -1;
  159. } else if ( rc == 0 ) {
  160. return 0;
  161. }
  162. for (rc = 0, i = 0; i < nfds; i++) {
  163. if (fds[i].fd != INVALID_SOCKET) {
  164. fds[i].revents = 0;
  165. if (FD_ISSET(fds[i].fd, &readfds)) {
  166. int save_errno = errno;
  167. char data[64] = {0};
  168. int ret;
  169. /* support for POLLHUP */
  170. // just check if there's incoming data, without removing it from the queue.
  171. ret = recv(fds[i].fd, data, 64, MSG_PEEK);
  172. #ifdef WIN32
  173. if ((ret == -1) &&
  174. (errno == WSAESHUTDOWN || errno == WSAECONNRESET ||
  175. (errno == WSAECONNABORTED) || errno == WSAENETRESET))
  176. #else
  177. if ((ret == -1) &&
  178. (errno == ESHUTDOWN || errno == ECONNRESET ||
  179. (errno == ECONNABORTED) || errno == ENETRESET))
  180. #endif
  181. {
  182. fds[i].revents |= POLLHUP;
  183. } else {
  184. fds[i].revents |= fds[i].events & (POLLIN | POLLRDNORM);
  185. }
  186. errno = save_errno;
  187. }
  188. if (FD_ISSET(fds[i].fd, &writefds)) {
  189. fds[i].revents |= fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND);
  190. }
  191. if (FD_ISSET(fds[i].fd, &exceptfds)) {
  192. fds[i].revents |= fds[i].events & (POLLPRI | POLLRDBAND);
  193. }
  194. if (fds[i].revents & ~POLLHUP) {
  195. rc++;
  196. }
  197. } else {
  198. fds[i].revents = POLLNVAL;
  199. }
  200. }
  201. return rc;
  202. #else
  203. // use an existing poll implementation
  204. int result = poll(fds, nfds, timeout);
  205. if ( result < 0 ) {
  206. // EINTR means that we got interrupted by a signal, and is not an error
  207. if(errno == EINTR) {
  208. result = 0;
  209. }
  210. }
  211. return result;
  212. #endif // poll_sockets functions
  213. }
  214. /*****************************************************************************
  215. ** Socket Utilities
  216. *****************************************************************************/
  217. /**
  218. * Sets the socket as non blocking.
  219. * @return int : 0 on success, WSAGetLastError()/errno on failure.
  220. */
  221. int set_non_blocking(socket_fd_t &socket) {
  222. #ifdef WIN32
  223. u_long non_blocking = 1;
  224. if(ioctlsocket( socket, FIONBIO, &non_blocking ) != 0 )
  225. {
  226. return WSAGetLastError();
  227. }
  228. #else
  229. if(fcntl(socket, F_SETFL, O_NONBLOCK) == -1)
  230. {
  231. return errno;
  232. }
  233. #endif
  234. return 0;
  235. }
  236. /**
  237. * @brief Close the socket.
  238. *
  239. * @return int : 0 on success, -1 on failure.
  240. */
  241. int close_socket(socket_fd_t &socket) {
  242. #ifdef WIN32
  243. if(::closesocket(socket) == SOCKET_ERROR ) {
  244. return -1;
  245. } else {
  246. return 0;
  247. }
  248. #else
  249. if (::close(socket) < 0) {
  250. return -1;
  251. } else {
  252. return 0;
  253. }
  254. #endif //WIN32
  255. }
  256. /*****************************************************************************
  257. ** Signal Pair
  258. *****************************************************************************/
  259. /**
  260. * This code is primarily from the msdn socket tutorials.
  261. * @param signal_pair : a pair of sockets linked to each other over localhost.
  262. * @return 0 on success, -1 on failure.
  263. */
  264. int create_signal_pair(signal_fd_t signal_pair[2]) {
  265. #ifdef WIN32 // use a socket pair
  266. signal_pair[0] = INVALID_SOCKET;
  267. signal_pair[1] = INVALID_SOCKET;
  268. union {
  269. struct sockaddr_in inaddr;
  270. struct sockaddr addr;
  271. } a;
  272. socklen_t addrlen = sizeof(a.inaddr);
  273. /*********************
  274. ** Listen Socket
  275. **********************/
  276. socket_fd_t listen_socket = INVALID_SOCKET;
  277. listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  278. if (listen_socket == INVALID_SOCKET) {
  279. return -1;
  280. }
  281. // allow it to be bound to an address already in use - do we actually need this?
  282. int reuse = 1;
  283. if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, (socklen_t) sizeof(reuse)) == SOCKET_ERROR ) {
  284. ::closesocket(listen_socket);
  285. return -1;
  286. }
  287. memset(&a, 0, sizeof(a));
  288. a.inaddr.sin_family = AF_INET;
  289. a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  290. // For TCP/IP, if the port is specified as zero, the service provider assigns
  291. // a unique port to the application from the dynamic client port range.
  292. a.inaddr.sin_port = 0;
  293. if (bind(listen_socket, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) {
  294. ::closesocket(listen_socket);
  295. return -1;
  296. }
  297. // we need this below because the system auto filled in some entries, e.g. port #
  298. if (getsockname(listen_socket, &a.addr, &addrlen) == SOCKET_ERROR) {
  299. ::closesocket(listen_socket);
  300. return -1;
  301. }
  302. // max 1 connection permitted
  303. if (listen(listen_socket, 1) == SOCKET_ERROR) {
  304. ::closesocket(listen_socket);
  305. return -1;
  306. }
  307. /*********************
  308. ** Connection
  309. **********************/
  310. // do we need io overlapping?
  311. // DWORD flags = (make_overlapped ? WSA_FLAG_OVERLAPPED : 0);
  312. DWORD overlapped_flag = 0;
  313. signal_pair[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, overlapped_flag);
  314. if (signal_pair[0] == INVALID_SOCKET) {
  315. ::closesocket(listen_socket);
  316. ::closesocket(signal_pair[0]);
  317. return -1;
  318. }
  319. // reusing the information from above to connect to the listener
  320. if (connect(signal_pair[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) {
  321. ::closesocket(listen_socket);
  322. ::closesocket(signal_pair[0]);
  323. return -1;
  324. }
  325. /*********************
  326. ** Accept
  327. **********************/
  328. signal_pair[1] = accept(listen_socket, NULL, NULL);
  329. if (signal_pair[1] == INVALID_SOCKET) {
  330. ::closesocket(listen_socket);
  331. ::closesocket(signal_pair[0]);
  332. ::closesocket(signal_pair[1]);
  333. return -1;
  334. }
  335. /*********************
  336. ** Nonblocking
  337. **********************/
  338. // should we do this or should we set io overlapping?
  339. if ( (set_non_blocking(signal_pair[0]) != 0) || (set_non_blocking(signal_pair[1]) != 0) ) {
  340. ::closesocket(listen_socket);
  341. ::closesocket(signal_pair[0]);
  342. ::closesocket(signal_pair[1]);
  343. return -1;
  344. }
  345. /*********************
  346. ** Cleanup
  347. **********************/
  348. ::closesocket(listen_socket); // the listener has done its job.
  349. return 0;
  350. #else // use a pipe pair
  351. // initialize
  352. signal_pair[0] = -1;
  353. signal_pair[1] = -1;
  354. if(pipe(signal_pair) != 0) {
  355. ROS_FATAL( "pipe() failed");
  356. return -1;
  357. }
  358. if(fcntl(signal_pair[0], F_SETFL, O_NONBLOCK) == -1) {
  359. ROS_FATAL( "fcntl() failed");
  360. return -1;
  361. }
  362. if(fcntl(signal_pair[1], F_SETFL, O_NONBLOCK) == -1) {
  363. ROS_FATAL( "fcntl() failed");
  364. return -1;
  365. }
  366. return 0;
  367. #endif // create_pipe
  368. }
  369. } // namespace ros