⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rvsocket.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 5 页
字号:
 *                        NULL if this parameter should be ignored.
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketBind(
    IN RvSocket*    sock,
    IN RvAddress*   address,
    IN RvPortRange* portRange)
{
    RvStatus ret;
    RvSocket ourSocket = 0;
    RvUint8 sockdata[RV_SOCKET_SOCKADDR_SIZE];
    int socklen;
    RvBool usePortRange;

#if (RV_SOCKET_TYPE == RV_SOCKET_NUCLEUS)
    /* In NUCLEUS, we make sure to have a portRange. If none is supplied, we just use
       the static one declared and used in this module. */
    if (portRange == NULL)
        portRange = &RvSocketPortRange;
#endif

    usePortRange = ((portRange != NULL) &&
        (RvAddressGetIpPort(address) == RV_ADDRESS_IPV4_ANYPORT));

    ret = RvSocketAddressToSockAddr(address, (RV_SOCKADDR_PTR)sockdata, &socklen);
    if (ret == RV_OK)
        ret = RvSocketSharerShare(sock, &ourSocket);

    if (ret == RV_OK)
    {
        if (usePortRange)
        {
            RvUint numberOfTries, port;

            ret = RvPortRangeGetNumberOfFreePorts(portRange, &numberOfTries);

            /* Try until we went through all available ports or until we find a vacant port */
            while ((numberOfTries > 0) && (ret == RV_OK))
            {
                /* Get a port */
                ret = RvPortRangeGetPort(portRange, &port);
                if (ret != RV_OK)
                    break;

                /* Fix port in address struct */
                ret = RvSocketSockAddrSetPort((RV_SOCKADDR_PTR)sockdata, port);
                if (ret != RV_OK)
                    break;

                /* Try to bind */
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
                if ((bind(ourSocket, (RV_SOCKADDR_PTR)sockdata, socklen)) >= 0)
                    break; /* We found a good one - exit the while loop */
#else
                if (NU_Bind(ourSocket, (struct sockaddr_in *)sockdata, 0) < 0)
                    break; /* We found a good one - exit the while loop */
#endif
                /* Check the error code to see if we want to resume our check */
#if (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)
                switch (WSAGetLastError())
                {
                case WSAEACCES:
                case WSAEADDRINUSE:
                case WSAEADDRNOTAVAIL:
                    /* We assume that adress is in use even if it's unavailable or we have an access violation */
                    break;
                default:
                    ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
                    break;
                }

#elif (RV_SOCKET_TYPE == RV_SOCKET_BSD)
                switch (RvSocketErrNo)
                {
                case EADDRINUSE:
                case EADDRNOTAVAIL:
#ifdef EACCES
                case EACCES: /* Not supported in WinCE or PSOS */
#endif
                    /* We assume that adress is in use even if it's unavailable or we have an access violation */
                    break;
                default:
                    ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
                    break;
                }
#endif

                /* No good - this port is taken by someone other than this port range. Release
                   this port back to pool of free ports - it might get free next time. */
                RvPortRangeReleasePort(portRange, port);
                numberOfTries--;
            }
        }
        else        
#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)
            /* Just bind and get it over with */
            if ((bind(ourSocket, (RV_SOCKADDR_PTR)sockdata, socklen)) < 0)
                ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#else
            if ((NU_Bind(ourSocket, (struct sockaddr_in *)sockdata, socklen)) < 0)
                ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);        
#endif
    }

    RvSocketSharerClose(&ourSocket);

#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
    if (ret == RV_OK)
    {
        RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
        RvAddressGetString(address, addr, sizeof(addr));
        RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketBind(sock=%d,addr=%s:%d,range=0x%p,useRange=%d)=0",
            *sock, addr, RvAddressGetIpPort(address), portRange, usePortRange));
    }
#endif

#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
    if (ret != RV_OK)
    {
        RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
        RvAddressGetString(address, addr, sizeof(addr));
        RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketBind(sock=%d,addr=%s:%d,range=0x%p,useRange=%d,errno=%d)=%d",
            *sock, addr, RvAddressGetIpPort(address), portRange, usePortRange, RvSocketErrNo, ret));
    }
#endif

    return ret;
}



/* =========================== */
/* ==== functions for TCP ==== */
/* =========================== */

