Index: ossp-pkg/l2/l2_ut_sa.c RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.c,v rcsdiff -q -kk '-r1.16' '-r1.17' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.c,v' 2>/dev/null --- l2_ut_sa.c 2001/10/26 10:59:47 1.16 +++ l2_ut_sa.c 2001/10/31 21:26:11 1.17 @@ -69,6 +69,11 @@ #define ssize_t long #endif +/* backward compatibility for O_NONBLOCK */ +#if !defined(O_NONBLOCK) && defined(O_NDELAY) +#define O_NONBLOCK O_NDELAY +#endif + /* system call structure declaration macros */ #define SA_SC_DECLARE_0(rc_t, fn) \ struct { \ @@ -492,7 +497,7 @@ if (cpHost[0] == '[') { /* IPv6 address (see RFC2732) */ #ifndef AF_INET6 - return SA_ERR_ARG; + return SA_ERR_IMP; #else bIPv6 = TRUE; cpHost++; @@ -607,6 +612,15 @@ if (saa == NULL || sabuf == NULL || salen == 0) return SA_ERR_ARG; + /* make sure we import only supported addresses */ + if (!( sabuf->sa_family == AF_LOCAL + || sabuf->sa_family == AF_INET +#ifdef AF_INET6 + || sabuf->sa_family == AF_INET6 +#endif + )) + return SA_ERR_USE; + /* create result address structure */ if (saa->saBuf != NULL) free(saa->saBuf); @@ -1054,6 +1068,61 @@ return SA_OK; } +/* configure socket option */ +sa_rc_t sa_option(sa_t *sa, sa_option_t id, ...) +{ + sa_rc_t rv; + va_list ap; + + /* argument sanity check(s) */ + if (sa == NULL) + return SA_ERR_ARG; + + /* process option */ + rv = SA_OK; + va_start(ap, id); + switch (id) { + case SA_OPTION_NAGLE: { + /* enable/disable Nagle's Algorithm (see RFC898) */ +#if defined(IPPROTO_TCP) && defined(TCP_NODELAY) + int mode = ((int)va_arg(ap, int) ? 1 : 0); + if (sa->fdSocket == -1) { + rv = SA_ERR_USE; + break; + } + if (setsockopt(sa->fdSocket, IPPROTO_TCP, TCP_NODELAY, + (void *)&mode, sizeof(mode)) < 0) + rv = SA_ERR_SYS; +#else + rv = SA_ERR_IMP; +#endif + break; + } + case SA_OPTION_NONBLOCK: { + /* enable/disable non-blocking I/O mode */ + int flags; + int mode = (int)va_arg(ap, int); + if ((flags = fcntl(sa->fdSocket, F_GETFL, 0)) < 0) { + rv = SA_ERR_SYS; + break; + } + if (mode == 0) + flags &= ~(O_NONBLOCK); + else + flags |= O_NONBLOCK; + if (fcntl(sa->fdSocket, F_SETFL, flags) < 0) + rv = SA_ERR_SYS; + break; + } + default: { + rv = SA_ERR_ARG; + } + } + va_end(ap); + + return rv; +} + /* override system call */ sa_rc_t sa_syscall(sa_t *sa, sa_syscall_t id, void (*fptr)(), void *fctx) { @@ -1451,14 +1520,12 @@ if (sa->fdSocket == -1) return SA_ERR_USE; - /* trigger a write buffer flush */ - if (sa->nWriteLen > 0) - sa_flush(sa); - /* perform read operation */ rv = SA_OK; if (sa->nReadSize == 0) { /* user-space unbuffered I/O */ + if (sa->nWriteLen > 0) + sa_flush(sa); res = sa_read_raw(sa, cpBuf, nBufReq); if (res == 0) rv = SA_ERR_EOF; @@ -1487,6 +1554,8 @@ res += sa->nReadLen; sa->nReadLen = 0; } + if (sa->nWriteLen > 0) + sa_flush(sa); if (nBufReq >= sa->nReadSize) { /* buffer is too small at all, so read directly */ n = sa_read_raw(sa, cpBuf, nBufReq); @@ -1916,6 +1985,7 @@ else if (rv == SA_ERR_EOF) sz = "End Of Communication"; else if (rv == SA_ERR_TMT) sz = "Communication Timeout"; else if (rv == SA_ERR_SYS) sz = "Operating System Error"; + else if (rv == SA_ERR_IMP) sz = "Implementation Not Available"; else if (rv == SA_ERR_INT) sz = "Internal Error"; else sz = "Invalid Result Code"; return sz; Index: ossp-pkg/l2/l2_ut_sa.h RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.h,v rcsdiff -q -kk '-r1.11' '-r1.12' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.h,v' 2>/dev/null --- l2_ut_sa.h 2001/10/11 08:00:37 1.11 +++ l2_ut_sa.h 2001/10/31 21:26:11 1.12 @@ -107,15 +107,16 @@ /* return codes */ typedef enum { - SA_OK, /* Everything Ok */ - SA_ERR_ARG, /* Invalid Argument */ - SA_ERR_USE, /* Invalid Use Or Context */ - SA_ERR_MEM, /* Not Enough Memory */ - SA_ERR_MTC, /* Matching Failed */ - SA_ERR_EOF, /* End Of Communication */ - SA_ERR_TMT, /* Communication Timeout */ - SA_ERR_SYS, /* Operating System Error */ - SA_ERR_INT /* Internal Error */ + SA_OK, /* Everything Ok */ + SA_ERR_ARG, /* Invalid Argument */ + SA_ERR_USE, /* Invalid Use Or Context */ + SA_ERR_MEM, /* Not Enough Memory */ + SA_ERR_MTC, /* Matching Failed */ + SA_ERR_EOF, /* End Of Communication */ + SA_ERR_TMT, /* Communication Timeout */ + SA_ERR_SYS, /* Operating System Error */ + SA_ERR_IMP, /* Implementation Not Available */ + SA_ERR_INT /* Internal Error */ } sa_rc_t; /* list of timeouts */ @@ -133,6 +134,12 @@ SA_BUFFER_WRITE } sa_buffer_t; +/* list of options */ +typedef enum { + SA_OPTION_NAGLE, + SA_OPTION_NONBLOCK +} sa_option_t; + /* list of system calls */ typedef enum { SA_SYSCALL_CONNECT, @@ -163,6 +170,7 @@ sa_rc_t sa_type (sa_t *sa, sa_type_t type); sa_rc_t sa_timeout (sa_t *sa, sa_timeout_t id, long sec, long usec); sa_rc_t sa_buffer (sa_t *sa, sa_buffer_t id, size_t size); +sa_rc_t sa_option (sa_t *sa, sa_option_t id, ...); sa_rc_t sa_syscall (sa_t *sa, sa_syscall_t id, void (*fptr)(), void *fctx); /* socket connection operations */