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.4' '-r1.5' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.c,v' 2>/dev/null --- l2_ut_sa.c 2001/09/08 22:05:46 1.4 +++ l2_ut_sa.c 2001/09/09 15:54:31 1.5 @@ -24,9 +24,10 @@ ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** -** l2_ut_sa.c: utility library for socket address handling +** l2_ut_sa.c: socket abstraction library */ +/* system headers */ #include #include #include @@ -34,6 +35,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -41,15 +45,24 @@ #include #include +/* own headers */ #include "l2_config.h" #include "l2_ut_sa.h" +struct sa_addr_st { + struct sockaddr *saa_buf; + socklen_t saa_len; + int saa_family; + int saa_proto; +}; + #if !defined(AF_LOCAL) && defined(AF_UNIX) #define AF_LOCAL AF_UNIX #endif -#ifndef HAVE_INET_PTON -#ifdef HAVE_INET_ATON +#if defined(HAVE_INET_PTON) +#define sa_inet_pton inet_pton +#elif defined(HAVE_INET_ATON) static int inet_pton(int family, const char *strptr, void *addrptr) { struct in_addr in_val; @@ -67,16 +80,69 @@ #else #error "neither inet_pton nor inet_aton available" #endif + +#if defined(HAVE_INET_NTOP) +#define sa_inet_ntop inet_ntop +#elif defined(HAVE_INET_NTOA) +static char *inet_ntop(int family, const void *src, char *dst, size_t size) +{ + struct in_addr in_val; + char *cp; + int n; + + if (family == AF_INET) { + if ((cp = inet_ntoa(src)) != NULL) { + n = strlen(cp); + if (n > size-1) + n = size-1; + memcpy(dst, cp, n); + dst[n] = '\0'; + return 1; + } + return 0; + } + errno = EAFNOSUPPORT; + return -1; +} +#else +#error "neither inet_ntop nor inet_ntoa available" +#endif + +#if defined(HAVE_VSNPRINTF) +#define sa_vsnprintf vsnprintf +#elif defined(HAVE_VSPRINTF) +static int sa_vsnprintf(char *str, size_t size, const char *fmt, va_list ap) +{ + int rv; + + rv = vsprintf(str, fmt, ap); + if (rv > size) { + fprintf(stderr, "ERROR: vsprintf(3) buffer overflow!\n"); + abort(); + } +} +#else +#error "neither vsnprintf nor vsprintf available" #endif -#ifndef NUL -#define NUL '\0' +#if defined(HAVE_SNPRINTF) +#define sa_snprintf snprintf +#else +static int sa_snprintf(char *str, size_t size, const char *fmt, ...) +{ + va_list ap; + int rv; + + va_start(ap, fmt); + rv = sa_vsnprintf(str, size, fmt, ap); + va_end(ap); + return rv; +} #endif -l2_util_sa_t *l2_util_sa_create(int sa_type, ...) +sa_rc_t sa_u2a(sa_addr_t **saa, const char *uri, ...) { va_list ap; - l2_util_sa_t *rc; int nPort; socklen_t sl; struct sockaddr *sa; @@ -84,135 +150,644 @@ #ifdef AF_INET6 struct sockaddr_in6 sa6; #endif - struct sockaddr_un sau; struct hostent *he; struct servent *se; struct protoent *pe; int bNumeric; int i; - char *cpPath; - int nPath; char *cpProto; int nProto; char *cpHost; char *cpPort; + char uribuf[1024]; + char *cp; + int sf; + + if (saa == NULL || uri == NULL) + return SA_ERR_ARG; + + /* create or just take over URI */ + va_start(ap, uri); + sa_vsnprintf(uribuf, sizeof(uribuf), uri, ap); + va_end(ap); - va_start(ap, sa_type); - sa = NULL; - sl = 0; - if (sa_type == L2_UTIL_SA_UNIX) { -#if defined(AF_LOCAL) - if ((cpPath = va_arg(ap, char *)) == NULL) - return NULL; - if ((nPath = strlen(cpPath)) >= (sizeof(sau.sun_path)-1)) - return NULL; - nProto = 0; - memset(&sau, 0, sizeof(sau)); - sau.sun_family = AF_LOCAL; - memcpy(sau.sun_path, cpPath, nPath + 1); - sa = (struct sockaddr *)&sau; - sl = sizeof(sau); -#else - return NULL; -#endif + /* parse URI into protocol, host and port parts */ + uri = uribuf; + cpProto = "tcp"; + if ((cp = strstr(uri, "://")) != NULL) { + cpProto = (char *)uri; + *cp = '\0'; + uri = cp+3; } - else if (sa_type == L2_UTIL_SA_IP) { - if ((cpProto = va_arg(ap, char *)) == NULL) - return NULL; - if ((cpHost = va_arg(ap, char *)) == NULL) - return NULL; - if ((cpPort = va_arg(ap, char *)) == NULL) - return NULL; - - /* resolve protocol */ - if ((pe = getprotobyname(cpProto)) == NULL) - return NULL; - nProto = pe->p_proto; - - /* resolve port */ - bNumeric = 1; - for (i = 0; cpPort[i] != NUL; i++) { - if (!isdigit((int)cpPort[i])) { - bNumeric = 0; - break; - } - } - if (bNumeric) - nPort = atoi(cpPort); - else { - if ((se = getservbyname(cpPort, cpProto)) == NULL) - return NULL; - nPort = ntohs(se->s_port); + cpHost = (char *)uri; + if ((cp = strchr(uri, ':')) == NULL) + return SA_ERR_ARG; + *cp++ = '\0'; + cpPort = cp; + + /* resolve protocol */ + if ((pe = getprotobyname(cpProto)) == NULL) + return SA_ERR_SYS; + nProto = pe->p_proto; + + /* resolve port */ + bNumeric = 1; + for (i = 0; cpPort[i] != '\0'; i++) { + if (!isdigit((int)cpPort[i])) { + bNumeric = 0; + break; } + } + if (bNumeric) + nPort = atoi(cpPort); + else { + if ((se = getservbyname(cpPort, cpProto)) == NULL) + return SA_ERR_SYS; + nPort = ntohs(se->s_port); + } - /* mandatory initialization */ - memset(&sa4, 0, sizeof(sa4)); + /* mandatory(!) socket address structure initialization */ + memset(&sa4, 0, sizeof(sa4)); #ifdef AF_INET6 - memset(&sa6, 0, sizeof(sa6)); + memset(&sa6, 0, sizeof(sa6)); #endif - /* resolve host */ - if (inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) { + + /* resolve host by trying to parse it as either directly a IPv4 or + IPv6 address or by resolving it to either a IPv4 or IPv6 address */ + sa = NULL; + sl = 0; + sf = 0; + if (inet_pton(AF_INET, cpHost, &sa4.sin_addr.s_addr) == 1) { + sa4.sin_family = AF_INET; + sa4.sin_port = htons(nPort); + sa = (struct sockaddr *)&sa4; + sl = sizeof(sa4); + sf = AF_INET; + } +#ifdef AF_INET6 + else if (inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) { + sa6.sin6_family = AF_INET6; + sa6.sin6_port = htons(nPort); + sa = (struct sockaddr *)&sa6; + sl = sizeof(sa6); + sf = AF_INET6; + } +#endif + else if ((he = gethostbyname(cpHost)) != NULL) { + if (he->h_addrtype == AF_INET) { sa4.sin_family = AF_INET; sa4.sin_port = htons(nPort); + memcpy(&sa4.sin_addr.s_addr, he->h_addr_list[0], sizeof(sa4.sin_addr.s_addr)); sa = (struct sockaddr *)&sa4; sl = sizeof(sa4); + sf = AF_INET; } #ifdef AF_INET6 - else if (inet_pton(AF_INET6, cpHost, &sa6.sin6_addr.s6_addr) == 1) { + 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], sizeof(sa6.sin6_addr.s6_addr)); sa = (struct sockaddr *)&sa6; sl = sizeof(sa6); + sf = AF_INET6; } #endif - else if ((he = gethostbyname(cpHost)) != NULL) { - if (he->h_addrtype == AF_INET) { - sa4.sin_family = AF_INET; - sa4.sin_port = htons(nPort); - memcpy(&sa4.sin_addr.s_addr, he->h_addr_list[0], sizeof(sa4.sin_addr.s_addr)); - sa = (struct sockaddr *)&sa4; - sl = sizeof(sa4); - } + } + if (sa == NULL) + return SA_ERR_ARG; + + /* create result address structure */ + if ((*saa = (sa_addr_t *)malloc(sizeof(sa_addr_t))) == NULL) + return SA_ERR_MEM; + if (((*saa)->saa_buf = (struct sockaddr *)malloc(sl)) == NULL) { + free(*saa); + return SA_ERR_MEM; + } + memcpy((*saa)->saa_buf, sa, sl); + (*saa)->saa_len = sl; + (*saa)->saa_family = sf; + (*saa)->saa_proto = nProto; + return SA_OK; +} + +sa_rc_t sa_s2a(sa_addr_t **saa, const struct sockaddr *sabuf, socklen_t salen) +{ + struct sockaddr_in *sa4; #ifdef AF_INET6 - 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], sizeof(sa6.sin6_addr.s6_addr)); - sa = (struct sockaddr *)&sa6; - sl = sizeof(sa6); - } + struct sockaddr_in6 *sa6; #endif - } + struct protoent *pe; + int sf; + + if (saa == NULL || sabuf == NULL || salen == 0) + return SA_ERR_ARG; + + /* create result address structure */ + if ((*saa = (sa_addr_t *)malloc(sizeof(sa_addr_t))) == NULL) + return SA_ERR_MEM; + if (((*saa)->saa_buf = (struct sockaddr *)malloc(salen)) == NULL) { + free(*saa); + return SA_ERR_MEM; } + memcpy((*saa)->saa_buf, sabuf, salen); + (*saa)->saa_len = salen; + + /* fill in family */ + sf = 0; + if (sizeof(struct sockaddr_in) == salen) { + sa4 = (struct sockaddr_in *)sabuf; + if (sa4->sin_family == AF_INET) + sf = AF_INET; + } +#ifdef AF_INET6 + else if (sizeof(struct sockaddr_in6) == salen) { + sa6 = (struct sockaddr_in6 *)sabuf; + if (sa6->sin6_family == AF_INET6) + sf = AF_INET6; + } +#endif + (*saa)->saa_family = sf; + + /* fill in protocol */ + if ((pe = getprotobyname("tcp")) != NULL) + (*saa)->saa_proto = pe->p_proto; else - return NULL; - va_end(ap); + (*saa)->saa_proto = 0; + return SA_OK; +} - if (sa == NULL) - return NULL; - - if ((rc = (l2_util_sa_t *)malloc(sizeof(l2_util_sa_t))) == NULL) - return NULL; - if ((rc->sa_buf = (struct sockaddr *)malloc(sl)) == NULL) { - free(rc); - return NULL; +sa_rc_t sa_a2u(const sa_addr_t *saa, char **uri) +{ + char uribuf[1024]; + struct protoent *pe; + struct sockaddr_in *sa4; +#ifdef AF_INET6 + struct sockaddr_in6 *sa6; +#endif + char caHost[512]; + int nPort; + + if (saa == NULL || uri == NULL) + return SA_ERR_ARG; + if ((pe = getprotobynumber(saa->saa_proto)) == NULL) + return SA_ERR_SYS; + if (saa->saa_family == AF_INET) { + sa4 = (struct sockaddr_in *)saa->saa_buf; + inet_ntop(AF_INET, &sa4->sin_addr.s_addr, caHost, sizeof(caHost)); + nPort = ntohs(sa4->sin_port); } - memcpy(rc->sa_buf, sa, sl); - rc->sa_len = sl; - rc->sa_proto = nProto; +#ifdef AF_INET6 + else if (saa->saa_family == AF_INET6) { + sa6 = (struct sockaddr_in6 *)saa->saa_buf; + inet_ntop(AF_INET6, &sa6->sin6_addr.s6_addr, caHost, sizeof(caHost)); + nPort = ntohs(sa6->sin6_port); + } +#endif + else + return SA_ERR_ARG; + sa_snprintf(uribuf, sizeof(uribuf), "%s://%s:%d", pe->p_name, caHost, nPort); + *uri = strdup(uribuf); + return SA_OK; +} + +sa_rc_t sa_a2s(const sa_addr_t *saa, struct sockaddr **sabuf, socklen_t *salen) +{ + if (saa == NULL || sabuf == NULL || salen == 0) + return SA_ERR_ARG; - return rc; + if ((*sabuf = (struct sockaddr *)malloc(saa->saa_len)) == NULL) + return SA_ERR_MEM; + memmove(*sabuf, saa->saa_buf, saa->saa_len); + *salen = saa->saa_len; + return SA_OK; } -void l2_util_sa_destroy(l2_util_sa_t *sa) +struct sa_st { + int sSocket; + int bTimeout; + struct timeval tvTimeout; + int nReadLen; + int nReadSize; + char *cpReadBuf; + int nWriteLen; + int nWriteSize; + char *cpWriteBuf; +}; + +static sa_rc_t sa_socket_init(sa_t *sa, int family, int proto) { if (sa == NULL) - return; + return SA_ERR_ARG; + if (sa->sSocket != -1) + return SA_ERR_USE; + if ((sa->sSocket = socket(family, SOCK_STREAM, proto)) == -1) + return SA_ERR_SYS; + return SA_OK; +} + +static sa_rc_t sa_socket_kill(sa_t *sa) +{ + if (sa == NULL) + return SA_ERR_ARG; + if (sa->sSocket == -1) { + close(sa->sSocket); + sa->sSocket = -1; + } + return SA_OK; +} + +sa_rc_t sa_create(sa_t **sap) +{ + sa_t *sa; - if (sa->sa_buf != NULL) - free(sa->sa_buf); + if ((sa = (sa_t *)malloc(sizeof(sa_t))) == NULL) + return SA_ERR_MEM; + sa->sSocket = -1; + sa->bTimeout = 0; + sa->nReadLen = 0; + sa->nReadSize = 1024; + if ((sa->cpReadBuf = (char *)malloc(sa->nReadSize)) == NULL) { + free(sa); + return SA_ERR_MEM; + } + sa->nWriteLen = 0; + sa->nWriteSize = 1024; + if ((sa->cpWriteBuf = (char *)malloc(sa->nWriteSize)) == NULL) { + free(sa->cpReadBuf); + free(sa); + return SA_ERR_MEM; + } + *sap = sa; + return SA_OK; +} + +sa_rc_t sa_destroy(sa_t *sa) +{ + if (sa == NULL) + return SA_ERR_ARG; + sa_socket_kill(sa); + if (sa->cpReadBuf != NULL) + free(sa->cpReadBuf); + if (sa->cpWriteBuf != NULL) + free(sa->cpWriteBuf); free(sa); + return SA_OK; +} + +sa_rc_t sa_timeout(sa_t *sa, long sec, long usec) +{ + if (sa == NULL) + return SA_ERR_ARG; + if (sec == 0 && usec == 0) { + sa->bTimeout = 0; + sa->tvTimeout.tv_sec = 0; + sa->tvTimeout.tv_usec = 0; + } + else { + sa->bTimeout = 1; + sa->tvTimeout.tv_sec = sec; + sa->tvTimeout.tv_usec = usec; + } + return SA_OK; +} + +sa_rc_t sa_buffers(sa_t *sa, size_t rsize, size_t wsize) +{ + char *cp; + + if (sa == NULL) + return SA_ERR_ARG; + if (sa->nReadLen > rsize || sa->nWriteLen > wsize) + return SA_ERR_ARG; + if ((cp = (char *)realloc(sa->cpReadBuf, rsize)) == NULL) + return SA_ERR_SYS; + sa->cpReadBuf = cp; + sa->nReadSize = rsize; + if ((cp = (char *)realloc(sa->cpWriteBuf, wsize)) == NULL) + return SA_ERR_SYS; + sa->cpWriteBuf = cp; + sa->nWriteSize = wsize; + return SA_OK; +} + +sa_rc_t sa_bind(sa_t *sa, sa_addr_t *laddr) +{ + sa_rc_t rv; + + if (sa->sSocket == -1) + if ((rv = sa_socket_init(sa, laddr->saa_family, laddr->saa_proto)) != SA_OK) + return rv; + /* NOT YET IMPLEMENTED */ + return SA_ERR_INT; +} + +sa_rc_t sa_connect(sa_t *sa, sa_addr_t *raddr) +{ + int flags, n, error; + fd_set rset, wset; + socklen_t len; + sa_rc_t rv; + + if (sa == NULL) + return SA_ERR_ARG; + + if (sa->sSocket == -1) + if ((rv = sa_socket_init(sa, raddr->saa_family, raddr->saa_proto)) != SA_OK) + return rv; + + if (!sa->bTimeout) + return connect(sa->sSocket, raddr->saa_buf, raddr->saa_len); + + error = 0; + rv = SA_OK; + + /* remember socket flags */ + flags = fcntl(sa->sSocket, F_GETFL, 0); + + /* switch to non-blocking mode */ + fcntl(sa->sSocket, F_SETFL, flags|O_NONBLOCK); + + /* perform the connect */ + if ((n = connect(sa->sSocket, raddr->saa_buf, raddr->saa_len)) < 0) { + if (errno != EINPROGRESS) { + error = errno; + goto done; + } + } + + /* if connect completed immediately */ + if (n == 0) + goto done; + + /* wait for read or write possibility */ + FD_ZERO(&rset); + FD_ZERO(&wset); + FD_SET(sa->sSocket, &rset); + FD_SET(sa->sSocket, &wset); + do { + n = select(sa->sSocket+1, &rset, &wset, NULL, &sa->tvTimeout); + } while (n == -1 && errno == EINTR); + + /* decide on return semantic */ + if (n < 0) { + error = errno; + goto done; + } + else if (n == 0) { + error = ETIMEDOUT; + goto done; + } + + /* fetch pending error */ + len = sizeof(error); + if (getsockopt(sa->sSocket, SOL_SOCKET, SO_ERROR, &error, &len) < 0) + error = errno; + + done: + + /* reset socket flags */ + fcntl(sa->sSocket, F_SETFL, flags); + + /* optionally set errno */ + if (error != 0) { + errno = error; + rv = SA_ERR_SYS; + } + + return rv; +} + +sa_rc_t sa_listen(sa_t *sa) +{ + /* FIXME: NOT YET IMPLEMENTED */ + return SA_ERR_INT; +} + +sa_rc_t sa_accept(sa_t *sa, sa_t **sa_new) +{ + /* FIXME: NOT YET IMPLEMENTED */ + return SA_ERR_INT; +} + +static int sa_read_raw(sa_t *sa, char *cpBuf, int nBufLen) +{ + int rv; + fd_set fds; + + if (sa->bTimeout) { + FD_ZERO(&fds); + FD_SET(sa->sSocket, &fds); + do { + rv = select(sa->sSocket+1, &fds, NULL, NULL, &sa->tvTimeout); + } while (rv == -1 && errno == EINTR); + if (rv == 0) { + errno = ETIMEDOUT; + return -1; + } + } + do { + rv = read(sa->sSocket, cpBuf, nBufLen); + } while (rv == -1 && errno == EINTR); + return rv; +} + +sa_rc_t sa_read(sa_t *sa, char *cpBuf, size_t nBufReq, size_t *nBufRes) +{ + int n; + int rv; + + if (sa == NULL) + return 0; + + /* flush write buffer */ + if (sa->nWriteLen > 0) + sa_flush(sa); + rv = SA_OK; + *nBufRes = 0; + while (1) { + if (nBufReq <= sa->nReadLen) { + /* buffer holds enough data, so use this */ + memmove(cpBuf, sa->cpReadBuf, nBufReq); + memmove(sa->cpReadBuf, sa->cpReadBuf+nBufReq, sa->nReadLen-nBufReq); + sa->nReadLen -= nBufReq; + *nBufRes += nBufReq; + } + else { + if (sa->nReadLen > 0) { + /* fetch already existing buffer contents as a start */ + memmove(cpBuf, sa->cpReadBuf, sa->nReadLen); + nBufReq -= sa->nReadLen; + cpBuf += sa->nReadLen; + *nBufRes += sa->nReadLen; + sa->nReadLen = 0; + } + if (nBufReq >= sa->nReadSize) { + /* buffer is too small at all, so read directly */ + n = sa_read_raw(sa, cpBuf, nBufReq); + if (n > 0) + *nBufRes += n; + else if (n <= 0) + rv = SA_ERR_SYS; + } + else { + /* fill buffer with new data */ + n = sa_read_raw(sa, sa->cpReadBuf, sa->nReadSize); + if (n <= 0) + rv = SA_ERR_SYS; + else { + sa->nReadLen = n; + continue; + } + } + } + break; + } + return rv; +} + +sa_rc_t sa_readfrom(sa_t *sa, char *buf, size_t buflen, size_t *bufdone, sa_addr_t *addr) +{ + sa_rc_t rv; + + if (sa->sSocket == -1) + if ((rv = sa_socket_init(sa, addr->saa_family, addr->saa_proto)) != SA_OK) + return rv; + /* FIXME: NOT YET IMPLEMENTED */ + return SA_ERR_INT; +} + +sa_rc_t sa_readline(sa_t *sa, char *cpBuf, size_t nBufReq, size_t *nBufRes) +{ + char c; + size_t n; + + if (sa == NULL) + return SA_ERR_ARG; + *nBufRes = 0; + while ((*nBufRes) < (nBufReq-1)) { + sa_read(sa, &c, 1, &n); + if (n <= 0) + break; + cpBuf[(*nBufRes)++] = c; + if (c == '\n') + break; + } + cpBuf[(*nBufRes)] = '\0'; + return SA_OK; +} + +static int sa_write_raw(sa_t *sa, const char *cpBuf, int nBufLen) +{ + int rv; + fd_set fds; + + if (sa->bTimeout) { + FD_ZERO(&fds); + FD_SET(sa->sSocket, &fds); + do { + rv = select(sa->sSocket+1, NULL, &fds, NULL, &sa->tvTimeout); + } while (rv == -1 && errno == EINTR); + if (rv == 0) { + errno = ETIMEDOUT; + return -1; + } + } + do { + rv = write(sa->sSocket, cpBuf, nBufLen); + } while (rv == -1 && errno == EINTR); + return rv; +} + +sa_rc_t sa_write(sa_t *sa, const char *cpBuf, size_t nBufReq, size_t *nBufRes) +{ + size_t n; + + if (sa == NULL) + return SA_ERR_ARG; + + if (nBufReq > (sa->nWriteSize - sa->nWriteLen)) { + /* not enough space in buffer, so flush buffer */ + sa_flush(sa); + } + if (nBufReq >= sa->nWriteSize) { + /* buffer too small at all, so write immediately */ + *nBufRes = 0; + while (nBufReq > 0) { + n = sa_write_raw(sa, cpBuf, nBufReq); + if (n <= 0) + break; + nBufReq -= n; + cpBuf += n; + *nBufRes += n; + } + } + else { + /* (again) enough sprace in buffer, so store data */ + memmove(sa->cpWriteBuf+sa->nWriteLen, cpBuf, nBufReq); + sa->nWriteLen += nBufReq; + *nBufRes = nBufReq; + } + return SA_OK; +} + +sa_rc_t sa_writeto(sa_t *sa, const char *buf, size_t buflen, size_t *bufdone, sa_addr_t *addr) +{ + sa_rc_t rv; + + if (sa->sSocket == -1) + if ((rv = sa_socket_init(sa, addr->saa_family, addr->saa_proto)) != SA_OK) + return rv; + /* FIXME: NOT YET IMPLEMENTED */ + return SA_ERR_INT; +} + +sa_rc_t sa_printf(sa_t *sa, const char *cpFmt, ...) +{ + va_list ap; + size_t n; + char caBuf[1024]; + + if (sa == NULL) + return SA_ERR_ARG; + va_start(ap, cpFmt); + n = sa_vsnprintf(caBuf, sizeof(caBuf), cpFmt, ap); + sa_write(sa, caBuf, n, &n); + va_end(ap); + return SA_OK; +} + +sa_rc_t sa_flush(sa_t *sa) +{ + size_t n; + + if (sa == NULL) + return SA_ERR_ARG; + while (sa->nWriteLen > 0) { + n = sa_write_raw(sa, sa->cpWriteBuf, sa->nWriteLen); + if (n <= 0) + break; + memmove(sa->cpWriteBuf, sa->cpWriteBuf+n, sa->nWriteLen-n); + sa->nWriteLen -= n; + } + sa->nWriteLen = 0; + return SA_OK; +} + +sa_rc_t sa_shutdown(sa_t *sa, char *flags) +{ + int how; - return; + if (sa == NULL || flags == NULL) + return SA_ERR_ARG; + how = 0; + if (strcmp(flags, "r") == 0) + how = SHUT_RD; + else if (strcmp(flags, "w") == 0) + how = SHUT_WR; + else if (strcmp(flags, "rw") == 0) + how = SHUT_RDWR; + if (shutdown(sa->sSocket, how) == -1) + return SA_ERR_SYS; + return SA_OK; } 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.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ut_sa.h,v' 2>/dev/null --- l2_ut_sa.h 2001/09/06 17:17:41 1.2 +++ l2_ut_sa.h 2001/09/09 15:54:31 1.3 @@ -24,31 +24,58 @@ ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** -** l2_ut_sa.h: utility library for socket address handling +** l2_ut_sa.h: socket abstraction library */ #ifndef __L2_UT_SA_H__ #define __L2_UT_SA_H__ -#include +#include #include -#include #include -#include -typedef struct { - struct sockaddr *sa_buf; - socklen_t sa_len; - int sa_proto; -} l2_util_sa_t; - -enum { - L2_UTIL_SA_UNIX, - L2_UTIL_SA_IP -}; +struct sa_st; +typedef struct sa_st sa_t; -l2_util_sa_t *l2_util_sa_create(int, ...); -void l2_util_sa_destroy(l2_util_sa_t *); +struct sa_addr_st; +typedef struct sa_addr_st sa_addr_t; + +typedef enum { + SA_OK, + SA_ERR_ARG, + SA_ERR_USE, + SA_ERR_MEM, + SA_ERR_SYS, + SA_ERR_INT +} sa_rc_t; + +sa_rc_t sa_u2a (sa_addr_t **asaa, const char *uri, ...); +sa_rc_t sa_s2a (sa_addr_t **saa, const struct sockaddr *sabuf, socklen_t salen); +sa_rc_t sa_a2u (const sa_addr_t *saa, char **uri); +sa_rc_t sa_a2s (const sa_addr_t *saa, struct sockaddr **sabuf, socklen_t *salen); + +sa_rc_t sa_create (sa_t **sa); +sa_rc_t sa_destroy (sa_t *sa); + +sa_rc_t sa_timeout (sa_t *sa, long sec, long usec); +sa_rc_t sa_buffers (sa_t *sa, size_t rsize, size_t wsize); + +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); +sa_rc_t sa_accept (sa_t *sa, sa_t **sa_new); + +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_read (sa_t *sa, char *buf, size_t buflen, size_t *bufdone); +sa_rc_t sa_readfrom (sa_t *sa, char *buf, size_t buflen, size_t *bufdone, sa_addr_t *addr); +sa_rc_t sa_readline (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_writeto (sa_t *sa, const char *buf, size_t buflen, size_t *bufdone, sa_addr_t *addr); +sa_rc_t sa_printf (sa_t *sa, const char *fmt, ...); +sa_rc_t sa_flush (sa_t *sa); +sa_rc_t sa_shutdown (sa_t *sa, char *flags); #endif /* __L2_UT_SA_H__ */