OSSP CVS Repository

ossp - Check-in [2796]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 2796
Date: 2002-Nov-09 15:44:31 (local)
2002-Nov-09 14:44:31 (UTC)
User:rse
Branch:
Comment: Upgrade to OSSP sa 1.0.1
Tickets:
Inspections:
Files:
ossp-pkg/l2/l2_ch_socket.c      1.36 -> 1.37     1 inserted, 1 deleted
ossp-pkg/l2/l2_ch_syslog.c      1.31 -> 1.32     2 inserted, 2 deleted
ossp-pkg/l2/l2_ut_sa.ac      1.6 -> 1.7     4 inserted, 4 deleted
ossp-pkg/l2/l2_ut_sa.c      1.19 -> 1.20     284 inserted, 130 deleted
ossp-pkg/l2/l2_ut_sa.h      1.15 -> 1.16     36 inserted, 35 deleted

ossp-pkg/l2/l2_ch_socket.c 1.36 -> 1.37

--- l2_ch_socket.c       2002/07/30 19:08:25     1.36
+++ l2_ch_socket.c       2002/11/09 14:44:31     1.37
@@ -151,7 +151,7 @@
         if (strcmp(cfg->szProto, "tcp") == 0)
             rc = sa_write(cfg->saRemote, buf, sizeRemain, &sizeWrite);
         else
-            rc = sa_send(cfg->saRemote, buf, sizeRemain, &sizeWrite, cfg->saaRemote);
+            rc = sa_send(cfg->saRemote, cfg->saaRemote, buf, sizeRemain, &sizeWrite);
         if (rc != SA_OK)
             return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_INT);
         sizeRemain = sizeRemain - sizeWrite; /* how much is left? */


ossp-pkg/l2/l2_ch_syslog.c 1.31 -> 1.32

--- l2_ch_syslog.c       2002/07/30 19:08:25     1.31
+++ l2_ch_syslog.c       2002/11/09 14:44:31     1.32
@@ -297,8 +297,8 @@
                                 cfg->szIdent, buf);
         if ((n = strlen(caBuf)) > 1024)
             return L2_ERR_IO;
-        if ((rc = sa_send(cfg->saRemoteSock, caBuf, n, 
-                          NULL, cfg->saaRemoteAddr)) != SA_OK)
+        if ((rc = sa_send(cfg->saRemoteSock, cfg->saaRemoteAddr,
+                          caBuf, n, NULL)) != SA_OK)
             return (rc == SA_ERR_SYS ? L2_ERR_SYS : L2_ERR_IO);
     }
 


ossp-pkg/l2/l2_ut_sa.ac 1.6 -> 1.7

--- l2_ut_sa.ac  2002/10/11 16:00:48     1.6
+++ l2_ut_sa.ac  2002/11/09 14:44:31     1.7
@@ -42,8 +42,8 @@
 changequote(<<,>>)dnl
 <<(^|[^a-zA-Z_0-9])$1[^a-zA-Z_0-9]>>dnl
 changequote([,]), [
-#include <$2>], 
-            ac_cv_typedef_$1=yes, 
+#include <$2>],
+            ac_cv_typedef_$1=yes,
             ac_cv_typedef_$1=no
         )
     ])dnl
@@ -62,12 +62,12 @@
     AC_CHECK_LIB(nsl, gethostname)
     if test ".`echo $LIBS | grep nsl`" = .; then
         AC_CHECK_LIB(nsl, gethostbyname)
-    fi  
+    fi
     AC_CHECK_LIB(socket, accept)
 
     #   make sure some platforms find their IPv6 library
     AC_CHECK_LIB(inet6, getaddrinfo)
-    
+
     #   check for system headers
     AC_CHECK_HEADERS(string.h sys/types.h sys/socket.h netdb.h netinet/in.h)
 


ossp-pkg/l2/l2_ut_sa.c 1.19 -> 1.20

--- l2_ut_sa.c   2002/10/21 15:14:04     1.19
+++ l2_ut_sa.c   2002/11/09 14:44:31     1.20
@@ -45,7 +45,7 @@
 #include <sys/time.h>    /* for "struct timeval" */
 #include <sys/un.h>      /* for "struct sockaddr_un" */
 #include <netinet/in.h>  /* for "struct sockaddr_in[6]" */
-#include <sys/socket.h>  /* for "PF_XXX", "AF_XXX" and "SOCK_XXX" */
+#include <sys/socket.h>  /* for "PF_XXX", "AF_XXX", "SOCK_XXX" and "SHUT_XX" */
 #include <arpa/inet.h>   /* for "inet_XtoX" */
 
 /* include own API header */
@@ -88,6 +88,19 @@
 #define PF_INET6 AF_INET6
 #endif
 
+/* backward compatibility for SHUT_XX. Some platforms (like brain-dead
+   OpenUNIX) define those only if _XOPEN_SOURCE is defined, but unfortunately
+   then fail in their other vendor includes due to internal inconsistencies. */
+#if !defined(SHUT_RD)
+#define SHUT_RD 0
+#endif
+#if !defined(SHUT_WR)
+#define SHUT_WR 1
+#endif
+#if !defined(SHUT_RDWR)
+#define SHUT_RDWR 2
+#endif
+
 /* backward compatibility for ssize_t */
 #if !defined(HAVE_SSIZE_T)
 #define ssize_t long
