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
61namespace 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 bool
234 atoaddr( std::string address, struct sockaddr_in& addr)
235 {
236 int status;
237 struct addrinfo *servinfo; // will point to the results
238
239 struct addrinfo hints;
240 memset(&hints, 0, sizeof hints); // make sure the struct is empty
241 hints.ai_family = AF_INET; // restrict to IPv4?
242 hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
243 hints.ai_flags = AI_PASSIVE; // fill in my IP for me
244
245 if ((status = getaddrinfo(address.c_str(), nullptr, &hints, &servinfo)) != 0) {
246 return false;
247 }
248
249 bool valid = false;
250
251 for (struct addrinfo *p = servinfo; p != nullptr; p = p->ai_next) {
252 if (p->ai_family == AF_INET) { // IPv4
253 addr = *(struct sockaddr_in *)p->ai_addr;
254 addr.sin_port = htons((unsigned short)port_);
255 valid = true;
256 break;
257 }
258 }
259
260 freeaddrinfo(servinfo); // free the linked list
261
262 return valid;
263 }
264
265
266 // ----------------------------------------------------------------------
267 Socket*
269 accept(const bool create)
270 {
271 if( socket_ >= 0 )
272 return nullptr;
273
274 struct sockaddr_in client_addr;
275#ifdef WIN32
276 int addrlen = sizeof(client_addr);
277#else
278 socklen_t addrlen = sizeof(client_addr);
279#endif
280
281 if( server_socket_ < 0 )
282 {
283 struct sockaddr_in self;
284
285 //Create the server socket
286 server_socket_ = static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
287 if( server_socket_ < 0 )
288 BailOnSocketError("tcpip::Socket::accept() @ socket");
289
290 //"Address already in use" error protection
291 {
292
293 #ifdef WIN32
294 //setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, sizeof(reuseaddr));
295 // No address reuse in Windows!!!
296 #else
297 int reuseaddr = 1;
298 setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
299 #endif
300 }
301
302 // Initialize address/port structure
303 memset(&self, 0, sizeof(self));
304 self.sin_family = AF_INET;
305 self.sin_port = htons((unsigned short)port_);
306 self.sin_addr.s_addr = htonl(INADDR_ANY);
307
308 // Assign a port number to the socket
309 if ( bind(server_socket_, (struct sockaddr*)&self, sizeof(self)) != 0 )
310 BailOnSocketError("tcpip::Socket::accept() Unable to create listening socket");
311
312
313 // Make it a "listening socket"
314 if ( listen(server_socket_, 10) == -1 )
315 BailOnSocketError("tcpip::Socket::accept() Unable to listen on server socket");
316
317 // Make the newly created socket blocking or not
319 }
320
321 socket_ = static_cast<int>(::accept(server_socket_, (struct sockaddr*)&client_addr, &addrlen));
322
323 if( socket_ >= 0 )
324 {
325 int x = 1;
326 setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
327 if (create) {
328 Socket* result = new Socket(0);
329 result->socket_ = socket_;
330 socket_ = -1;
331 return result;
332 }
333 }
334 return nullptr;
335 }
336
337 // ----------------------------------------------------------------------
338 void
340 set_blocking(bool blocking)
341 {
342 blocking_ = blocking;
343
344 if( server_socket_ > 0 )
345 {
346#ifdef WIN32
347 ULONG NonBlock = blocking_ ? 0 : 1;
348 if (ioctlsocket(server_socket_, FIONBIO, &NonBlock) == SOCKET_ERROR)
349 BailOnSocketError("tcpip::Socket::set_blocking() Unable to initialize non blocking I/O");
350#else
351 long arg = fcntl(server_socket_, F_GETFL, NULL);
352 if (blocking_)
353 {
354 arg &= ~O_NONBLOCK;
355 } else {
356 arg |= O_NONBLOCK;
357 }
358 fcntl(server_socket_, F_SETFL, arg);
359#endif
360 }
361
362 }
363
364 // ----------------------------------------------------------------------
365 void
367 connect()
368 {
369 sockaddr_in address;
370
371 if( !atoaddr( host_.c_str(), address) )
372 BailOnSocketError("tcpip::Socket::connect() @ Invalid network address");
373
374 socket_ = static_cast<int>(socket( PF_INET, SOCK_STREAM, 0 ));
375 if( socket_ < 0 )
376 BailOnSocketError("tcpip::Socket::connect() @ socket");
377
378 if( ::connect( socket_, (sockaddr const*)&address, sizeof(address) ) < 0 )
379 BailOnSocketError("tcpip::Socket::connect() @ connect");
380
381 if( socket_ >= 0 )
382 {
383 int x = 1;
384 setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
385 }
386 }
387
388 // ----------------------------------------------------------------------
389 void
391 close()
392 {
393 // Close client-connection
394 if( socket_ >= 0 )
395 {
396#ifdef WIN32
397 ::closesocket( socket_ );
398#else
399 ::close( socket_ );
400#endif
401
402 socket_ = -1;
403 }
404 }
405
406 // ----------------------------------------------------------------------
407 void
409 send( const std::vector<unsigned char> &buffer)
410 {
411 if( socket_ < 0 )
412 return;
413
414 printBufferOnVerbose(buffer, "Send");
415
416 size_t numbytes = buffer.size();
417 unsigned char const *bufPtr = &buffer[0];
418 while( numbytes > 0 )
419 {
420#ifdef WIN32
421 int bytesSent = ::send( socket_, (const char*)bufPtr, static_cast<int>(numbytes), 0 );
422#else
423 int bytesSent = ::send( socket_, bufPtr, numbytes, 0 );
424#endif
425 if( bytesSent < 0 )
426 BailOnSocketError( "send failed" );
427
428 numbytes -= bytesSent;
429 bufPtr += bytesSent;
430 }
431 }
432
433
434
435 // ----------------------------------------------------------------------
436
437 void
439 sendExact( const Storage &b)
440 {
441 int length = static_cast<int>(b.size());
442 Storage length_storage;
443 length_storage.writeInt(lengthLen + length);
444
445 // Sending length_storage and b independently would probably be possible and
446 // avoid some copying here, but both parts would have to go through the
447 // TCP/IP stack on their own which probably would cost more performance.
448 std::vector<unsigned char> msg;
449 msg.insert(msg.end(), length_storage.begin(), length_storage.end());
450 msg.insert(msg.end(), b.begin(), b.end());
451 send(msg);
452 }
453
454
455 // ----------------------------------------------------------------------
456 size_t
458 recvAndCheck(unsigned char * const buffer, std::size_t len)
459 const
460 {
461#ifdef WIN32
462 const int bytesReceived = recv( socket_, (char*)buffer, static_cast<int>(len), 0 );
463#else
464 const int bytesReceived = static_cast<int>(recv( socket_, buffer, len, 0 ));
465#endif
466 if( bytesReceived == 0 )
467 throw SocketException( "tcpip::Socket::recvAndCheck @ recv: peer shutdown" );
468 if( bytesReceived < 0 )
469 BailOnSocketError( "tcpip::Socket::recvAndCheck @ recv" );
470
471 return static_cast<size_t>(bytesReceived);
472 }
473
474
475 // ----------------------------------------------------------------------
476 void
478 receiveComplete(unsigned char * buffer, size_t len)
479 const
480 {
481 while (len > 0)
482 {
483 const size_t bytesReceived = recvAndCheck(buffer, len);
484 len -= bytesReceived;
485 buffer += bytesReceived;
486 }
487 }
488
489
490 // ----------------------------------------------------------------------
491 void
493 printBufferOnVerbose(const std::vector<unsigned char> buffer, const std::string &label)
494 const
495 {
496 if (verbose_)
497 {
498 std::cerr << label << " " << buffer.size() << " bytes via tcpip::Socket: [";
499 // cache end iterator for performance
500 const std::vector<unsigned char>::const_iterator end = buffer.end();
501 for (std::vector<unsigned char>::const_iterator it = buffer.begin(); end != it; ++it)
502 std::cerr << " " << static_cast<int>(*it) << " ";
503 std::cerr << "]" << std::endl;
504 }
505 }
506
507
508 // ----------------------------------------------------------------------
509 std::vector<unsigned char>
511 receive(int bufSize)
512 {
513 std::vector<unsigned char> buffer;
514
515 if( socket_ < 0 )
516 connect();
517
518 if( !datawaiting( socket_) )
519 return buffer;
520
521 buffer.resize(bufSize);
522 const size_t bytesReceived = recvAndCheck(&buffer[0], bufSize);
523
524 buffer.resize(bytesReceived);
525
526 printBufferOnVerbose(buffer, "Rcvd");
527
528 return buffer;
529 }
530
531 // ----------------------------------------------------------------------
532
533
534 bool
537 {
538 // buffer for received bytes
539 // According to the C++ standard elements of a std::vector are stored
540 // contiguously. Explicitly &buffer[n] == &buffer[0] + n for 0 <= n < buffer.size().
541 std::vector<unsigned char> buffer(lengthLen);
542
543 // receive length of TraCI message
544 receiveComplete(&buffer[0], lengthLen);
545 Storage length_storage(&buffer[0], lengthLen);
546 const int totalLen = length_storage.readInt();
547 assert(totalLen > lengthLen);
548
549 // extent buffer
550 buffer.resize(totalLen);
551
552 // receive remaining TraCI message
553 receiveComplete(&buffer[lengthLen], totalLen - lengthLen);
554
555 // copy message content into passed Storage
556 msg.reset();
557 msg.writePacket(&buffer[lengthLen], totalLen - lengthLen);
558
559 printBufferOnVerbose(buffer, "Rcvd Storage with");
560
561 return true;
562 }
563
564
565 // ----------------------------------------------------------------------
566 bool
569 const
570 {
571 return socket_ >= 0;
572 }
573
574 // ----------------------------------------------------------------------
575 bool
578 {
579 return blocking_;
580 }
581
582
583#ifdef WIN32
584 // ----------------------------------------------------------------------
585 std::string
586 Socket::
587 GetWinsockErrorString(int err)
588 {
589
590 switch( err)
591 {
592 case 0: return "No error";
593 case WSAEINTR: return "Interrupted system call";
594 case WSAEBADF: return "Bad file number";
595 case WSAEACCES: return "Permission denied";
596 case WSAEFAULT: return "Bad address";
597 case WSAEINVAL: return "Invalid argument";
598 case WSAEMFILE: return "Too many open sockets";
599 case WSAEWOULDBLOCK: return "Operation would block";
600 case WSAEINPROGRESS: return "Operation now in progress";
601 case WSAEALREADY: return "Operation already in progress";
602 case WSAENOTSOCK: return "Socket operation on non-socket";
603 case WSAEDESTADDRREQ: return "Destination address required";
604 case WSAEMSGSIZE: return "Message too long";
605 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
606 case WSAENOPROTOOPT: return "Bad protocol option";
607 case WSAEPROTONOSUPPORT: return "Protocol not supported";
608 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
609 case WSAEOPNOTSUPP: return "Operation not supported on socket";
610 case WSAEPFNOSUPPORT: return "Protocol family not supported";
611 case WSAEAFNOSUPPORT: return "Address family not supported";
612 case WSAEADDRINUSE: return "Address already in use";
613 case WSAEADDRNOTAVAIL: return "Can't assign requested address";
614 case WSAENETDOWN: return "Network is down";
615 case WSAENETUNREACH: return "Network is unreachable";
616 case WSAENETRESET: return "Net Socket reset";
617 case WSAECONNABORTED: return "Software caused tcpip::Socket abort";
618 case WSAECONNRESET: return "Socket reset by peer";
619 case WSAENOBUFS: return "No buffer space available";
620 case WSAEISCONN: return "Socket is already connected";
621 case WSAENOTCONN: return "Socket is not connected";
622 case WSAESHUTDOWN: return "Can't send after socket shutdown";
623 case WSAETOOMANYREFS: return "Too many references, can't splice";
624 case WSAETIMEDOUT: return "Socket timed out";
625 case WSAECONNREFUSED: return "Socket refused";
626 case WSAELOOP: return "Too many levels of symbolic links";
627 case WSAENAMETOOLONG: return "File name too long";
628 case WSAEHOSTDOWN: return "Host is down";
629 case WSAEHOSTUNREACH: return "No route to host";
630 case WSAENOTEMPTY: return "Directory not empty";
631 case WSAEPROCLIM: return "Too many processes";
632 case WSAEUSERS: return "Too many users";
633 case WSAEDQUOT: return "Disc quota exceeded";
634 case WSAESTALE: return "Stale NFS file handle";
635 case WSAEREMOTE: return "Too many levels of remote in path";
636 case WSASYSNOTREADY: return "Network system is unavailable";
637 case WSAVERNOTSUPPORTED: return "Winsock version out of range";
638 case WSANOTINITIALISED: return "WSAStartup not yet called";
639 case WSAEDISCON: return "Graceful shutdown in progress";
640 case WSAHOST_NOT_FOUND: return "Host not found";
641 case WSANO_DATA: return "No host data of that type was found";
642 }
643
644 return "unknown";
645 }
646
647#endif // WIN32
648
649} // namespace tcpip
650
651#endif // BUILD_TCPIP
652
653/*-----------------------------------------------------------------------
654* Source $Source: $
655* Version $Revision: 645 $
656* Date $Date: 2012-04-27 14:03:33 +0200 (Fri, 27 Apr 2012) $
657*-----------------------------------------------------------------------
658* $Log: $
659*-----------------------------------------------------------------------*/
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:493
bool receiveExact(Storage &)
Receive a complete TraCI message from Socket::socket_.
Definition: socket.cpp:536
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:511
bool blocking_
Definition: socket.h:123
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:458
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:125
bool is_blocking()
Definition: socket.cpp:577
int server_socket_
Definition: socket.h:122
~Socket()
Destructor.
Definition: socket.cpp:148
bool atoaddr(std::string, struct sockaddr_in &addr)
Definition: socket.cpp:234
void sendExact(const Storage &)
Definition: socket.cpp:439
int socket_
Definition: socket.h:121
bool has_client_connection() const
Definition: socket.cpp:568
void connect()
Connects to host_:port_.
Definition: socket.cpp:367
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:192
void set_blocking(bool)
Definition: socket.cpp:340
Socket * accept(const bool create=false)
Wait for a incoming connection to port_.
Definition: socket.cpp:269
void receiveComplete(unsigned char *const buffer, std::size_t len) const
Receive len bytes from Socket::socket_.
Definition: socket.cpp:478
void send(const std::vector< unsigned char > &buffer)
Definition: socket.cpp:409
Socket(std::string host, int port)
Constructor that prepare to connect to host:port.
Definition: socket.cpp:73
void close()
Definition: socket.cpp:391
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
static std::string strerror()
Definition: socket.cpp:62