SUMO - Simulation of Urban MObility

socket.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002  ** This file is part of the network simulator Shawn.                  **
00003  ** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project  **
00004  ** Shawn is free software; you can redistribute it and/or modify it   **
00005  ** under the terms of the BSD License. Refer to the shawn-licence.txt **
00006  ** file in the root of the Shawn source tree for further details.     **
00007  ************************************************************************/
00008 
00009 #ifdef SHAWN
00010     #include <apps/tcpip/socket.h>
00011     #include <sys/simulation/simulation_controller.h>
00012 #else
00013     #include "socket.h"
00014 #endif
00015 
00016 #ifdef BUILD_TCPIP
00017 
00018 
00019 #ifndef WIN32
00020     #include <sys/types.h>
00021     #include <sys/socket.h>
00022     #include <netinet/in.h>
00023     #include <netinet/tcp.h>
00024     #include <arpa/inet.h>
00025     #include <netdb.h>
00026     #include <errno.h>
00027     #include <fcntl.h>
00028 #else
00029     #ifdef ERROR
00030         #undef ERROR
00031     #endif
00032 
00033     #include <winsock2.h>
00034 
00035     #ifndef vsnprintf
00036         #define vsnprintf _vsnprintf
00037     #endif
00038 
00039 #endif
00040 
00041 #include <cstdio>
00042 #include <cstring>
00043 #include <cstdarg>
00044 #include <cassert>
00045 #include <string>
00046 #include <vector>
00047 #include <string>
00048 #include <algorithm>
00049 #include <string.h>
00050 
00051 using namespace std;
00052 
00053 
00054 #ifdef SHAWN
00055     extern "C" void init_tcpip( shawn::SimulationController& sc )
00056     {
00057             // std::cout << "tcpip init" << std::endl;
00058     }
00059 #endif
00060 
00061 namespace tcpip
00062 {
00063     const int Socket::lengthLen = 4;
00064 
00065 #ifdef WIN32
00066     bool Socket::init_windows_sockets_ = true;
00067     bool Socket::windows_sockets_initialized_ = false;
00068     int Socket::instance_count_ = 0;
00069 #endif
00070 
00071     // ----------------------------------------------------------------------
00072     Socket::
00073         Socket(std::string host, int port) 
00074         : host_( host ),
00075         port_( port ),
00076         socket_(-1),
00077         server_socket_(-1),
00078         blocking_(true),
00079         verbose_(false)
00080     {
00081         init();
00082     }
00083 
00084     // ----------------------------------------------------------------------
00085     Socket::
00086 		Socket(int port) 
00087         : host_(""),
00088         port_( port ),
00089         socket_(-1),
00090         server_socket_(-1),
00091         blocking_(true),
00092         verbose_(false)
00093     {
00094         init();
00095     }
00096 
00097     // ----------------------------------------------------------------------
00098     void
00099         Socket::
00100 		init()
00101     {
00102 #ifdef WIN32
00103         instance_count_++;
00104 
00105         if( init_windows_sockets_ && !windows_sockets_initialized_ )
00106         {
00107             WSAData wsaData;
00108             if( WSAStartup(MAKEWORD(1, 1), &wsaData) != 0 )
00109                 BailOnSocketError("Unable to init WSA Sockets");
00110             windows_sockets_initialized_ = true;
00111         }
00112 #endif
00113     }
00114 
00115     // ----------------------------------------------------------------------
00116     Socket::
00117 		~Socket()
00118     {
00119         // Close first an existing client connection ...
00120         close();
00121 #ifdef WIN32
00122         instance_count_--;
00123 #endif
00124 
00125         // ... then the server socket
00126         if( server_socket_ >= 0 )
00127         {
00128 #ifdef WIN32
00129             ::closesocket( server_socket_ );
00130 #else
00131 			::close( server_socket_ );
00132 #endif
00133             server_socket_ = -1;
00134         }
00135 
00136 #ifdef WIN32
00137         if( server_socket_ == -1 && socket_ == -1 
00138             && init_windows_sockets_ && instance_count_ == 0 )
00139                 WSACleanup();
00140                 windows_sockets_initialized_ = false;
00141 #endif
00142     }
00143 
00144     // ----------------------------------------------------------------------
00145     void 
00146         Socket::
00147 		BailOnSocketError( std::string context) 
00148         const throw( SocketException )
00149     {
00150 #ifdef WIN32
00151         int e = WSAGetLastError();
00152         std::string msg = GetWinsockErrorString( e );
00153 #else
00154         std::string msg = strerror( errno );
00155 #endif
00156         throw SocketException( context + ": " + msg );
00157     }
00158 
00159     // ----------------------------------------------------------------------
00160     int  
00161         Socket::
00162 		port()
00163     {
00164         return port_;
00165     }
00166 
00167 
00168     // ----------------------------------------------------------------------
00169     bool 
00170         Socket::
00171 		datawaiting(int sock) 
00172         const throw()
00173     {
00174         fd_set fds;
00175         FD_ZERO( &fds );
00176         FD_SET( sock, &fds );
00177 
00178         struct timeval tv;
00179         tv.tv_sec = 0;
00180         tv.tv_usec = 0;
00181 
00182         int r = select( sock+1, &fds, NULL, NULL, &tv);
00183 
00184         if (r < 0)
00185             BailOnSocketError("tcpip::Socket::datawaiting @ select");
00186 
00187         if( FD_ISSET( sock, &fds ) )
00188             return true;
00189         else
00190             return false;
00191     }
00192 
00193     // ----------------------------------------------------------------------
00194     bool
00195         Socket::
00196 		atoaddr( std::string address, struct in_addr& addr)
00197     {
00198         struct hostent* host;
00199         struct in_addr saddr;
00200 
00201         // First try nnn.nnn.nnn.nnn form
00202         saddr.s_addr = inet_addr(address.c_str());
00203         if (saddr.s_addr != static_cast<unsigned int>(-1)) 
00204         {
00205             addr = saddr;
00206             return true;
00207         }
00208 
00209         host = gethostbyname(address.c_str());
00210         if( host ) {
00211             addr = *((struct in_addr*)host->h_addr_list[0]);
00212             return true;
00213         }
00214 
00215         return false;
00216     }
00217 
00218 
00219     // ----------------------------------------------------------------------
00220     void 
00221         Socket::
00222 		accept()
00223         throw( SocketException )
00224     {
00225         if( socket_ >= 0 )
00226             return;
00227 
00228         struct sockaddr_in client_addr;
00229 #ifdef WIN32
00230         int addrlen = sizeof(client_addr);
00231 #else
00232         socklen_t addrlen = sizeof(client_addr);
00233 #endif
00234 
00235         if( server_socket_ < 0 )
00236         {
00237             struct sockaddr_in self;
00238 
00239             //Create the server socket
00240             server_socket_ = static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
00241             if( server_socket_ < 0 )
00242                 BailOnSocketError("tcpip::Socket::accept() @ socket");
00243             
00244             //"Address already in use" error protection
00245             {
00246                 int reuseaddr = 1;
00247 
00248                 #ifdef WIN32
00249                     //setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, sizeof(reuseaddr));
00250                     // No address reuse in Windows!!!
00251                 #else
00252                     setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
00253                 #endif
00254             }
00255 
00256             // Initialize address/port structure
00257             memset(&self, 0, sizeof(self));
00258             self.sin_family = AF_INET;
00259             self.sin_port = htons(port_);
00260             self.sin_addr.s_addr = htonl(INADDR_ANY);
00261 
00262             // Assign a port number to the socket
00263             if ( bind(server_socket_, (struct sockaddr*)&self, sizeof(self)) != 0 )
00264                 BailOnSocketError("tcpip::Socket::accept() Unable to create listening socket");
00265 
00266 
00267             // Make it a "listening socket"
00268             if ( listen(server_socket_, 10) == -1 )
00269                 BailOnSocketError("tcpip::Socket::accept() Unable to listen on server socket");
00270 
00271             // Make the newly created socket blocking or not
00272             set_blocking(blocking_);
00273         }
00274 
00275         socket_ = static_cast<int>(::accept(server_socket_, (struct sockaddr*)&client_addr, &addrlen));
00276 
00277         if( socket_ >= 0 )
00278         {
00279             int x = 1;
00280             setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
00281         }
00282     }
00283 
00284     // ----------------------------------------------------------------------
00285     void 
00286         Socket::
00287 		set_blocking(bool blocking) 
00288         throw(SocketException )
00289     {
00290         blocking_ = blocking;
00291 
00292         if( server_socket_ > 0 )
00293         {
00294 #ifdef WIN32
00295             ULONG NonBlock = blocking_ ? 0 : 1;
00296             if (ioctlsocket(server_socket_, FIONBIO, &NonBlock) == SOCKET_ERROR)
00297                 BailOnSocketError("tcpip::Socket::set_blocking() Unable to initialize non blocking I/O");
00298 #else
00299             long arg = fcntl(server_socket_, F_GETFL, NULL);
00300             if (blocking_)
00301             {
00302                 arg &= ~O_NONBLOCK;
00303             } else {
00304                 arg |= O_NONBLOCK;
00305             }
00306             fcntl(server_socket_, F_SETFL, arg);
00307 #endif
00308         }
00309     
00310     }
00311 
00312     // ----------------------------------------------------------------------
00313     void 
00314         Socket::
00315 		connect()
00316         throw( SocketException )
00317     {
00318         in_addr addr;
00319         if( !atoaddr( host_.c_str(), addr) )
00320             BailOnSocketError("tcpip::Socket::connect() @ Invalid network address");
00321 
00322         sockaddr_in address;
00323         memset( (char*)&address, 0, sizeof(address) );
00324         address.sin_family = AF_INET;
00325         address.sin_port = htons( port_ );
00326         address.sin_addr.s_addr = addr.s_addr;
00327 
00328         socket_ = static_cast<int>(socket( PF_INET, SOCK_STREAM, 0 ));
00329         if( socket_ < 0 )
00330             BailOnSocketError("tcpip::Socket::connect() @ socket");
00331 
00332         if( ::connect( socket_, (sockaddr const*)&address, sizeof(address) ) < 0 )
00333             BailOnSocketError("tcpip::Socket::connect() @ connect");
00334 
00335         if( socket_ >= 0 )
00336         {
00337             int x = 1;
00338             setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
00339         }
00340 
00341     }
00342 
00343     // ----------------------------------------------------------------------
00344     void 
00345         Socket::
00346 		close()
00347     {
00348         // Close client-connection 
00349         if( socket_ >= 0 )
00350         {
00351 #ifdef WIN32
00352             ::closesocket( socket_ );
00353 #else
00354 			::close( socket_ );
00355 #endif
00356 
00357             socket_ = -1;
00358         }
00359     }
00360 
00361     // ----------------------------------------------------------------------
00362     void 
00363         Socket::
00364 		send( const std::vector<unsigned char> &buffer)
00365         throw( SocketException )
00366     {
00367         if( socket_ < 0 )
00368             return;
00369 
00370         printBufferOnVerbose(buffer, "Send");
00371 
00372         size_t numbytes = buffer.size();
00373         unsigned char const *bufPtr = &buffer[0];
00374         while( numbytes > 0 )
00375         {
00376 #ifdef WIN32
00377             int bytesSent = ::send( socket_, (const char*)bufPtr, static_cast<int>(numbytes), 0 );
00378 #else
00379             int bytesSent = ::send( socket_, bufPtr, numbytes, 0 );
00380 #endif
00381             if( bytesSent < 0 )
00382                 BailOnSocketError( "send failed" );
00383 
00384             numbytes -= bytesSent;
00385             bufPtr += bytesSent;
00386         }
00387     }
00388 
00389 
00390 
00391     // ----------------------------------------------------------------------
00392 
00393     void
00394         Socket::
00395 		sendExact( const Storage &b)
00396         throw( SocketException )
00397     {
00398         int length = static_cast<int>(b.size());
00399         Storage length_storage;
00400         length_storage.writeInt(lengthLen + length);
00401 
00402         // Sending length_storage and b independently would probably be possible and
00403         // avoid some copying here, but both parts would have to go through the
00404         // TCP/IP stack on their own which probably would cost more performance.
00405         vector<unsigned char> msg;
00406         msg.insert(msg.end(), length_storage.begin(), length_storage.end());
00407         msg.insert(msg.end(), b.begin(), b.end());
00408         send(msg);
00409     }
00410 
00411 
00412     // ----------------------------------------------------------------------
00413     size_t
00414         Socket::
00415 		recvAndCheck(unsigned char * const buffer, std::size_t len)
00416         const
00417     {
00418 #ifdef WIN32
00419         const int bytesReceived = recv( socket_, (char*)buffer, static_cast<int>(len), 0 );
00420 #else
00421         const int bytesReceived = static_cast<int>(recv( socket_, buffer, len, 0 ));
00422 #endif
00423         if( bytesReceived == 0 )
00424             throw SocketException( "tcpip::Socket::recvAndCheck @ recv: peer shutdown" );
00425         if( bytesReceived < 0 )
00426             BailOnSocketError( "tcpip::Socket::recvAndCheck @ recv" );
00427 
00428         return static_cast<size_t>(bytesReceived);
00429     }
00430 
00431 
00432     // ----------------------------------------------------------------------
00433     void
00434         Socket::
00435 		receiveComplete(unsigned char * buffer, size_t len)
00436         const
00437     {
00438         while (len > 0)
00439         {
00440             const size_t bytesReceived = recvAndCheck(buffer, len);
00441             len -= bytesReceived;
00442             buffer += bytesReceived;
00443         }
00444     }
00445 
00446 
00447     // ----------------------------------------------------------------------
00448     void
00449         Socket::
00450 		printBufferOnVerbose(const std::vector<unsigned char> buffer, const std::string &label)
00451         const
00452     {
00453         if (verbose_)
00454         {
00455             cerr << label << " " << buffer.size() <<  " bytes via tcpip::Socket: [";
00456             // cache end iterator for performance
00457             const vector<unsigned char>::const_iterator end = buffer.end();
00458             for (vector<unsigned char>::const_iterator it = buffer.begin(); end != it; ++it)
00459                 cerr << " " << static_cast<int>(*it) << " ";
00460             cerr << "]" << endl;
00461         }
00462     }
00463 
00464 
00465     // ----------------------------------------------------------------------
00466     vector<unsigned char> 
00467         Socket::
00468 		receive(int bufSize)
00469         throw( SocketException )
00470     {
00471         vector<unsigned char> buffer;
00472 
00473         if( socket_ < 0 )
00474             connect();
00475 
00476         if( !datawaiting( socket_) )
00477             return buffer;
00478 
00479         buffer.resize(bufSize);
00480         const size_t bytesReceived = recvAndCheck(&buffer[0], bufSize);
00481 
00482         buffer.resize(bytesReceived);
00483 
00484         printBufferOnVerbose(buffer, "Rcvd");
00485 
00486         return buffer;
00487     }
00488 
00489     // ----------------------------------------------------------------------
00490     
00491 
00492     bool
00493         Socket::
00494 		receiveExact( Storage &msg )
00495         throw( SocketException )
00496     {
00497         // buffer for received bytes
00498         // According to the C++ standard elements of a std::vector are stored
00499         // contiguously. Explicitly &buffer[n] == &buffer[0] + n for 0 <= n < buffer.size().
00500         vector<unsigned char> buffer(lengthLen);
00501 
00502         // receive length of TraCI message
00503         receiveComplete(&buffer[0], lengthLen);
00504         Storage length_storage(&buffer[0], lengthLen);
00505         const int totalLen = length_storage.readInt();
00506         assert(totalLen > lengthLen);
00507 
00508         // extent buffer
00509         buffer.resize(totalLen);
00510 
00511         // receive remaining TraCI message
00512         receiveComplete(&buffer[lengthLen], totalLen - lengthLen);
00513 
00514         // copy message content into passed Storage
00515         msg.reset();
00516         msg.writePacket(&buffer[lengthLen], totalLen - lengthLen);
00517         
00518         printBufferOnVerbose(buffer, "Rcvd Storage with");
00519 
00520         return true;
00521     }
00522     
00523     
00524     // ----------------------------------------------------------------------
00525     bool 
00526         Socket::
00527 		has_client_connection() 
00528         const
00529     {
00530         return socket_ >= 0;
00531     }
00532 
00533     // ----------------------------------------------------------------------
00534     bool 
00535         Socket::
00536 		is_blocking() 
00537         throw()
00538     {
00539         return blocking_;
00540     }
00541 
00542 
00543 #ifdef WIN32
00544     // ----------------------------------------------------------------------
00545     std::string 
00546         Socket::
00547         GetWinsockErrorString(int err) 
00548         const
00549     {
00550 
00551         switch( err)
00552         {
00553         case 0:                 return "No error";
00554         case WSAEINTR:          return "Interrupted system call";
00555         case WSAEBADF:          return "Bad file number";
00556         case WSAEACCES:         return "Permission denied";
00557         case WSAEFAULT:         return "Bad address";
00558         case WSAEINVAL:         return "Invalid argument";
00559         case WSAEMFILE:         return "Too many open sockets";
00560         case WSAEWOULDBLOCK:    return "Operation would block";
00561         case WSAEINPROGRESS:    return "Operation now in progress";
00562         case WSAEALREADY:       return "Operation already in progress";
00563         case WSAENOTSOCK:       return "Socket operation on non-socket";
00564         case WSAEDESTADDRREQ:   return "Destination address required";
00565         case WSAEMSGSIZE:       return "Message too long";
00566         case WSAEPROTOTYPE:     return "Protocol wrong type for socket";
00567         case WSAENOPROTOOPT:    return "Bad protocol option";
00568         case WSAEPROTONOSUPPORT:    return "Protocol not supported";
00569         case WSAESOCKTNOSUPPORT:    return "Socket type not supported";
00570         case WSAEOPNOTSUPP:     return "Operation not supported on socket";
00571         case WSAEPFNOSUPPORT:   return "Protocol family not supported";
00572         case WSAEAFNOSUPPORT:   return "Address family not supported";
00573         case WSAEADDRINUSE:     return "Address already in use";
00574         case WSAEADDRNOTAVAIL:  return "Can't assign requested address";
00575         case WSAENETDOWN:       return "Network is down";
00576         case WSAENETUNREACH:    return "Network is unreachable";
00577         case WSAENETRESET:      return "Net Socket reset";
00578         case WSAECONNABORTED:   return "Software caused tcpip::Socket abort";
00579         case WSAECONNRESET:     return "Socket reset by peer";
00580         case WSAENOBUFS:        return "No buffer space available";
00581         case WSAEISCONN:        return "Socket is already connected";
00582         case WSAENOTCONN:       return "Socket is not connected";
00583         case WSAESHUTDOWN:      return "Can't send after socket shutdown";
00584         case WSAETOOMANYREFS:   return "Too many references, can't splice";
00585         case WSAETIMEDOUT:      return "Socket timed out";
00586         case WSAECONNREFUSED:   return "Socket refused";
00587         case WSAELOOP:          return "Too many levels of symbolic links";
00588         case WSAENAMETOOLONG:   return "File name too long";
00589         case WSAEHOSTDOWN:      return "Host is down";
00590         case WSAEHOSTUNREACH:   return "No route to host";
00591         case WSAENOTEMPTY:      return "Directory not empty";
00592         case WSAEPROCLIM:       return "Too many processes";
00593         case WSAEUSERS:         return "Too many users";
00594         case WSAEDQUOT:         return "Disc quota exceeded";
00595         case WSAESTALE:         return "Stale NFS file handle";
00596         case WSAEREMOTE:        return "Too many levels of remote in path";
00597         case WSASYSNOTREADY:    return "Network system is unavailable";
00598         case WSAVERNOTSUPPORTED:    return "Winsock version out of range";
00599         case WSANOTINITIALISED: return "WSAStartup not yet called";
00600         case WSAEDISCON:        return "Graceful shutdown in progress";
00601         case WSAHOST_NOT_FOUND: return "Host not found";
00602         case WSANO_DATA:        return "No host data of that type was found";
00603         }
00604 
00605         return "unknown";
00606     }
00607 
00608 #endif // WIN32
00609 
00610 } // namespace tcpip
00611 
00612 #endif // BUILD_TCPIP
00613 
00614 /*-----------------------------------------------------------------------
00615 * Source  $Source: $
00616 * Version $Revision: 612 $
00617 * Date    $Date: 2011-06-14 15:16:52 +0200 (Di, 14. Jun 2011) $
00618 *-----------------------------------------------------------------------
00619 * $Log: $
00620 *-----------------------------------------------------------------------*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines