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