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

📄 rvsocket.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 5 页
字号:
                sin->sin_family = AF_INET;
                sin->sin_port = htons(ipv4Addr->port);
                sin->sin_addr.s_addr = RvAddressIpv4GetIp(ipv4Addr);
                *socklen = sizeof(struct sockaddr_in);

                /* We use htons and not our internal RvConvertHostToNetwork16() since Tru64
                   doesn't work properly otherwise */
            }
        }
        break;

#if RV_SOCKET_HAS_IPV6
    case RV_ADDRESS_TYPE_IPV6:
        {
            struct sockaddr_in6 *sin= (struct sockaddr_in6 *)sockaddr;
            RvUint8 ip[16];
            RvUint16 port;
            RvUint32 flowInfo;
            RvUint32 scopeId;

            res = RvAddressGetIpv6(address, ip, &port, &flowInfo, &scopeId);

            if (res == RV_OK)
            {
                memset((char *)sin, 0, sizeof(sin));
                sin->sin6_family = AF_INET6;
                memcpy(&(sin->sin6_addr), ip, sizeof(ip));
                sin->sin6_scope_id = scopeId;
                sin->sin6_flowinfo = flowInfo;
                sin->sin6_port= htons(port);
            }
        }
        break;
#endif  /* RV_SOCKET_HAS_IPV6 */

    default:
        res = RvSocketErrorCode(RV_ERROR_BADPARAM);
        break;
    }

    return res;
}


/********************************************************************************************
 * RvSocketAddressToSockAddr
 *
 * purpose : Set the port inside a sockaddr struct to a specified port value
 * input   : sockaddr   - Socket address to modify
 *           port       - Port to set in address
 * output  : None
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
static RvStatus RvSocketSockAddrSetPort(
    IN RV_SOCKADDR_PTR  sockaddr,
    IN RvUint           port)
{
    switch (sockaddr->sa_family)
    {
    case AF_INET:
        {
            RvUint16 port16 = (RvUint16)port;
            struct sockaddr_in* sin = (struct sockaddr_in *)sockaddr;
            sin->sin_port = htons(port16);
        }
        break;
#if RV_SOCKET_HAS_IPV6
    case AF_INET6:
        {
            RvUint16 port16 = (RvUint16)port;
            struct sockaddr_in6 *sin= (struct sockaddr_in6 *)sockaddr;
            sin->sin6_port= htons(port16);
        }
        break;
#endif
    default:
        return RvSocketErrorCode(RV_ERROR_UNKNOWN);
    }

    return RV_OK;
}





/********************************************************************************************
 *
 *                                      Public functions
 *
 ********************************************************************************************/



RvStatus RvSocketInit(void)
{
    RvStatus status;
    RvUint16 endianTest = 1;

    /* Make sure we've compiled this with the right endian */
#if (RV_ARCH_ENDIAN == RV_ARCH_LITTLE_ENDIAN)
    if (endianTest == RvConvertHostToNetwork16(endianTest))
        return RvSocketErrorCode(RV_ERROR_NOTSUPPORTED);
#elif (RV_ARCH_ENDIAN == RV_ARCH_BIG_ENDIAN)
    if (endianTest != RvConvertHostToNetwork16(endianTest))
        return RvSocketErrorCode(RV_ERROR_NOTSUPPORTED);
#endif

    status = RvSocketSharerInit();
    if (status != RV_OK)
        return status;

    status = RvLogSourceConstruct(RvLogGet(), &rvSocketLogSource, RV_LOG_LIBCODE_CCORE, "SOCKET", "Sockets interface");
    if (status != RV_OK)
    {
        RvSocketSharerEnd();
        return status;
    }

#if (RV_SOCKET_TYPE == RV_SOCKET_NUCLEUS)

#define MAX_TIMERS_PER_THREAD 100

    /* Create the default ephemeral port range for NUCLEUS */
    status = RvPortRangeConstruct(&RvSocketPortRange, 49152, 65535);

    /* timer initialization */
    RvTimerInit();
    status = RvTimerQueueConstruct(&timerQueue, RV_TIMER_QTYPE_FIXED, MAX_TIMERS_PER_THREAD, 0, 0, 0, 40, NULL);

    RvMemoryAlloc(NULL, (void **)&nuConInfo, (RvSize_t)(sizeof(connectionInfo)*RvSelectGetMaxFileDescriptors()));
    if (nuConInfo == NULL)
        return RvSocketErrorCode(RV_ERROR_UNKNOWN);

    memset(nuConInfo, 0, (RvSize_t)(sizeof(nuConInfo)*RvSelectGetMaxFileDescriptors()));

#elif (RV_SOCKET_TYPE == RV_SOCKET_BSD)

#if (RV_OS_TYPE != RV_OS_TYPE_WINCE) && (RV_OS_TYPE != RV_OS_TYPE_OSE)
    /* Catch SIGPIPE signals and ignore them instead of core-dumping */
    if (signal(SIGPIPE, RvSocketHandleSigPipe) == SIG_ERR)
        status = RvSocketErrorCode(RV_ERROR_UNKNOWN);
#endif

#endif

    if (status != RV_OK)
    {
        RvLogSourceDestruct(RvLogGet(), &rvSocketLogSource);
        RvSocketSharerEnd();
    }

    return status;
}