@@ -203,7 +216,13 @@
     SA_SC_DECLARE_6(ssize_t, recvfrom, int, void *, size_t, int, struct sockaddr *, socklen_t *)
     SA_SC_DECLARE_6(ssize_t, sendto,   int, const void *, size_t, int, const struct sockaddr *, socklen_t)
 } sa_syscall_tab_t;
- 
+
+/* socket option information */
+typedef struct {
+    int todo;
+    int value;
+} sa_optinfo_t;
+
 /* socket abstraction object */
 struct sa_st {
     sa_type_t        eType;            /* socket type (stream or datagram) */
@@ -216,6 +235,7 @@
     int              nWriteSize;       /* write buffer current size */
     char            *cpWriteBuf;       /* write buffer memory chunk */
     sa_syscall_tab_t scSysCall;        /* table of system calls */
+    sa_optinfo_t     optInfo[5];       /* option storage */
 };
 
 /* socket address abstraction object */
@@ -270,7 +290,7 @@
 #ifdef HAVE_INET_NTOA
         /* at least for IPv4 we can rely on the old inet_ntoa(3)
            and for IPv6 inet_ntop(3) would exist anyway */
-        if ((cp = inet_ntoa(*((struct in_addr *)src))) == NULL) 
+        if ((cp = inet_ntoa(*((struct in_addr *)src))) == NULL)
             return NULL;
         n = strlen(cp);
         if (n > size-1)
@@ -289,14 +309,14 @@
 static int sa_mvxprintf(int (*output)(void *ctx, const char *buffer, size_t bufsize), void *ctx, const char *format, va_list ap)
 {
     /* sufficient integer buffer: <available-bits> x log_10(2) + safety */
-    char ibuf[((sizeof(int)*8)/3)+10]; 
+    char ibuf[((sizeof(int)*8)/3)+10];
     char *cp;
     char c;
     int d;
     int n;
     int bytes;
 
-    if (format == NULL || ap == NULL)
+    if (format == NULL)
         return -1;
     bytes = 0;
     while (*format != '\0') {
@@ -378,11 +398,11 @@
     int n;
     sa_mvsnprintf_cb_t ctx;
 
-    if (format == NULL || ap == NULL)
+    if (format == NULL)
         return -1;
     if (buffer != NULL && bufsize == 0)
         return -1;
-    if (buffer == NULL) 
+    if (buffer == NULL)
         /* just determine output length */
         n = sa_mvxprintf(NULL, NULL, format, ap);
     else {
@@ -489,7 +509,7 @@
     sl = 0;
     sf = 0;
 
-    /* parse URI and resolve contents. 
+    /* parse URI and resolve contents.
        The following syntax is recognized:
        - unix:<path>
        - inet://<host>:<port>[#(tcp|udp)] */
@@ -609,7 +629,7 @@
             else if (he->h_addrtype == AF_INET6) {
                 sa6.sin6_family = AF_INET6;
                 sa6.sin6_port = htons(nPort);
-                memcpy(&sa6.sin6_addr.s6_addr, he->h_addr_list[0], 
+                memcpy(&sa6.sin6_addr.s6_addr, he->h_addr_list[0],
                        sizeof(sa6.sin6_addr.s6_addr));
                 sa = (struct sockaddr *)&sa6;
                 sl = sizeof(sa6);
@@ -691,7 +711,7 @@
             || saa->slBuf < sizeof(struct sockaddr_un))
             /* in case the remote side of a Unix Domain socket was not
                bound, a "struct sockaddr_un" can occur with a length less
-               than the expected one. Then there is actually no path at all. 
+               than the expected one. Then there is actually no path at all.
                This has been verified under FreeBSD, Linux and Solaris. */
             sa_msnprintf(uribuf, sizeof(uribuf), "unix:/NOT-BOUND");
         else
@@ -780,7 +800,7 @@
 #ifdef AF_INET6
     else if (   (saa1->nFamily == AF_INET  && saa2->nFamily == AF_INET6)
              || (saa1->nFamily == AF_INET6 && saa2->nFamily == AF_INET )) {
-        /* special case of comparing a regular IPv4 address (1.2.3.4) with an 
+        /* special case of comparing a regular IPv4 address (1.2.3.4) with an
            "IPv4-mapped IPv6 address" (::ffff:1.2.3.4). For details see RFC 2373. */
         if (saa1->nFamily == AF_INET6) {
             np1  = (unsigned int)(((struct sockaddr_in6 *)saa1->saBuf)->sin6_port);
@@ -837,7 +857,7 @@
         prefixlen = nBits;
     }
 
-    /* perform address representation comparison 
+    /* perform address representation comparison
        (assumption guaranteed by API: network byte order is used) */
     nBytes = (prefixlen / 8);
     nBits  = (prefixlen % 8);
@@ -864,25 +884,120 @@
 /* set timeouts if timeouts or done in kernel */
 static sa_rc_t sa_socket_settimeouts(sa_t *sa)
 {
+    /* stop processing if socket is still not allocated */
+    if (sa->fdSocket == -1)
+        return SA_OK;
+
 #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,
-                           (const void *)(&sa->tvTimeout[SA_TIMEOUT_READ]),
-                           (socklen_t)(sizeof(sa->tvTimeout[SA_TIMEOUT_READ]))) < 0)
-                return SA_RC(SA_ERR_SYS);
-        }
-        if (SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_WRITE])) {
-            if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_SNDTIMEO,
-                           (const void *)(&sa->tvTimeout[SA_TIMEOUT_WRITE]),
-                           (socklen_t)(sizeof(sa->tvTimeout[SA_TIMEOUT_WRITE]))) < 0)
-                return SA_RC(SA_ERR_SYS);
-        }
+    if (SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_READ])) {
+        if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_RCVTIMEO,
+                       (const void *)(&sa->tvTimeout[SA_TIMEOUT_READ]),
+                       (socklen_t)(sizeof(sa->tvTimeout[SA_TIMEOUT_READ]))) < 0)
+            return SA_RC(SA_ERR_SYS);
+    }
+    if (SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_WRITE])) {
+        if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_SNDTIMEO,
+                       (const void *)(&sa->tvTimeout[SA_TIMEOUT_WRITE]),
+                       (socklen_t)(sizeof(sa->tvTimeout[SA_TIMEOUT_WRITE]))) < 0)
+            return SA_RC(SA_ERR_SYS);
     }
 #endif
     return SA_OK;
 }
 
