media/webrtc/signaling/src/sipcc/cpr/win32/cpr_win_socket.c
author Phil Ringnalda <philringnalda@gmail.com>
Mon, 08 Dec 2014 20:53:07 -0800
changeset 218811 960303b07c909e69db87467d0b499351d65c82af
permissions -rw-r--r--
Backed out 10 changesets (bug 1091242) for Android/b2g non-unified build bustage CLOSED TREE Backed out changeset 7f72b55c5de7 (bug 1091242) Backed out changeset f1501aa24397 (bug 1091242) Backed out changeset 7fde5994aee5 (bug 1091242) Backed out changeset 59b415714087 (bug 1091242) Backed out changeset dadb65fedc08 (bug 1091242) Backed out changeset 21be81424e4e (bug 1091242) Backed out changeset 498fb1dafba5 (bug 1091242) Backed out changeset 8d0653eb85ab (bug 1091242) Backed out changeset c82d484e135a (bug 1091242) Backed out changeset 3e0c8932f1b1 (bug 1091242)

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "ctype.h"
#include "cpr_types.h"
#include "cpr_debug.h"
#include "cpr_socket.h"
#include "cpr_stdlib.h"
#include "cpr_string.h"
#include "cpr_timers.h"
#include "cpr_errno.h"
#include "cpr_win_defines.h"

#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "ws2_32.lib")

#define IN6ADDRSZ   16
#define INT16SZ     2
#define	INADDRSZ	4
#define IS_DIGIT(ch)   ((ch >= '0') && (ch <= '9'))

//const cpr_in6_addr_t in6addr_any = IN6ADDR_ANY_INIT;
const cpr_ip_addr_t ip_addr_invalid = {0};

// Function prototypes for windows calls until CPR is in such a state that it can include windows sockets.


/*
 * WinSock 2 extension -- manifest constants for shutdown()
 */
#define SD_RECEIVE      0x00
#define SD_SEND         0x01
#define SD_BOTH         0x02



#define BYTE uint8_t
#define WORD uint16_t
#define DWORD_PTR unsigned long

#if !defined(MAKEWORD)
#define MAKEWORD(low,high) \
        ((WORD)(((BYTE)(low)) | ((WORD)((BYTE)(high))) << 8))
#endif
#ifndef LOBYTE
#define LOBYTE(w)           ((BYTE)((DWORD_PTR)(w) & 0xff))
#endif
#ifndef HIBYTE
#define HIBYTE(w)           ((BYTE)((DWORD_PTR)(w) >> 8))
#endif

#define WSADESCRIPTION_LEN      256
#define WSASYS_STATUS_LEN       128



/*
 * Commands for ioctlsocket(),  taken from the BSD file fcntl.h.
 *
 *
 * Ioctl's have the command encoded in the lower word,
 * and the size of any in or out parameters in the upper
 * word.  The high 2 bits of the upper word are used
 * to encode the in/out status of the parameter; for now
 * we restrict parameters to at most 128 bytes.
 */
#define IOCPARM_MASK    0x7f        /* parameters must be < 128 bytes */
#define IOC_VOID        0x20000000  /* no parameters */
#define IOC_OUT         0x40000000  /* copy out parameters */
#define IOC_IN          0x80000000  /* copy in parameters */
#define IOC_INOUT       (IOC_IN|IOC_OUT)
                                        /* 0x20000000 distinguishes new &
                                         * old ioctl's */
#define _IO(x,y)        (IOC_VOID|((x)<<8)|(y))

#define _IOR(x,y,t)     (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))

#define _IOW(x,y,t)     (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))

#define FIONREAD    _IOR('f', 127, u_long) /* get # bytes to read */
#define FIONBIO     _IOW('f', 126, u_long) /* set/clear non-blocking i/o */
#define FIOASYNC    _IOW('f', 125, u_long) /* set/clear async i/o */




//////////////////////////////////////////////////////////////////////////
/*
 * Secure socket implementation
 */

#define SRVR_SECURE		9
#define SRVR_TYPE_CCM	2	/* CCM server  */

int SECReq_LookupSrvr(char* serverAddr, int serverType) ;

