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