+/* set socket options */
+static sa_rc_t sa_socket_setoptions(sa_t *sa)
+{
+    int i;
+    sa_rc_t rv;
+
+    /* stop processing if socket is still not allocated */
+    if (sa->fdSocket == -1)
+        return SA_OK;
+
+    /* check for pending options */
+    rv = SA_OK;
+    for (i = 0; i < (sizeof(sa->optInfo)/sizeof(sa->optInfo[0])); i++) {
+        if (sa->optInfo[i].todo) {
+            switch (i) {
+                /* enable/disable Nagle's Algorithm (see RFC898) */
+                case SA_OPTION_NAGLE: {
+#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
+                    int mode = sa->optInfo[i].value;
+                    if (setsockopt(sa->fdSocket, IPPROTO_TCP, TCP_NODELAY,
+                                   (const void *)&mode,
+                                   (socklen_t)sizeof(mode)) < 0)
+                        rv = SA_ERR_SYS;
+                    else
+                        sa->optInfo[i].todo = FALSE;
+#endif
+                    break;
+                }
+                /* enable/disable linger close semantics */
+                case SA_OPTION_LINGER: {
+#if defined(SO_LINGER)
+                    struct linger linger;
+                    linger.l_onoff  = (sa->optInfo[i].value == 0 ? 0 : 1);
+                    linger.l_linger = sa->optInfo[i].value;
+                    if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_LINGER,
+                                   (const void *)&linger,
+                                   (socklen_t)sizeof(struct linger)) < 0)
+                        rv = SA_ERR_SYS;
+                    else
+                        sa->optInfo[i].todo = FALSE;
+#endif
+                    break;
+                }
+                /* enable/disable reusability of binding to address */
+                case SA_OPTION_REUSEADDR: {
+#if defined(SO_REUSEADDR)
+                    int mode = sa->optInfo[i].value;
+                    if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_REUSEADDR,
+                                   (const void *)&mode, (socklen_t)sizeof(mode)) < 0)
+                        rv = SA_ERR_SYS;
+                    else
+                        sa->optInfo[i].todo = FALSE;
+#endif
+                    break;
+                }
+                /* enable/disable reusability of binding to port */
+                case SA_OPTION_REUSEPORT: {
+#if defined(SO_REUSEPORT)
+                    int mode = sa->optInfo[i].value;
+                    if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_REUSEPORT,
+                                   (const void *)&mode, (socklen_t)sizeof(mode)) < 0)
+                        rv = SA_ERR_SYS;
+                    else
+                        sa->optInfo[i].todo = FALSE;
+#endif
+                    break;
+                }
+                /* enable/disable non-blocking I/O mode */
+                case SA_OPTION_NONBLOCK: {
+                    int mode = sa->optInfo[i].value;
+                    int flags;
+                    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;
+                    else
+                        sa->optInfo[i].todo = FALSE;
+                    break;
+                }
+                default: /* NOTREACHED */ break;
+            }
+        }
+    }
+
+    return SA_RC(rv);
+}
+
 /* internal lazy/delayed initialization of underlying socket */
 static sa_rc_t sa_socket_init(sa_t *sa, int nFamily)
 {
@@ -891,6 +1006,7 @@
 #if !(defined(IPPROTO_TCP) && defined(IPPROTO_UDP))
     struct protoent *pe;
 #endif
+    sa_rc_t rv;
 
     /* argument sanity check(s) */
     if (sa == NULL)
@@ -909,7 +1025,7 @@
         return SA_RC(SA_ERR_INT);
 
     /* determine socket protocol */
-    if (nFamily == AF_LOCAL) 
+    if (nFamily == AF_LOCAL)
         nProto = 0;
 #ifdef AF_INET6
     else if (nFamily == AF_INET || nFamily == AF_INET6) {
@@ -943,7 +1059,12 @@
         return SA_RC(SA_ERR_SYS);
 
     /* optionally set kernel timeouts */
-    sa_socket_settimeouts(sa);
+    if ((rv = sa_socket_settimeouts(sa)) != SA_OK)
+        return SA_RC(rv);
+
+    /* optionally configure changed options */
+    if ((rv = sa_socket_setoptions(sa)) != SA_OK)
+        return SA_RC(rv);
 
     return SA_OK;
 }
@@ -996,6 +1117,12 @@
         sa->tvTimeout[i].tv_usec = 0;
     }
 
+    /* init options object attributes */
+    for (i = 0; i < (sizeof(sa->optInfo)/sizeof(sa->optInfo[0])); i++) {
+        sa->optInfo[i].todo  = FALSE;
+        sa->optInfo[i].value = 0;
+    }
+
     /* init syscall object attributes */
     SA_SC_ASSIGN(sa, connect,  connect,  NULL);
     SA_SC_ASSIGN(sa, accept,   accept,   NULL);