RvStatus RvSocketEnd(void)
{
    RvStatus status;

    RvLogSourceDestruct(RvLogGet(), &rvSocketLogSource);
    status = RvSocketSharerEnd();

#if (RV_SOCKET_TYPE == RV_SOCKET_NUCLEUS)
    status = RvPortRangeDestruct(&RvSocketPortRange);

    /* end timer module */
    status = RvTimerQueueStop(&timerQueue);

    RvMemoryFree(nuConInfo);

#endif

    return status;
}




/* ================================================================ */
/* ==== General functions (used by both TCP and UDP protocols) ==== */
/* ================================================================ */


/********************************************************************************************
 * RvSocketConstruct
 *
 * purpose : Allocate a new socket.
 * input   : sock           - pointer to the socket info.
 *           addressType    - IPv4 or IPv6.
 *           protocolType   - TCP or UDP.
 * output  : None
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketConstruct(
    IN RvSocket*        sock,
    IN RvInt            addressType,
    IN RvSocketProtocol protocolType)
{
    RvStatus res;

#if defined(RV_OTHERCHECK)
    if ((protocolType != RvSocketProtocolUdp) && (protocolType != RvSocketProtocolTcp))
        return RvSocketErrorCode(RV_ERROR_BADPARAM);
#endif

#if (RV_SOCKET_USE_SHARER == 1)
    res = RvSocketSharerConstruct(sock, addressType, protocolType);
#else
    res = RvSocketConstructHere(sock, addressType, protocolType);
#endif

    RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
        "RvSocketConstruct(socket=%d,type=%d,protocol=%d)=%d", *sock, addressType, protocolType, res));

    return res;
}

/********************************************************************************************
 * RvSocketShutdown
 *
 * purpose : Shutdown a TCP socket. This function should be called before calling
 *           RvSocketDestruct() for TCP sockets.
 * input   : sock           - Socket to shutdown
 *           cleanSocket    - RV_TRUE if you want to clean the socket before shutting it down.
 *                            this will try to receive from the socket some buffers.
 *                            It is suggested to set this value to RV_TRUE.
 * output  : None
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketShutdown(
    IN RvSocket*    sock,
    IN RvBool       cleanSocket)
{
    RvSocket ourSocket;
    RvStatus ret;

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

#if (RV_SOCKET_TYPE != RV_SOCKET_NUCLEUS)

    if (shutdown(ourSocket, SD_SEND) < 0)
        ret = RvSocketErrorCode(RV_ERROR_UNKNOWN);

    RvSocketSharerClose(&ourSocket);

    if (cleanSocket)
    {
        RvUint8 tmpBuffer[128];
        RvInt safetyCounter = 10;
        RvSize_t bytesReceived = 1;
        ret = RV_OK;

        /* Clean the socket as much as we can */
        while ((safetyCounter > 0) && (ret == RV_OK) && (bytesReceived > 0))
        {
            ret = RvSocketReceiveBuffer(sock, tmpBuffer, sizeof(tmpBuffer), &bytesReceived, NULL);
            safetyCounter--;
        }
    }
