Index: ossp-pkg/sa/sa.c RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.c,v rcsdiff -q -kk '-r1.24' '-r1.25' -u '/v/ossp/cvs/ossp-pkg/sa/sa.c,v' 2>/dev/null --- sa.c 2001/10/09 19:58:46 1.24 +++ sa.c 2001/10/09 20:19:58 1.25 @@ -163,7 +163,7 @@ struct sa_st { sa_type_t eType; /* socket type (stream or datagram) */ int fdSocket; /* socket file descriptor */ - struct timeval tvTimeout[6]; /* timeout values (sec, usec) */ + struct timeval tvTimeout[4]; /* timeout values (sec, usec) */ int nReadLen; /* read buffer current length */ int nReadSize; /* read buffer current size */ char *cpReadBuf; /* read buffer memory chunk */ @@ -796,6 +796,28 @@ return SA_OK; } +/* set timeouts if timeouts or done in kernel */ +static sa_rc_t sa_socket_settimeouts(sa_t *sa) +{ +#if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) + if (sa->fdSocket != -1) { + if (SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_READ])) { + if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_RCVTIMEO, + &sa->tvTimeout[SA_TIMEOUT_READ], + sizeof(sa->tvTimeout[SA_TIMEOUT_READ])) < 0) + return SA_ERR_SYS; + } + if (SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_WRITE])) { + if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_SNDTIMEO, + &sa->tvTimeout[SA_TIMEOUT_WRITE], + sizeof(sa->tvTimeout[SA_TIMEOUT_WRITE])) < 0) + return SA_ERR_SYS; + } + } +#endif + return SA_OK; +} + /* internal lazy/delayed initialization of underlying socket */ static sa_rc_t sa_socket_init(sa_t *sa, int nFamily) { @@ -845,6 +867,9 @@ if ((sa->fdSocket = socket(nFamily, nType, nProto)) == -1) return SA_ERR_SYS; + /* optionally set kernel timeouts */ + sa_socket_settimeouts(sa); + return SA_OK; } @@ -973,6 +998,9 @@ sa->tvTimeout[id].tv_usec = usec; } + /* optionally set kernel timeouts */ + sa_socket_settimeouts(sa); + return SA_OK; } @@ -1369,10 +1397,13 @@ static int sa_read_raw(sa_t *sa, char *cpBuf, int nBufLen) { int rv; +#if !(defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO)) fd_set fds; +#endif /* if timeout is enabled, perform explicit/smart blocking instead of implicitly/hard blocking in the read(2) system call */ +#if !(defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO)) if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_READ])) { FD_ZERO(&fds); FD_SET(sa->fdSocket, &fds); @@ -1385,12 +1416,18 @@ return -1; } } +#endif /* perform read operation on underlying socket */ do { rv = SA_SC_CALL_3(sa, read, sa->fdSocket, cpBuf, nBufLen); } while (rv == -1 && errno == EINTR); +#if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) + if (rv == -1 && errno == EWOULDBLOCK) + errno = ETIMEDOUT; +#endif + return rv; } @@ -1535,10 +1572,13 @@ static int sa_write_raw(sa_t *sa, const char *cpBuf, int nBufLen) { int rv; +#if !(defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO)) fd_set fds; +#endif /* if timeout is enabled, perform explicit/smart blocking instead of implicitly/hard blocking in the write(2) system call */ +#if !(defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO)) if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_WRITE])) { FD_ZERO(&fds); FD_SET(sa->fdSocket, &fds); @@ -1551,12 +1591,18 @@ return -1; } } +#endif /* perform write operation on underlying socket */ do { rv = SA_SC_CALL_3(sa, write, sa->fdSocket, cpBuf, nBufLen); } while (rv == -1 && errno == EINTR); +#if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) + if (rv == -1 && errno == EWOULDBLOCK) + errno = ETIMEDOUT; +#endif + return rv; } @@ -1756,12 +1802,12 @@ /* if timeout is enabled, perform explicit/smart blocking instead of implicitly/hard blocking in the recvfrom(2) system call */ - if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_RECV])) { + if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_READ])) { FD_ZERO(&fds); FD_SET(sa->fdSocket, &fds); do { n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL, - &sa->tvTimeout[SA_TIMEOUT_RECV]); + &sa->tvTimeout[SA_TIMEOUT_READ]); } while (n == -1 && errno == EINTR); if (n == 0) errno = ETIMEDOUT; @@ -1812,12 +1858,12 @@ /* if timeout is enabled, perform explicit/smart blocking instead of implicitly/hard blocking in the sendto(2) system call */ - if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_SEND])) { + if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_WRITE])) { FD_ZERO(&fds); FD_SET(sa->fdSocket, &fds); do { n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, NULL, &fds, NULL, - &sa->tvTimeout[SA_TIMEOUT_SEND]); + &sa->tvTimeout[SA_TIMEOUT_WRITE]); } while (n == -1 && errno == EINTR); if (n == 0) errno = ETIMEDOUT; Index: ossp-pkg/sa/sa.h RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.h,v rcsdiff -q -kk '-r1.19' '-r1.20' -u '/v/ossp/cvs/ossp-pkg/sa/sa.h,v' 2>/dev/null --- sa.h 2001/10/09 18:55:22 1.19 +++ sa.h 2001/10/09 20:19:58 1.20 @@ -121,9 +121,7 @@ SA_TIMEOUT_ACCEPT = 0, SA_TIMEOUT_CONNECT = 1, SA_TIMEOUT_READ = 2, - SA_TIMEOUT_WRITE = 3, - SA_TIMEOUT_RECV = 4, - SA_TIMEOUT_SEND = 5 + SA_TIMEOUT_WRITE = 3 } sa_timeout_t; /* list of system calls */