Back to index

im-sdk  12.3.91
Classes | Typedefs | Enumerations | Functions
stream-socket.c File Reference
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <iiimp.h>
#include "stream.h"

Go to the source code of this file.

Classes

struct  IIIMF_stream_socket_private

Typedefs

typedef struct IIIMF_stream_socket_private

Enumerations

enum  IIIMF_STREAM_SOCKET_FLAGS { IIIMF_STREAM_SOCKET_LISTEN, IIIMF_STREAM_SOCKET_OPEN }

Functions

static IIIMF_status stream_socket_read (IIIMF_stream_private private, void *buf, size_t nbyte)
static IIIMF_status stream_socket_write (IIIMF_stream_private private, const void *buf, size_t nbyte)
static
IIIMF_stream_socket_private
create_sockpriv (int flags, int fd, int timeout)
static void delete_sockpriv (IIIMF_stream_socket_private *psockpriv)
IIIMF_status iiimf_connect_socket_stream (const char *node, const char *service, int timeout, IIIMF_stream **stream_ret)
IIIMF_status iiimf_listen_socket_stream (const char *node, const char *service, int timeout, IIIMF_stream **stream_ret)
IIIMF_status iiimf_accept_socket_stream (IIIMF_stream *stream, IIIMF_stream **stream_ret)
IIIMF_status iiimf_delete_socket_stream (IIIMF_stream *stream)

Class Documentation

struct IIIMF_stream_socket_private

Definition at line 61 of file stream-socket.c.

Class Members
int fd
int flags
int timeout

Typedef Documentation

Definition at line 60 of file stream-socket.c.


Enumeration Type Documentation

Enumerator:
IIIMF_STREAM_SOCKET_LISTEN 
IIIMF_STREAM_SOCKET_OPEN 

Definition at line 55 of file stream-socket.c.


Function Documentation

static IIIMF_stream_socket_private* create_sockpriv ( int  flags,
int  fd,
int  timeout 
) [static]

Definition at line 68 of file stream-socket.c.

{
    IIIMF_stream_socket_private *p;

#ifdef HAVE_SO_NOSIGPIPE
    int optval = 1;
#endif
    p = (IIIMF_stream_socket_private*) malloc(sizeof(*p));
    if (!p) return NULL;
    p->timeout = timeout;
    p->flags = flags;
    p->fd = fd;
#ifdef HAVE_SO_NOSIGPIPE
    /* need error handling ? */
    setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof (int));
#endif
    return p;
}

Here is the caller graph for this function:

static void delete_sockpriv ( IIIMF_stream_socket_private psockpriv) [static]

Definition at line 92 of file stream-socket.c.

{
    free(psockpriv);
}

Here is the caller graph for this function:

Definition at line 469 of file stream-socket.c.

