io.cpp
Go to the documentation of this file.
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 
38 #include <ros/io.h>
39 #include <ros/assert.h> // don't need if we dont call the pipe functions.
40 #include <errno.h> // for EFAULT and co.
41 #include <iostream>
42 #include <sstream>
43 #ifdef WIN32
44 #else
45  #include <cstring> // strerror
46  #include <fcntl.h> // for non-blocking configuration
47 #endif
48 
49 /*****************************************************************************
50 ** Namespaces
51 *****************************************************************************/
52 
53 namespace ros {
54 
56  #ifdef WIN32
57  return WSAGetLastError();
58  #else
59  return errno;
60  #endif
61 }
62 const char* last_socket_error_string() {
63  #ifdef WIN32
64  // could fix this to use FORMAT_MESSAGE and print a real string later,
65  // but not high priority.
66  std::stringstream ostream;
67  ostream << "WSA Error: " << WSAGetLastError();
68  return ostream.str().c_str();
69  #else
70  return strerror(errno);
71  #endif
72 }
73 
75 #if defined(WIN32)
76  if ( WSAGetLastError() == WSAEWOULDBLOCK ) {
77  return true;
78  } else {
79  return false;
80  }
81 #else
82  if ( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) ) { // posix permits either
83  return true;
84  } else {
85  return false;
86  }
87 #endif
88 }
89 
90 /*****************************************************************************
91 ** Service Robotics/Libssh Functions
92 *****************************************************************************/
104 int poll_sockets(socket_pollfd *fds, nfds_t nfds, int timeout) {
105 #if defined(WIN32)
106  fd_set readfds, writefds, exceptfds;
107  struct timeval tv, *ptv;
108  socket_fd_t max_fd;
109  int rc;
110  nfds_t i;
111 
112  if (fds == NULL) {
113  errno = EFAULT;
114  return -1;
115  }
116 
117  FD_ZERO (&readfds);
118  FD_ZERO (&writefds);
119  FD_ZERO (&exceptfds);
120 
121  /*********************
122  ** Compute fd sets
123  **********************/
124  // also find the largest descriptor.
125  for (rc = -1, max_fd = 0, i = 0; i < nfds; i++) {
126  if (fds[i].fd == INVALID_SOCKET) {
127  continue;
128  }
129  if (fds[i].events & (POLLIN | POLLRDNORM)) {
130  FD_SET (fds[i].fd, &readfds);
131  }
132  if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) {
133  FD_SET (fds[i].fd, &writefds);
134  }
135  if (fds[i].events & (POLLPRI | POLLRDBAND)) {
136  FD_SET (fds[i].fd, &exceptfds);
137  }
138  if (fds[i].fd > max_fd &&
139  (fds[i].events & (POLLIN | POLLOUT | POLLPRI |
140  POLLRDNORM | POLLRDBAND |
141  POLLWRNORM | POLLWRBAND))) {
142  max_fd = fds[i].fd;
143  rc = 0;
144  }
145  }
146 
147  if (rc == -1) {
148  errno = EINVAL;
149  return -1;
150  }
151  /*********************
152  ** Setting the timeout
153  **********************/
154  if (timeout < 0) {
155  ptv = NULL;
156  } else {
157  ptv = &tv;
158  if (timeout == 0) {
159  tv.tv_sec = 0;
160  tv.tv_usec = 0;
161  } else {
162  tv.tv_sec = timeout / 1000;
163  tv.tv_usec = (timeout % 1000) * 1000;
164  }
165  }
166 
167  rc = select (max_fd + 1, &readfds, &writefds, &exceptfds, ptv);
168  if (rc < 0) {
169  return -1;
170  } else if ( rc == 0 ) {
171  return 0;
172  }
173 
174  for (rc = 0, i = 0; i < nfds; i++) {
175  if (fds[i].fd != INVALID_SOCKET) {
176  fds[i].revents = 0;
177 
178  if (FD_ISSET(fds[i].fd, &readfds)) {
179  int save_errno = errno;
180  char data[64] = {0};
181  int ret;
182 
183  /* support for POLLHUP */
184  // just check if there's incoming data, without removing it from the queue.
185  ret = recv(fds[i].fd, data, 64, MSG_PEEK);
186  #ifdef WIN32
187  if ((ret == -1) &&
188  (errno == WSAESHUTDOWN || errno == WSAECONNRESET ||
189  (errno == WSAECONNABORTED) || errno == WSAENETRESET))
190  #else
191  if ((ret == -1) &&
192  (errno == ESHUTDOWN || errno == ECONNRESET ||
193  (errno == ECONNABORTED) || errno == ENETRESET))
194  #endif
195  {
196  fds[i].revents |= POLLHUP;
197  } else {
198  fds[i].revents |= fds[i].events & (POLLIN | POLLRDNORM);
199  }
200  errno = save_errno;
201  }
202  if (FD_ISSET(fds[i].fd, &writefds)) {
203  fds[i].revents |= fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND);
204  }
205 
206  if (FD_ISSET(fds[i].fd, &exceptfds)) {
207  fds[i].revents |= fds[i].events & (POLLPRI | POLLRDBAND);
208  }
209 
210  if (fds[i].revents & ~POLLHUP) {
211  rc++;
212  }
213  } else {
214  fds[i].revents = POLLNVAL;
215  }
216  }
217  return rc;
218 #else
219  // use an existing poll implementation
220  int result = poll(fds, nfds, timeout);
221  if ( result < 0 ) {
222  // EINTR means that we got interrupted by a signal, and is not an error
223  if(errno == EINTR) {
224  result = 0;
225  }
226  }
227  return result;
228 #endif // poll_sockets functions
229 }
230 /*****************************************************************************
231 ** Socket Utilities
232 *****************************************************************************/
238 #ifdef WIN32
239  u_long non_blocking = 1;
240  if(ioctlsocket( socket, FIONBIO, &non_blocking ) != 0 )
241  {
242  return WSAGetLastError();
243  }
244 #else
245  if(fcntl(socket, F_SETFL, O_NONBLOCK) == -1)
246  {
247  return errno;
248  }
249 #endif
250  return 0;
251 }
252 
258 int close_socket(socket_fd_t &socket) {
259 #ifdef WIN32
260  if(::closesocket(socket) == SOCKET_ERROR ) {
261  return -1;
262  } else {
263  return 0;
264  }
265 #else
266  if (::close(socket) < 0) {
267  return -1;
268  } else {
269  return 0;
270  }
271 #endif //WIN32
272 }
273 
274 /*****************************************************************************
275 ** Signal Pair
276 *****************************************************************************/
282 int create_signal_pair(signal_fd_t signal_pair[2]) {
283 #ifdef WIN32 // use a socket pair
284  signal_pair[0] = INVALID_SOCKET;
285  signal_pair[1] = INVALID_SOCKET;
286 
287  union {
288  struct sockaddr_in inaddr;
289  struct sockaddr addr;
290  } a;
291  socklen_t addrlen = sizeof(a.inaddr);
292 
293  /*********************
294  ** Listen Socket
295  **********************/
296  socket_fd_t listen_socket = INVALID_SOCKET;
297  listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
298  if (listen_socket == INVALID_SOCKET) {
299  return -1;
300  }
301 
302  // allow it to be bound to an address already in use - do we actually need this?
303  int reuse = 1;
304  if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*) &reuse, (socklen_t) sizeof(reuse)) == SOCKET_ERROR ) {
305  ::closesocket(listen_socket);
306  return -1;
307  }
308 
309  memset(&a, 0, sizeof(a));
310  a.inaddr.sin_family = AF_INET;
311  a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
312  // For TCP/IP, if the port is specified as zero, the service provider assigns
313  // a unique port to the application from the dynamic client port range.
314  a.inaddr.sin_port = 0;
315 
316  if (bind(listen_socket, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) {
317  ::closesocket(listen_socket);
318  return -1;
319  }
320  // we need this below because the system auto filled in some entries, e.g. port #
321  if (getsockname(listen_socket, &a.addr, &addrlen) == SOCKET_ERROR) {
322  ::closesocket(listen_socket);
323  return -1;
324  }
325  // max 1 connection permitted
326  if (listen(listen_socket, 1) == SOCKET_ERROR) {
327  ::closesocket(listen_socket);
328  return -1;
329  }
330 
331  /*********************
332  ** Connection
333  **********************/
334  // do we need io overlapping?
335  // DWORD flags = (make_overlapped ? WSA_FLAG_OVERLAPPED : 0);
336  DWORD overlapped_flag = 0;
337  signal_pair[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, overlapped_flag);
338  if (signal_pair[0] == INVALID_SOCKET) {
339  ::closesocket(listen_socket);
340  ::closesocket(signal_pair[0]);
341  return -1;
342  }
343  // reusing the information from above to connect to the listener
344  if (connect(signal_pair[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) {
345  ::closesocket(listen_socket);
346  ::closesocket(signal_pair[0]);
347  return -1;
348  }
349  /*********************
350  ** Accept
351  **********************/
352  signal_pair[1] = accept(listen_socket, NULL, NULL);
353  if (signal_pair[1] == INVALID_SOCKET) {
354  ::closesocket(listen_socket);
355  ::closesocket(signal_pair[0]);
356  ::closesocket(signal_pair[1]);
357  return -1;
358  }
359  /*********************
360  ** Nonblocking
361  **********************/
362  // should we do this or should we set io overlapping?
363  if ( (set_non_blocking(signal_pair[0]) != 0) || (set_non_blocking(signal_pair[1]) != 0) ) {
364  ::closesocket(listen_socket);
365  ::closesocket(signal_pair[0]);
366  ::closesocket(signal_pair[1]);
367  return -1;
368  }
369  /*********************
370  ** Cleanup
371  **********************/
372  ::closesocket(listen_socket); // the listener has done its job.
373  return 0;
374 #else // use a pipe pair
375  // initialize
376  signal_pair[0] = -1;
377  signal_pair[1] = -1;
378 
379  if(pipe(signal_pair) != 0) {
380  ROS_FATAL( "pipe() failed");
381  return -1;
382  }
383  if(fcntl(signal_pair[0], F_SETFL, O_NONBLOCK) == -1) {
384  ROS_FATAL( "fcntl() failed");
385  return -1;
386  }
387  if(fcntl(signal_pair[1], F_SETFL, O_NONBLOCK) == -1) {
388  ROS_FATAL( "fcntl() failed");
389  return -1;
390  }
391  return 0;
392 #endif // create_pipe
393 }
394 
395 } // namespace ros
#define ROS_FATAL(...)
ROSCPP_DECL int set_non_blocking(socket_fd_t &socket)
Definition: io.cpp:237
int signal_fd_t
Definition: io.h:137
int socket_fd_t
Definition: io.h:136
ROSCPP_DECL const char * last_socket_error_string()
Definition: io.cpp:62
ROSCPP_DECL bool last_socket_error_is_would_block()
Definition: io.cpp:74
ROSCPP_DECL int poll_sockets(socket_pollfd *fds, nfds_t nfds, int timeout)
A cross platform polling function for sockets.
Definition: io.cpp:104
struct pollfd socket_pollfd
Definition: io.h:138
ROSCPP_DECL int create_signal_pair(signal_fd_t signal_pair[2])
Definition: io.cpp:282
ROSCPP_DECL int last_socket_error()
Definition: io.cpp:55
ROSCPP_DECL int close_socket(socket_fd_t &socket)
Close the socket.
Definition: io.cpp:258


roscpp
Author(s): Morgan Quigley, Josh Faust, Brian Gerkey, Troy Straszheim
autogenerated on Wed Dec 20 2017 03:58:41