RVCOREAPI
RvStatus RVCALLCONV RvSocketConnect(IN RvSocket *sock, IN RvAddress* address)
{
    RvSocket ourSocket;
    RvStatus ret;
    RvUint8 sockdata[RV_SOCKET_SOCKADDR_SIZE];
    int socklen;

    ret = RvSocketAddressToSockAddr(address, (RV_SOCKADDR_PTR)sockdata, &socklen);
    if (ret != RV_OK)
        return ret;

    ret = RvSocketSharerShare(sock, &ourSocket);
    if (ret != RV_OK)
        return ret;

#if (RV_SOCKET_TYPE == RV_SOCKET_BSD)       /* B S D */

#if (RV_OS_TYPE != RV_OS_TYPE_NUCLEUS)      /* B S D - All OS */
    if (connect(ourSocket, (RV_SOCKADDR_PTR)sockdata, socklen) != 0)
    {
        /* Make sure the error is not due to the non-blocking nature of this socket */
        if (RvSocketErrNo != EINPROGRESS)
            ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
    }
#else                                       /* B S D - Nucleus */
    /* Set timer to 45s connection time */
    ret = RvTimerStart(nuConInfo[ourSocket].timer, timerQueue, 
        RV_TIMER_TYPE_ONESHOT, 45000 /* 45 seconds */, 
        RvSocketEvTimerExp, ourSocket);
    if (ret != RV_OK)
    {
        /* print log */
        return RvSocketErrorCode(RV_ERROR_UNKNOWN);
    }

    nuConInfo[ourSocket].sockAddress = *address;
    RvThreadConstruct(&nuConInfo[ourSocket].threadId, RvSocketEventsTask, ourSocket);
    nuConInfo[ourSocket].socketState = RvSocketState_Connecting;
    ret = RvThreadStart(nuConInfo[ourSocket].threadId);
    if (ret != RV_OK)
    {
        nuConInfo[ourSocket].socketState == RvSocketState_Idle;
        return RvSocketErrorCode(RV_ERROR_UNKNOWN);
    }
    else
        nuConInfo[ourSocket].socketState == RvThreadState_Running;
#endif

#elif (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)
    if (WSAConnect(ourSocket, (RV_SOCKADDR_PTR)sockdata, socklen, NULL, NULL, NULL, NULL) == SOCKET_ERROR)
    {
        /* Would-Block error is just fine with us... */
        int wsaError = WSAGetLastError();
        if (wsaError != WSAEWOULDBLOCK)
            ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
    }
#endif

    RvSocketSharerClose(&ourSocket);

#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
    if (ret == RV_OK)
    {
        RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
        RvAddressGetString(address, addr, sizeof(addr));
        RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketConnect(sock=%d,addr=%s:%d)=0",
            *sock, addr, RvAddressGetIpPort(address)));
    }
#endif

#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
    if (ret != RV_OK)
    {
        RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
        RvAddressGetString(address, addr, sizeof(addr));
        RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketConnect(sock=%d,addr=%s:%d,errno=%d)=%d",
            *sock, addr, RvAddressGetIpPort(address), RvSocketErrNo, ret));
    }
#endif

    return ret;
}



/********************************************************************************************
 * RvSocketAccept
 *
 * purpose : Accept an incoming socket request
 * input   : sock           - Listening socket receiving the incoming connection
 * output  : newSocket      - Accepted socket information
 *           remoteAddress  - Address of remote side of connection
 *                            Can be passed as NULL if not needed
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketAccept(
    IN  RvSocket*       sock,
    OUT RvSocket*       newSocket,
    OUT RvAddress*      remoteAddress)
{
    RvSocket ourSocket;
    RvStatus ret;
    RvUint8 sockdata[RV_SOCKET_SOCKADDR_SIZE];
    int socklen = RV_SOCKET_SOCKADDR_SIZE;

    ret = RvSocketSharerShare(sock, &ourSocket);
    if (ret != RV_OK)
        return ret;

#if (RV_SOCKET_TYPE == RV_SOCKET_BSD)
#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
    if ((*newSocket = NU_Accept(ourSocket, (RV_SOCKADDR_PTR)sockdata, 0)) < 0)
        ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);

    /* check socket state - if still idle, close it in its task */
    if (nuConInfo[*newSocket].socketState)
    {
        RvSocketTaskClean(*newSocket);
        RvSocketCallback(*newSocket,RV_SELECT_CLOSE);
    }

    memset(nuConInfo+(*newSocket),0,sizeof(nuConInfo[*newSocket]));
    nuConInfo[*newSocket].socketState = RvSocketState_Connected;
