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

📄 tpkt.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 4 页
字号:
                    tpkt->recv.eventHandler((HTPKT)tpkt,selectEvent,tpktLen,RV_FALSE,tpkt->recv.context);
                    emaReturnFromCallback((EMAElement)tpkt, numOfLocks);
                }
            }
        }
        break;


        /* Treat the event of closing of a connection */
        case RvSelectClose:
        {
            RvLogDebug(&globals->log, (&globals->log,
                "tpktEvent(connection=%p, RvSelectClose, error=%d, context=%p)", connection, error, globals));

            /* In case we are not in a closing process already */
            if (!tpkt->close)
            {
                /* mark the connection as closing */
                tpkt->close = RV_TRUE;

                /* notify that the close occured (as a recv event) */
                if (tpkt->recv.eventHandler != NULL)
                {
                    int numOfLocks;

                    numOfLocks = emaPrepareForCallback((EMAElement)tpkt);
                    tpkt->recv.eventHandler((HTPKT)tpkt,selectEvent,0,RV_FALSE,tpkt->recv.context);
                    emaReturnFromCallback((EMAElement)tpkt, numOfLocks);
                }
                else
                /* if no recv callback use the send callback (?) */
                if (tpkt->send.eventHandler != NULL)
                {
                    int numOfLocks;

                    numOfLocks = emaPrepareForCallback((EMAElement)tpkt);
                    tpkt->send.eventHandler((HTPKT)tpkt,selectEvent,0,RV_FALSE,tpkt->send.context);
                    emaReturnFromCallback((EMAElement)tpkt, numOfLocks);
                }
            }
            /* if we already got a close event on this connection */
            else
            {
                /* Close the tpkt object */
                tpktClose((HTPKT)tpkt);
            }
        }
        break;
    }
    emaUnlock((EMAElement)tpkt);
}

/*******************************************************************************************
 * tpktOpen
 *
 * Purpose: Allocate a socket and start either a connect process in case of a client which
 *      supplied a full address, or a listenning process in case of server.
 *      For a client that didn't supply an address yet, just create the socket.
 *
 * Input:   hTpktCtrl       - Handle to the tpkt instance
 *          localAddress    - Local address to use
 *          connectionType  - What type of connection we request (Tcp or TcpServer)
 *          standard        - Standard to use on connection (Q931 or H245)
 *          context         - Additional data to be supplied on the callback
 *
 * Return Value: A handle to the tpkt object created
 *******************************************************************************************/