@@ -1054,6 +1181,7 @@
 sa_rc_t sa_timeout(sa_t *sa, sa_timeout_t id, long sec, long usec)
 {
     int i;
+    sa_rc_t rv;
 
     /* argument sanity check(s) */
     if (sa == NULL)
@@ -1070,8 +1198,9 @@
         sa->tvTimeout[id].tv_usec = usec;
     }
 
-    /* optionally set kernel timeouts */
-    sa_socket_settimeouts(sa);
+    /* try to already set timeouts */
+    if ((rv = sa_socket_settimeouts(sa)) != SA_OK)
+        return SA_RC(rv);
 
     return SA_OK;
 }
@@ -1095,7 +1224,7 @@
             else
                 cp = (char *)realloc(sa->cpReadBuf, size);
             if (cp == NULL)
-                return SA_RC(SA_ERR_SYS);
+                return SA_RC(SA_ERR_MEM);
             sa->cpReadBuf = cp;
             sa->nReadSize = size;
         }
@@ -1116,7 +1245,7 @@
             else
                 cp = (char *)realloc(sa->cpWriteBuf, size);
             if (cp == NULL)
-                return SA_RC(SA_ERR_SYS);
+                return SA_RC(SA_ERR_MEM);
             sa->cpWriteBuf = cp;
             sa->nWriteSize = size;
         }
@@ -1148,16 +1277,10 @@
     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, 
-                           (const void *)&mode, (socklen_t)sizeof(mode)) < 0)
-                rv = SA_ERR_SYS;
+            sa->optInfo[SA_OPTION_NAGLE].value = mode;
+            sa->optInfo[SA_OPTION_NAGLE].todo = TRUE;
 #else
             rv = SA_ERR_IMP;
 #endif
@@ -1165,61 +1288,40 @@
         }
         case SA_OPTION_LINGER: {
 #if defined(SO_LINGER)
-            struct linger *linger = (struct linger *)va_arg(ap, void *);
-            if (sa->fdSocket == -1) {
-                rv = SA_ERR_USE;
-                break;
-            }
-            if (setsockopt(sa->fdSocket, SOL_SOCKET, SO_LINGER, 
-                           (const void *)linger, (socklen_t)sizeof(struct linger)) < 0)
-                rv = SA_ERR_SYS;
+            int amount = ((int)va_arg(ap, int) ? 1 : 0);
+            sa->optInfo[SA_OPTION_LINGER].value = amount;
+            sa->optInfo[SA_OPTION_LINGER].todo = TRUE;
 #else
             rv = SA_ERR_IMP;
 #endif
             break;
         }
         case SA_OPTION_REUSEADDR:
-#ifdef SA_OPTION_REUSEPORT
-        case SA_OPTION_REUSEPORT: 
+        {
+#if defined(SO_REUSEADDR)
+            int mode = ((int)va_arg(ap, int) ? 1 : 0);
+            sa->optInfo[SA_OPTION_REUSEADDR].value = mode;
+            sa->optInfo[SA_OPTION_REUSEADDR].todo = TRUE;
+#else
+            rv = SA_ERR_IMP;
 #endif
+            break;
+        }
+        case SA_OPTION_REUSEPORT:
         {
-            /* enable/disable reusability of binding to address or port */
+#if defined(SO_REUSEPORT)
             int mode = ((int)va_arg(ap, int) ? 1 : 0);
-            int flag;
-            if (sa->fdSocket == -1) {
-                rv = SA_ERR_USE;
-                break;
-            }
-            switch (id) {
-                case SA_OPTION_REUSEADDR: flag = SO_REUSEADDR; break;
-#ifdef SA_OPTION_REUSEPORT
-                case SA_OPTION_REUSEPORT: flag = SO_REUSEPORT; break;
+            sa->optInfo[SA_OPTION_REUSEPORT].value = mode;
+            sa->optInfo[SA_OPTION_REUSEPORT].todo = TRUE;
+#else
+            rv = SA_ERR_IMP;
 #endif
-                default: flag = 0; break;
-            }
-            if (setsockopt(sa->fdSocket, SOL_SOCKET, flag, 
-                           (const void *)&mode, (socklen_t)sizeof(mode)) < 0)
-                rv = SA_ERR_SYS;
             break;
         }
         case SA_OPTION_NONBLOCK: {
-            /* enable/disable non-blocking I/O mode */
-            int flags;
             int mode = (int)va_arg(ap, int);
-            if (sa->fdSocket == -1) {
-                rv = SA_ERR_USE;
-                break;
-            }
-            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;
+            sa->optInfo[SA_OPTION_NONBLOCK].value = mode;
+            sa->optInfo[SA_OPTION_NONBLOCK].todo = TRUE;
             break;
         }
         default: {
@@ -1228,7 +1330,15 @@
     }
     va_end(ap);
 
-    return SA_RC(rv);
+    /* if an error already occured, stop here */
+    if (rv != SA_OK)
+        return SA_RC(rv);
+
+    /* else already (re)set) options (if possible) */
+    if ((rv = sa_socket_setoptions(sa)) != SA_OK)
+        return SA_RC(rv);
+
+    return SA_OK;
 }
 
 /* override system call */