#else
    if ((*newSocket = accept(ourSocket, (RV_SOCKADDR_PTR)sockdata, &socklen)) < 0)
        ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#endif
    if (ret == RV_OK)
    {
        /* Some Unix systems don't like setting the options of the listening socket in the
           accepted one, so we have to change the defaults to fit the regular needs. */
        int yes = RV_TRUE;

        /* Disable Nagle algorithm - we want our messages to be sent as soon as possible */
        if (RvSocketSetSockOpt(newSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof(yes)) != 0)
        {
            RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
                "RvSocketAccept: Failed to setsockopt(TCP_NODELAY) %d",
                RvSocketErrNo));
        }

        /* We're working with non-blocking sockets */
        RvSocketSetBlocking(newSocket, RV_FALSE);
    }

#elif (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)

    *newSocket = WSAAccept(ourSocket, (RV_SOCKADDR_PTR)&sockdata, &socklen, NULL, 0);
    if ((*newSocket) == INVALID_SOCKET)
        ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);

#endif

    RvSocketSharerClose(&ourSocket);

    if ((ret == RV_OK) && (remoteAddress != NULL))
        ret = RvSocketSockAddrToAddress(sockdata, socklen, remoteAddress);

#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
    if (ret == RV_OK)
    {
        RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
        if (remoteAddress != NULL)
            RvAddressGetString(remoteAddress, addr, sizeof(addr));
        else
            addr[0] = '\0';
        RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketAccept(sock=%d,new=%d,addr=%s:%d)=0",
            *sock, *newSocket, addr, RvAddressGetIpPort(remoteAddress)));
    }
#endif

#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
    if (ret != RV_OK)
    {
        RvChar addr[RV_ADDRESS_MAXSTRINGSIZE];
        if (remoteAddress != NULL)
            RvAddressGetString(remoteAddress, addr, sizeof(addr));
        else
            addr[0] = '\0';
        RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketAccept(sock=%d,new=%d,addr=%s:%d,errno=%d)=%d",
            *sock, *newSocket, addr, RvAddressGetIpPort(remoteAddress), RvSocketErrNo, ret));
    }
#endif

    return ret;
}


/********************************************************************************************
 * RvSocketListen
 *
 * purpose : Waits for an incoming connection.
 * input   : sock           - Listening socket receiving the incoming connection
 *           queuelen       -
 * output  : None.
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketListen(IN RvSocket *sock, IN RvUint32 queuelen)
{
    RvSocket ourSocket;
    RvStatus ret;

    ret = RvSocketSharerShare(sock, &ourSocket);
    if (ret != RV_OK)
        return ret;

#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
    if (NU_Listen(ourSocket, (int)queuelen) < 0)
        ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);

    ret = RvSocketSetBlocking(&ourSocket, RV_FALSE);
#else
    if (listen(ourSocket, (int)queuelen) < 0)
        ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#endif
    RvSocketSharerClose(&ourSocket);

#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_DEBUG)
    if (ret == RV_OK)
    {
        RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketListen(sock=%d,len=%d)=0",
            *sock, queuelen));
    }
#endif

#if (RV_LOGMASK_COMPILEMASK & RV_LOGLEVEL_ERROR)
    if (ret != RV_OK)
    {
        RvLogError(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketConnect(sock=%d,len=%d,errno=%d)=%d",
            *sock, queuelen, RvSocketErrNo, ret));
    }
#endif

    return ret;
}


/********************************************************************************************
 * RvSocketSendBuffer
 *
 * purpose : Send a buffer on a connection
 * input   : sock           - Socket to send the buffer on
 *           buffer         - Buffer to send
 *           bytesToSend    - Number of bytes to send from buffer
 *           remoteAddress  - Address to send the buffer to.
 *                            Can be NULL on connection-oriented sockets (TCP).
 * output  : bytesSent      - Number of bytes we sent
 *                            If less than bytesToSend, then we would block if we tried on a
 *                            blocking socket. The application in this cas should wait for a
 *                            WRITE event before trying again.
 * return  : RV_OK on success, other on failure
 * notes   : A blocked socket returns RV_OK with bytesSent=0
 ********************************************************************************************/
RVCOREAPI

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -