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