@@ -1250,7 +1360,7 @@
         case SA_SYSCALL_WRITE:    SA_SC_ASSIGN(sa, write,    fptr, fctx); break;
         case SA_SYSCALL_RECVFROM: SA_SC_ASSIGN(sa, recvfrom, fptr, fctx); break;
         case SA_SYSCALL_SENDTO:   SA_SC_ASSIGN(sa, sendto,   fptr, fctx); break;
-        default: rv = SA_ERR_ARG; 
+        default: rv = SA_ERR_ARG;
     }
 
     return SA_RC(rv);
@@ -1296,7 +1406,7 @@
     if (sa == NULL || raddr == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* connecting is only possible for stream communication */ 
+    /* connecting is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1329,7 +1439,7 @@
 
         /* ok if connect completed immediately */
         if (n == 0)
-            goto done; 
+            goto done;
 
         /* wait for read or write possibility */
         FD_ZERO(&rset);
@@ -1381,7 +1491,7 @@
     if (sa == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* listening is only possible for stream communication */ 
+    /* listening is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1409,7 +1519,7 @@
         struct sockaddr_in6 sa6;
 #endif
     } sa_buf;
-    socklen_t sa_len;
+    socklen_t sa_size;
     int s;
     int i;
 
@@ -1417,7 +1527,7 @@
     if (sa == NULL || caddr == NULL || csa == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* accepting connections is only possible for stream communication */ 
+    /* accepting connections is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1433,21 +1543,21 @@
             n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL,
                              &sa->tvTimeout[SA_TIMEOUT_ACCEPT]);
         } while (n == -1 && errno == EINTR);
-        if (n == 0) 
+        if (n == 0)
             return SA_RC(SA_ERR_TMT);
         if (n <= 0)
             return SA_RC(SA_ERR_SYS);
     }
 
     /* perform accept operation on underlying socket */
-    sa_len = sizeof(sa_buf);
-    if ((s = SA_SC_CALL_3(sa, accept, sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_len)) == -1)
+    sa_size = sizeof(sa_buf);
+    if ((s = SA_SC_CALL_3(sa, accept, sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_size)) == -1)
         return SA_RC(SA_ERR_SYS);
 
     /* create result address object */
     if ((rv = sa_addr_create(caddr)) != SA_OK)
         return SA_RC(rv);
-    if ((rv = sa_addr_s2a(*caddr, (struct sockaddr *)&sa_buf, sa_len)) != SA_OK) {
+    if ((rv = sa_addr_s2a(*caddr, (struct sockaddr *)&sa_buf, sa_size)) != SA_OK) {
         sa_addr_destroy(*caddr);
         return SA_RC(rv);
     }
@@ -1489,13 +1599,13 @@
         struct sockaddr_in6 sa6;
 #endif
     } sa_buf;
-    socklen_t sa_len;
+    socklen_t sa_size;
 
     /* argument sanity check(s) */
     if (sa == NULL || raddr == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* peers exist only for stream communication */ 
+    /* peers exist only for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1504,14 +1614,14 @@
         return SA_RC(SA_ERR_USE);
 
     /* determine remote address of underlying socket */
-    sa_len = sizeof(sa_buf);
-    if (getpeername(sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_len) < 0)
+    sa_size = sizeof(sa_buf);
+    if (getpeername(sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_size) < 0)
         return SA_RC(SA_ERR_SYS);
 
     /* create result address object */
     if ((rv = sa_addr_create(raddr)) != SA_OK)
         return SA_RC(rv);
-    if ((rv = sa_addr_s2a(*raddr, (struct sockaddr *)&sa_buf, sa_len)) != SA_OK) {
+    if ((rv = sa_addr_s2a(*raddr, (struct sockaddr *)&sa_buf, sa_size)) != SA_OK) {
         sa_addr_destroy(*raddr);
         return SA_RC(rv);
     }
@@ -1529,7 +1639,7 @@
         struct sockaddr_in6 sa6;
 #endif
     } sa_buf;
-    socklen_t sa_len;
+    socklen_t sa_size;
 
     /* argument sanity check(s) */
     if (sa == NULL || laddr == NULL)
@@ -1540,14 +1650,14 @@
         return SA_RC(SA_ERR_USE);
 
     /* determine local address of underlying socket */
-    sa_len = sizeof(sa_buf);
-    if (getsockname(sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_len) < 0)
+    sa_size = sizeof(sa_buf);
+    if (getsockname(sa->fdSocket, (struct sockaddr *)&sa_buf, &sa_size) < 0)
         return SA_RC(SA_ERR_SYS);
 
     /* create result address object */
     if ((rv = sa_addr_create(laddr)) != SA_OK)
         return SA_RC(rv);
-    if ((rv = sa_addr_s2a(*laddr, (struct sockaddr *)&sa_buf, sa_len)) != SA_OK) {
+    if ((rv = sa_addr_s2a(*laddr, (struct sockaddr *)&sa_buf, sa_size)) != SA_OK) {
         sa_addr_destroy(*laddr);
         return SA_RC(rv);
     }
@@ -1580,14 +1690,14 @@
     fd_set fds;
 #endif
 
-    /* if timeout is enabled, perform explicit/smart blocking instead 
+    /* 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);
         do {
-            rv = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL, 
+            rv = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL,
                               &sa->tvTimeout[SA_TIMEOUT_READ]);
         } while (rv == -1 && errno == EINTR);
         if (rv == 0) {
@@ -1621,7 +1731,7 @@
     if (sa == NULL || cpBuf == NULL || nBufReq == 0)
         return SA_RC(SA_ERR_ARG);
 
-    /* reading is only possible for stream communication */ 
+    /* reading is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1686,7 +1796,7 @@
                     else if (n < 0)
                         /* error on this read, but perhaps ok as a whole */
                         rv = (res == 0 ? SA_ERR_SYS : SA_OK);
-                    if (n == 0)
+                    else if (n == 0)
                         /* EOF on this read, but perhaps ok as a whole */
                         rv = (res == 0 ? SA_ERR_EOF : SA_OK);
                     else {
@@ -1699,7 +1809,7 @@
         }
     }
 
-    /* pass number of actually read bytes to caller */ 
+    /* pass number of actually read bytes to caller */
     if (nBufRes != NULL)
         *nBufRes = (size_t)res;
 
@@ -1718,7 +1828,7 @@
     if (sa == NULL || cpBuf == NULL || nBufReq == 0)
         return SA_RC(SA_ERR_ARG);
 
-    /* reading is only possible for stream communication */ 
+    /* reading is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1759,14 +1869,14 @@
     fd_set fds;
 #endif
 
-    /* if timeout is enabled, perform explicit/smart blocking instead 
+    /* 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);
         do {
-            rv = SA_SC_CALL_5(sa, select, sa->fdSocket+1, NULL, &fds, NULL, 
+            rv = SA_SC_CALL_5(sa, select, sa->fdSocket+1, NULL, &fds, NULL,
                               &sa->tvTimeout[SA_TIMEOUT_WRITE]);
         } while (rv == -1 && errno == EINTR);
         if (rv == 0) {
@@ -1800,7 +1910,7 @@
     if (sa == NULL || cpBuf == NULL || nBufReq == 0)
         return SA_RC(SA_ERR_ARG);
 
-    /* writing is only possible for stream communication */ 
+    /* writing is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1867,8 +1977,8 @@
     sa_writef_cb_t *ctx = (sa_writef_cb_t *)_ctx;
 
     if ((ctx->rv = sa_write(ctx->sa, buffer, bufsize, &n)) != SA_OK)
-        n = -1;
-    return n;
+        return -1;
+    return (int)n;
 }
 
 /* write formatted string to socket (convinience function) */
@@ -1882,7 +1992,7 @@
     if (sa == NULL || cpFmt == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* writing is only possible for stream communication */ 
+    /* writing is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1910,7 +2020,7 @@
     if (sa == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* flushing is only possible for stream communication */ 
+    /* flushing is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1946,7 +2056,7 @@
     if (sa == NULL || flags == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* shutdown is only possible for stream communication */ 
+    /* shutdown is only possible for stream communication */
     if (sa->eType != SA_TYPE_STREAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1960,11 +2070,15 @@
         how = SHUT_RD;
     else if (strcmp(flags, "w") == 0)
         how = SHUT_WR;
-    else if (strcmp(flags, "rw") == 0)
+    else if (strcmp(flags, "rw") == 0 || strcmp(flags, "wr") == 0)
         how = SHUT_RDWR;
     else
         return SA_RC(SA_ERR_ARG);
 
+    /* flush write buffers */
+    if ((how & SHUT_WR) || (how & SHUT_RDWR))
+        sa_flush(sa);
+
     /* perform shutdown operation on underlying socket */
     if (shutdown(sa->fdSocket, how) == -1)
         return SA_RC(SA_ERR_SYS);
@@ -1973,7 +2087,7 @@
 }
 
 /* receive data via socket */
-sa_rc_t sa_recv(sa_t *sa, char *buf, size_t buflen, size_t *bufdone, sa_addr_t **raddr)
+sa_rc_t sa_recv(sa_t *sa, sa_addr_t **raddr, char *buf, size_t buflen, size_t *bufdone)
 {
     sa_rc_t rv;
     union {
@@ -1982,7 +2096,7 @@
         struct sockaddr_in6 sa6;
 #endif
     } sa_buf;
-    socklen_t sa_len;
+    socklen_t sa_size;
     size_t n;
     fd_set fds;
 
@@ -1990,7 +2104,7 @@
     if (sa == NULL || buf == NULL || buflen == 0 || raddr == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* receiving is only possible for datagram communication */ 
+    /* receiving is only possible for datagram communication */
     if (sa->eType != SA_TYPE_DATAGRAM)
         return SA_RC(SA_ERR_USE);
 
@@ -1998,31 +2112,31 @@
     if (sa->fdSocket == -1)
         return SA_RC(SA_ERR_USE);
 
-    /* if timeout is enabled, perform explicit/smart blocking instead 
+    /* 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_READ])) {
         FD_ZERO(&fds);
         FD_SET(sa->fdSocket, &fds);
         do {
-            n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL, 
+            n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &fds, NULL, NULL,
                              &sa->tvTimeout[SA_TIMEOUT_READ]);
         } while (n == -1 && errno == EINTR);
-        if (n == 0) 
+        if (n == 0)
             errno = ETIMEDOUT;
         if (n <= 0)
             return SA_RC(SA_ERR_SYS);
     }
 
     /* perform receive operation on underlying socket */
-    sa_len = sizeof(sa_buf);
-    if ((n = SA_SC_CALL_6(sa, recvfrom, sa->fdSocket, buf, buflen, 0, 
-                          (struct sockaddr *)&sa_buf, &sa_len)) == -1)
+    sa_size = sizeof(sa_buf);
+    if ((n = SA_SC_CALL_6(sa, recvfrom, sa->fdSocket, buf, buflen, 0,
+                          (struct sockaddr *)&sa_buf, &sa_size)) == -1)
         return SA_RC(SA_ERR_SYS);
 
     /* create result address object */
     if ((rv = sa_addr_create(raddr)) != SA_OK)
         return rv;
-    if ((rv = sa_addr_s2a(*raddr, (struct sockaddr *)&sa_buf, sa_len)) != SA_OK) {
+    if ((rv = sa_addr_s2a(*raddr, (struct sockaddr *)&sa_buf, sa_size)) != SA_OK) {
         sa_addr_destroy(*raddr);
         return rv;
     }
@@ -2035,7 +2149,7 @@
 }
 
 /* send data via socket */
-sa_rc_t sa_send(sa_t *sa, const char *buf, size_t buflen, size_t *bufdone, sa_addr_t *raddr)
+sa_rc_t sa_send(sa_t *sa, sa_addr_t *raddr, const char *buf, size_t buflen, size_t *bufdone)
 {
     size_t n;
     fd_set fds;
@@ -2045,7 +2159,7 @@
     if (sa == NULL || buf == NULL || buflen == 0 || raddr == NULL)
         return SA_RC(SA_ERR_ARG);
 
-    /* sending is only possible for datagram communication */ 
+    /* sending is only possible for datagram communication */
     if (sa->eType != SA_TYPE_DATAGRAM)
         return SA_RC(SA_ERR_USE);
 
@@ -2054,16 +2168,16 @@
         if ((rv = sa_socket_init(sa, raddr->nFamily)) != SA_OK)
             return rv;
 
-    /* if timeout is enabled, perform explicit/smart blocking instead 
+    /* 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_WRITE])) {
         FD_ZERO(&fds);
         FD_SET(sa->fdSocket, &fds);
         do {
-            n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, NULL, &fds, NULL, 
+            n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, NULL, &fds, NULL,
                              &sa->tvTimeout[SA_TIMEOUT_WRITE]);
         } while (n == -1 && errno == EINTR);
-        if (n == 0) 
+        if (n == 0)
             errno = ETIMEDOUT;
         if (n <= 0)
             return SA_RC(SA_ERR_SYS);
@@ -2080,6 +2194,46 @@
     return SA_OK;
 }
 
+/* send formatted string to socket (convinience function) */
+sa_rc_t sa_sendf(sa_t *sa, sa_addr_t *raddr, const char *cpFmt, ...)
+{
+    va_list ap;
+    size_t nBuf;
+    char *cpBuf;
+    sa_rc_t rv;
+    char caBuf[1024];
+
+    /* argument sanity check(s) */
+    if (sa == NULL || raddr == NULL || cpFmt == NULL)
+        return SA_RC(SA_ERR_ARG);
+
+    /* format string into temporary buffer */
+    va_start(ap, cpFmt);
+    nBuf = sa_mvsnprintf(NULL, 0, cpFmt, ap);
+    va_end(ap);
+    if ((nBuf+1) > sizeof(caBuf)) {
+        /* requires a larger buffer, so allocate dynamically */
+        if ((cpBuf = (char *)malloc(nBuf+1)) == NULL)
+            return SA_RC(SA_ERR_MEM);
+    }
+    else {
+        /* fits into small buffer, so allocate statically */
+        cpBuf = caBuf;
+    }
+    va_start(ap, cpFmt);
+    sa_mvsnprintf(cpBuf, nBuf+1, cpFmt, ap);
+    va_end(ap);
+
+    /* pass-through to sa_send() */
+    rv = sa_send(sa, raddr, cpBuf, nBuf, NULL);
+
+    /* cleanup dynamically allocated buffer */
+    if ((nBuf+1) > sizeof(caBuf))
+        free(cpBuf);
+
+    return rv;
+}
+
 /* return error string */
 char *sa_error(sa_rc_t rv)
 {


ossp-pkg/l2/l2_ut_sa.h 1.15 -> 1.16

--- l2_ut_sa.h   2002/10/21 15:14:04     1.15
+++ l2_ut_sa.h   2002/11/09 14:44:31     1.16
@@ -137,11 +137,11 @@
 
 /* list of options */
 typedef enum {
-    SA_OPTION_NAGLE,
-    SA_OPTION_LINGER,
-    SA_OPTION_REUSEADDR,
-    SA_OPTION_REUSEPORT,
-    SA_OPTION_NONBLOCK
+    SA_OPTION_NAGLE     = 0,
+    SA_OPTION_LINGER    = 1,
+    SA_OPTION_REUSEADDR = 2,
+    SA_OPTION_REUSEPORT = 3,
+    SA_OPTION_NONBLOCK  = 4
 } sa_option_t;
 
 /* list of system calls */
@@ -159,50 +159,51 @@
 extern const char sa_id[];
 
 /* address object operations */
-sa_rc_t sa_addr_create  (sa_addr_t **saa);
-sa_rc_t sa_addr_destroy (sa_addr_t *saa);
+extern sa_rc_t sa_addr_create  (sa_addr_t **__saa);
+extern sa_rc_t sa_addr_destroy (sa_addr_t  *__saa);
 
 /* address operations */
-sa_rc_t sa_addr_u2a     (sa_addr_t *saa, const char *uri, ...);
-sa_rc_t sa_addr_s2a     (sa_addr_t *saa, const struct sockaddr *sabuf, socklen_t salen);
-sa_rc_t sa_addr_a2u     (sa_addr_t *saa, char **uri);
-sa_rc_t sa_addr_a2s     (sa_addr_t *saa, struct sockaddr **sabuf, socklen_t *salen);
-sa_rc_t sa_addr_match   (sa_addr_t *saa1, sa_addr_t *saa2, int prefixlen);
+extern sa_rc_t sa_addr_u2a     (sa_addr_t  *__saa, const char *__uri, ...);
+extern sa_rc_t sa_addr_s2a     (sa_addr_t  *__saa, const struct sockaddr *__sabuf, socklen_t __salen);
+extern sa_rc_t sa_addr_a2u     (sa_addr_t  *__saa, char **__uri);
+extern sa_rc_t sa_addr_a2s     (sa_addr_t  *__saa, struct sockaddr **__sabuf, socklen_t *__salen);
+extern sa_rc_t sa_addr_match   (sa_addr_t  *__saa1, sa_addr_t *__saa2, int __prefixlen);
 
 /* socket object operations */
-sa_rc_t sa_create       (sa_t **sa);
-sa_rc_t sa_destroy      (sa_t *sa);
+extern sa_rc_t sa_create       (sa_t **__sa);
+extern sa_rc_t sa_destroy      (sa_t  *__sa);
 
 /* socket parameter operations */
-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);
+extern sa_rc_t sa_type         (sa_t  *__sa, sa_type_t    __id);
+extern sa_rc_t sa_timeout      (sa_t  *__sa, sa_timeout_t __id, long __sec, long __usec);
+extern sa_rc_t sa_buffer       (sa_t  *__sa, sa_buffer_t  __id, size_t __size);
+extern sa_rc_t sa_option       (sa_t  *__sa, sa_option_t  __id, ...);
+extern sa_rc_t sa_syscall      (sa_t  *__sa, sa_syscall_t __id, void (*__fptr)(), void *__fctx);
 
 /* socket connection operations */
-sa_rc_t sa_bind         (sa_t *sa, sa_addr_t *laddr);
-sa_rc_t sa_connect      (sa_t *sa, sa_addr_t *raddr);
-sa_rc_t sa_listen       (sa_t *sa, int backlog);
-sa_rc_t sa_accept       (sa_t *sa, sa_addr_t **caddr, sa_t **csa);
-sa_rc_t sa_getremote    (sa_t *sa, sa_addr_t **raddr);
-sa_rc_t sa_getlocal     (sa_t *sa, sa_addr_t **laddr);
-sa_rc_t sa_getfd        (sa_t *sa, int *fd);
-sa_rc_t sa_shutdown     (sa_t *sa, char *flags);
+extern sa_rc_t sa_bind         (sa_t  *__sa, sa_addr_t  *__laddr);
+extern sa_rc_t sa_connect      (sa_t  *__sa, sa_addr_t  *__raddr);
+extern sa_rc_t sa_listen       (sa_t  *__sa, int __backlog);
+extern sa_rc_t sa_accept       (sa_t  *__sa, sa_addr_t **__caddr, sa_t **__csa);
+extern sa_rc_t sa_getremote    (sa_t  *__sa, sa_addr_t **__raddr);
+extern sa_rc_t sa_getlocal     (sa_t  *__sa, sa_addr_t **__laddr);
+extern sa_rc_t sa_getfd        (sa_t  *__sa, int *__fd);
+extern sa_rc_t sa_shutdown     (sa_t  *__sa, char *__flags);
 
 /* socket input/output operations (stream communication) */
-sa_rc_t sa_read         (sa_t *sa, char *buf, size_t buflen, size_t *bufdone);
-sa_rc_t sa_readln       (sa_t *sa, char *buf, size_t buflen, size_t *bufdone);
-sa_rc_t sa_write        (sa_t *sa, const char *buf, size_t buflen, size_t *bufdone);
-sa_rc_t sa_writef       (sa_t *sa, const char *fmt, ...);
-sa_rc_t sa_flush        (sa_t *sa);
+extern sa_rc_t sa_read         (sa_t  *__sa, char       *__buf, size_t __buflen, size_t *__bufdone);
+extern sa_rc_t sa_readln       (sa_t  *__sa, char       *__buf, size_t __buflen, size_t *__bufdone);
+extern sa_rc_t sa_write        (sa_t  *__sa, const char *__buf, size_t __buflen, size_t *__bufdone);
+extern sa_rc_t sa_writef       (sa_t  *__sa, const char *__fmt, ...);
+extern sa_rc_t sa_flush        (sa_t  *__sa);
 
 /* socket input/output operations (datagram communication) */
-sa_rc_t sa_recv         (sa_t *sa, char *buf, size_t buflen, size_t *bufdone, sa_addr_t **raddr);
-sa_rc_t sa_send         (sa_t *sa, const char *buf, size_t buflen, size_t *bufdone, sa_addr_t *raddr);
+extern sa_rc_t sa_recv         (sa_t  *__sa, sa_addr_t **__raddr, char       *__buf, size_t __buflen, size_t *__bufdone);
+extern sa_rc_t sa_send         (sa_t  *__sa, sa_addr_t  *__raddr, const char *__buf, size_t __buflen, size_t *__bufdone);
+extern sa_rc_t sa_sendf        (sa_t  *__sa, sa_addr_t  *__raddr, const char *__fmt, ...);
 
 /* error handling operations */
-char   *sa_error        (sa_rc_t rv);
+extern char   *sa_error        (sa_rc_t __rv);
 
 /* cleanup */
 #if defined(HAVE_CONFIG_H) && !defined(HAVE_SOCKLEN_T)

CVSTrac 2.0.1