SUMO - Simulation of Urban MObility
socket.cpp
Go to the documentation of this file.
1 /************************************************************************
2  ** This file is part of the network simulator Shawn. **
3  ** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project **
4  ** Shawn is free software; you can redistribute it and/or modify it **
5  ** under the terms of the BSD License. Refer to the shawn-licence.txt **
6  ** file in the root of the Shawn source tree for further details. **
7  ************************************************************************/
8 
9 #ifdef SHAWN
10  #include <apps/tcpip/socket.h>
11  #include <sys/simulation/simulation_controller.h>
12 #else
13  #include "socket.h"
14 #endif
15 
16 #ifdef BUILD_TCPIP
17 
18 
19 #ifndef WIN32
20  #include <sys/types.h>
21  #include <sys/socket.h>
22  #include <netinet/in.h>
23  #include <netinet/tcp.h>
24  #include <arpa/inet.h>
25  #include <netdb.h>
26  #include <errno.h>
27  #include <fcntl.h>
28  #include <unistd.h>
29 #else
30  #ifdef ERROR
31  #undef ERROR
32  #endif
33 
34  #include <winsock2.h>
35 
36  #ifndef vsnprintf
37  #define vsnprintf _vsnprintf
38  #endif
39 
40 #endif
41 
42 #include <cstdio>
43 #include <cstring>
44 #include <cstdarg>
45 #include <cassert>
46 #include <string>
47 #include <vector>
48 #include <string>
49 #include <algorithm>
50 #include <string.h>
51 
52 
53 #ifdef SHAWN
54  extern "C" void init_tcpip( shawn::SimulationController& sc )
55  {
56  // std::cout << "tcpip init" << std::endl;
57  }
58 #endif
59 
60 namespace tcpip
61 {
62  const int Socket::lengthLen = 4;
63 
64 #ifdef WIN32
65  bool Socket::init_windows_sockets_ = true;
66  bool Socket::windows_sockets_initialized_ = false;
67  int Socket::instance_count_ = 0;
68 #endif
69 
70  // ----------------------------------------------------------------------
71  Socket::
72  Socket(std::string host, int port)
73  : host_( host ),
74  port_( port ),
75  socket_(-1),
76  server_socket_(-1),
77  blocking_(true),
78  verbose_(false)
79  {
80  init();
81  }
82 
83  // ----------------------------------------------------------------------
84  Socket::
86  : host_(""),
87  port_( port ),
88  socket_(-1),
89  server_socket_(-1),
90  blocking_(true),
91  verbose_(false)
92  {
93  init();
94  }
95 
96  // ----------------------------------------------------------------------
97  void
98  Socket::
100  {
101 #ifdef WIN32
102  instance_count_++;
103 
104  if( init_windows_sockets_ && !windows_sockets_initialized_ )
105  {
106  WSAData wsaData;
107  if( WSAStartup(MAKEWORD(1, 1), &wsaData) != 0 )
108  BailOnSocketError("Unable to init WSA Sockets");
109  windows_sockets_initialized_ = true;
110  }
111 #endif
112  }
113 
114  // ----------------------------------------------------------------------
115  Socket::
117  {
118  // Close first an existing client connection ...
119  close();
120 #ifdef WIN32
121  instance_count_--;
122 #endif
123 
124  // ... then the server socket
125  if( server_socket_ >= 0 )
126  {
127 #ifdef WIN32
128  ::closesocket( server_socket_ );
129 #else
131 #endif
132  server_socket_ = -1;
133  }
134 
135 #ifdef WIN32
136  if( server_socket_ == -1 && socket_ == -1
137  && init_windows_sockets_ && instance_count_ == 0 )
138  WSACleanup();
139  windows_sockets_initialized_ = false;
140 #endif
141  }
142 
143  // ----------------------------------------------------------------------
144  void
145  Socket::
146  BailOnSocketError( std::string context)
147  const throw( SocketException )
148  {
149 #ifdef WIN32
150  int e = WSAGetLastError();
151  std::string msg = GetWinsockErrorString( e );
152 #else
153  std::string msg = strerror( errno );
154 #endif
155  throw SocketException( context + ": " + msg );
156  }
157 
158  // ----------------------------------------------------------------------
159  int
160  Socket::
162  {
163  return port_;
164  }
165 
166 
167  // ----------------------------------------------------------------------
168  bool
169  Socket::
170  datawaiting(int sock)
171  const throw()
172  {
173  fd_set fds;
174  FD_ZERO( &fds );
175  FD_SET( (unsigned int)sock, &fds );
176 
177  struct timeval tv;
178  tv.tv_sec = 0;
179  tv.tv_usec = 0;
180 
181  int r = select( sock+1, &fds, NULL, NULL, &tv);
182 
183  if (r < 0)
184  BailOnSocketError("tcpip::Socket::datawaiting @ select");
185 
186  if( FD_ISSET( sock, &fds ) )
187  return true;
188  else
189  return false;
190  }
191 
192  // ----------------------------------------------------------------------
193  bool
194  Socket::
195  atoaddr( std::string address, struct in_addr& addr)
196  {
197  struct hostent* host;
198  struct in_addr saddr;
199 
200  // First try nnn.nnn.nnn.nnn form
201  saddr.s_addr = inet_addr(address.c_str());
202  if (saddr.s_addr != static_cast<unsigned int>(-1))
203  {
204  addr = saddr;
205  return true;
206  }
207 
208  host = gethostbyname(address.c_str());
209  if( host ) {
210  addr = *((struct in_addr*)host->h_addr_list[0]);
211  return true;
212  }
213 
214  return false;
215  }
216 
217 
218  // ----------------------------------------------------------------------
219  void
220  Socket::
222  throw( SocketException )
223  {
224  if( socket_ >= 0 )
225  return;
226 
227  struct sockaddr_in client_addr;
228 #ifdef WIN32
229  int addrlen = sizeof(client_addr);
230 #else
231  socklen_t addrlen = sizeof(client_addr);
232 #endif
233 
234  if( server_socket_ < 0 )
235  {
236  struct sockaddr_in self;
237 
238  //Create the server socket
239  server_socket_ = static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
240  if( server_socket_ < 0 )
241  BailOnSocketError("tcpip::Socket::accept() @ socket");
242 
243  //"Address already in use" error protection
244  {
245 
246  #ifdef WIN32
247  //setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, sizeof(reuseaddr));
248  // No address reuse in Windows!!!
249  #else
250  int reuseaddr = 1;
251  setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
252  #endif
253  }
254 
255  // Initialize address/port structure
256  memset(&self, 0, sizeof(self));
257  self.sin_family = AF_INET;
258  self.sin_port = htons((unsigned short)port_);
259  self.sin_addr.s_addr = htonl(INADDR_ANY);
260 
261  // Assign a port number to the socket
262  if ( bind(server_socket_, (struct sockaddr*)&self, sizeof(self)) != 0 )
263  BailOnSocketError("tcpip::Socket::accept() Unable to create listening socket");
264 
265 
266  // Make it a "listening socket"
267  if ( listen(server_socket_, 10) == -1 )
268  BailOnSocketError("tcpip::Socket::accept() Unable to listen on server socket");
269 
270  // Make the newly created socket blocking or not
272  }
273 
274  socket_ = static_cast<int>(::accept(server_socket_, (struct sockaddr*)&client_addr, &addrlen));
275 
276  if( socket_ >= 0 )
277  {
278  int x = 1;
279  setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
280  }
281  }
282 
283  // ----------------------------------------------------------------------
284  void
285  Socket::
286  set_blocking(bool blocking)
287  throw(SocketException )
288  {
289  blocking_ = blocking;
290 
291  if( server_socket_ > 0 )
292  {
293 #ifdef WIN32
294  ULONG NonBlock = blocking_ ? 0 : 1;
295  if (ioctlsocket(server_socket_, FIONBIO, &NonBlock) == SOCKET_ERROR)
296  BailOnSocketError("tcpip::Socket::set_blocking() Unable to initialize non blocking I/O");
297 #else
298  long arg = fcntl(server_socket_, F_GETFL, NULL);
299  if (blocking_)
300  {
301  arg &= ~O_NONBLOCK;
302  } else {
303  arg |= O_NONBLOCK;
304  }
305  fcntl(server_socket_, F_SETFL, arg);
306 #endif
307  }
308 
309  }
310 
311  // ----------------------------------------------------------------------
312  void
313  Socket::
315  throw( SocketException )
316  {
317  in_addr addr;
318  if( !atoaddr( host_.c_str(), addr) )
319  BailOnSocketError("tcpip::Socket::connect() @ Invalid network address");
320 
321  sockaddr_in address;
322  memset( (char*)&address, 0, sizeof(address) );
323  address.sin_family = AF_INET;
324  address.sin_port = htons((unsigned short)port_);
325  address.sin_addr.s_addr = addr.s_addr;
326 
327  socket_ = static_cast<int>(socket( PF_INET, SOCK_STREAM, 0 ));
328  if( socket_ < 0 )
329  BailOnSocketError("tcpip::Socket::connect() @ socket");
330 
331  if( ::connect( socket_, (sockaddr const*)&address, sizeof(address) ) < 0 )
332  BailOnSocketError("tcpip::Socket::connect() @ connect");
333 
334  if( socket_ >= 0 )
335  {
336  int x = 1;
337  setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
338  }
339 
340  }
341 
342  // ----------------------------------------------------------------------
343  void
344  Socket::
346  {
347  // Close client-connection
348  if( socket_ >= 0 )
349  {
350 #ifdef WIN32
351  ::closesocket( socket_ );
352 #else
353  ::close( socket_ );
354 #endif
355 
356  socket_ = -1;
357  }
358  }
359 
360  // ----------------------------------------------------------------------
361  void
362  Socket::
363  send( const std::vector<unsigned char> &buffer)
364  throw( SocketException )
365  {
366  if( socket_ < 0 )
367  return;
368 
369  printBufferOnVerbose(buffer, "Send");
370 
371  size_t numbytes = buffer.size();
372  unsigned char const *bufPtr = &buffer[0];
373  while( numbytes > 0 )
374  {
375 #ifdef WIN32
376  int bytesSent = ::send( socket_, (const char*)bufPtr, static_cast<int>(numbytes), 0 );
377 #else
378  int bytesSent = ::send( socket_, bufPtr, numbytes, 0 );
379 #endif
380  if( bytesSent < 0 )
381  BailOnSocketError( "send failed" );
382 
383  numbytes -= bytesSent;
384  bufPtr += bytesSent;
385  }
386  }
387 
388 
389 
390  // ----------------------------------------------------------------------
391 
392  void
393  Socket::
394  sendExact( const Storage &b)
395  throw( SocketException )
396  {
397  int length = static_cast<int>(b.size());
398  Storage length_storage;
399  length_storage.writeInt(lengthLen + length);
400 
401  // Sending length_storage and b independently would probably be possible and
402  // avoid some copying here, but both parts would have to go through the
403  // TCP/IP stack on their own which probably would cost more performance.
404  std::vector<unsigned char> msg;
405  msg.insert(msg.end(), length_storage.begin(), length_storage.end());
406  msg.insert(msg.end(), b.begin(), b.end());
407  send(msg);
408  }
409 
410 
411  // ----------------------------------------------------------------------
412  size_t
413  Socket::
414  recvAndCheck(unsigned char * const buffer, std::size_t len)
415  const
416  {
417 #ifdef WIN32
418  const int bytesReceived = recv( socket_, (char*)buffer, static_cast<int>(len), 0 );
419 #else
420  const int bytesReceived = static_cast<int>(recv( socket_, buffer, len, 0 ));
421 #endif
422  if( bytesReceived == 0 )
423  throw SocketException( "tcpip::Socket::recvAndCheck @ recv: peer shutdown" );
424  if( bytesReceived < 0 )
425  BailOnSocketError( "tcpip::Socket::recvAndCheck @ recv" );
426 
427  return static_cast<size_t>(bytesReceived);
428  }
429 
430 
431  // ----------------------------------------------------------------------
432  void
433  Socket::
434  receiveComplete(unsigned char * buffer, size_t len)
435  const
436  {
437  while (len > 0)
438  {
439  const size_t bytesReceived = recvAndCheck(buffer, len);
440  len -= bytesReceived;
441  buffer += bytesReceived;
442  }
443  }
444 
445 
446  // ----------------------------------------------------------------------
447  void
448  Socket::
449  printBufferOnVerbose(const std::vector<unsigned char> buffer, const std::string &label)
450  const
451  {
452  if (verbose_)
453  {
454  std::cerr << label << " " << buffer.size() << " bytes via tcpip::Socket: [";
455  // cache end iterator for performance
456  const std::vector<unsigned char>::const_iterator end = buffer.end();
457  for (std::vector<unsigned char>::const_iterator it = buffer.begin(); end != it; ++it)
458  std::cerr << " " << static_cast<int>(*it) << " ";
459  std::cerr << "]" << std::endl;
460  }
461  }
462 
463 
464  // ----------------------------------------------------------------------
465  std::vector<unsigned char>
466  Socket::
467  receive(int bufSize)
468  throw( SocketException )
469  {
470  std::vector<unsigned char> buffer;
471 
472  if( socket_ < 0 )
473  connect();
474 
475  if( !datawaiting( socket_) )
476  return buffer;
477 
478  buffer.resize(bufSize);
479  const size_t bytesReceived = recvAndCheck(&buffer[0], bufSize);
480 
481  buffer.resize(bytesReceived);
482 
483  printBufferOnVerbose(buffer, "Rcvd");
484 
485  return buffer;
486  }
487 
488  // ----------------------------------------------------------------------
489 
490 
491  bool
492  Socket::
494  throw( SocketException )
495  {
496  // buffer for received bytes
497  // According to the C++ standard elements of a std::vector are stored
498  // contiguously. Explicitly &buffer[n] == &buffer[0] + n for 0 <= n < buffer.size().
499  std::vector<unsigned char> buffer(lengthLen);
500 
501  // receive length of TraCI message
502  receiveComplete(&buffer[0], lengthLen);
503  Storage length_storage(&buffer[0], lengthLen);
504  const int totalLen = length_storage.readInt();
505  assert(totalLen > lengthLen);
506 
507  // extent buffer
508  buffer.resize(totalLen);
509 
510  // receive remaining TraCI message
511  receiveComplete(&buffer[lengthLen], totalLen - lengthLen);
512 
513  // copy message content into passed Storage
514  msg.reset();
515  msg.writePacket(&buffer[lengthLen], totalLen - lengthLen);
516 
517  printBufferOnVerbose(buffer, "Rcvd Storage with");
518 
519  return true;
520  }
521 
522 
523  // ----------------------------------------------------------------------
524  bool
525  Socket::
527  const
528  {
529  return socket_ >= 0;
530  }
531 
532  // ----------------------------------------------------------------------
533  bool
534  Socket::
536  throw()
537  {
538  return blocking_;
539  }
540 
541 
542 #ifdef WIN32
543  // ----------------------------------------------------------------------
544  std::string
545  Socket::
546  GetWinsockErrorString(int err)
547  const
548  {
549 
550  switch( err)
551  {
552  case 0: return "No error";
553  case WSAEINTR: return "Interrupted system call";
554  case WSAEBADF: return "Bad file number";
555  case WSAEACCES: return "Permission denied";
556  case WSAEFAULT: return "Bad address";
557  case WSAEINVAL: return "Invalid argument";
558  case WSAEMFILE: return "Too many open sockets";
559  case WSAEWOULDBLOCK: return "Operation would block";
560  case WSAEINPROGRESS: return "Operation now in progress";
561  case WSAEALREADY: return "Operation already in progress";
562  case WSAENOTSOCK: return "Socket operation on non-socket";
563  case WSAEDESTADDRREQ: return "Destination address required";
564  case WSAEMSGSIZE: return "Message too long";
565  case WSAEPROTOTYPE: return "Protocol wrong type for socket";
566  case WSAENOPROTOOPT: return "Bad protocol option";
567  case WSAEPROTONOSUPPORT: return "Protocol not supported";
568  case WSAESOCKTNOSUPPORT: return "Socket type not supported";
569  case WSAEOPNOTSUPP: return "Operation not supported on socket";
570  case WSAEPFNOSUPPORT: return "Protocol family not supported";
571  case WSAEAFNOSUPPORT: return "Address family not supported";
572  case WSAEADDRINUSE: return "Address already in use";
573  case WSAEADDRNOTAVAIL: return "Can't assign requested address";
574  case WSAENETDOWN: return "Network is down";
575  case WSAENETUNREACH: return "Network is unreachable";
576  case WSAENETRESET: return "Net Socket reset";
577  case WSAECONNABORTED: return "Software caused tcpip::Socket abort";
578  case WSAECONNRESET: return "Socket reset by peer";
579  case WSAENOBUFS: return "No buffer space available";
580  case WSAEISCONN: return "Socket is already connected";
581  case WSAENOTCONN: return "Socket is not connected";
582  case WSAESHUTDOWN: return "Can't send after socket shutdown";
583  case WSAETOOMANYREFS: return "Too many references, can't splice";
584  case WSAETIMEDOUT: return "Socket timed out";
585  case WSAECONNREFUSED: return "Socket refused";
586  case WSAELOOP: return "Too many levels of symbolic links";
587  case WSAENAMETOOLONG: return "File name too long";
588  case WSAEHOSTDOWN: return "Host is down";
589  case WSAEHOSTUNREACH: return "No route to host";
590  case WSAENOTEMPTY: return "Directory not empty";
591  case WSAEPROCLIM: return "Too many processes";
592  case WSAEUSERS: return "Too many users";
593  case WSAEDQUOT: return "Disc quota exceeded";
594  case WSAESTALE: return "Stale NFS file handle";
595  case WSAEREMOTE: return "Too many levels of remote in path";
596  case WSASYSNOTREADY: return "Network system is unavailable";
597  case WSAVERNOTSUPPORTED: return "Winsock version out of range";
598  case WSANOTINITIALISED: return "WSAStartup not yet called";
599  case WSAEDISCON: return "Graceful shutdown in progress";
600  case WSAHOST_NOT_FOUND: return "Host not found";
601  case WSANO_DATA: return "No host data of that type was found";
602  }
603 
604  return "unknown";
605  }
606 
607 #endif // WIN32
608 
609 } // namespace tcpip
610 
611 #endif // BUILD_TCPIP
612 
613 /*-----------------------------------------------------------------------
614 * Source $Source: $
615 * Version $Revision: 645 $
616 * Date $Date: 2012-04-27 14:03:33 +0200 (Fri, 27 Apr 2012) $
617 *-----------------------------------------------------------------------
618 * $Log: $
619 *-----------------------------------------------------------------------*/
Definition: socket.cpp:60
bool receiveExact(Storage &)
Receive a complete TraCI message from Socket::socket_.
Definition: socket.cpp:493
int server_socket_
Definition: socket.h:136
void printBufferOnVerbose(const std::vector< unsigned char > buffer, const std::string &label) const
Print label and buffer to stderr if Socket::verbose_ is set.
Definition: socket.cpp:449
std::vector< unsigned char > receive(int bufSize=2048)
Receive up to bufSize available bytes from Socket::socket_.
Definition: socket.cpp:467
void accept()
Wait for a incoming connection to port_.
Definition: socket.cpp:221
bool blocking_
Definition: socket.h:137
static const int lengthLen
Length of the message length part of a TraCI message.
Definition: socket.h:115
Socket(std::string host, int port)
Constructor that prepare to connect to host:port.
Definition: socket.cpp:72
virtual void writeInt(int)
void connect()
Connects to host_:port_.
Definition: socket.cpp:314
bool datawaiting(int sock) const
Definition: socket.cpp:170
bool atoaddr(std::string, struct in_addr &addr)
Definition: socket.cpp:195
std::string host_
Definition: socket.h:133
StorageType::const_iterator end() const
Definition: storage.h:118
virtual int readInt()
~Socket()
Destructor.
Definition: socket.cpp:116
void BailOnSocketError(std::string) const
Definition: socket.cpp:146
size_t recvAndCheck(unsigned char *const buffer, std::size_t len) const
Receive up to len available bytes from Socket::socket_.
Definition: socket.cpp:414
void send(const std::vector< unsigned char > &buffer)
Definition: socket.cpp:363
void sendExact(const Storage &)
Definition: socket.cpp:394
bool is_blocking()
Definition: socket.cpp:535
void receiveComplete(unsigned char *const buffer, std::size_t len) const
Receive len bytes from Socket::socket_.
Definition: socket.cpp:434
int port()
Definition: socket.cpp:161
StorageType::const_iterator begin() const
Definition: storage.h:117
void init()
Definition: socket.cpp:99
bool verbose_
Definition: socket.h:139
bool has_client_connection() const
Definition: socket.cpp:526
int socket_
Definition: socket.h:135
void set_blocking(bool)
Definition: socket.cpp:286
void close()
Definition: socket.cpp:345