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