Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

socket_ew_common.c

Go to the documentation of this file.
00001 
00002 /*
00003  *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
00004  *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
00005  *
00006  *    $Id: socket__ew__common_8c-source.html 2161 2006-05-19 16:55:03Z paulf $
00007  *
00008  *    Revision history:
00009  *     $Log$
00009  *     Revision 1.1  2006/05/19 16:55:02  paulf
00009  *     first inclusion
00009  *
00010  *     Revision 1.4  2000/12/01 23:48:54  lombard
00011  *     Fixed a few more logit format errors.
00012  *
00013  *     Revision 1.3  2000/07/10 21:14:51  lombard
00014  *     Fixed bug in recvfrom_ew where improper arguments were used in recvfrom calls
00015  *
00016  *     Revision 1.2  2000/06/28 17:17:54  lombard
00017  *     Fixed bug in format for logit calls after select errors, several places
00018  *
00019  *     Revision 1.1  2000/02/14 18:51:48  lucky
00020  *     Initial revision
00021  *
00022  *
00023  */
00024 
00025 /****************** socket_ew_common *************************/
00026 
00027 /*
00028  * Changes:
00029  * 12/7/1999, PNL
00030  * Accept_ew now sets the new socket to non-blocking mode.
00031  *  Previously it was assumed that the new socket inherited non-blocking
00032  *  from the original socket; this is not true in WinNT or Solaris 2.6.
00033  * Errors from select() calls are now handled.
00034  */
00035 /********************* #INCLUDES *****************************/
00036 /*************************************************************/
00037 #include <errno.h>
00038 #include <socket_ew.h>
00039 
00040 /********************** GLOBAL *******************************/
00041 /********************* VARIABLES *****************************/
00042 /*************************************************************/
00043 /* Timeout used for select() calls: 0.2 seconds */
00044 int SELECT_TIMEOUT_SECONDS=0;
00045 int SELECT_TIMEOUT_uSECONDS=200000;
00046 
00047 int EW_SOCKET_DEBUG=0;       /* Set by setSocket_ewDebug() */
00048 
00049 extern int SOCKET_SYS_INIT;  /* Global initialization flag.
00050                                 Declared in sys-dependent socket_ew.c,
00051                                 set in SocketSysInit(), 
00052                                 checked in socket_ew()  */
00053 
00054 /********************* SOCKET_ew *****************************/
00055 /*********** Internal Utility Function Prototypes ************/
00056 /*************************************************************/
00057 struct timeval FAR * resetTimeout(struct timeval FAR *);
00058 Time_ew adjustTimeoutLength(int timeout_msec);
00059 
00060 
00061 /********************* SOCKET_ew *****************************/
00062 /********************* Functions *****************************/
00063 /*************************************************************/
00064 
00065 SOCKET socket_ew (int af, int type, int protocol)
00066 {
00067   /* socket_ew() allocates a socket descriptor and associated 
00068      resources. It first makes sure that the Socket system has 
00069      been initialized, then it calls socket(), and finally sets 
00070      the socket descriptor to non-blocking mode.
00071      Arguments af, type and protocol are passed directly to socket().
00072      No network I/O occurs.
00073      Caller can call socketGetError_ew() for details about any 
00074      failures.
00075   */
00076 
00077   SOCKET newSocket;
00078   static char * MyFuncName = "socket_ew()";
00079   int retVal;
00080   unsigned long lOnOff=1;
00081 
00082   if (EW_SOCKET_DEBUG)
00083     logit("et","Entering %s\n",MyFuncName);
00084 
00085   if (!SOCKET_SYS_INIT)
00086     SocketSysInit();
00087 
00088   newSocket = socket(af,type,protocol);
00089   if (newSocket == INVALID_SOCKET  && EW_SOCKET_DEBUG)
00090     logit("et","Error: %d, occurred in %s\n",
00091           socketGetError_ew(),MyFuncName);
00092   
00093   if (newSocket != INVALID_SOCKET)
00094   {
00095     retVal=ioctlsocket(newSocket,FIONBIO,&lOnOff);
00096     if (retVal==SOCKET_ERROR)
00097     {
00098       if(EW_SOCKET_DEBUG)
00099         logit("et","Error: %d, occurred in %s during change to non-blocking\n",
00100               socketGetError_ew(),MyFuncName);
00101       closesocket(newSocket);
00102       return(SOCKET_ERROR);
00103     }
00104   }
00105   
00106   if(EW_SOCKET_DEBUG)
00107     logit("et","Exiting %s\n",MyFuncName);
00108   return(newSocket);
00109 }
00110 
00111 /*************************************************************/
00112 
00113 int connect_ew(SOCKET s, struct sockaddr FAR* name, 
00114                int namelen, int timeout_msec)
00115 {
00116   /* connect_ew() attempts to create a socket connection during a
00117    * period specified by timeout.  
00118    * Arguments s, name, and namelenare passed directly to connect().
00119    * On success conect_ew() returns zero.
00120    * On failure, either due to a network error, or a timeout, conect_ew
00121    * closes the socket and returns SOCKET_ERROR.
00122    * *Note:  The timeout clock starts after connect_ew() calls
00123    * connect(), not when connect_ew() starts.
00124    * A timeout value of -1 causes connect_ew() to revert to a blocking
00125    * connect call.
00126    * Caller can call socketGetError_ew() for details about any 
00127    * failures.
00128    */
00129 
00130    static char * MyFuncName = "connect_ew()";
00131 
00132    int     retVal, ioctlRetVal, connectRetVal, selectRetVal;
00133    fd_set  ConnectedSockets;
00134    long    lOnOff;
00135    int     lastError;
00136    struct  timeval SelectTimeout;
00137    
00138   if ( EW_SOCKET_DEBUG )
00139     logit( "et" , "Entering %s\n", MyFuncName );
00140 
00141 /* If there is no timeout, make the socket blocking
00142    ************************************************/
00143    if ( timeout_msec == -1 )
00144    {
00145      lOnOff = 0;
00146      ioctlRetVal = ioctlsocket( s, FIONBIO, &lOnOff );
00147      if ( ioctlRetVal < 0 )
00148      {
00149        if ( EW_SOCKET_DEBUG )
00150          logit( "et", "Error: %d, occurred in %s during change to blocking\n",
00151                 socketGetError_ew(), MyFuncName );
00152        retVal = -1;
00153        goto Done;
00154      }
00155 
00156 /* Try to get a connection (blocking)
00157  **********************************/
00158      if ( connect( s, name, namelen ) == 0 )     /* Got a connection */
00159        retVal = 0;
00160      else                                        /* Didn't get a connection */
00161        retVal = -1;
00162      
00163 /* Change the socket back to non-blocking so
00164    we don't screw up any further operations
00165    *****************************************/
00166       lOnOff = 1;
00167       ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00168       if ( ioctlRetVal < 0 )
00169       {
00170         logit( "et", "Error: %d, occurred in %s during change to non-blocking\n",
00171                socketGetError_ew(), MyFuncName );
00172         retVal = -1;
00173       }
00174       goto Done;
00175    }
00176    
00177 /* Initiate a non-blocking connection request
00178    ******************************************/
00179    connectRetVal = connect( s, name, namelen );
00180 
00181    if ( connectRetVal == 0 )                         /* Got a connection */
00182    {
00183       retVal = 0;
00184       goto Done;
00185    }
00186 
00187    lastError = socketGetError_ew();
00188 
00189    if ( lastError != CONNECT_WOULDBLOCK_EW )         /* Connect() error */
00190    {
00191      logit( "et", "Connect request failed in connect_ew(): %s.\n",
00192             strerror(lastError) );
00193      retVal = -1;
00194      goto Done;
00195    }
00196 
00197 /* Hang around in select() until connect is successful
00198                         or until timeout period expires
00199    ****************************************************/
00200    FD_ZERO( &ConnectedSockets );
00201    FD_SET( s, &ConnectedSockets );
00202 
00203    SelectTimeout.tv_sec  = timeout_msec/1000;
00204    SelectTimeout.tv_usec = (timeout_msec%1000)*1000;
00205 
00206    selectRetVal = select( s+1, 0, &ConnectedSockets, 0, &SelectTimeout );
00207 
00208 /* select() failed 
00209    ***************/
00210    if ( selectRetVal == -1 )                           
00211    {
00212      logit( "et", "select() failed in connect_ew(). Error: %d\n",
00213             socketGetError_ew() );
00214      retVal = -1;
00215    }
00216 
00217 /* select() succeeded; connection may have been completed
00218    ******************************************************/
00219    else if ( selectRetVal > 0  &&  FD_ISSET( s, &ConnectedSockets ) )  
00220    {                                             
00221    /* NOTE: For Solaris, we must do one more connection test.
00222     *       Other possible tests besides getsockopt(SO_ERROR) could 
00223     *       be a zero-length read() or a call to getpeername() 
00224     */    
00225      int error, len, rc;
00226      error = 0;
00227      len = sizeof(error);
00228      rc  = getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&error, &len); 
00229      
00230      if ( rc < 0 )          /* Pending error on some systems  */
00231      {
00232        error = socketGetError_ew(); 
00233        retVal = -1;
00234      }
00235      else if ( error )      /* Pending error on others systems */
00236      {
00237        retVal = -1;
00238      }
00239      else                   /* OK, got a connection! */
00240      {
00241        if ( EW_SOCKET_DEBUG ) 
00242          logit( "et", "Got a connection\n" );
00243        retVal = 0;
00244      }
00245 
00246      if ( retVal == -1  &&  EW_SOCKET_DEBUG ) 
00247        logit("et", "connect_ew() connection failed; "
00248              "getsockopt detected error: %s.\n", 
00249              strerror(error) ); 
00250    }
00251 
00252 /* Only other possibility: select timed out! 
00253    *****************************************/
00254    else
00255    {
00256      if ( EW_SOCKET_DEBUG ) /* this line added by Alex 2/9/99 */
00257        logit( "et", "connect timed out in connect_ew().\n" );
00258      retVal = -1;
00259    }
00260    
00261 Done:
00262    if ( retVal == -1 )
00263    {
00264      closesocket_ew( s, SOCKET_CLOSE_SIMPLY_EW ); /*skip setsockopt()*/
00265      retVal = SOCKET_ERROR;
00266    }
00267    
00268    if ( EW_SOCKET_DEBUG )
00269      logit("et","Exiting %s\n",MyFuncName);
00270    
00271    return(retVal);
00272 }
00273 
00274 /*************************************************************/
00275 
00276 int bind_ew (SOCKET s, struct sockaddr FAR* name, int namelen )
00277 {
00278   /* bind_ew() attempts to bind the socket s to a name/port number.
00279      This is basicly same as normal bind() call, with some logging added.
00280      Caller can call socketGetError_ew() for details about any failures.  
00281   */
00282 
00283   int retVal;
00284   static char * MyFuncName = "bind_ew()";
00285 
00286   if(EW_SOCKET_DEBUG)
00287     logit("et","Entering %s\n",MyFuncName);
00288 
00289   retVal=bind(s,name,namelen);
00290   if (retVal < 0  && EW_SOCKET_DEBUG)
00291     logit("et","Error: %d, occurred in %s\n",
00292           socketGetError_ew(),MyFuncName);
00293   
00294   if(EW_SOCKET_DEBUG)
00295     logit("et","Exiting %s\n",MyFuncName);
00296 
00297   return(retVal);
00298 }
00299 
00300 /*************************************************************/
00301 
00302 int listen_ew (SOCKET s, int backlog ) 
00303 {
00304   /* listen_ew() signals the mysterious protocol stack god, that the
00305      socket is ready to accept connections.
00306      Arguments are passed directly to listen().
00307      Caller can call socketGetError_ew() for details about any failures.  
00308   */
00309 
00310   int retVal;
00311   static char * MyFuncName = "listen_ew()";
00312 
00313   if(EW_SOCKET_DEBUG)
00314     logit("et","Entering %s\n",MyFuncName);
00315 
00316   retVal=listen(s, backlog);
00317   if (retVal < 0  && EW_SOCKET_DEBUG)
00318     logit("et","Error: %d, occurred in %s\n",
00319           socketGetError_ew(),MyFuncName);
00320 
00321   if(EW_SOCKET_DEBUG)
00322     logit("et","Exiting %s\n",MyFuncName);
00323 
00324   return(retVal);
00325 }
00326 
00327 /*************************************************************/
00328 
00329 SOCKET accept_ew(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen,
00330                  int timeout_msec)
00331 {
00332   /* accept_ew() attempts to accept a connection on a socket.
00333      Arguments s, addr, addrlen are passed directly to accept(),
00334      timeout_msec: length of time in milliseconds that accept_ew() 
00335       will wait before returning. Timeout is measure from the
00336       point after the initial accept() call. 
00337      Pass timeout of -1 for accept_ew to revert to blocking 
00338       accept() call.
00339      If no connection is accepted before the timeout expires, 
00340       or if an error occurs, the function returns INVALID_SOCKET.  
00341      Caller can call socketGetError_ew() for details about 
00342      any failures. 
00343      If the latest socket error was WOULDBLOCK_EW, then 
00344       no connections were made during the timeout period.
00345   */
00346 
00347   SOCKET newSocket;
00348   static char * MyFuncName = "accept_ew()";
00349   Time_ew StartTime;
00350   fd_set AcceptedSockets;
00351   struct timeval SelectTimeout; 
00352   Time_ew timeout=adjustTimeoutLength(timeout_msec);
00353   int retVal;
00354   long lOnOff;
00355   int sel;
00356   
00357   if(EW_SOCKET_DEBUG)
00358     logit("et","Entering %s\n",MyFuncName);
00359 
00360   /* If there is no timeout, make the socket blocking */
00361   if(timeout_msec == -1)
00362   {
00363     lOnOff = 0;
00364     retVal=ioctlsocket(s,FIONBIO,&lOnOff);
00365     
00366     if (retVal < 0)
00367     {
00368       if(EW_SOCKET_DEBUG)
00369         logit("et","Error: %d, occurred in %s during change to blocking\n",
00370               socketGetError_ew(),MyFuncName);
00371       goto Abort;
00372     }
00373   }
00374 
00375   newSocket=accept(s,addr,addrlen);
00376   
00377   /* If there is no timeout, then the call was made blocking,
00378      change it back so that we don't screw up any further operations
00379   */
00380   if(timeout_msec == -1)
00381   {
00382     lOnOff = 1;
00383     retVal=ioctlsocket(s,FIONBIO,&lOnOff);
00384     if (retVal==SOCKET_ERROR)
00385     {
00386       if(EW_SOCKET_DEBUG)
00387         logit("et","Error: %d, occurred in %s during change to non-blocking\n",
00388               socketGetError_ew(),MyFuncName);
00389       goto Abort;
00390     }
00391   }
00392   
00393   if (newSocket == INVALID_SOCKET)
00394   {
00395     if (socketGetError_ew() == WOULDBLOCK_EW)
00396     {
00397       FD_ZERO(&AcceptedSockets);
00398       FD_SET(s,&AcceptedSockets);
00399       StartTime=GetTime_ew();
00400       while( (sel = select(s+1, &AcceptedSockets, 0, 0,
00401                            resetTimeout(&SelectTimeout))) == 0)
00402       { /* select timed out; if timeout hasn't expired, reset and try again */
00403         if ( GetTime_ew() - timeout > StartTime )
00404           return INVALID_SOCKET;
00405         
00406         FD_ZERO(&AcceptedSockets);
00407         FD_SET(s,&AcceptedSockets);
00408         sleep_ew(1000);  /* Sleep for a second, and then try again.*/
00409       }
00410       if (sel < 0 && EW_SOCKET_DEBUG)
00411       {
00412         logit("et", "Error %d occured during select() in %s\n",
00413               socketGetError_ew(), MyFuncName);
00414         goto Abort;
00415       }
00416       newSocket=accept(s,addr,addrlen);
00417     }
00418     if(newSocket == INVALID_SOCKET && EW_SOCKET_DEBUG)
00419     {
00420       logit("et","Error: %d, occurred in %s\n",
00421             socketGetError_ew(),MyFuncName);
00422     }
00423   }
00424   
00425   /* Set the new socket to non-blocking mode */
00426   lOnOff = 1;
00427   retVal = ioctlsocket(newSocket,FIONBIO,&lOnOff);
00428   if (retVal == SOCKET_ERROR)
00429   {
00430     if (EW_SOCKET_DEBUG)
00431       logit("et","Error: %d, occurred in %s setting new socket to non-blocking\n",
00432             socketGetError_ew(),MyFuncName);
00433     goto Abort;
00434   }
00435   return(newSocket);
00436 
00437 Abort:
00438   if (newSocket > 0) closesocket_ew(newSocket, 0);
00439   newSocket = INVALID_SOCKET;
00440   closesocket_ew(s, 0);
00441   s = INVALID_SOCKET;
00442   return(newSocket);
00443 }
00444 
00445 /*************************************************************/
00446 
00447 int recv_all (SOCKET s,char FAR* buf,int len,int flags, int timeout_msec)
00448 {
00449   /* recv_all attempts to receive data on a connection oriented scoket.
00450      buf:     buffer for incoming data, which must be provided by the caller
00451      len:     number of bytes to read; buffer must be at least len + 1 bytes.
00452      flags:   flags that are passed directly to recv().
00453      timeout: length of time in milliseconds that the recv_ew() will wait
00454      before returning(if no data is received), after making the initial recv()
00455      call.  
00456 
00457      If timeout_msec > 0, recv_all() returns when the sooner of two things
00458      happens: 
00459      1.  The timeout from the time of the first recv() call, expires; 
00460      2.  "len" bytes of data are received.
00461 
00462      recv_all() returns the number of bytes of data received, or SOCKET_ERROR
00463      on error.  The caller is responsible for noting any discrepencies in the
00464      difference between the number of bytes requested to be sent, and the
00465      number of reported bytes sent.  If there is a discrepency, then a timeout
00466      or error occured. Caller can call socketGetError_ew() for details about 
00467      any failures.
00468 
00469      If timeout_msec == -1, recv_all() sets the socket to blocking and returns
00470      when:
00471      1. "len" bytes of data are received.
00472      2. EOF is detected by recv returning 0 bytes.
00473      */
00474 
00475   int retVal,ioctlRetVal;
00476   static char * MyFuncName = "recv_all()";
00477   fd_set ReadableSockets;
00478   Time_ew StartTime;
00479   struct timeval SelectTimeout; 
00480   Time_ew timeout=adjustTimeoutLength(timeout_msec);
00481   int BytesToRecv = len;
00482   int BytesRcvd = 0;
00483   int BytesJustRcvd;
00484   long lOnOff;
00485   int sel;
00486   
00487   if(EW_SOCKET_DEBUG)
00488     logit("et","Entering %s\n",MyFuncName);
00489 
00490   /* If there is no timeout, make the socket blocking */
00491   if(timeout_msec == -1)
00492   {
00493     lOnOff = 0;
00494     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00495     if (ioctlRetVal==SOCKET_ERROR)
00496     {
00497       if(EW_SOCKET_DEBUG)
00498         logit("et","Error: %d, occurred in %s during change to blocking\n",
00499               socketGetError_ew(),MyFuncName);
00500       return ioctlRetVal;
00501     }
00502   }
00503 
00504   StartTime = GetTime_ew();
00505   while ( BytesRcvd < BytesToRecv )
00506   {
00507     if ( (timeout_msec > 0) && ((GetTime_ew() - timeout) > StartTime ))
00508     {  /* Time is up; return what we got */
00509       retVal = BytesRcvd;
00510       goto Done;
00511     }
00512     BytesJustRcvd = recv(s, buf + BytesRcvd, BytesToRecv - BytesRcvd, flags);
00513     if ( BytesJustRcvd == 0 )        /* apparently EOF */
00514     {
00515       retVal = BytesRcvd;
00516       goto Done;
00517     }
00518     if ( BytesJustRcvd < 0 ) /* Error happened */
00519     {
00520       if ( socketGetError_ew() == WOULDBLOCK_EW )
00521       {
00522         FD_ZERO(&ReadableSockets);
00523         FD_SET(s,&ReadableSockets);
00524         while( (sel = select(s+1, &ReadableSockets, 0, 0,
00525                        resetTimeout(&SelectTimeout))) == 0)
00526         { /* select timed out; if timeout hasn't expired, reset and try again */
00527           if ( GetTime_ew() - timeout > StartTime )
00528           {
00529             retVal = BytesRcvd;
00530             goto Done;
00531           }
00532           FD_ZERO(&ReadableSockets);
00533           FD_SET(s,&ReadableSockets);
00534           sleep_ew(100);  /* Wait a while, and then try
00535                              again */
00536         }
00537         if (sel < 0)
00538         {
00539           logit("et", "Error %d occured during select() in %s\n",
00540                 socketGetError_ew(), MyFuncName);
00541           retVal = BytesRcvd;
00542           goto Done;
00543         }
00544         
00545         /* Set BytesJustRcvd, so that we are not kicked out of the
00546            while loop because of a hard error on a recv.  Note: we
00547            will still be kicked out if we have exceeded the timeout.
00548         */
00549         BytesJustRcvd = 0;
00550       }
00551       else  /* some other error occured */
00552       {
00553         if(EW_SOCKET_DEBUG)
00554           logit("et","Error: %d, occurred in %s\n",
00555                 socketGetError_ew(),MyFuncName);
00556         retVal = BytesJustRcvd; /* the error condition */
00557         goto Done;
00558       }
00559     }  /* End of If there was an error on recv() */
00560     else
00561     {
00562       BytesRcvd += BytesJustRcvd;
00563     }
00564   }  /* End: while not all data sent */
00565   retVal = BytesRcvd;
00566   
00567  Done:
00568   /* If there is no timeout, then the call was made blocking,
00569      change it back so that we don't screw up any further operations
00570   */
00571   if(timeout_msec == -1)
00572   {
00573     lOnOff = 1;
00574     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00575     if (ioctlRetVal==SOCKET_ERROR)
00576     {
00577       if(EW_SOCKET_DEBUG)
00578         logit("et","Error: %d, occurred in %s during change to non-blocking\n",
00579               socketGetError_ew(),MyFuncName);
00580     }
00581   }
00582   
00583   if(EW_SOCKET_DEBUG)
00584     logit("et","Exiting %s\n",MyFuncName);
00585   
00586   return(retVal);
00587 }
00588 
00589 /*************************************************************/
00590 
00591 int recv_ew (SOCKET s, char FAR* buf, int len, int flags, int timeout_msec)
00592 {
00593   /* recv_ew attempts to receive data on a connection oriented scoket.
00594      buf:     buffer for incoming data, which must be provided by the caller
00595      len:     length of the buffer.
00596      flags:   flags that are passed directly to recv().
00597      timeout: length of time in milliseconds. that the recv_ew() will wait 
00598      before returning(if no data is received), after making
00599      the initial recv() call. If data (or a shutdown request) is not
00600      received before the timeout expires, or if an error occurs, the 
00601      function returns SOCKET_ERROR. As soon as any data is received, 
00602      the function returns; the function does not attempt to completely
00603      fill the buffer before returning.  
00604      Caller can call socketGetError_ew() for details about any failures.
00605      If the latest socket error is WOULDBLOCK_EW, then recv_ew timed out
00606      before receiving any data,
00607      
00608      If (-1) is passed for timeout_msec, then recv_ew() reverts to a blocking
00609      recv() call.
00610   */
00611 
00612   int retVal,ioctlRetVal;
00613   static char * MyFuncName = "recv_ew()";
00614   fd_set ReadableSockets;
00615   Time_ew StartTime;
00616   struct timeval SelectTimeout; 
00617   Time_ew timeout=adjustTimeoutLength(timeout_msec);
00618   long lOnOff;
00619   int sel;
00620   
00621   if(EW_SOCKET_DEBUG)
00622     logit("et","Entering %s\n",MyFuncName);
00623 
00624   /* If there is no timeout, make the socket blocking */
00625   if(timeout_msec == -1)
00626   {
00627     lOnOff = 0;
00628     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00629     if (ioctlRetVal==SOCKET_ERROR)
00630     {
00631       logit("et","Error: %d, occurred in %s during change to blocking\n",
00632             socketGetError_ew(),MyFuncName);
00633     }
00634   }
00635   retVal=recv(s,buf,len,flags);
00636   
00637   /* If there is no timeout, then the call was made blocking,
00638      change it back so that we don't screw up any further operations
00639   */
00640   if(timeout_msec == -1)
00641   {
00642     lOnOff = 1;
00643     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00644       if (ioctlRetVal==SOCKET_ERROR)
00645       {
00646         logit("et","Error: %d, occurred in %s during change to non-blocking\n",
00647               socketGetError_ew(),MyFuncName);
00648       }
00649   }
00650 
00651   /* Use select() to wait for something to read. We use a small time interval
00652    * (0.2 seconds) in select, and check the clock against timeout_msec (here
00653    * converted to seconds) in a while() loop.
00654    */
00655   if (retVal < 0 && socketGetError_ew() == WOULDBLOCK_EW)
00656   {
00657     FD_ZERO(&ReadableSockets);
00658     FD_SET(s,&ReadableSockets);
00659     StartTime=GetTime_ew();
00660     while( (sel = select(s+1, &ReadableSockets, 0, 0, 
00661                          resetTimeout(&SelectTimeout))) == 0 )
00662     {  /* select timed out; if timeout hasn't expired, reset and try again */
00663       
00664       if ( GetTime_ew() - timeout > StartTime )
00665         break;
00666       FD_ZERO(&ReadableSockets);
00667       FD_SET(s,&ReadableSockets);
00668       sleep_ew(100);  /* Wait a while, and then try again */
00669     }
00670     if (sel < 0)
00671     {
00672       logit("et", "Error %d occured during select() in %s\n",
00673             socketGetError_ew(), MyFuncName);
00674       return(SOCKET_ERROR);
00675     }
00676     /* Try to read, even if select() timed out */
00677     retVal=recv(s,buf,len,flags);
00678   }
00679 
00680   if(retVal <0  && EW_SOCKET_DEBUG)
00681   {
00682     if (sel == 0)
00683       logit("et", "Timeout occured in %s\n", MyFuncName);
00684     else
00685       logit("et","Error: %d, occurred in %s\n",
00686             socketGetError_ew(),MyFuncName);
00687   }
00688 
00689   if(EW_SOCKET_DEBUG)
00690                 logit("et","Exiting %s\n",MyFuncName);
00691 
00692   return(retVal);
00693 }
00694 
00695 /*************************************************************/
00696 
00697 int recvfrom_ew (SOCKET s, char FAR* buf, int len, int flags, 
00698                           struct sockaddr FAR* from, int FAR* fromlen,
00699                           int timeout_msec)
00700 {
00701 
00702   /* recvfrom_ew() is similar to recv_ew(), except used for datagram
00703      sockets.  timeout is specified in milliseconds.  Caller can call 
00704      socketGetError_ew() for details about any failures. 
00705   */
00706 
00707   int retVal, ioctlRetVal;
00708   static char * MyFuncName = "recvfrom_ew()";
00709   fd_set ReadableSockets;
00710   Time_ew StartTime;
00711   struct timeval SelectTimeout; 
00712   Time_ew timeout=adjustTimeoutLength(timeout_msec);
00713   long lOnOff;
00714   int sel, flen;
00715   
00716   if(EW_SOCKET_DEBUG)
00717     logit("et","Entering %s\n",MyFuncName);
00718 
00719 
00720   /* If there is no timeout, make the socket blocking */
00721   if(timeout_msec == -1)
00722   {
00723     lOnOff = 0;
00724     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00725     if (ioctlRetVal==SOCKET_ERROR)
00726     {
00727       logit("et","Error: %d, occurred in %s during change to blocking\n",
00728             socketGetError_ew(),MyFuncName);
00729       /* Should we return this error, or continue? */
00730     }
00731   }
00732   /* Use a local copy of fromlen (because recvfrom sets fromlen=0 if socket is
00733      non-blocking and there's no data => fromlen=0 input to second recvfrom) */
00734   flen = *fromlen;
00735   retVal = recvfrom(s,buf,len,flags,from,&flen);
00736 
00737   /* If there is no timeout, then the call was made blocking,
00738      change it back so that we don't screw up any further operations */
00739   if(timeout_msec == -1)
00740   {
00741     lOnOff = 1;
00742     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00743     if (ioctlRetVal==SOCKET_ERROR)
00744     {
00745       logit("et","Error: %d, occurred in %s during change to non-blocking\n",
00746             socketGetError_ew(),MyFuncName);
00747     }
00748   }
00749   
00750   if (retVal < 0 && socketGetError_ew() == WOULDBLOCK_EW)
00751   {
00752     FD_ZERO(&ReadableSockets);
00753     FD_SET(s,&ReadableSockets);
00754     StartTime=GetTime_ew();
00755     while( (sel = select(s+1, &ReadableSockets, 0, 0,
00756                          resetTimeout(&SelectTimeout))) == 0 )
00757     {  /* select timed out; if timeout hasn't expired, reset and try again */
00758       
00759       if ( GetTime_ew() - timeout > StartTime )
00760         break;
00761 
00762       FD_ZERO(&ReadableSockets);
00763       FD_SET(s,&ReadableSockets);
00764       sleep_ew(100);  /* Wait a while, and then try
00765                     again */
00766     }
00767     if (sel < 0)
00768     {
00769       logit("et", "Error %d occured during select() in %s\n",
00770             socketGetError_ew(), MyFuncName);
00771       return(SOCKET_ERROR);
00772     }
00773     /* Try to read, even if select() timed out */
00774     flen = *fromlen;
00775     retVal = recvfrom(s,buf,len,flags,from,&flen);
00776   }
00777 
00778   if(retVal <0  && EW_SOCKET_DEBUG)
00779   {
00780     logit("et","Error: %d, occurred in %s\n",
00781               socketGetError_ew(),MyFuncName);
00782   }
00783 
00784   if(EW_SOCKET_DEBUG)
00785                 logit("et","Exiting %s\n",MyFuncName);
00786 
00787   *fromlen = flen;
00788   return(retVal);
00789 }
00790 
00791 /*************************************************************/
00792 
00793 int send_ew ( SOCKET s, const char FAR * buf, int len, int flags, 
00794               int timeout_msec)
00795 {
00796   /* Send `len' bytes from `buf' out a socket `s'.
00797      Argument `flags' is passed directly to send().
00798      If timeout_msec > 0, send_ew() returns when the sooner of two things 
00799      happens:  
00800      1.  The timeout measured in milliseconds expires;  
00801      2.  All of the data provided by the caller is sent.
00802      If timeout_msec == -1, the socket is set to blocking and send_ew() 
00803      returns when all the data is sent or an error occured.
00804      send_ew() always returns when an unexpected error occurs.
00805      send_ew() returns the number of bytes of data sent, or
00806      SOCKET_ERROR on error.  The caller is responsible for noting
00807      any discrepencies in the difference between the number of bytes
00808      requested to be sent, and the number of reported bytes sent.  If
00809      there is a discrepency, then a timeout may have occured.
00810      Caller can call socketGetError_ew() for details about any failures.
00811      If the latest socket error was WOULDBLOCK_EW, then 
00812       the timeout occured before all the data was sent.
00813      */
00814 
00815   int retVal, ioctlRetVal;
00816   static char * MyFuncName = "send_ew()";
00817   int BytesToSend=len;
00818   int BytesSent=0;
00819   int BytesJustSent=0;
00820   Time_ew StartTime;
00821   fd_set WriteableSockets;
00822   struct timeval SelectTimeout; 
00823   Time_ew timeout=adjustTimeoutLength(timeout_msec);
00824   long lOnOff;
00825   int sel;
00826   
00827   if(EW_SOCKET_DEBUG)
00828     logit("et","Entering %s\n",MyFuncName);
00829   
00830   /* If there is no timeout, make the socket blocking */
00831   if(timeout_msec == -1)
00832   {
00833     lOnOff = 0;
00834     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00835     if (ioctlRetVal==SOCKET_ERROR)
00836     {
00837       if(EW_SOCKET_DEBUG)
00838         logit("et","Error: %d, occurred in %s during change to blocking\n",
00839               socketGetError_ew(),MyFuncName);
00840       return (ioctlRetVal);
00841     }
00842   }
00843   
00844   StartTime = GetTime_ew();
00845   while( BytesSent < BytesToSend )
00846   {
00847     if ( (timeout_msec >= 0) && ((GetTime_ew() - timeout) > StartTime ))
00848     {
00849       retVal = BytesSent;
00850       goto Done;
00851     }
00852     BytesJustSent = send(s, buf+BytesSent, min(len-BytesSent, MAXSENDSIZE_EW),
00853                          flags);
00854     if (BytesJustSent <= 0)
00855     {
00856       if (BytesJustSent == 0 || socketGetError_ew() == WOULDBLOCK_EW)
00857       {
00858         FD_ZERO(&WriteableSockets);
00859         FD_SET(s,&WriteableSockets);
00860         while( (sel = select(s+1, 0, &WriteableSockets, 0,
00861                              resetTimeout(&SelectTimeout))) == 0)
00862         {  /* select timed out; if timeout hasn't expired, reset and try again */
00863           if ( GetTime_ew() - timeout > StartTime )
00864           {
00865             retVal = BytesSent;
00866             goto Done;
00867           }
00868           
00869           FD_ZERO(&WriteableSockets);
00870           FD_SET(s,&WriteableSockets);
00871           sleep_ew(100);  /* Wait a while, and then try again */
00872         }
00873         if (sel < 0)
00874         {
00875           logit("et", "Error %d occured during select() in %s\n",
00876                 socketGetError_ew(), MyFuncName);
00877           retVal = BytesSent;
00878           goto Done;
00879         }
00880 
00881         /* Set BytesJustSent, so that we are not kicked out of the
00882         while loop because of a hard error on a send.  Note:  we
00883         will still be kicked out if we have exceeded the timeout.
00884         */
00885         BytesJustSent = 0;
00886       }
00887       else  /* some other error occured */
00888       {
00889         if(EW_SOCKET_DEBUG)
00890           logit("et","Error: %d, occurred in %s\n",
00891                 socketGetError_ew(),MyFuncName);
00892         retVal = BytesSent;
00893         goto Done;
00894       }
00895     }  /* End of If there was an error on send() */
00896     else
00897     {
00898       BytesSent += BytesJustSent;
00899     }
00900   }  /* End: while not all data sent */
00901   retVal = BytesSent;
00902 
00903 Done:
00904   /* If there is no timeout, then the call was made blocking,
00905   change it back so that we don't screw up any further operations
00906   */
00907   if(timeout_msec == -1)
00908   {
00909     lOnOff = 1;
00910     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00911     if (ioctlRetVal < 0)
00912     {
00913       if(EW_SOCKET_DEBUG)
00914         logit("et","Error: %d, occurred in %s during change to non-blocking\n",
00915         socketGetError_ew(),MyFuncName);
00916       retVal = SOCKET_ERROR;
00917     }
00918   }
00919 
00920   if(EW_SOCKET_DEBUG)
00921     logit("et","Exiting %s\n",MyFuncName);
00922 
00923   return(retVal);
00924 }
00925 
00926 /*************************************************************/
00927 
00928 int sendto_ew (SOCKET s, const char FAR * buf, int len, 
00929                int flags, const struct sockaddr FAR * to,
00930                int tolen, int timeout_msec)
00931 {
00932   /* sendto_ew() is similar to send_ew(), except used for datagram
00933      sockets. Once the socket is ready for sending, sendto_ew calls
00934      sendto() only once. No checks are made to ensure all data is sent.
00935      Arguments s, flags, to,  and tolen are passed directly to sendto().
00936      Timeout is specified in milliseconds; value of -1 sets socket to 
00937      blocking mode and turns off timing. 
00938      Caller can call socketGetError_ew() for details about any failures. 
00939   */
00940 
00941   int retVal, ioctlRetVal;
00942   static char * MyFuncName = "sendto_ew()";
00943   Time_ew StartTime;
00944   fd_set WriteableSockets;
00945   struct timeval SelectTimeout; 
00946   Time_ew timeout=adjustTimeoutLength(timeout_msec);
00947   long lOnOff;
00948   int sel;
00949   
00950   if(EW_SOCKET_DEBUG)
00951     logit("et","Entering %s\n",MyFuncName);
00952 
00953   /* If there is no timeout, make the socket blocking */
00954   if(timeout_msec == -1)
00955   {
00956     lOnOff = 0;
00957     ioctlRetVal=ioctlsocket(s,FIONBIO,&lOnOff);
00958     if (ioctlRetVal==SOCKET_ERROR)
00959     {
00960       if(EW_SOCKET_DEBUG)
00961       {
00962         logit("et","Error: %d, occurred in %s during change to blocking\n",
00963               socketGetError_ew(),MyFuncName);
00964       }
00965       return ioctlRetVal;
00966     }
00967   }
00968   
00969   StartTime=GetTime_ew();
00970   retVal = sendto(s,buf,len,flags,to,tolen);
00971   
00972   /* If there is no timeout, then the call was made blocking,
00973      change it back so that we don't screw up any further operations
00974   */
00975   if(timeout_msec == -1)
00976   {
00977     lOnOff = 1;
00978     ioctlRetVal = ioctlsocket(s,FIONBIO,&lOnOff);
00979     if (ioctlRetVal < 0)
00980     {
00981       if(EW_SOCKET_DEBUG)
00982         logit("et","Error: %d, occurred in %s during change to non-blocking\n",
00983         socketGetError_ew(),MyFuncName);
00984       return SOCKET_ERROR;
00985     }
00986   }
00987 
00988   if (retVal < 0 && socketGetError_ew() == WOULDBLOCK_EW)
00989   {
00990     FD_ZERO(&WriteableSockets);
00991     FD_SET(s,&WriteableSockets);
00992     while( (sel = select(s+1, 0, &WriteableSockets, 0,
00993                          resetTimeout(&SelectTimeout))) == 0)
00994     {  /* select timed out; if timeout hasn't expired, reset and try again */
00995       if ( GetTime_ew() - timeout > StartTime )
00996         return SOCKET_ERROR;
00997 
00998       FD_ZERO(&WriteableSockets);
00999       FD_SET(s,&WriteableSockets);
01000       sleep_ew(100);  
01001       /* Wait a while, and then try again */
01002     }
01003     if (sel < 0)
01004     {
01005       logit("et", "Error %d occured during select() in %s\n",
01006             socketGetError_ew(), MyFuncName);
01007       return SOCKET_ERROR;
01008     }
01009     retVal=sendto(s,buf,len,flags,to,tolen);
01010   }
01011   
01012   if(retVal <0  && EW_SOCKET_DEBUG)
01013   {
01014     logit("et","Error: %d, occurred in %s\n",
01015           socketGetError_ew(),MyFuncName);
01016   }
01017   
01018   if(EW_SOCKET_DEBUG)
01019     logit("et","Exiting %s\n",MyFuncName);
01020   
01021   return(retVal);
01022 }
01023 
01024 /*************************************************************/
01025 
01026 struct timeval FAR * resetTimeout(struct timeval FAR * pSelectTimeout)
01027 {
01028 
01029   /* resetTimeout() reinitializes the TIMEVAL structure used in
01030      select() calls.  Depending on the OS, the timeout value
01031      maybe altered during the select() call, and therefore needs
01032      to be reinitialized before every select() call.
01033      */
01034   static char * MyFuncName = "resetTimeout()";
01035   static int EW_SOCKET_DEBUG_R=0;
01036   if(EW_SOCKET_DEBUG_R)
01037     logit("et","Entering %s\n",MyFuncName);
01038 
01039   pSelectTimeout->tv_sec=SELECT_TIMEOUT_SECONDS;
01040   pSelectTimeout->tv_usec=SELECT_TIMEOUT_uSECONDS;
01041 
01042   if(EW_SOCKET_DEBUG_R)
01043     logit("et","Exiting %s\n",MyFuncName);
01044 
01045   return(pSelectTimeout);
01046 }
01047 
01048 /*************************************************************/
01049 
01050 int closesocket_ew(SOCKET s,int HowToClose)
01051 {
01052   /* closesocket_ew() closes the socket s.  HowToClose indicates
01053      whether the socket should be closed gracefully or immediately.
01054      Use SOCKET_CLOSE_IMMEDIATELY_EW or SOCKET_CLOSE_GRACEFULLY_EW
01055      to indicate closure method.  Caller can call socketGetError_ew()
01056      for details about any failures.
01057   */
01058 
01059   /*
01060     #define SOCKET_CLOSE_IMMEDIATELY_EW 0
01061     #define SOCKET_CLOSE_GRACEFULLY_EW -1
01062     #define SOCKET_CLOSE_SIMPLY_EW     -2
01063   */
01064 
01065   static char * MyFuncName = "closesocket_ew()";
01066   struct linger Linger_Value;
01067   int retVal;
01068 
01069   if(EW_SOCKET_DEBUG)
01070     logit("et","Entering %s\n",MyFuncName);
01071 
01072 /* Note1: setsockopt(SO_LINGER) doesn't seem to work on x86 Solaris 2.5, 
01073           at least when the socket isn't connected. WMK 981019   
01074    Note2: Added the case SOCKET_CLOSE_SIMPLY_EW to skip the call to 
01075           setsockopt. This case is used in connect_ew when the connection
01076           has failed.  LDD 981022
01077  *************************************************************************/
01078   if ( HowToClose != SOCKET_CLOSE_SIMPLY_EW )
01079   {
01080     if ( HowToClose == SOCKET_CLOSE_IMMEDIATELY_EW )
01081     {
01082       Linger_Value.l_onoff=1;     /* Reset or hard close */
01083       Linger_Value.l_linger=0;    /* Set timeout to 0 seconds */
01084     }
01085     else
01086     {
01087       Linger_Value.l_onoff=0;     /* Non-blocking graceful close (NBGC) */
01088       Linger_Value.l_linger=0;
01089     }
01090     
01091     if ( setsockopt(s,SOL_SOCKET,SO_LINGER,(char *) &Linger_Value,
01092                     sizeof(struct linger)) == -1 )
01093     {
01094       if(EW_SOCKET_DEBUG)
01095         logit( "et", "closesocket_ew:setsockopt error: %s\n", 
01096                strerror(socketGetError_ew()) );
01097     }
01098   }
01099   
01100   retVal=closesocket(s);
01101   
01102   if(EW_SOCKET_DEBUG)
01103     logit("et","Exiting %s\n",MyFuncName);
01104   
01105   return (retVal);
01106 }
01107 
01108 /*************************************************************/
01109 
01110 int select_ew (int nfds, fd_set FAR * readfds, fd_set FAR * writefds, 
01111                fd_set FAR * exceptfds, 
01112                int timeout_msec)
01113 
01114      /* select_ew() determines the state of sets of sockets, by 
01115      calling select().  Timeout is in milliseconds, and is
01116      converted by select_ew to the select() timeout structure, and
01117      passed on (to select()). No "-1" feature here; if you are willing to
01118      block indefinitely in select(), you might as well wait in the actual
01119      I/O call instead.
01120      Caller can call socketGetError_ew() for details about any failures.
01121      */
01122 {
01123   int retVal;
01124   static char * MyFuncName = "select_ew()";
01125   struct timeval SelectTimeout={0,0};
01126 
01127   if(EW_SOCKET_DEBUG)
01128     logit("et","Entering %s\n",MyFuncName);
01129   
01130   SelectTimeout.tv_usec=1000 * timeout_msec;
01131   
01132   retVal = select(nfds,readfds,writefds,exceptfds,&SelectTimeout);
01133   if (retVal < 0  && EW_SOCKET_DEBUG)
01134     logit("et","Error: %d, occurred in %s\n",
01135           socketGetError_ew(),MyFuncName);
01136   
01137   if(EW_SOCKET_DEBUG)
01138     logit("et","Exiting %s\n",MyFuncName);
01139   
01140   return(retVal);
01141 }
01142 
01143 /*************************************************************/
01144 
01145 int setSocket_ewDebug(int debug)
01146 {
01147   /* setSocket_ewDebug() turns debugging on or off for 
01148      the SOCKET_ew routines.
01149   */
01150   EW_SOCKET_DEBUG=debug;
01151   return(0);
01152 }
01153 
01154 /*************************************************************/
01155 
01156 int setSocket_ewSelectTimeout(unsigned int Timeout)
01157 {
01158   /* setSocket_ewSelectTimeout() sets the timeout period
01159      passed to select() calls made internally within the 
01160      SOCKET_ew routines.  The timeout period is in 
01161      milliseconds.
01162   */
01163   SELECT_TIMEOUT_uSECONDS=1000*Timeout;
01164   return(0);
01165 }
01166 
01167 

Generated on Tue May 6 09:16:10 2003 for Earthworm Libs by doxygen1.3-rc3