{
    IIIMF_stream_socket_private *sockpriv = (IIIMF_stream_socket_private*) stream->private_data;
    IIIMF_status     status;
    struct sockaddr  address;
    socklen_t        address_len;
    int                     fd;
#if defined(HAVE_POLL)
    struct pollfd    fds[1];
    int                     poll_ret;
#else /* !HAVE_POLL */
    fd_set           fdvar;
    struct timeval   timeout;
    int                     select_ret;

    timeout.tv_sec = sockpriv->timeout / 1000;
    timeout.tv_usec = sockpriv->timeout % 1000;
#endif /* !HAVE_POLL */

    if (sockpriv->flags != IIIMF_STREAM_SOCKET_LISTEN)
       return IIIMF_STATUS_ARGUMENT;

    if (0 <= sockpriv->timeout) {
#if defined(HAVE_POLL)
       fds[0].fd = sockpriv->fd;
       fds[0].events = POLLIN;
       poll_ret = poll(fds, 1, sockpriv->timeout);
       if (0 == poll_ret) {
           return IIIMF_STATUS_TIMEOUT;
       } else if (-1 == poll_ret) {
           return IIIMF_STATUS_STREAM;
       }
#else /* !HAVE_POLL */
       do {
           FD_ZERO(&fdvar);
           FD_SET(sockpriv->fd, &fdvar);
           select_ret = select(sockpriv->fd + 1, NULL,
                            &fdvar, NULL, &timeout);
       } while ((-1 == select_ret) && (EINTR == errno));
       if (-1 == select_ret) return IIIMF_STATUS_TIMEOUT;
#endif /* !HAVE_POLL */
    }
    address_len = (sizeof (address));
    fd = accept(sockpriv->fd, &address, &address_len);
    if (-1 == fd) return IIIMF_STATUS_STREAM;

    {
       IIIMF_stream *stream_new;
       IIIMF_stream_socket_private *sockpriv_new;

       sockpriv_new = create_sockpriv(IIIMF_STREAM_SOCKET_OPEN, fd,
                                   sockpriv->timeout);
       if (!sockpriv_new) {
           close(fd);
           return IIIMF_STATUS_MALLOC;
       }
       status = iiimf_create_stream(stream_socket_read, stream_socket_write,
                                 sockpriv_new, sockpriv->timeout, &stream_new);
       if (status != IIIMF_STATUS_SUCCESS) return status;
       *stream_ret = stream_new;
    }

    return IIIMF_STATUS_SUCCESS;
}

Here is the call graph for this function:

IIIMF_status iiimf_connect_socket_stream ( const char *  node,
const char *  service,
int  timeout,
IIIMF_stream **  stream_ret 
)

Definition at line 167 of file stream-socket.c.