#else
    if (nuConInfo[ourSocket].timer != NULL)
        RvTimerCancel(nuConInfo[ourSocket].timer, RV_TIMER_CANCEL_NONBLOCKING);

    if (nuConInfo[ourSocket].socketState == RvSocketState_Connecting)
        NU_Abort(ourSocket);
    if (nuConInfo[ourSocket].threadState == RvThreadState_Stopped)
        RvSocketTaskClean(ourSocket);
    nuConInfo[ourSocket].socketState = RvSocketState_Closing;

    /* todo: Make sure the following if statement is ok */
    if (nuConInfo[ourSocket].threadState == RvThreadState_Idle)
    {
        RvThreadConstruct(&(nuConInfo[ourSocket].threadId), RvSocketEventsTask, (void*)&ourSocket);
        ret = RvThreadStart(&(nuConInfo[ourSocket].threadId));
        if (ret>=0)
            nuConInfo[ourSocket].threadState = RvThreadState_Running;
    }

#endif  /* (RV_SOCKET_TYPE != RV_SOCKET_NUCLEUS) */

    RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
        "RvSocketShutdown(socket=%d,clean=%d)=%d", *sock, cleanSocket, ret));

    return ret;
}

/********************************************************************************************
 * RvSocketDestruct
 *
 * purpose : Close a socket.
 * input   : sock           - Socket to shutdown
 *           cleanSocket    - RV_TRUE if you want to clean the socket before shutting it down.
 *                            this will try to receive from the socket some buffers.
 *                            It is suggested to set this value to RV_TRUE for TCP sockets.
 *                            It should be set to RV_FALSE for UDP sockets.
 *           portRange      - Port range to return this socket's port to. If NULL, the
 *                            socket's port will not be added to any port range object.
 * output  : None
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSocketDestruct(
    IN RvSocket*    sock,
    IN RvBool       cleanSocket,
    IN RvPortRange* portRange)
{
    RvStatus res = RV_OK;
/* todo: add sharer */
#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

    if (portRange != NULL)
    {
        /* We should try and return this socket's port to the port-range object */
        RvAddress localAddress;
        RvUint16 port;
        res = RvSocketErrorCode(RV_ERROR_UNKNOWN);

        if (RvSocketGetLocalAddress(sock, &localAddress) == RV_OK)
        {
            port = RvAddressGetIpPort(&localAddress);

            if (port > 0)
            {
                RvUint fromPort, toPort;

                /* Make sure this one is within the range we're dealing with */
                res = RvPortRangeGetRange(portRange, &fromPort, &toPort);
                if (res == RV_OK)
                {
                    /* Add this port to list of available ports */
                    res = RvPortRangeReleasePort(portRange, (RvUint)port);
                }
            }
        }
    }

#if (RV_SOCKET_TYPE != RV_SOCKET_NUCLEUS)
    if (cleanSocket)
    {
        RvUint8 tmpBuffer[128];
        RvInt safetyCounter = 10;
        RvSize_t bytesReceived = 1;
        RvStatus res = RV_OK;

        /* Clean the socket as much as we can */
        while ((safetyCounter > 0) && (res == RV_OK) && (bytesReceived > 0))
        {
            res = RvSocketReceiveBuffer(sock, tmpBuffer, sizeof(tmpBuffer), &bytesReceived, NULL);
            safetyCounter--;
        }
    }

    /* todo: RvSocketSharerDestruct */

    if (RvSocketClose(*sock) < 0)
    {
        RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
            "RvSocketDestruct: Error closing socket=%d (%d)", *sock, RvSocketErrNo));
        res = RvSocketErrorCode(RV_ERROR_UNKNOWN);
    }
#else
    RvSocketTaskClean(*sock);
    if (nuConInfo[*sock].socketState != RvSocketState_Closed)
    {
        NU_Abort(*sock);
        RvSocketClose(*sock);
        nuConInfo[*sock].socketState = RvSocketState_Closed;
    }
    if (nuConInfo[*sock].timer != NULL)
    {
        RvTimerCancel(nuConInfo[*sock].timer, RV_TIMER_CANCEL_NONBLOCKING);
        nuConInfo[*sock].timer = NULL;
    }
    memset(nuConInfo+*sock,0,sizeof(nuConInfo[*sock]));

#endif  /* (RV_SOCKET_TYPE != RV_SOCKET_NUCLEUS) */

    RvLogDebug(&rvSocketLogSource, (&rvSocketLogSource,
        "RvSocketDestruct(socket=%d,clean=%d,range=0x%p)=%d", *sock, cleanSocket, portRange, res));

    return res;
}


/********************************************************************************************
 * RvSocketBind
 *
 * purpose : Bind a socket to a local address
 * input   : sock       - Socket to bind
 *           address    - Address to bind socket to
 *           portRange  - Port range to use if address states an ANY port.

⌨️ 快捷键说明

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