SUMO - Simulation of Urban MObility
|
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 *-----------------------------------------------------------------------*/