Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ippSocket.cpp

Go to the documentation of this file.
00001 // 
00002 // DISCLAIMER: 
00003 //  This software was produced by the National Institute of Standards 
00004 //  and Technology (NIST), an agency of the U.S. government, and by statute is 
00005 //  not subject to copyright in the United States.  Recipients of this 
00006 //  software assume all responsibility associated with its operation,
00007 //  modification,maintenance, and subsequent redistribution. 
00008 //
00009 //  See NIST Administration Manual 4.09.07 b and Appendix I. 
00010 //
00011 #include "stdafx.h"
00012 // Socket class implementation file
00013 #include "ippdme/Socket/ippSocket.h"
00014 #include "ippdme/assert.h"
00015 #include "ippdme/winsock.h"
00016 
00017 #pragma comment(lib,"wsock32.lib")
00018 #pragma comment(lib,"Ws2_32.lib") // because we use W32 WS extensions
00019 #include <iostream>
00020 using  namespace std;
00021 
00022 static void getErrorString(int* errCode,std::string& errMsg);
00023 
00024 class ippSocketImpVerification
00025 {
00026 public:
00027   ippSocketImpVerification()
00028   {
00029     IPP_ASSERT(ippSocket::SOCKET_OK == 0);
00030     IPP_ASSERT(ippSocket::SOCKET_WOULD_BLOCK == WSAEWOULDBLOCK);
00031     IPP_ASSERT(ippSocket::SOCKET_IS_CONNECTED == WSAEISCONN);
00032   }
00033 } assert;
00034 
00035 class ippSocketImp
00036 {
00037 public:
00038   ippSocketImp();
00039 
00040   LPHOSTENT   _lpHostEntry;
00041   SOCKET          _theSocket;
00042   SOCKADDR_IN _saServer;
00043   int         _portNumber; 
00044   WSAEVENT    _Event;      
00045   
00046   mutable std::string _lastErrorMsg;
00047   mutable int         _lastError;
00048   // 
00049   
00051   ippSocket::SERROR SetNonBlocking();
00052   
00054   ippSocket::SERROR SetHostName(const char *hostName);
00055 
00057   void SetPortNumber(int portNumber);
00058 
00059   ippSocket::SERROR Connect();
00060   ippSocket::SERROR CanSendData();
00061   ippSocket::SERROR Read(char* buffer,int nb);
00062   ippSocket::SERROR Write(const char *sendbuf);
00063   ippSocket::SERROR Ping();
00064   bool Listen(int portNumber);
00065   ippSocket::SERROR Accept(ippSocket& socket);
00066   void Close();
00067   bool Create();
00068 private:
00069   ippSocketImp(const ippSocketImp&);
00070   void operator=(const ippSocketImp&);
00071 
00072 };
00073 
00074 
00075 /*
00076  * ippSocket socket contructor
00077  */
00078 ippSocketImp::ippSocketImp() 
00079  : _theSocket(INVALID_SOCKET)
00080  , _lastError(0)
00081  , _lpHostEntry(0)
00082  , _portNumber(1294)
00083  , _Event(WSA_INVALID_EVENT)
00084 {
00085   memset(&_saServer,0,sizeof(_saServer));
00086 }
00087 
00088 
00089 
00090 ippSocket::ippSocket()
00091 :_imp(new ippSocketImp())
00092 {
00093 }
00094 /*
00095  * ippSocket socket destructor
00096  */
00097 ippSocket::~ippSocket()
00098 {  
00099         Close();
00100 }
00101 
00102 
00103 /*
00104  * set the socket non blocking
00105  */
00106 ippSocket::SERROR ippSocketImp::SetNonBlocking()
00107 {
00108         unsigned long arg = 1;
00109   if (ioctlsocket(_theSocket, FIONBIO, &arg)<0) {
00110           getErrorString(&_lastError,_lastErrorMsg);;
00111                 return (ippSocket::SERROR)_lastError;
00112   }     else  {
00113                 return (ippSocket::SERROR)0;
00114   }
00115         
00116 }
00117 
00118 /*
00119  *  Connect the socket
00120  */
00121 ippSocket::SERROR ippSocket::Connect(const char* hostname,int port)
00122 {
00123   IPP_ASSERT(IsValid());
00124 
00125   _imp->SetHostName(hostname);
00126   _imp->SetPortNumber(port);
00127   _imp->SetNonBlocking();
00128 
00129   return _imp->Connect();
00130 }
00131 
00132 ippSocket::SERROR ippSocketImp::Connect()
00133 {
00134         int nRet;
00135   linger lingerOption;
00136   lingerOption.l_onoff = 0;
00137   lingerOption.l_linger = 0;
00138   nRet = setsockopt(_theSocket,SOL_SOCKET,SO_LINGER,(char*)&lingerOption,sizeof(lingerOption));
00139   if (nRet ==SOCKET_ERROR) {
00140     getErrorString(&_lastError,_lastErrorMsg);
00141   }
00142 
00143 
00144         nRet = connect(_theSocket,                              // Socket
00145                                   (LPSOCKADDR)&_saServer,         // Server address
00146                                   sizeof(struct sockaddr));     // Length of server address structure
00147         
00148 
00149   if (nRet == SOCKET_ERROR) {
00150                 if (WSAEWOULDBLOCK == WSAGetLastError()){
00151       return ippSocket::SOCKET_WOULD_BLOCK;
00152     }
00153     getErrorString(&_lastError,_lastErrorMsg);
00154                 return ippSocket::SOCKET_OTHER_ERROR;
00155   } else {
00156                 return ippSocket::SOCKET_OK;
00157   }
00158 }
00159 
00160 /*
00161  *  check if the socket is capable of sending data.
00162  */
00163 ippSocket::SERROR ippSocket::CanSendData() 
00164 {
00165   return _imp->CanSendData();
00166 }
00167 
00168 ippSocket::SERROR ippSocketImp::CanSendData() 
00169 {
00170   fd_set w;
00171   FD_ZERO(&w);
00172   FD_SET(_theSocket,&w);
00173   fd_set e;
00174   FD_ZERO(&e);
00175   FD_SET(_theSocket,&e);
00176   timeval t;
00177   t.tv_sec =0;
00178   t.tv_usec = 0;
00179   int nRet = select(0,0,&w,&e,&t);
00180   switch(nRet) {
00181   case SOCKET_ERROR :
00182     // an error has occur
00183     getErrorString(&_lastError,_lastErrorMsg);
00184     return ippSocket::SOCKET_OTHER_ERROR;
00185     break;
00186   case 1:
00187     // the socket is ready to send data
00188     nRet = send(_theSocket,"",0,0);
00189     if (nRet!=0) {
00190       getErrorString(&_lastError,_lastErrorMsg);
00191       return ippSocket::SOCKET_OTHER_ERROR;
00192     }
00193     return ippSocket::SOCKET_OK;
00194     break;
00195   case 0:
00196     return ippSocket::SOCKET_WOULD_BLOCK;
00197   }
00198   getErrorString(&_lastError,_lastErrorMsg);
00199   return ippSocket::SOCKET_OTHER_ERROR;
00200 }
00201 
00202 
00203 
00204 /*
00205  *  read some text from the socket  ( up to nb char ) 
00206  *  returns 0 if the read has been successfull.
00207  *  
00208  */
00209 ippSocket::SERROR ippSocket::Read(char* buffer,int nb)
00210 {
00211   return _imp->Read(buffer,nb);
00212 }
00213 
00214 ippSocket::SERROR ippSocketImp::Read(char* buffer,int nb)
00215 {
00216 
00217   buffer[0]=0;
00218         int nRead = recv(_theSocket,                    // Connected socket
00219                               buffer,                           // Receive buffer
00220                                     nb,0
00221                                     );                                          // Flags
00222 
00223  buffer[nRead]=0;
00224  if (nRead == 0 ){ 
00225    // nothing to read 
00226    return ippSocket::SOCKET_OK;
00227  }
00228  if (nRead == SOCKET_ERROR) {
00229    if ( WSAEWOULDBLOCK == WSAGetLastError() ) {
00230      _lastError = WSAEWOULDBLOCK;
00231      return ippSocket::SOCKET_WOULD_BLOCK;
00232    } 
00233    getErrorString(&_lastError,_lastErrorMsg);
00234    Close();
00235    return ippSocket::SOCKET_OTHER_ERROR;                
00236   } else {
00237     return ippSocket::SOCKET_OK;
00238   }     
00239 }
00240 
00241 /*
00242  *  write some string from the socket  ( null terminated ) 
00243  *  returns 0 if the write operation has been successfull.
00244  *  
00245  */
00246 ippSocket::SERROR ippSocket::Write(const char *sendbuf)
00247 {
00248   return _imp->Write(sendbuf);
00249 }
00250 ippSocket::SERROR ippSocketImp::Write(const char *sendbuf)
00251 {
00252   //Write line out socket
00253         int nRet = send(_theSocket,     // Connected socket
00254                                           sendbuf,                                  // Data buffer
00255                                           strlen(sendbuf),              // Length of data
00256                                           0);                                                 // Flags
00257         
00258   if (nRet == SOCKET_ERROR) {
00259     getErrorString(&_lastError,_lastErrorMsg);
00260     return ippSocket::SOCKET_OTHER_ERROR;               
00261   } else {
00262     return ippSocket::SOCKET_OK;
00263   }
00264 }
00265 
00266 /* 
00267  * set the hostname 
00268  */
00269 ippSocket::SERROR ippSocketImp::SetHostName(const char *hostName)
00270 {
00271         _lpHostEntry = gethostbyname(hostName);
00272   if (_lpHostEntry == NULL) {
00273     return ippSocket::SOCKET_OTHER_ERROR;
00274   }
00275         else {
00276 
00277           _saServer.sin_family = AF_INET;
00278           _saServer.sin_addr = *((LPIN_ADDR)*_lpHostEntry->h_addr_list);
00279                                                                                   // ^ Server's address
00280     return ippSocket::SOCKET_OK;
00281         }
00282 }
00283 
00284 /* 
00285  * set the Port Number  
00286  */
00287 void ippSocketImp::SetPortNumber(int portNumber)
00288 {
00289         _portNumber = portNumber;
00290         _saServer.sin_port = htons(_portNumber);        
00291 
00292 }
00293 
00297 bool ippSocket::Create()
00298 {
00299   return _imp->Create();
00300 }
00301 
00302 bool InitSocket()
00303 {
00304                 // initialize Winsock library
00305                 WSADATA wsaData;
00306                 WORD wVersionRequested = MAKEWORD(1, 1);
00307                 int nResult = WSAStartup(wVersionRequested, &wsaData);
00308                 if (nResult != 0)
00309                         return false;
00310 
00311                 if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
00312                 {
00313                         WSACleanup();
00314                         return false;
00315                 }
00316     return true;
00317 }
00318 
00319 
00320 bool ippSocketImp::Create()
00321 {
00322   IPP_ASSERT(_theSocket==INVALID_SOCKET && "Socket already created");
00323 
00324   _theSocket = socket(AF_INET,                  // Address family
00325                                               SOCK_STREAM,              // Socket type
00326                                               IPPROTO_TCP); // Protocol
00327 
00328   if (_theSocket == INVALID_SOCKET) { 
00329     // need a startup !
00330     InitSocket();
00331     _theSocket = socket(AF_INET,                        // Address family
00332                                               SOCK_STREAM,              // Socket type
00333                                               IPPROTO_TCP); // Protocol
00334   }
00335 
00336   if (_theSocket == INVALID_SOCKET) { 
00337     return FALSE; // it fails !
00338   }
00339   //-------------------------
00340   // Create a new event
00341   _Event = WSACreateEvent();
00342   IPP_ASSERT(_Event!=WSA_INVALID_EVENT);
00343   //-------------------------
00344   // Associate event types FD_CLOSE
00345   // with the listening socket and _Event
00346   int nRet = WSAEventSelect(_theSocket, _Event, FD_CLOSE);
00347   IPP_ASSERT(nRet==0 && " SOCKET_ERROR ?");
00348 
00349   return _theSocket != INVALID_SOCKET;
00350 
00351 }
00352 
00353 
00357 void ippSocket::Close()
00358 {
00359   _imp->Close();
00360 }
00361 
00362 void ippSocketImp::Close()
00363 {
00364   if (_theSocket !=INVALID_SOCKET) { 
00365     shutdown(_theSocket,2);
00366     int nRet = closesocket(_theSocket);
00367     _theSocket =INVALID_SOCKET;
00368   }
00369   if (_Event!= WSA_INVALID_EVENT) { 
00370      BOOL bRet = WSACloseEvent(_Event);
00371      IPP_ASSERT(bRet);
00372      _Event = WSA_INVALID_EVENT;
00373   }
00374 }
00375 
00382 ippSocket::SERROR ippSocket::Ping()
00383 {
00384   return _imp->Ping();
00385 }
00386 
00387 ippSocket::SERROR ippSocketImp::Ping()
00388 {
00389   IPP_ASSERT(_Event!=WSA_INVALID_EVENT);
00390   UINT nRet =  WSAWaitForMultipleEvents(1,&_Event,TRUE,0,FALSE);
00391   IPP_ASSERT(nRet!=WSA_WAIT_FAILED);
00392   if (nRet == WSA_WAIT_TIMEOUT) { 
00393     return ippSocket::SOCKET_OK;
00394   }
00395   getErrorString(&_lastError,_lastErrorMsg);
00396   return  ippSocket::SOCKET_CONNECTION_ABORTED;
00397 }
00398 
00404 bool ippSocket::Initialize() 
00405 {
00406         WORD wVersionRequested = MAKEWORD(1,1);
00407         WSADATA wsaData;
00408         int nRet;
00409         //
00410         // Initialize WinSock and check the version
00411         //
00412         nRet = WSAStartup(wVersionRequested, &wsaData);
00413         if (wsaData.wVersion != wVersionRequested){     
00414           return false;
00415         }
00416   return true;
00417 }
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00429 bool ippSocket::Listen(int portNumber)
00430 {
00431   return _imp->Listen(portNumber);
00432 }
00433 
00434 bool ippSocketImp::Listen(int portNumber)
00435 {
00436   IPP_ASSERT(_theSocket == INVALID_SOCKET);
00437   _theSocket = socket(AF_INET,                  // Address family
00438                                                      SOCK_STREAM,               // Socket type
00439                                                      IPPROTO_TCP); // Protocol
00440 
00441 
00442   if(_theSocket == INVALID_SOCKET) {
00443     InitSocket();
00444     _theSocket = socket(AF_INET,                        // Address family
00445                                                        SOCK_STREAM,             // Socket type
00446                                                        IPPROTO_TCP); // Protocol
00447 
00448     if(_theSocket == INVALID_SOCKET) {
00449       getErrorString(&_lastError,_lastErrorMsg);
00450       IPP_ASSERT_FAIL("Cannot create socket");
00451       return false;
00452     }
00453   }
00454   _portNumber = portNumber;
00455         _saServer.sin_family = AF_INET;
00456         _saServer.sin_addr.s_addr = INADDR_ANY; // Let WinSock supply address
00457         _saServer.sin_port = htons(_portNumber); // Use port from GUI
00458         //
00459         // bind the name to the socket
00460         //
00461 
00462         int nRet = bind(_theSocket,                       // Socket 
00463                                 (LPSOCKADDR)&_saServer, // Our address
00464                                 sizeof(struct sockaddr));       // Size of address structure
00465         
00466         if (nRet == SOCKET_ERROR)
00467         {
00468     getErrorString(&_lastError,_lastErrorMsg);
00469     Close();
00470                 return false;
00471         }
00472 
00473         // Set socket to non-blocking
00474         unsigned long arg = 1;
00475         if (ioctlsocket(_theSocket, FIONBIO, &arg)<0)
00476         {
00477     getErrorString(&_lastError,_lastErrorMsg);
00478     Close();
00479                 return false;
00480         }
00481         // Set the socket to listen
00482         //
00483   
00484   int request_in_queue = 0;
00485   nRet = ::listen(_theSocket,request_in_queue);
00486   
00487         if (nRet == SOCKET_ERROR)       {
00488     getErrorString(&_lastError,_lastErrorMsg);
00489     Close();
00490                 return false;
00491         }
00492         
00493 
00494         char szBuf[1000] = "";
00495         nRet = gethostname(szBuf, sizeof(szBuf));
00496         if (nRet == SOCKET_ERROR)
00497         {
00498     int err = WSAGetLastError();
00499     Close();
00500     return false;
00501         }
00502 
00503 
00504   return true;
00505 }
00506 
00507 
00508 
00519 ippSocket::SERROR ippSocket::Accept(ippSocket& socket)
00520 {
00521   return _imp->Accept(socket);
00522 }
00523 
00524 ippSocket::SERROR ippSocketImp::Accept(ippSocket& socket)
00525 {
00526   IPP_ASSERT(!socket.IsValid());
00527 
00528         SOCKET  sock = accept(_theSocket,       // Listening socket
00529                                                           NULL,                           // Optional client address
00530                                                                 NULL);  
00531                 
00532         if (sock == INVALID_SOCKET){
00533     _lastError = WSAGetLastError();
00534                 if (WSAEWOULDBLOCK == _lastError ){
00535       return ippSocket::SOCKET_WOULD_BLOCK;                     
00536                 }       else {
00537                         getErrorString(&_lastError,_lastErrorMsg);;
00538       Close();
00539       return ippSocket::SOCKET_OTHER_ERROR;
00540                 }
00541         }
00542   socket._imp->_theSocket = sock;
00543   IPP_ASSERT(socket._imp->_Event==WSA_INVALID_EVENT);
00544   socket._imp->_Event = WSACreateEvent();
00545 
00546   //-------------------------
00547   // Associate event types FD_CLOSE
00548   // with the listening socket and _Event
00549   WSAEventSelect(socket._imp->_theSocket, socket._imp->_Event, FD_CLOSE);  
00550   
00551   return ippSocket::SOCKET_OK;
00552 }
00553 
00554 
00560 bool ippSocket::IsValid() const
00561 {
00562   return _imp->_theSocket!= INVALID_SOCKET;
00563 }
00564 
00565 
00566 void getErrorString(int* errCode,string& errMsg)
00572 {
00573         *errCode = WSAGetLastError();
00574   errMsg ="";
00575   switch(*errCode) {
00576          case WSANOTINITIALISED:
00577                 errMsg.append("Successful WSAStartup must occur before using this function."); 
00578     break;
00579    case WSAENETDOWN:
00580                 errMsg.append("The network subsystem or the associated service provider has failed.");
00581     break;
00582    case WSAEAFNOSUPPORT:
00583                 errMsg.append("The specified address family is not supported.");
00584     break;
00585    case WSAEINPROGRESS:
00586                 errMsg.append("A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.");
00587     break;
00588    case WSAEMFILE:
00589                 errMsg.append("No more socket descriptors are available.");
00590     break;
00591    case WSAENOBUFS:
00592                 errMsg.append("No buffer space is available. The socket cannot be created.");
00593     break;
00594    case  WSAEPROTONOSUPPORT:
00595                 errMsg.append("The specified protocol is not supported.");
00596     break;
00597    case WSAEPROTOTYPE:
00598                 errMsg.append("The specified protocol is the wrong type for this socket.");
00599     break;
00600    case WSAESOCKTNOSUPPORT:
00601                 errMsg.append("The specified socket type is not supported in this address family.");
00602     break;
00603    case WSAEINVAL:
00604                 errMsg.append("level is not valid, or the information in optval is not valid.");
00605     break;
00606    case WSAENETRESET:
00607                 errMsg.append("Connection has timed out when SO_KEEPALIVE is set.");
00608     break;
00609    case WSAENOPROTOOPT:
00610                 errMsg.append("The option is unknown or unsupported for the specified provider or socket (see SO_GROUP_PRIORITY limitations).");
00611     break;
00612    case WSAENOTCONN:
00613                 errMsg.append("Connection has been reset when SO_KEEPALIVE is set.");
00614     break;
00615    case WSAENOTSOCK:
00616                 errMsg.append("The descriptor is not a socket.");
00617     break;
00618    case WSAEADDRINUSE:
00619                 errMsg.append("A process on the machine is already bound to the same\n");
00620                 errMsg.append("fully-qualified address and the socket has not been marked\n"); 
00621                 errMsg.append("to allow address re-use with SO_REUSEADDR. For example,\n");
00622                 errMsg.append("IP address and port are bound in the af_inet case");
00623     break;
00624    case WSAEWOULDBLOCK:
00625      errMsg.append("WSAEWOULDBLOCK");
00626     break;
00627    case WSAECONNABORTED:
00628      errMsg.append("Connection aborted");
00629     break;
00630         default:
00631           errMsg.append("unknown problems!");
00632   }
00633 }
00634 
00635 
00636 IPPDME_EXT_CLASS void ippSleep(int time_in_milisecond)
00637 {
00638   ::Sleep(time_in_milisecond);
00639 }

Generated on Wed Nov 8 00:20:06 2006 for IPPDME by  doxygen 1.4.1