--- sa.c 2004/04/02 18:21:07 1.80
+++ sa.c 2004/04/02 18:47:39 1.81
@@ -1452,6 +1452,7 @@
fd_set rset, wset;
socklen_t len;
sa_rc_t rv;
+ struct timeval *tv;
/* argument sanity check(s) */
if (sa == NULL || raddr == NULL)
@@ -1466,72 +1467,75 @@
if ((rv = sa_socket_init(sa, raddr->nFamily)) != SA_OK)
return SA_RC(rv);
+ /* prepare return code decision */
rv = SA_OK;
- if (SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT])) {
- /* standard/non-timeout-aware connect operation */
- if (SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf) < 0)
- rv = SA_ERR_SYS;
- }
- else {
- /* emulated/timeout-aware connect operation */
- error = 0;
+ error = 0;
- /* temporarily switch underlying socket to non-blocking mode */
+ /* temporarily switch underlying socket to non-blocking mode
+ (necessary under timeout-aware operation only) */
+ flags = 0;
+ if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT])) {
flags = fcntl(sa->fdSocket, F_GETFL, 0);
(void)fcntl(sa->fdSocket, F_SETFL, flags|O_NONBLOCK);
+ }
- /* perform the connect operation */
- if ((n = SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf)) < 0) {
- if (errno != EINPROGRESS) {
- error = errno;
- goto done;
- }
- }
-
- /* ok if connect completed immediately */
- if (n == 0)
- goto done;
-
- /* wait for read or write possibility */
- FD_ZERO(&rset);
- FD_ZERO(&wset);
- FD_SET(sa->fdSocket, &rset);
- FD_SET(sa->fdSocket, &wset);
- do {
- n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &rset, &wset, NULL,
- &sa->tvTimeout[SA_TIMEOUT_CONNECT]);
- } while (n == -1 && errno == EINTR);
-
- /* decide on return semantic */
- if (n < 0) {
+ /* perform the connect operation */
+ if ((n = SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf)) < 0) {
+ if (errno != EINTR && errno != EINPROGRESS) {
error = errno;
goto done;
}
- else if (n == 0) {
- (void)close(sa->fdSocket); /* stop TCP three-way handshake */
- sa->fdSocket = -1;
- rv = SA_ERR_TMT;
- goto done;
- }
-
- /* fetch pending error */
- len = (socklen_t)sizeof(error);
- if (getsockopt(sa->fdSocket, SOL_SOCKET, SO_ERROR, (void *)&error, &len) < 0)
- error = errno;
+ }
- done:
+ /* ok if connect completed immediately */
+ if (n == 0)
+ goto done;
+
+ /* wait for read or write possibility */
+ FD_ZERO(&rset);
+ FD_ZERO(&wset);
+ FD_SET(sa->fdSocket, &rset);
+ FD_SET(sa->fdSocket, &wset);
+ if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT]))
+ tv = &sa->tvTimeout[SA_TIMEOUT_CONNECT];
+ else
+ tv = NULL;
+ do {
+ n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &rset, &wset, NULL, tv);
+ } while (n == -1 && errno == EINTR);
+
+ /* decide on return semantic */
+ if (n < 0) {
+ error = errno;
+ goto done;
+ }
+ else if (n == 0) {
+ (void)close(sa->fdSocket); /* stop TCP three-way handshake */
+ sa->fdSocket = -1;
+ rv = SA_ERR_TMT;
+ goto done;
+ }
- /* reset socket flags */
+ /* fetch pending error */
+ len = (socklen_t)sizeof(error);
+ if (getsockopt(sa->fdSocket, SOL_SOCKET, SO_ERROR, (void *)&error, &len) < 0)
+ error = errno;
+
+ done:
+
+ /* reset socket flags
+ (necessary under timeout-aware operation only) */
+ if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT]))
(void)fcntl(sa->fdSocket, F_SETFL, flags);
- /* optionally set errno */
- if (error != 0) {
- (void)close(sa->fdSocket); /* just in case */
- sa->fdSocket = -1;
- errno = error;
- rv = SA_ERR_SYS;
- }
+ /* optionally set errno */
+ if (error != 0) {
+ (void)close(sa->fdSocket); /* just in case */
+ sa->fdSocket = -1;
+ errno = error;
+ rv = SA_ERR_SYS;
}
+
return SA_RC(rv);
}
|