{
    int                     fd;
    int                     fd_flag;

#if defined(HAVE_GETADDRINFO)
    int                     e;
    struct addrinfo *       res;
    struct addrinfo *       aip;
    struct addrinfo  hints;

#if defined(HAVE_UNIX_SOCKET)
    if (*node == '/') {
       return create_socket_stream_unix(node, service, timeout, stream_ret);
    }
#endif
    fd = -1;

    (void)memset(&hints, 0, sizeof (hints));
    hints.ai_flags = AI_CANONNAME;
    hints.ai_socktype = SOCK_STREAM;

    e = getaddrinfo(node, service, &hints, &res);
    if (0 != e) {
       return -1;
    }

    for (aip = res; NULL != aip; aip = aip->ai_next) {
       fd = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
       if (-1 == fd) {
           break;
       }

       if (-1 == connect(fd, aip->ai_addr, aip->ai_addrlen)) {
           (void)close(fd);
           fd = -1;
           continue;
       } else {
           break;
       }
    }

    freeaddrinfo(res);

    if (-1 == fd) return IIIMF_STATUS_STREAM;

#else /* !HAVE_GETADDRINFO */

#if defined(WIN32)
    unsigned short int      port_number;
#else /* !WIN32 */
    int                     port_number;
#endif /* !WIN32 */
    int                     r;
    int                     optval;
    unsigned long    in_addr;
    struct hostent * hostp;
    struct sockaddr_in      addr;
    struct servent * srvp;

#if defined(HAVE_UNIX_SOCKET)
    if (*node == '/') {
       return create_socket_stream_unix(node, service, timeout, stream_ret);
    }
#endif
#if defined(WIN32)
    start_winsock(1, 1);
#endif

    fd = socket(PF_INET, SOCK_STREAM, 0);
    if (fd < 0 ) return IIIMF_STATUS_STREAM;

    port_number = 0;

    (void)memset((char *)(&addr), 0, sizeof (addr));
    addr.sin_family = PF_INET;

    if (0 < strlen(service)) {
       srvp = getservbyname(service, "tcp");
       if (NULL != srvp) {
           port_number = srvp->s_port;
       }
       (void)endservent();
       if (0 == port_number) {
           port_number = atoi(service);
       }
    }
    if (0 == port_number) {
       port_number = 9010;
    }
    addr.sin_port = htons(port_number);
    in_addr = inet_addr(node);
    if ((unsigned long)(-1) != in_addr) {
       (void)memcpy(&addr.sin_addr, &in_addr, sizeof (in_addr));
    } else {
       hostp = gethostbyname(node);
       if (NULL == hostp) {
#if defined(WIN32)
           (void)sock_close(fd);
#else /* !WIN32 */
           (void)close(fd);
#endif /* !WIN32 */
           return IIIMF_STATUS_STREAM;
       }

       if (0 < hostp->h_length) {
           (void)memcpy(&addr.sin_addr, hostp->h_addr,
                      hostp->h_length);
       } else {
#if defined(WIN32)
           sock_close(fd);
#else /* !WIN32 */
           (void)close(fd);
#endif /* !WIN32 */
           return IIIMF_STATUS_STREAM;
       }
    }

    r = connect(fd, (struct sockaddr *)(&addr), sizeof (addr));
#if defined(WIN32)
    if (SOCKET_ERROR == r) {
       sock_close(fd);
       return IIIMF_STATUS_STREAM;
    }
#else /* !WIN32 */
    if (r < 0) {
       (void)close(fd);
       return IIIMF_STATUS_STREAM;
    }
#endif /* !WIN32 */
#endif /* !HAVE_GETADDRINFO */

    fd_flag = fcntl(fd, F_GETFD);
    fd_flag |= FD_CLOEXEC;
    (void)fcntl(fd, F_SETFD, fd_flag);

    {
       IIIMF_status st;
       IIIMF_stream *stream;
       IIIMF_stream_socket_private *sockpriv;

       sockpriv = create_sockpriv(IIIMF_STREAM_SOCKET_OPEN, fd,
                               timeout);
       if (!sockpriv) {
           close(fd);
           return IIIMF_STATUS_MALLOC;
       }

       st = iiimf_create_stream(stream_socket_read, stream_socket_write,
                             sockpriv, timeout, &stream);
       if (st != IIIMF_STATUS_SUCCESS) return st;
       *stream_ret = stream;
    }

    return IIIMF_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 538 of file stream-socket.c.

{
    IIIMF_stream_socket_private *sockpriv = (IIIMF_stream_socket_private*) stream->private_data;
    
    if (sockpriv->fd > 0) close(sockpriv->fd);
    delete_sockpriv(sockpriv);
    iiimf_stream_delete(stream);
    return IIIMF_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

IIIMF_status iiimf_listen_socket_stream ( const char *  node,
const char *  service,
int  timeout,
IIIMF_stream **  stream_ret 
)

Definition at line 330 of file stream-socket.c.

{
    int                     fd;
    int                     fd_flag;
    int                     optval;
    int                     r = 0;

#if defined(HAVE_GETADDRINFO)
    int                     e;
    struct addrinfo *       a;
    struct addrinfo *       aip;
    struct addrinfo  hints;

    fd = -1;

    (void)memset(&hints, 0, sizeof (hints));
    hints.ai_flags = AI_PASSIVE;
    hints.ai_socktype = SOCK_STREAM;

    e = getaddrinfo(NULL, service, &hints, &aip);
    if (0 != e) return IIIMF_STATUS_STREAM;

    for (a = aip; NULL != a; a = a->ai_next) {
       fd = socket(a->ai_family, a->ai_socktype, a->ai_protocol);
       if (-1 != fd) {
           r = bind(fd, aip->ai_addr, sizeof (struct sockaddr));
           if (-1 != r) break;
           (void)close(fd);
           fd = -1;
       }
    }
    freeaddrinfo(aip);
    if ((-1 == fd) || (-1 == r)) return IIIMF_STATUS_STREAM;
    r = listen(fd, 5);
    if (-1 == r) return IIIMF_STATUS_STREAM;
#else /* !HAVE_GETADDRINFO */

#if defined(WIN32)
    unsigned short int      port_number;
#else /* !WIN32 */
    int                     port_number;
#endif /* !WIN32 */
#if defined(PF_INET6) && defined(ENABLE_IPV6)
    struct sockaddr_in6     addr;
#else /* !PF_INET6 && ENABLE_IPV6 */
    struct sockaddr_in      addr;
#endif /* !PF_INET6 && ENABLE_IPV6 */
    struct servent * srvp;

#if defined(WIN32)
    start_winsock(1, 1);
#endif

#if defined(PF_INET6) && defined(ENABLE_IPV6)
    fd = socket(PF_INET6, SOCK_STREAM, 0);
#else /* !PF_INET6 && ENABLE_IPV6 */
    fd = socket(PF_INET, SOCK_STREAM, 0);
#endif /* !PF_INET6 && ENABLE_IPV6 */

    if (fd < 0 ) return IIIMF_STATUS_STREAM;

    port_number = 0;

    if (0 < strlen(service)) {
       srvp = getservbyname(service, "tcp");
       if (NULL != srvp) {
           port_number = srvp->s_port;
       }
       (void)endservent();
       if (0 == port_number) {
           port_number = atoi(service);
       }
    }
    if (0 == port_number) {
       port_number = 9010;
    }

    (void)memset((char *)(&addr), 0, sizeof (addr));
#if defined(PF_INET6) && defined(ENABLE_IPV6)
    addr.sin6_family = PF_INET6;
    addr.sin6_flowinfo = 0;
    addr.sin6_port = htons(port_number);
    addr.sin6_addr = in6addr_any;
#else /* !PF_INET6 && ENABLE_IPV6 */
    addr.sin_family = PF_INET;
    addr.sin_port = htons(port_number);
#endif /* !PF_INET6 && ENABLE_IPV6 */

    if ((bind(fd, (struct sockaddr *)(&addr), sizeof (addr)) < 0) ||
       (listen(fd, 5) < 0) ) {
#if defined(WIN32)
       sock_close(fd);
#else /* !WIN32 */
       (void)close(fd);
#endif /* !WIN32 */
       return IIIMF_STATUS_STREAM;
    }
#endif /* !HAVE_GETADDRINFO */

    optval = 1;
    r = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int));
    if (-1 == r) {
#if defined(WIN32)
       sock_close(fd);
#else /* !WIN32 */
       (void)close(fd);
#endif /* !WIN32 */
       return IIIMF_STATUS_STREAM;
    }

    fd_flag = fcntl(fd, F_GETFD);
    fd_flag |= FD_CLOEXEC;
    (void)fcntl(fd, F_SETFD, fd_flag);

    {
       IIIMF_status st;
       IIIMF_stream *stream;
       IIIMF_stream_socket_private *sockpriv;

       sockpriv = create_sockpriv(IIIMF_STREAM_SOCKET_LISTEN, fd, timeout);
       if (!sockpriv) {
           close(fd);
           return IIIMF_STATUS_MALLOC;
       }

       st = iiimf_create_stream(NULL, NULL, sockpriv, timeout, &stream);
       if (st != IIIMF_STATUS_SUCCESS) return st;
       *stream_ret = stream;
    }

    return IIIMF_STATUS_SUCCESS;
}