int SECSock_connect (int    appType,
					 char * srvrAddrAndPort,
					 int    blockingConnect,
					 int    connTimeout,
					 int    ipTOS) ;
int SECSock_getFD(int nSSL) ;
int SECSock_isConnected(int nSSL) ;

int SECSock_close(int nSSL) ;
int SECSock_read(int fd, char* buff, int nLen) ;
int SECSock_write(int fd, char* buff, int nLen) ;

#define secReq_LookupSrvr	SECReq_LookupSrvr
#define secSock_connect		SECSock_connect
#define secSock_getFD		SECSock_getFD
#define secSock_isConnected	SECSock_isConnected
#define secSock_close		SECSock_close
#define secSock_read		SECSock_read
#define secSock_write		SECSock_write

#define CLNT_SCCP			1
#define CLNT_TMO_DEFAULT	0
#define TCP_PORT_RETRY_CNT	5
#define MAX_CONNECTIONS		5

#define CLNT_CONN_OK       0   /* secure connection setup complete  */
#define CLNT_CONN_FAILED   1   /* secure connection setup failed.*/
#define CLNT_CONN_WAITING  2   /* secure connection setup is in progress */

int
SECReq_LookupSrvr(char* serverAddr, int serverType)
{
    CPR_ERROR("SECReq_LookupSrvr: %s %d\n", serverAddr, serverType);
    return -1;
}

int
SECSock_connect(int    appType,
				char * srvrAddrAndPort,
				int    blockingConnect,
				int    connTimeout,
				int    ipTOS)
{
    CPR_ERROR("SECSock_connect: %d %s %d %d %d\n", appType, srvrAddrAndPort, blockingConnect, connTimeout, ipTOS);
    return -1;
}

int
SECSock_getFD(int nSSL)
{
    CPR_ERROR("SECSock_getFD: %d\n", nSSL);
    return -1;
}

#ifdef NON_BLOCKING_MODE_IS_USED
int
SECSock_isConnected(int nSSL)
{
    CPR_ERROR("SECSock_isConnected: %d\n", nSSL);
    return CLNT_CONN_FAILED;
}
#endif

int
SECSock_close(int nSSL)
{
    CPR_ERROR("SECSock_close: %d\n", nSSL);
    return -1;
}

int
SECSock_read(int fd, char* buff, int nLen)
{
    CPR_ERROR("SECSock_read: %d %d\n", fd, nLen);
    return -1;
}

int
SECSock_write(int fd, char* buff, int nLen)
{
    CPR_ERROR("SECSock_write: %d %d\n", fd, nLen);
    return -1;
}


/* Macro definition for chacking a valid connid (TCP/UDP) */
#define VALID_CONNID(connid) \
       (connid >= 0 && connid < MAX_CONNECTIONS)


typedef struct
{
	cpr_socket_t      fd;           /* Socket file descriptor */
	int		ssl ;
} cpr_sec_conn_t ;

cpr_sec_conn_t cpr_sec_conn_tab[MAX_CONNECTIONS];

/**
 *
 * cpr_sec_fd_to_connid
 *
 * returns the tcp conn table index for a particular socket
 *
 * Parameters:   fd - the file descriptor
 *
 * Return Value: cpr_sec_conn_tab index
 *
 */
int
cpr_sec_fd_to_connid (cpr_socket_t fd)
{
    int i;

	if(fd == -1)
		return -1 ;

    for (i = 0; i < MAX_CONNECTIONS; ++i) {
        if (cpr_sec_conn_tab[i].fd == fd) {
            return i;
        }
    }
    return -1;
}

/*
 * cpr_sec_get_free_conn_entry ()
 *
 * Description  : This procedure returns the first free entry from the TCP
 *                conn table.
 *
 * Input Params : None.
 *
 * Returns      : Index to the Connection table (if SUCCESSFUL)
 *                -1 in case of failure.
 */
int
cpr_sec_get_free_conn_entry (void)
{
    int i;

    for (i = 0; i < MAX_CONNECTIONS; ++i) {
        if (cpr_sec_conn_tab[i].fd == -1) {
            /* Zero the connection table entry */
            memset((cpr_sec_conn_tab + i), 0, sizeof(cpr_sec_conn_t));
            return i;
        }
    }

    //CPR_ERROR("cpr_sec_get_free_conn_entry: Connection table full\n");

    return -1;
}

