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