HTPKT tpktOpen(
    IN HTPKTCTRL            hTpktCtrl,
    IN cmTransportAddress*  localAddress,
    IN RvH323ConnectionType connType,
    IN tpktTypes            tpktType,
    IN LPTPKTEVENTHANDLER   eventHandler,
    IN void*                context)
{
    tpktGlobals* globals = (tpktGlobals *)hTpktCtrl;
    RvAddress coreAddress, *pCoreAddress;
    tpktInfo* tpktNew;
    RvStatus res;

    RvLogEnter(&globals->log, (&globals->log, "tpktOpen"));

    tpktNew = (tpktInfo *)emaAdd(globals->hEma, context);

    /* check that an element was created */
    if (tpktNew == NULL)
    {
        RvLogLeave(&globals->log, (&globals->log, "tpktOpen - Out of resoruces"));
        return NULL;
    }
    memset(tpktNew, 0, sizeof(tpktInfo));

    if (localAddress == NULL)
        pCoreAddress = NULL;
    else
    {
        RvH323CmToCoreAddress(localAddress, &coreAddress);
        pCoreAddress = &coreAddress;
    }

    /* Create an IO connection to work with */
    tpktNew->connection.type = RvH323ConnectionNone;
    tpktNew->connection.context = globals;
    res = RvSocketConstruct(&tpktNew->connection.socket, RV_ADDRESS_TYPE_IPV4, RvSocketProtocolTcp);

    if (res != RV_OK)
    {
        RvLogLeave(&globals->log, (&globals->log, "tpktOpen - Error constructing a connection (%d)", res));
        emaDelete((EMAElement)tpktNew);
        return NULL;
    }

    /* We're always working with non-blocking sockets */
    RvSocketSetBlocking(&tpktNew->connection.socket, RV_FALSE);
   {
   	int optval = 1;
	setsockopt (tpktNew->connection.socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval));
    }/**so we can reuse the port**/
    /* bind it to the listening address */
    if (RvSocketBind(&tpktNew->connection.socket, pCoreAddress, globals->pPortRange) != RV_OK)
    {
       /* todo: h.e  (by the way we have this peace of code 3 times)
          (probably  "goto" is not so bad ) */
        RvSocketDestruct(&tpktNew->connection.socket, RV_TRUE, globals->pPortRange);
        RvLogLeave(&globals->log, (&globals->log, "tpktOpen - Error listening (%d)", res));
        emaDelete((EMAElement)tpktNew);
        return NULL;
    }

    /* for server - start listenning on the socket */
    if ((tpktType == tpktMultiServer) || (tpktType == tpktServer))
    {
        /* Listen to incoming connections */
        if ((RvSocketListen(&tpktNew->connection.socket, 16) != RV_OK) ||
            (RvFdConstruct(&tpktNew->connection.fd, &tpktNew->connection.socket) != RV_OK))
        {
            RvSocketDestruct(&tpktNew->connection.socket, RV_TRUE, globals->pPortRange);
            RvLogLeave(&globals->log, (&globals->log, "tpktOpen - Error listening (%d)", res));
            emaDelete((EMAElement)tpktNew);
            return NULL;
        }
        else
        {
            tpktNew->event = RvSelectAccept;
            if (RvSelectAdd(globals->pSelEngine, &tpktNew->connection.fd, tpktNew->event, tpktEvent) != RV_OK)
            {
                RvFdDestruct(&tpktNew->connection.fd);
                RvSocketDestruct(&tpktNew->connection.socket, RV_TRUE, globals->pPortRange);
                RvLogLeave(&globals->log, (&globals->log, "tpktOpen - Error adding to Select (%d)", res));
                emaDelete((EMAElement)tpktNew);
                return NULL;
            }
        }
    }

    tpktNew->connection.type = connType;

    /* Initialize the TPKT object */
    tpktNew->type = tpktType;
    tpktNew->bytesLeftToRead = TPKT_HEADER_SIZE;
    tpktNew->readingHeader = RV_TRUE;
    tpktNew->errorEncountered = RV_FALSE;
    tpktNew->header[0] = 0; /* Mark header as empty */

    tpktNew->send.eventHandler=eventHandler;
    tpktNew->recv.eventHandler=eventHandler;

    tpktNew->send.context=context;
    tpktNew->recv.context=context;

    RvLogLeave(&globals->log, (&globals->log, "tpktOpen(hTpkt=%p)=%d", tpktNew, res));
    return (HTPKT)tpktNew;
}


/*******************************************************************************************
 * tpktConnect
 *
 * Purpose: This routine supplements the tpktOpen routine, for clients which didn't supply
 *          an address and now wish to do the actual connect operation on the already allocated
 *          socket.
 *
 * Input:   hTpkt           - Handle to the tpktInfo element
 *          remoteAddress   - Address to connect to
 *
 * Return Value: Non-negative value on success, other on failure
 *******************************************************************************************/
int tpktConnect(IN HTPKT hTpkt, IN cmTransportAddress* remoteAddress)
{
    tpktInfo* tpkt = (tpktInfo *)hTpkt;
    tpktGlobals* globals = (tpktGlobals *)emaGetUserData((EMAElement)tpkt);
    RvAddress coreAddress;
    RvStatus status = RV_ERROR_UNKNOWN;

    if (globals == NULL)
        return RV_ERROR_NULLPTR;

    if (emaLock((EMAElement)tpkt))
    {
        /* Let's try to connect it */
        RvH323CmToCoreAddress(remoteAddress, &coreAddress);
#if (RV_OS_TYPE != RV_OS_TYPE_WIN32)
        status = RvSocketConnect(&tpkt->connection.socket, &coreAddress);
        if (status == RV_OK)
#endif
        {
            /* the other side, if listening, will consider the socket connected - so should we */
            tpkt->event = RvSelectConnect;
            tpkt->isConnected = RV_TRUE;

            /* set event for socket */
            RvFdConstruct(&tpkt->connection.fd, &tpkt->connection.socket);
            RvSelectAdd(globals->pSelEngine, &tpkt->connection.fd, tpkt->event, tpktEvent);
        }
#if (RV_OS_TYPE == RV_OS_TYPE_WIN32)
        status = RvSocketConnect(&tpkt->connection.socket, &coreAddress);
#endif
        RvAddressDestruct(&coreAddress);

        emaUnlock((EMAElement)tpkt);
    }

    return status;
}