/*
 * cpr_sec_init_conn_table()
 * Description : Cleans up the entry associated with the connid
 *               from the cpr_sec_conn_tab
 *
 * Input : void
 *
 * Output : void
 *
 */
void
cpr_sec_init_conn_table (void)
{
    static boolean initial_call = TRUE;
    int idx;

    if (initial_call) {
        /*
         * Initialize the tcp conn table
         */
        for (idx = 0; idx < MAX_CONNECTIONS; ++idx) {
            cpr_sec_conn_tab[idx].fd = -1;
        }
        initial_call = FALSE;
    }
}

/*
 * cpr_sec_purge_entry()
 * Description : Cleans up the entry associated with the connid
 *               from the cpr_sec_conn_tab
 *
 * Input : connid
 *
 * Output : None
 *
 */
void
cpr_sec_purge_entry (int connid)
{
    cpr_sec_conn_t *entry = cpr_sec_conn_tab + connid;

    if (!VALID_CONNID(connid)) {
        //CPR_INFO("TCP:INVALID_CONNID (%ld) in TCPSOCK_CLOSE_CONNECTION", connid);
        return;
    }

    entry->fd = -1;  /* Free the connection table entry in the BEGINNING ! */
    entry->ssl= 0;

    return;
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////

/*
 *  Copyright (c) 2004-2009 by Cisco Systems, Inc.
 *  All Rights Reserved.
 *
 *  FILENAME
 *     cpr_socket.c
 *
 *  DESCRIPTION
 *     Cisco Portable Runtime WIN layer for the socket interface
 */

#include "cpr_assert.h"

static boolean initialized = 0;

cpr_status_e
cprSocketInit (void)
{
    WSADATA wsaData;
    const int nMajor = 2;
    const int nMinor = 2;

    if (initialized == TRUE) {
        return CPR_SUCCESS;
    }

    if (WSAStartup(MAKEWORD(nMinor, nMajor), &wsaData)) {
        /* startup failed */
        return CPR_FAILURE;
    }
    if ((LOBYTE(wsaData.wVersion) != nMinor) ||
        (HIBYTE(wsaData.wVersion) != nMajor)) {
        /* startup failed */
        return CPR_FAILURE;
    }
	cpr_sec_init_conn_table() ;

    initialized = TRUE;

    return CPR_SUCCESS;
}

cpr_status_e
cprSocketCleanup (void)
{
    if (initialized == FALSE) {
        return CPR_SUCCESS;
    }

    /* wait for all of the sockets to close before cleaning up */
    cprSleep(500);

    if (WSACleanup() == SOCKET_ERROR) {
        /* startup failed */
        return CPR_FAILURE;
    }
    initialized = FALSE;

    return CPR_SUCCESS;
}

cpr_socket_t
cprSocket (uint32_t domain,
           uint32_t type,
           uint32_t protocol)
{
    cpr_socket_t s;

    s = socket(domain, type, protocol);
    if (s == -1) {
    	return INVALID_SOCKET;
    }
    return s;
}

cpr_socket_t
cprAccept (cpr_socket_t socket,
           cpr_sockaddr_t * RESTRICT addr,
           cpr_socklen_t * RESTRICT addr_len)
{
    cpr_socket_t s;

    cprAssert(addr != NULL, INVALID_SOCKET);
    cprAssert(addr_len != NULL, INVALID_SOCKET);

    s = accept(socket, (struct sockaddr *) addr, addr_len);
    if (s == -1) {
        return INVALID_SOCKET;
    }
    return s;
}

cpr_status_e
cprBind (cpr_socket_t socket,
         CONST cpr_sockaddr_t * RESTRICT addr,
         cpr_socklen_t addr_len)
{
    cprAssert(addr != NULL, CPR_FAILURE);

    return ((bind(socket, (struct sockaddr *) addr, addr_len) != 0) ?
            CPR_FAILURE : CPR_SUCCESS);
}

cpr_status_e
cprCloseSocket (cpr_socket_t socket)
{
	int	connid ;

	connid = cpr_sec_fd_to_connid(socket);
	if(connid == -1)
		return ((closesocket(socket) != 0) ? CPR_FAILURE : CPR_SUCCESS);
	secSock_close(cpr_sec_conn_tab[connid].ssl) ;
	cpr_sec_purge_entry(connid) ;

	return CPR_SUCCESS ;
}

cpr_status_e
cprConnect (cpr_socket_t socket,
            SUPPORT_CONNECT_CONST cpr_sockaddr_t * RESTRICT addr,
            cpr_socklen_t addr_len)
{
	int retry = 0, retval = 0;
	cpr_status_e returnValue = CPR_FAILURE;

    cprAssert(addr != NULL, CPR_FAILURE);

    retval = connect(socket, (struct sockaddr *) addr, addr_len );

    while (retval == -1 && (cpr_errno == CPR_EAGAIN || cpr_errno == CPR_EINPROGRESS || cpr_errno == CPR_EALREADY) && retry < MAX_RETRY_FOR_EAGAIN)
    {
    	cprSleep(100);
    	retry++;
    	retval = connect(socket, (struct sockaddr *) addr, addr_len);
    }

	if (0 == retval || (-1 == retval && cpr_errno == CPR_EISCONN))
    {
    	returnValue = CPR_SUCCESS;
    }

    return returnValue;
}

cpr_status_e
cprGetPeerName (cpr_socket_t socket,
                cpr_sockaddr_t * RESTRICT addr,
                cpr_socklen_t * RESTRICT addr_len)
{
    cprAssert(addr != NULL, CPR_FAILURE);
    cprAssert(addr_len != NULL, CPR_FAILURE);

    return ((getpeername(socket, (struct sockaddr *) addr, addr_len) != 0) ?
            CPR_FAILURE : CPR_SUCCESS);
}

cpr_status_e
cprGetSockName (cpr_socket_t socket,
                cpr_sockaddr_t * RESTRICT addr,
                cpr_socklen_t * RESTRICT addr_len)
{
    cprAssert(addr != NULL, CPR_FAILURE);
    cprAssert(addr_len != NULL, CPR_FAILURE);

    return ((getsockname(socket, (struct sockaddr *) addr, addr_len) != 0) ?
            CPR_FAILURE : CPR_SUCCESS);
}

cpr_status_e
cprGetSockOpt (cpr_socket_t socket,
               uint32_t level,
               uint32_t opt_name,
               void * RESTRICT opt_val,
               cpr_socklen_t * RESTRICT opt_len)
{
    cprAssert(opt_val != NULL, CPR_FAILURE);
    cprAssert(opt_len != NULL, CPR_FAILURE);

    if (getsockopt(socket, level, opt_name, (char*)opt_val, opt_len) != 0) {
        return CPR_FAILURE;
    }
    return CPR_SUCCESS;
}

cpr_status_e
cprListen (cpr_socket_t socket,
           uint16_t backlog)
{
    return ((listen(socket, backlog) != 0) ? CPR_FAILURE : CPR_SUCCESS);
}

ssize_t
cprRecv (cpr_socket_t socket,
         void * RESTRICT buf,
         size_t len,
         int32_t flags)
{
    ssize_t rc;
	int	connid ;

    cprAssert(buf != NULL, CPR_FAILURE);

	connid = cpr_sec_fd_to_connid(socket);
	if(connid == -1)
  		rc = recv(socket, (char*)buf, len, flags);
	else
		rc = secSock_read(cpr_sec_conn_tab[connid].ssl, (char*)buf, len) ;
    if (rc == -1) {
        return SOCKET_ERROR;
    }

    return rc;
}

ssize_t
cprRecvFrom (cpr_socket_t socket,
             void * RESTRICT buf,
             size_t len,
             int32_t flags,
             cpr_sockaddr_t * RESTRICT from,
             cpr_socklen_t * RESTRICT fromlen)
{
    ssize_t rc;

    cprAssert(buf != NULL, CPR_FAILURE);
    cprAssert(from != NULL, CPR_FAILURE);
    cprAssert(fromlen != NULL, CPR_FAILURE);

    rc = recvfrom(socket, (char*)buf, len, flags, (struct sockaddr *) from, fromlen);
    if (rc == -1) {
        int err = WSAGetLastError();
        return SOCKET_ERROR;
    }
    return rc;
}

int16_t
cprSelect (uint32_t nfds,
           fd_set * RESTRICT read_fds,
           fd_set * RESTRICT write_fds,
           fd_set * RESTRICT except_fds,
           struct cpr_timeval * RESTRICT timeout)
{
    int rc;
    struct timeval tv;

    tv.tv_sec = (long) (timeout->tv_sec + (timeout->tv_usec / 1000000));
    tv.tv_usec = (long) timeout->tv_usec % 1000000;

    if ((read_fds && (read_fds->fd_count != 0)) ||
        (write_fds && (write_fds->fd_count != 0)) ||
        (except_fds && (except_fds->fd_count != 0))) {

        rc = select(nfds, read_fds, write_fds, except_fds, &tv);

        if (rc == -1) {
            int error = WSAGetLastError();

            return SOCKET_ERROR;
        }
    } else {
        /* Convert to milliseconds (seconds * 1000) + (micro seconds / 1000) */
        uint32_t sleepTime = (uint32_t)((long)tv.tv_sec * 1000) + (tv.tv_usec / 1000);
        cprSleep(sleepTime);
        rc = 0;
    }
    return (int16_t) rc;
}

ssize_t
cprSend (cpr_socket_t socket,
         CONST void *buf,
         size_t len,
         int32_t flags)
{
    ssize_t rc;
	int	connid ;

    cprAssert(buf != NULL, CPR_FAILURE);

	connid = cpr_sec_fd_to_connid(socket);
	if(connid == -1)
  	    rc = send(socket, (char*)buf, len, flags);
	else
		rc = secSock_write(cpr_sec_conn_tab[connid].ssl, (char*)buf, len) ;
    if (rc == -1) {
        return SOCKET_ERROR;
    }
    return rc;
}

ssize_t
cprSendTo (cpr_socket_t socket,
           CONST void *msg,
           size_t len,
           int32_t flags,
           CONST cpr_sockaddr_t *dest_addr,
           cpr_socklen_t dest_len)
{
    ssize_t rc;

    cprAssert(msg != NULL, CPR_FAILURE);
    cprAssert(dest_addr != NULL, CPR_FAILURE);

    rc = sendto(socket, (char*)msg, len, flags,
                (struct sockaddr *) dest_addr, dest_len);
    if (rc == -1) {
        return SOCKET_ERROR;
    }
    return rc;
}

cpr_status_e
cprSetSockOpt (cpr_socket_t socket,
               uint32_t level,
               uint32_t opt_name,
               CONST void *opt_val,
               cpr_socklen_t opt_len)
{
#ifndef NEED_TO_CALL_FOR_WIN32
	cprAssert(opt_val != NULL, CPR_FAILURE);

    return ((setsockopt(socket, level, opt_name, (char*)opt_val, opt_len) != 0) ?
            CPR_FAILURE : CPR_SUCCESS);
#else
    // Found out that the above call fails for windows. So the
    // socket created is in blocking mode. Need to enable
    // ioctlsocket() call to put the socket in non-blocking mode.
    //
    //-------------------------
    // Set the socket I/O mode: In this case FIONBIO
    // enables or disables the blocking mode for the
    // socket based on the numerical value of iMode.
    // If iMode = 0, blocking is enabled;
    // If iMode != 0, non-blocking mode is enabled.
    int iMode = 1;

    return ((ioctlsocket(socket, FIONBIO, (u_long FAR *) &iMode) != 0) ?
            CPR_FAILURE : CPR_SUCCESS);
#endif /* NEED_TO_CALL_FOR_WIN32 */

}

cpr_status_e
cprSetSockNonBlock (cpr_socket_t socket)
{
	unsigned long iMode = 1;
	return ((ioctlsocket(socket, FIONBIO, (u_long FAR *) &iMode) != 0) ? CPR_FAILURE : CPR_SUCCESS);
}

cpr_status_e
cprShutDown (cpr_socket_t socket,
             cpr_shutdown_e how)
{
    int os_how;

    switch (how) {
    case CPR_SHUTDOWN_RECEIVE:
        os_how = SD_RECEIVE;
        break;
    case CPR_SHUTDOWN_SEND:
        os_how = SD_SEND;
        break;
    default:
    case CPR_SHUTDOWN_BOTH:
        os_how = SD_BOTH;
        break;
    }

    return ((shutdown(socket, os_how) != 0) ? CPR_FAILURE : CPR_SUCCESS);
}

/**
 *
 * Lookup the secure status of the server in the CTL
 *
 * @param   ipaddr_str   server ip address
 *
 * @return  Server is not enabled for security
 *          CPR_SOC_NONSECURE
 *
 * @todo    Security is not implemented for win32
 *
 */
cpr_soc_sec_status_e
cprSecLookupSrvr (char* ipaddr_str)
{
    int ret;

    cprAssert(ipaddr_str != NULL, CPR_FAILURE);
    ret = secReq_LookupSrvr(ipaddr_str, SRVR_TYPE_CCM);
    if (ret == SRVR_SECURE) {
        return CPR_SOC_SECURE;
    }
    return CPR_SOC_NONSECURE;
}

#define HOST_AND_PORT_SIZE 64

/**
 *
 * Securely connect to a remote server
 *
 * @param[in]  hostAndPort  server addr and port in host:port form
 * @param[in]  mode         blocking connect or not
 *                          FALSE : non-blocking; TRUE: blocking
 * @param[in]  tos          TOS value
 *
 * @param[out] localPort    local port used for the connection
 *
 * @return     INVALID SOCKET, connect failed
 *
 * @todo       Security is not implemented for win32
 *
 */
cpr_socket_t
cprSecSocConnect (char *host,
                  int     port,
                  int     ipMode,
                  boolean mode,
                  uint32_t tos,
                  uint16_t *localPort)
{
	int ssl = 0 ;
	int idx;
    uint16_t loopCnt  = 0;
    uint16_t sec_port = 0;
    cpr_socket_t sock = INVALID_SOCKET;
    char hostAndPort[HOST_AND_PORT_SIZE];

    cprAssert(host != NULL, CPR_FAILURE);
    cprAssert(localPort != NULL, CPR_FAILURE);
    snprintf(hostAndPort, HOST_AND_PORT_SIZE, "%s:%d", host, port);
    while (loopCnt < TCP_PORT_RETRY_CNT) {
        ssl = secSock_connect(CLNT_SCCP,       /* type          */
                               hostAndPort,          /* host:port     */
                               mode,                 /* 1 - block     */
                               CLNT_TMO_DEFAULT,     /* timeout value */
                               0);                   /* TOS value     */
        if (ssl == -1) {
			return INVALID_SOCKET;
        }
		else
		{
			cpr_sockaddr_t local_addr;
			cpr_socklen_t local_addr_len = sizeof(cpr_sockaddr_t);

			sock = secSock_getFD(ssl) ;

			if (cprGetSockName(sock, &local_addr, &local_addr_len) != CPR_FAILURE)
			{
				cpr_sockaddr_in_t *local_addr_ptr;
				local_addr_ptr = (cpr_sockaddr_in_t *)&local_addr;
				*localPort = ntohs(local_addr_ptr->sin_port);
			}
			else
			{
				secSock_close(ssl) ;
				ssl = 0 ;
				sock = INVALID_SOCKET ;

				return INVALID_SOCKET;
			}

			// Setup the secure connection structure
		    idx = cpr_sec_get_free_conn_entry();
			if (idx == -1) {
				secSock_close(ssl) ;
				*localPort = 0 ;
				//CPR_ERROR("cpr_sec_get_free_conn_entry failed\n");
				return INVALID_SOCKET;
			}
			cpr_sec_conn_tab[idx].fd = sock ;
			cpr_sec_conn_tab[idx].ssl = ssl ;
            return (sock);
        }
    }
    return INVALID_SOCKET;
}

/**
 *
 * Determine the status of a secure connection that was initiated
 * in non-blocking mode
 *
 * @param    sock   socket descriptor
 *
 * @return   connection failed, CPR_SOC_CONN_FAILED
 *
 * @todo     Security is not implemented for win32
 *
 */
cpr_soc_connect_status_e
cprSecSockIsConnected (cpr_socket_t sock)
{
#ifdef NON_BLOCKING_MODE_IS_USED
    int conn_status;
	int	connid ;

	connid = cpr_sec_fd_to_connid(sock);
	if(connid == -1)
		return CPR_SOC_CONN_FAILED;

    conn_status = secSock_isConnected(cpr_sec_conn_tab[connid].ssl);
    if (conn_status == CLNT_CONN_OK) {
        return CPR_SOC_CONN_OK;
    } else if (conn_status == CLNT_CONN_WAITING) {
        return CPR_SOC_CONN_WAITING;
    }
    return CPR_SOC_CONN_FAILED;
#else
	return CPR_SOC_CONN_OK;
#endif;
}

/**
 * cprSocketPair
 *
 * @todo The socketpair() call is not supported on win32.
 */
cpr_status_e
cprSocketPair (uint32_t domain,
               uint32_t type,
               uint32_t protocol,
               cpr_socket_t sockets[2])
{
    WSASetLastError(WSAEOPNOTSUPP);
    return CPR_FAILURE;
}


/* int
 * inet_pton4(src, dst, pton)
 *	when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
 *	when last arg is 1: inet_pton(). decimal dotted-quad only.
 * return:
 *	1 if `src' is a valid input, else 0.
 * notice:
 *	does not touch `dst' unless it's returning 1.
 */
static int
cpr_inet_pton4(const char *src, uint8_t *dst, int pton)
{
	uint32_t val;
	uint32_t digit;
	int base, n;
	unsigned char c;
	uint32_t parts[4];
	uint32_t *pp = parts;

	c = *src;
	for (;;) {
		/*
		 * Collect number up to ``.''.
		 * Values are specified as for C:
		 * 0x=hex, 0=octal, isdigit=decimal.
		 */
		if (!isdigit(c))
			return (0);
		val = 0; base = 10;
		if (c == '0') {
			c = *++src;
			if (c == 'x' || c == 'X')
				base = 16, c = *++src;
			else if (isdigit(c) && c != '9')
				base = 8;
		}
		/* inet_pton() takes decimal only */
		if (pton && base != 10)
			return (0);
		for (;;) {
			if (isdigit(c)) {
				digit = c - '0';
				if (digit >= (uint16_t)base)
					break;
				val = (val * base) + digit;
				c = *++src;
			} else if (base == 16 && isxdigit(c)) {
				digit = c + 10 - (islower(c) ? 'a' : 'A');
				if (digit >= 16)
					break;
				val = (val << 4) | digit;
				c = *++src;
			} else
				break;
		}
		if (c == '.') {
			/*
			 * Internet format:
			 *	a.b.c.d
			 *	a.b.c	(with c treated as 16 bits)
			 *	a.b	(with b treated as 24 bits)
			 *	a	(with a treated as 32 bits)
			 */
			if (pp >= parts + 3)
				return (0);
			*pp++ = val;
			c = *++src;
		} else
			break;
	}
	/*
	 * Check for trailing characters.
	 */
	if (c != '\0' && !isspace(c))
		return (0);
	/*
	 * Concoct the address according to
	 * the number of parts specified.
	 */
	n = pp - parts + 1;
	/* inet_pton() takes dotted-quad only.  it does not take shorthand. */
	if (pton && n != 4)
		return (0);
	switch (n) {

	case 0:
		return (0);		/* initial nondigit */

	case 1:				/* a -- 32 bits */
		break;

	case 2:				/* a.b -- 8.24 bits */
		if (parts[0] > 0xff || val > 0xffffff)
			return (0);
		val |= parts[0] << 24;
		break;

	case 3:				/* a.b.c -- 8.8.16 bits */
		if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
			return (0);
		val |= (parts[0] << 24) | (parts[1] << 16);
		break;

	case 4:				/* a.b.c.d -- 8.8.8.8 bits */
		if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
			return (0);
		val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
		break;
	}
	if (dst) {
		val = htonl(val);
		memcpy(dst, &val, INADDRSZ);
	}
	return (1);
}

/* int
 * inet_pton6(src, dst)
 *	convert presentation level address to network order binary form.
 * return:
 *	1 if `src' is a valid [RFC1884 2.2] address, else 0.
 * notice:
 *	(1) does not touch `dst' unless it's returning 1.
 *	(2) :: in a full address is silently ignored.
 */
static int
cpr_inet_pton6(const char *src, uint8_t *dst)
{
	static const char xdigits_l[] = "0123456789abcdef",
			  xdigits_u[] = "0123456789ABCDEF";
	uint8_t tmp[IN6ADDRSZ], *tp, *endp, *colonp;
	const char *xdigits, *curtok;
	int ch, saw_xdigit;
	unsigned int val;

	memset((tp = tmp), '\0', IN6ADDRSZ);
	endp = tp + IN6ADDRSZ;
	colonp = NULL;
	/* Leading :: requires some special handling. */
	if (*src == ':')
		if (*++src != ':')
			return (0);
	curtok = src;
	saw_xdigit = 0;
	val = 0;
	while ((ch = *src++) != '\0') {
		const char *pch;

		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
			pch = strchr((xdigits = xdigits_u), ch);
		if (pch != NULL) {
			val <<= 4;
			val |= (pch - xdigits);
			if (val > 0xffff)
				return (0);
			saw_xdigit = 1;
			continue;
		}
		if (ch == ':') {
			curtok = src;
			if (!saw_xdigit) {
				if (colonp)
					return (0);
				colonp = tp;
				continue;
			} else if (*src == '\0')
				return (0);
			if (tp + INT16SZ > endp)
				return (0);
			*tp++ = (uint8_t) (val >> 8) & 0xff;
			*tp++ = (uint8_t) val & 0xff;
			saw_xdigit = 0;
			val = 0;
			continue;
		}
		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
		    cpr_inet_pton4(curtok, tp, 1) > 0) {
			tp += INADDRSZ;
			saw_xdigit = 0;
			break;	/* '\0' was seen by inet_pton4(). */
		}
		return (0);
	}
	if (saw_xdigit) {
		if (tp + INT16SZ > endp)
			return (0);
		*tp++ = (uint8_t) (val >> 8) & 0xff;
		*tp++ = (uint8_t) val & 0xff;
	}
	if (colonp != NULL) {
		/*
		 * Since some memmove()'s erroneously fail to handle
		 * overlapping regions, we'll do the shift by hand.
		 */
		const int n = tp - colonp;
		int i;

		if (tp == endp)
			return (0);
		for (i = 1; i <= n; i++) {
			endp[- i] = colonp[n - i];
			colonp[n - i] = 0;
		}
		tp = endp;
	}
	if (tp != endp)
		return (0);
	memcpy(dst, tmp, IN6ADDRSZ);
	return (1);
}

/* int
 * inet_pton(af, src, dst)
 *	convert from presentation format (which usually means ASCII printable)
 *	to network format (which is usually some kind of binary format).
 * return:
 *	1 if the address was valid for the specified address family
 *	0 if the address wasn't valid (`dst' is untouched in this case)
 *	-1 if some other error occurred (`dst' is untouched in this case, too)
 */
int
cpr_inet_pton (int af, const char *src, void *dst)
{

	switch (af) {
	case AF_INET:
		return (cpr_inet_pton4(src, (uint8_t*)dst, 1));
	case AF_INET6:
		return (cpr_inet_pton6(src, (uint8_t*)dst));
	default:
		return (-1);
	}
	/* NOTREACHED */
}

void cpr_set_sockun_addr(cpr_sockaddr_un_t *addr, const char *name, pid_t pid)
{
  /* COPIED FROM OTHER PLATFORM AS A PLACE HOLDER */
  /* Bind to the local socket */
  memset(addr, 0, sizeof(cpr_sockaddr_un_t));
  addr->sun_family = AF_INET;
  snprintf(addr->sun_path, sizeof(addr->sun_path), name, pid);
}