|
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 #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 *-----------------------------------------------------------------------*/