/*******************************************************************************************
 * tpktClose
 *
 * Purpose: Starts the closing procedure of a tpkt object.
 *          Frees all its resources if an Idle event won't arrive from the IO layer for the
 *          TPKT object.
 *
 * Input:   hTpkt - Handle to the tpktInfo element
 *
 * Return Value: Non-negative value on success, other on failure
 *******************************************************************************************/
int tpktClose(IN HTPKT hTpkt)
{
    tpktInfo* tpkt = (tpktInfo *)hTpkt;
    tpktGlobals* globals = (tpktGlobals *)emaGetUserData((EMAElement)tpkt);
    RvStatus res = RV_ERROR_UNKNOWN;

    if (globals == NULL)
        return RV_ERROR_NULLPTR;
    if (!emaLock((EMAElement)tpkt)) return RV_ERROR_DESTRUCTED;

    RvLogInfo(&globals->log, (&globals->log, "tpktClose(HTPKT %p)", hTpkt));

    /* if indeed the connection is connected and not yet in a closing state */
    if ((tpkt->isConnected == RV_TRUE) && !tpkt->close)
    {
        /* Mark the connection as closing */
        tpkt->close = RV_TRUE;

        /* make sure we're called for the grand closing */
        tpkt->event = (RvSelectEvents) (RvSelectRead | RvSelectClose);
        RvSelectUpdate(globals->pSelEngine, &tpkt->connection.fd, tpkt->event, tpktEvent);

        /* now close */
        res = RvSocketShutdown(&tpkt->connection.socket, RV_TRUE);
        if(res != RV_OK)
        {
            /* In case of an error trying to close the TPKT gracefully, we just brotally
            kill it and get it all over with */
            RvSelectRemove(globals->pSelEngine, &tpkt->connection.fd);
            RvFdDestruct(&tpkt->connection.fd);
            res = RvSocketDestruct(&tpkt->connection.socket, RV_FALSE, globals->pPortRange);
            emaDelete((EMAElement)tpkt);

            /* Make sure we unlink the host from this TPKT element, so it won't mess up the
            deletion procedure
            emaSetApplicationHandle((EMAElement)tpkt, NULL);*/
        }
        /* Mark this session as being in the closing process */
        tpkt->isConnected = RV_FALSE;
    }
    else
    {
        /* The connection is already closing -
           Vehemently close the socket and release the tpkt object */
        if (tpkt->event != 0)
        {
            /* We have an event to remove */
            RvSelectRemove(globals->pSelEngine, &tpkt->connection.fd);
            RvFdDestruct(&tpkt->connection.fd);
        }
        res = RvSocketDestruct(&tpkt->connection.socket, RV_FALSE, globals->pPortRange);
        emaDelete((EMAElement)tpkt);
    }
    emaUnlock((EMAElement)tpkt);
    return res;
}


/*******************************************************************************************
 * tpktSendFromRpool
 *
 * Purpose: This routine sends a given rpool message over a connection, assuming that the message
 *      already contains a tpkt header.
 *
 * Input:   hTpkt           - Handle to the tpktInfo element
 *          hRpool          - handle to the rpool.
 *          message         - points to the message to be sent.
 *          offset          - where in the message to start the sending.
 *          rpoolLock       - The lock of the rpool
 *
 * Return Value: 0 or RV_ERROR_UNKNOWN
 *******************************************************************************************/
int tpktSendFromRpool(HTPKT hTpkt,
                      HRPOOL hRpool,
                      HRPOOLELEM message,
                      int offset,
                      RvLock* rpoolLock)
{
    tpktInfo    *tpkt=(tpktInfo*)hTpkt;
    tpktGlobals *globals = (tpktGlobals *)emaGetUserData((EMAElement)tpkt);

    int         sent;
    int         length;

⌨️ 快捷键说明

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