/**
 * See pcsl_serversocket.h for definition.
 */
int pcsl_serversocket_open(
	int port,
	void **pHandle)
{
    int truebuf = 1;
    int fd = -1;
    struct sockaddr_in addr;
    int status;
    int flags;

    fd = socket(AF_INET, SOCK_STREAM, 0);
    lastError = errno;
    if (fd == INVALID_SOCKET) {
        return PCSL_NET_IOERROR;
    }

    status =
        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &truebuf, sizeof(truebuf));
    lastError = errno;

    if (status == -1) {
        /* printf("setsockopt failed errno=%d\n", errno); */
        (void)close(fd);
        return PCSL_NET_IOERROR;
    }

    flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);

    addr.sin_family      = AF_INET;
    addr.sin_port        = htons((unsigned short)port);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    status = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
    lastError = errno;

    if (status == -1) {
        /* printf("bind failed errno=%d\n", errno); */
        (void)close(fd);
        return PCSL_NET_IOERROR;
    }


    status = listen(fd, SERVERSOCKET_BACKLOG);

    if (status == 0) {
        *pHandle = na_create(fd);
        return PCSL_NET_SUCCESS;
    }

    /* printf("listen failed errno=%d\n", errno); */
    (void)close(fd);
    return PCSL_NET_IOERROR;
}
/**
 * Common functionality for accept start and finish
 */
static int pcsl_serversocket_accept_common(
    void *handle,
    void **pConnectionHandle,
    void **pContext)
{
    int connfd;
    int flags;
    struct sockaddr_in sa;
    int saLen = sizeof (sa);
    int listenfd = na_get_fd(handle);

    connfd = accept(listenfd, (struct sockaddr *)&sa, (socklen_t *)&saLen);

    if (connfd == SOCKET_ERROR) {
        if (errno == EWOULDBLOCK || errno == ECONNABORTED) {
            /*
             * The "listenfd" is marked as non-blocking and no connections 
             * are present to be accepted.
             */
            na_register_for_read((void *)handle);
            *pContext = NULL;
            return PCSL_NET_WOULDBLOCK;
        } else {
            na_unregister_for_read((void *)handle);
            return PCSL_NET_IOERROR;
        }
    } else {
        na_unregister_for_read((void *)handle);
        /*
         * Linux accept does _not_ inherit socket flags like O_NONBLOCK.
         * So, irrespective of the blocking or non-blockimg mode of listenfd,
         * connfd, must be set to non-blocking mode; otherwise VM will 
         * be blocked for any I/O operation on this new socket descriptor.
         */
        flags = fcntl(connfd, F_GETFL, 0);
        fcntl(connfd, F_SETFL, flags | O_NONBLOCK);

        *pConnectionHandle = na_create(connfd);

        return PCSL_NET_SUCCESS;
    }
}
Example #3
0
/**
 * See pcsl_datagram.h for definition.
 */
int
pcsl_datagram_open_start(
    int port, 
    void **pHandle, 
    void **pContext) 
{
    struct sockaddr_in addr;
    int fd;
    int res;
    int i;
	int flags;
    int result; 

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    lastError = errno;
    if (fd == INVALID_SOCKET) {
        return PCSL_NET_IOERROR;
    }

    i = port;

   /*
    * Here is a total mystery to me. If I give solaris a port number of zero
    * then it allocated one somewhere above 50000. The problem is that when I
    * do a recvfrom() on a socket that is bound to a port > 32767 it never sees
    * any data.
    *
    * Temporary solution (seems to work all the time):
    * Start at port 6000 and just go upwards until a free port is found
    */
    if (i <= 0) {
        i = 6000;
    }

    res = EADDRINUSE;
    do {
        addr.sin_family      = AF_INET;
        addr.sin_port        = htons((short)i++);
        addr.sin_addr.s_addr = htonl(INADDR_ANY);

        res = bind(fd, (struct sockaddr*)&addr, sizeof( addr ));
        lastError = errno;
    } while ((res == SOCKET_ERROR) && (errno == EADDRINUSE) && 
             (port == 0) && (i < 32767));

    if (res != SOCKET_ERROR) {
        *pHandle = na_create(fd);
       
        /* 
        printf("creating SMS datagram handle, handle = %d, fd = %d, 
                port = %d\n", (int)(*pHandle), fd, (i-1));
        */
 
        /* Set the datagram socket to non-blocking mode */
        flags = fcntl(fd, F_GETFL, 0);
        fcntl(fd, F_SETFL, flags | O_NONBLOCK);

        return PCSL_NET_SUCCESS;
    }

    close(fd);
    return PCSL_NET_IOERROR;
}
/**
 * See pcsl_socket.h for definition.
 */
int pcsl_socket_open_start(
    unsigned char *ipBytes,
    int port,
    void **pHandle,
    void **pContext)
{
    int truebuf = 1;
    int fd = -1;
    struct sockaddr_in addr;
    int status;
    int flags;

    fd = socket(AF_INET, SOCK_STREAM, 0);
    lastError = errno;
    if (fd == INVALID_SOCKET) {
        return PCSL_NET_IOERROR;
    }

    status =
        setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &truebuf, sizeof(truebuf));
    lastError = errno;

    if (status == -1) {
        /*
         * DEBUG:
         * printf("setsockopt failed errno=%d\n", errno);
         */
        (void)close(fd);
        return PCSL_NET_IOERROR;
    }

    addr.sin_family      = AF_INET;
    addr.sin_port        = htons((unsigned short)port);

    memcpy(&addr.sin_addr.s_addr, ipBytes, sizeof(addr.sin_addr.s_addr));

    flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    status = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
    lastError = errno;

    /*
       connect() may return 0 in case of non-blocking sockets if
       server is on the same host as client. No need to create a
       a blocked handle if connection is successfully established
    */

    if (status == 0) {
        *pHandle = na_create(fd);
        return PCSL_NET_SUCCESS;
    }

    if ((status == SOCKET_ERROR) &&
            (errno == EINPROGRESS || errno == EALREADY)) {
        *pContext = NULL;
        *pHandle = na_create(fd);
        na_register_for_write(*pHandle);
        return PCSL_NET_WOULDBLOCK;
    }

    close(fd);
    return PCSL_NET_CONNECTION_NOTFOUND;
}