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