Line data Source code
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 : // ----------------------------------------------------------------------
72 1860 : Socket::
73 1860 : Socket(std::string host, int port)
74 1860 : : host_( host ),
75 1860 : port_( port ),
76 1860 : socket_(-1),
77 1860 : server_socket_(-1),
78 1860 : blocking_(true),
79 1860 : verbose_(false)
80 : {
81 1860 : init();
82 1860 : }
83 :
84 : // ----------------------------------------------------------------------
85 5683 : Socket::
86 5683 : Socket(int port)
87 5683 : : host_(""),
88 5683 : port_( port ),
89 5683 : socket_(-1),
90 5683 : server_socket_(-1),
91 5683 : blocking_(true),
92 5683 : verbose_(false)
93 : {
94 5683 : init();
95 5683 : }
96 :
97 : // ----------------------------------------------------------------------
98 : void
99 7543 : Socket::
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 7543 : }
114 :
115 :
116 : int
117 569 : Socket::
118 : getFreeSocketPort()
119 : {
120 569 : 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 569 : int sock = static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
123 : struct sockaddr_in self;
124 : memset(&self, 0, sizeof(self));
125 569 : self.sin_family = AF_INET;
126 : self.sin_port = htons(0);
127 : self.sin_addr.s_addr = htonl(INADDR_ANY);
128 :
129 569 : socklen_t address_len = sizeof(self);
130 : // bind with port==0 assigns free port
131 569 : if ( bind(sock, (struct sockaddr*) &self, address_len) < 0)
132 0 : BailOnSocketError("tcpip::Socket::getFreeSocketPort() Unable to bind socket");
133 : // get the assigned port with getsockname
134 569 : if ( getsockname(sock, (struct sockaddr*) &self, &address_len) < 0)
135 0 : BailOnSocketError("tcpip::Socket::getFreeSocketPort() Unable to get socket name");
136 569 : const int port = ntohs(self.sin_port);
137 : #ifdef WIN32
138 : ::closesocket( sock );
139 : #else
140 569 : ::close( sock );
141 : #endif
142 569 : return port;
143 569 : }
144 :
145 :
146 : // ----------------------------------------------------------------------
147 7530 : Socket::
148 : ~Socket()
149 : {
150 : // Close first an existing client connection ...
151 7530 : close();
152 : #ifdef WIN32
153 : instance_count_--;
154 : #endif
155 :
156 : // ... then the server socket
157 7530 : if( server_socket_ >= 0 )
158 : {
159 : #ifdef WIN32
160 : ::closesocket( server_socket_ );
161 : #else
162 2476 : ::close( server_socket_ );
163 : #endif
164 2476 : 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 7530 : }
174 :
175 : // ----------------------------------------------------------------------
176 : void
177 1375 : Socket::
178 : BailOnSocketError( std::string context)
179 : {
180 : #ifdef WIN32
181 : int e = WSAGetLastError();
182 : std::string msg = GetWinsockErrorString( e );
183 : #else
184 1375 : std::string msg = strerror( errno );
185 : #endif
186 2750 : throw SocketException( context + ": " + msg );
187 : }
188 :
189 : // ----------------------------------------------------------------------
190 : int
191 0 : Socket::
192 : port()
193 : {
194 0 : 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
205 0 : Socket::
206 : datawaiting(int sock)
207 : const
208 : {
209 : fd_set fds;
210 0 : FD_ZERO( &fds );
211 0 : FD_SET( (unsigned int)sock, &fds );
212 :
213 : struct timeval tv;
214 0 : tv.tv_sec = 0;
215 0 : tv.tv_usec = 0;
216 :
217 0 : int r = select( sock+1, &fds, nullptr, nullptr, &tv);
218 :
219 0 : if (r < 0)
220 0 : BailOnSocketError("tcpip::Socket::datawaiting @ select");
221 :
222 0 : if( FD_ISSET( sock, &fds ) )
223 : return true;
224 : else
225 0 : return false;
226 : }
227 : #ifdef _MSC_VER
228 : #pragma warning(pop)
229 : #endif
230 :
231 : // ----------------------------------------------------------------------
232 : Socket*
233 2642 : Socket::
234 : accept(const bool create)
235 : {
236 2642 : 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 2642 : socklen_t addrlen = sizeof(client_addr);
244 : #endif
245 :
246 2642 : if( server_socket_ < 0 )
247 : {
248 : struct sockaddr_in self;
249 :
250 : //Create the server socket
251 2476 : server_socket_ = static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
252 2476 : if( server_socket_ < 0 )
253 0 : 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 2476 : int reuseaddr = 1;
263 2476 : 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 2476 : self.sin_family = AF_INET;
270 2476 : 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 2476 : if ( bind(server_socket_, (struct sockaddr*)&self, sizeof(self)) != 0 )
275 4 : BailOnSocketError("tcpip::Socket::accept() Unable to create listening socket");
276 :
277 :
278 : // Make it a "listening socket"
279 2472 : if ( listen(server_socket_, 10) == -1 )
280 0 : BailOnSocketError("tcpip::Socket::accept() Unable to listen on server socket");
281 :
282 : // Make the newly created socket blocking or not
283 2472 : set_blocking(blocking_);
284 : }
285 :
286 2638 : socket_ = static_cast<int>(::accept(server_socket_, (struct sockaddr*)&client_addr, &addrlen));
287 :
288 2638 : if( socket_ >= 0 )
289 : {
290 2638 : int x = 1;
291 2638 : setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
292 2638 : if (create) {
293 2638 : Socket* result = new Socket(0);
294 2638 : result->socket_ = socket_;
295 2638 : socket_ = -1;
296 2638 : return result;
297 : }
298 : }
299 : return nullptr;
300 : }
301 :
302 : // ----------------------------------------------------------------------
303 : void
304 2472 : Socket::
305 : set_blocking(bool blocking)
306 : {
307 2472 : blocking_ = blocking;
308 :
309 2472 : 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 2472 : long arg = fcntl(server_socket_, F_GETFL, NULL);
317 2472 : if (blocking_)
318 : {
319 2472 : arg &= ~O_NONBLOCK;
320 : } else {
321 0 : arg |= O_NONBLOCK;
322 : }
323 2472 : fcntl(server_socket_, F_SETFL, arg);
324 : #endif
325 : }
326 :
327 2472 : }
328 :
329 : // ----------------------------------------------------------------------
330 : void
331 2616 : Socket::
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 2616 : hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
339 2616 : hints.ai_flags = AI_PASSIVE; // fill in my IP for me
340 :
341 5232 : if (getaddrinfo(host_.c_str(), std::to_string(port_).c_str(), &hints, &servinfo) != 0) {
342 0 : BailOnSocketError("tcpip::Socket::connect() @ Invalid network address");
343 : }
344 2616 : socket_ = -1;
345 3983 : for (struct addrinfo* p = servinfo; p != nullptr; p = p->ai_next) {
346 2616 : socket_ = (int)socket(p->ai_family, p->ai_socktype, p->ai_protocol);
347 2616 : if (socket_ >= 0) {
348 2616 : if (::connect(socket_, p->ai_addr, (int)p->ai_addrlen) == 0) {
349 1249 : int x = 1;
350 1249 : setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
351 : break;
352 : }
353 1367 : close();
354 : }
355 : }
356 2616 : freeaddrinfo(servinfo); // free the linked list
357 2616 : if (socket_ < 0) {
358 1367 : BailOnSocketError("tcpip::Socket::connect() @ socket");
359 : }
360 1249 : }
361 :
362 : // ----------------------------------------------------------------------
363 : void
364 10899 : Socket::
365 : close()
366 : {
367 : // Close client-connection
368 10899 : if( socket_ >= 0 )
369 : {
370 : #ifdef WIN32
371 : ::closesocket( socket_ );
372 : #else
373 5241 : ::close( socket_ );
374 : #endif
375 :
376 5241 : socket_ = -1;
377 : }
378 10899 : }
379 :
380 : // ----------------------------------------------------------------------
381 : void
382 18340344 : Socket::
383 : send( const std::vector<unsigned char> &buffer)
384 : {
385 18340344 : if( socket_ < 0 )
386 : return;
387 :
388 18340344 : printBufferOnVerbose(buffer, "Send");
389 :
390 : size_t numbytes = buffer.size();
391 : unsigned char const *bufPtr = &buffer[0];
392 36680686 : while( numbytes > 0 )
393 : {
394 : #ifdef WIN32
395 : int bytesSent = ::send( socket_, (const char*)bufPtr, static_cast<int>(numbytes), 0 );
396 : #else
397 18340344 : int bytesSent = ::send( socket_, bufPtr, numbytes, 0 );
398 : #endif
399 18340344 : if( bytesSent < 0 )
400 2 : BailOnSocketError( "send failed" );
401 :
402 18340342 : numbytes -= bytesSent;
403 18340342 : bufPtr += bytesSent;
404 : }
405 : }
406 :
407 :
408 :
409 : // ----------------------------------------------------------------------
410 :
411 : void
412 18340296 : Socket::
413 : sendExact( const Storage &b)
414 : {
415 18340296 : int length = static_cast<int>(b.size());
416 18340296 : Storage length_storage;
417 18340296 : 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 18340296 : msg.insert(msg.end(), length_storage.begin(), length_storage.end());
424 18340296 : msg.insert(msg.end(), b.begin(), b.end());
425 18340296 : send(msg);
426 18340296 : }
427 :
428 :
429 : // ----------------------------------------------------------------------
430 : size_t
431 36680626 : Socket::
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 36680626 : const int bytesReceived = static_cast<int>(recv( socket_, buffer, len, 0 ));
439 : #endif
440 36680626 : if( bytesReceived == 0 )
441 48 : throw SocketException( "tcpip::Socket::recvAndCheck @ recv: peer shutdown" );
442 36680602 : if( bytesReceived < 0 )
443 2 : BailOnSocketError( "tcpip::Socket::recvAndCheck @ recv" );
444 :
445 36680600 : return static_cast<size_t>(bytesReceived);
446 : }
447 :
448 :
449 : // ----------------------------------------------------------------------
450 : void
451 36680626 : Socket::
452 : receiveComplete(unsigned char * buffer, size_t len)
453 : const
454 : {
455 73361226 : while (len > 0)
456 : {
457 36680626 : const size_t bytesReceived = recvAndCheck(buffer, len);
458 36680600 : len -= bytesReceived;
459 36680600 : buffer += bytesReceived;
460 : }
461 36680600 : }
462 :
463 :
464 : // ----------------------------------------------------------------------
465 : void
466 36680644 : Socket::
467 : printBufferOnVerbose(const std::vector<unsigned char> buffer, const std::string &label)
468 : const
469 : {
470 36680644 : if (verbose_)
471 : {
472 0 : 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 0 : for (std::vector<unsigned char>::const_iterator it = buffer.begin(); end != it; ++it)
476 0 : std::cerr << " " << static_cast<int>(*it) << " ";
477 : std::cerr << "]" << std::endl;
478 : }
479 36680644 : }
480 :
481 :
482 : // ----------------------------------------------------------------------
483 : std::vector<unsigned char>
484 0 : Socket::
485 : receive(int bufSize)
486 : {
487 : std::vector<unsigned char> buffer;
488 :
489 0 : if( socket_ < 0 )
490 0 : connect();
491 :
492 0 : if( !datawaiting( socket_) )
493 : return buffer;
494 :
495 0 : buffer.resize(bufSize);
496 0 : const size_t bytesReceived = recvAndCheck(&buffer[0], bufSize);
497 :
498 0 : buffer.resize(bytesReceived);
499 :
500 0 : printBufferOnVerbose(buffer, "Rcvd");
501 :
502 0 : return buffer;
503 0 : }
504 :
505 : // ----------------------------------------------------------------------
506 :
507 :
508 : bool
509 18340326 : Socket::
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 18340326 : std::vector<unsigned char> buffer(lengthLen);
516 :
517 : // receive length of TraCI message
518 18340326 : receiveComplete(&buffer[0], lengthLen);
519 18340300 : Storage length_storage(&buffer[0], lengthLen);
520 18340300 : const int totalLen = length_storage.readInt();
521 : assert(totalLen > lengthLen);
522 :
523 : // extent buffer
524 18340300 : buffer.resize(totalLen);
525 :
526 : // receive remaining TraCI message
527 18340300 : receiveComplete(&buffer[lengthLen], totalLen - lengthLen);
528 :
529 : // copy message content into passed Storage
530 18340300 : msg.reset();
531 18340300 : msg.writePacket(&buffer[lengthLen], totalLen - lengthLen);
532 :
533 18340300 : printBufferOnVerbose(buffer, "Rcvd Storage with");
534 :
535 18340300 : return true;
536 18340326 : }
537 :
538 :
539 : // ----------------------------------------------------------------------
540 : bool
541 646277 : Socket::
542 : has_client_connection()
543 : const
544 : {
545 646277 : return socket_ >= 0;
546 : }
547 :
548 : // ----------------------------------------------------------------------
549 : bool
550 0 : Socket::
551 : is_blocking()
552 : {
553 0 : 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 : *-----------------------------------------------------------------------*/
|