Here is the call graph for this function:

static IIIMF_status stream_socket_read ( IIIMF_stream_private  private,
void *  buf,
size_t  nbyte 
) [static]

Definition at line 551 of file stream-socket.c.

{
    IIIMF_stream_socket_private *sockpriv = (IIIMF_stream_socket_private*) private;
    char *           p;
    ssize_t          n;
    ssize_t          r;

#if !defined(HAVE_SO_NOSIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) && defined(HAVE_SIGNAL)
    RETSIGTYPE (*old_sighandler)(int);
#endif

#if defined(HAVE_POLL)
    struct pollfd    fds[1];
    int                     poll_ret;
#else /* !HAVE_POLL */
    fd_set           fdvar;
    struct timeval   timeout;
    int                     select_ret;

    timeout.tv_sec = sockpriv->timeout / 1000;
    timeout.tv_usec = sockpriv->timeout % 1000;
#endif /* !HAVE_POLL */

#if !defined(HAVE_SO_NOSIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) && defined(HAVE_SIGNAL)
    /* block SIGPIPE */
    old_sighandler = signal(SIGPIPE, SIG_IGN);
#endif

    if (sockpriv->fd < 0) return IIIMF_STATUS_STREAM_RECEIVE;
    for (p = buf, n = nbyte; 0 < n; p += r, n -= r) {
       if (0 <= sockpriv->timeout) {
#if defined(HAVE_POLL)
           fds[0].fd = sockpriv->fd;
           fds[0].events = POLLIN;
           poll_ret = poll(fds, 1, sockpriv->timeout);
           if (0 == poll_ret) {
              return IIIMF_STATUS_TIMEOUT;
           } else if (-1 == poll_ret) {
              return IIIMF_STATUS_STREAM;
           }
#else /* !HAVE_POLL */
           do {
              FD_ZERO(&fdvar);
              FD_SET(sockpriv->fd, &fdvar);
              select_ret = select(sockpriv->fd + 1, NULL,
                                &fdvar, NULL, &timeout);
           } while ((-1 == select_ret) && (EINTR == errno));
#endif /* !HAVE_POLL */
       }

#ifdef HAVE_MSG_NOSIGNAL
        r = recv(sockpriv->fd, p, n, MSG_NOSIGNAL);
#else
       r = recv(sockpriv->fd, p, n, 0);
#endif
       if (r == 0) {
           return IIIMF_STATUS_CONNECTION_CLOSED;
       }
       if (r < 0) {
           if (EINTR == errno) {
              continue;
           } else {
#if !defined(HAVE_SO_NOSIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) && defined(HAVE_SIGNAL)
                /* restore old handler */
                signal(SIGPIPE, old_sighandler);
#endif
                if (EPIPE == errno) {
                    sockpriv->fd = -1;
                    return IIIMF_STATUS_CONNECTION_CLOSED;
                }
              return IIIMF_STATUS_STREAM_RECEIVE;
           }
       }
    }

#if !defined(HAVE_SO_NOSIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) && defined(HAVE_SIGNAL)
    /* restore old handler */
    signal(SIGPIPE, old_sighandler);
#endif

    return IIIMF_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static IIIMF_status stream_socket_write ( IIIMF_stream_private  private,
const void *  buf,
size_t  nbyte 
) [static]

Definition at line 638 of file stream-socket.c.

{
    IIIMF_stream_socket_private *sockpriv = (IIIMF_stream_socket_private*) private;
    const char *     p;
    ssize_t          n;
    ssize_t          r;

#if !defined(HAVE_SO_NOSIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) && defined(HAVE_SIGNAL)
    RETSIGTYPE (*old_sighandler)(int);
    /* block SIGPIPE */
    old_sighandler = signal(SIGPIPE, SIG_IGN);
#endif

    if (sockpriv->fd < 0) return IIIMF_STATUS_STREAM_SEND;

    for (p = buf, n = nbyte; 0 < n; p += r, n -= r) {
        #ifdef HAVE_MSG_NOSIGNAL
        r = send(sockpriv->fd, p, n, MSG_NOSIGNAL);
        #else
        r = send(sockpriv->fd, p, n, 0);
        #endif
       if (r < 0) {
            #if !defined(HAVE_SO_NOSIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) && defined(HAVE_SIGNAL)
            /* restore old handler */
            signal(SIGPIPE, old_sighandler);
            #endif
            if (EPIPE == errno) {
                sockpriv->fd = -1;
                return IIIMF_STATUS_CONNECTION_CLOSED;
            }
            return IIIMF_STATUS_STREAM_SEND;
        }
    }

#if !defined(HAVE_SO_NOSIGPIPE) && !defined(HAVE_MSG_NOSIGNAL) && defined(HAVE_SIGNAL)
    /* restore old handler */
    signal(SIGPIPE, old_sighandler);
#endif

    return IIIMF_STATUS_SUCCESS;
}

Here is the call graph for this function:

Here is the caller graph for this function: