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

📄 mti.c

📁 基于h323协议的软phone
💻 C
字号:
/***********************************************************************
        Copyright (c) 2002 RADVISION Ltd.
************************************************************************
NOTICE:
This document contains information that is confidential and proprietary
to RADVISION Ltd.. No part of this document may be reproduced in any
form whatsoever without written prior approval by RADVISION Ltd..

RADVISION Ltd. reserve the right to revise this publication and make
changes without obligation to notify any person of such revisions or
changes.
***********************************************************************/

#include "rvtimestamp.h"
#include "rvclock.h"
#include "ra.h"
#include "rvlog.h"
#include "rvh323timer.h"
#include "cm.h"
#include "mti.h"

#ifdef __cplusplus
extern "C" {
#endif


typedef struct RvH323ApplicationTimers_arg RvH323ApplicationTimers;
struct RvH323ApplicationTimers_arg
{
    RvLogSource                 log; /* MTI log source */
    RvH323TimerPoolHandle       timersPool; /* Timers pool to use */
    HRA                         timers; /* Array of timers we're holding */
    HAPPTIMER                   applicationHandle; /* Application handle for this set of timers */
    RvLock                      lock; /* Lock for these RA objects */

    RvH323ApplicationTimers*    prev; /* Previous timer pool used by application */
    RvH323ApplicationTimers*    next; /* Next timer pool used by application */
};


typedef struct
{
    RvH323ApplicationTimers*timers; /* Pool we're working in */
    RvTimer*                timer; /* Timer object we're working with */
    LPMTIMEREVENTHANDLER    eventHandler; /* Timer's callback to use */
    void*                   context; /* Context to use with the callback */
    RvBool                  inCallback; /* RV_TRUE if we're currently inside a user callback */
    RvBool                  deleted; /* RV_TRUE if timer should be deleted */
} RvH323ApplicationTimer;


/* todo: lock linked list access */
/* todo: change this parameter to thread specific */
static RvH323ApplicationTimers* mtiFirstApplTimers = NULL; /* First element in linked list
                                                              of application timers */



static RvBool mtimerTimerFunc(IN void* context)
{
    RvH323ApplicationTimers* timers;
    RvH323ApplicationTimer* timer = (RvH323ApplicationTimer *)context;
    RvBool result = RV_TRUE;

    /* Make sure element is valid and mark it */
    timers = timer->timers;
    if (timer == NULL)
    {
        /* Probably no timers at all */
        return RV_FALSE;
    }
    RvLockGet(&timers->lock);
    if (timer->timers == NULL)
    {
        RvLockRelease(&timers->lock);
        return RV_FALSE;
    }

    timer->inCallback = RV_TRUE;
    RvLockRelease(&timers->lock);

    /* Callback to application */
    timer->eventHandler(timer->context);

    /* Here, we just see if we have to kill this timer or not */
    RvLockGet(&timers->lock);
    timer->inCallback = RV_FALSE;

    if (timer->deleted)
    {
        RvH323TimerClear(timers->timersPool, &timer->timer);
        raDelete(timers->timers, (RAElement)timer);
        result = RV_FALSE;
    }

    RvLockRelease(&timers->lock);

    return result;
}




RVAPI RvUint32 RVCALLCONV timerGetTimeInMilliseconds(void)
{
    RvUint32 timestampInMillisec;

    timestampInMillisec = (RvUint32)Rv64Divide(RvTimestampGet(), RV_TIME_NSECPERMSEC);

    /* Make sure type-casted -1 is not used */
    if (timestampInMillisec == (RvUint32)-1)
        timestampInMillisec = 0;

    return timestampInMillisec;
}


RVAPI RvUint32 RVCALLCONV timerGetTimeInSeconds(void)
{
    return (RvUint32)RvClockGet(NULL);
}



RVAPI HSTIMER RVCALLCONV
mtimerInit(IN int maxTimers, IN HAPPTIMER appHndl)
{
    RvH323ApplicationTimers* timers;
    RvStatus status;

    status = cmStartUp();
    if (status != RV_OK)
        return NULL;

    status = RvMemoryAlloc(NULL, (void**)&timers, sizeof(RvH323ApplicationTimers));
    if (status!= RV_OK)
        return NULL;
    memset(timers, 0, sizeof(RvH323ApplicationTimers));

    status = RvLogSourceConstruct(RvLogGet(), &timers->log, RV_LOG_LIBCODE_H323, "MTI", "Application timers");
    if (status != RV_OK)
    {
        RvMemoryFree(timers);
        return NULL;
    }

    RvLogEnter(&timers->log, (&timers->log,
        "mtimerInit(maxTimers=%d,app=0x%p)", maxTimers, appHndl));

    timers->timers = raConstruct(sizeof(RvH323ApplicationTimer), maxTimers, RV_FALSE, "ApplicationTimers");
    if (timers == NULL)
    {
        RvLogSourceDestruct(RvLogGet(), &timers->log);
        RvMemoryFree(timers);
        return NULL;
    }

    /* Create the timers pool */
    timers->timersPool = RvH323TimerConstruct(maxTimers, NULL);
    if (timers->timersPool == NULL)
    {
        raDestruct(timers->timers);
        RvLogSourceDestruct(RvLogGet(), &timers->log);
        RvMemoryFree(timers);
        return NULL;
    }

    status = RvLockConstruct(&timers->lock);
    if (status != RV_OK)
    {
        RvH323TimerDestruct(timers->timersPool);
        raDestruct(timers->timers);
        RvLogSourceDestruct(RvLogGet(), &timers->log);
        RvMemoryFree(timers);
        return NULL;
    }

    timers->applicationHandle = appHndl;

    /* Fix linked list of timer pools */
    if (mtiFirstApplTimers == NULL)
        mtiFirstApplTimers = timers;
    else
    {
        /* We'll add this one as first in the list */
        mtiFirstApplTimers->prev = timers;
        timers->next = mtiFirstApplTimers;
        mtiFirstApplTimers = timers;
    }

    RvLogLeave(&timers->log, (&timers->log,
        "mtimerInit()=0x%p", timers));

    return (HSTIMER)timers;
}


RVAPI int RVCALLCONV
mtimerEnd(IN HSTIMER timer)
{
    RvH323ApplicationTimers* timers;

    if (timer == NULL)
        return RV_ERROR_NULLPTR;

    timers = (RvH323ApplicationTimers *)timer;

    RvLogEnter(&timers->log, (&timers->log,
        "mtimerEnd(timer=0x%p)", timer));

    /* Remove this pool from the list */
    if (timers == mtiFirstApplTimers)
    {
        /* Removing the first one in the list */
        mtiFirstApplTimers = timers->next;
        if (mtiFirstApplTimers != NULL)
            mtiFirstApplTimers->prev = NULL;
    }
    else
    {
        /* Not the first element in list */
        timers->prev->next = timers->next;
        if (timers->next != NULL)
            timers->next->prev = timers->prev;
    }

    /* Kill this pool */
    RvH323TimerDestruct(timers->timersPool);
    raDestruct(timers->timers);
    RvLockDestruct(&timers->lock);
    RvLogSourceDestruct(RvLogGet(), &timers->log);
    RvMemoryFree(timers);

    return cmShutdown();
}


RVAPI HTI RVCALLCONV
mtimerSet(
    IN HSTIMER              timer,
    IN LPMTIMEREVENTHANDLER eventHandler,
    IN void*                context,
    IN RvUint32             timeOut  /* 1 msec units */
    )
{
    RvH323ApplicationTimers* timers;
    RvH323ApplicationTimer* userTimer;
    int res;

    if (timer == NULL)
        return HTI_NULL_TIMER;

    timers = (RvH323ApplicationTimers *)timer;

    RvLogEnter(&timers->log, (&timers->log,
        "mtimerSet(timer=0x%p,handler=0x%p,context=0x%p,timeout=%d)",
        timer, eventHandler, context, timeOut));

    RvLockGet(&timers->lock);

    res = raAdd(timers->timers, (RAElement *)&userTimer);
    if (res < 0)
    {
        RvLogError(&timers->log, (&timers->log,
            "mtimerSet: Out of resources. Too many timers are already allocated."));
        res = -1;
    }
    else
    {
        if (timeOut == 0)
            timeOut = 1;

        userTimer->timer = RvH323TimerStartPeriodic(timers->timersPool, mtimerTimerFunc, userTimer, timeOut);
        if (userTimer->timer == NULL)
        {
            RvLogError(&timers->log, (&timers->log,
                "mtimerSet: Error starting the timer"));
            res = -1;

            raDelete(timers->timers, (RAElement)userTimer);
        }
        else
        {
            userTimer->timers = timers;
            userTimer->eventHandler = eventHandler;
            userTimer->context = context;
            userTimer->inCallback = RV_FALSE;
        }
    }

    RvLockRelease(&timers->lock);

    RvLogLeave(&timers->log, (&timers->log,
        "mtimerSet()=0x%p", (HTI)res));

    return (HTI)res;
}



RVAPI int RVCALLCONV
mtimerReset(
    IN HSTIMER  timer,
    IN HTI      tElem)
{
    RvH323ApplicationTimers* timers;
    RvH323ApplicationTimer* userTimer;

    if ((timer == NULL) || ((RvInt32)tElem < 0))
        return RV_ERROR_NULLPTR;

    timers = (RvH323ApplicationTimers *)timer;

    RvLogEnter(&timers->log, (&timers->log,
        "mtimerReset(timer=0x%p,tElem=0x%p", timer, tElem));

    userTimer = (RvH323ApplicationTimer *)raGet(timers->timers, (int)tElem);
    if (userTimer == NULL)
    {
        RvLogError(&timers->log, (&timers->log,
            "mtimerReset: Timer element 0x%p doesn't exist or not allocated!", tElem));
        return RV_ERROR_BADPARAM;
    }

    RvLockGet(&timers->lock);
    if (userTimer->timers != timers)
    {
        RvLogError(&timers->log, (&timers->log,
            "mtimerReset: Timer element 0x%p failed the sanity check", tElem));
        RvLockRelease(&timers->lock);
        return RV_ERROR_BADPARAM;
    }

    if (userTimer->inCallback)
    {
        userTimer->deleted = RV_TRUE;
    }
    else
    {
        RvH323TimerCancel(timers->timersPool, &userTimer->timer);
        raDelete(timers->timers, (RAElement)userTimer);
    }

    RvLockRelease(&timers->lock);

    RvLogLeave(&timers->log, (&timers->log, "mtimerReset()=0"));
    return RV_OK;
}





#ifdef RV_H323_COMPILE_WITH_DEAD_FUNCTIONS

RVAPI int RVCALLCONV
mtimerEndByHandle(IN HAPPTIMER appHndl)
{
    RvH323ApplicationTimers* timers;

    /* First we'll try to find this one */
    timers = mtiFirstApplTimers;
    while (timers != NULL)
    {
        if (timers->applicationHandle == appHndl)
        {
            /* Found it! */
            return mtimerEnd((HSTIMER)timers);
        }

        timers = timers->next;
    }

    return RV_ERROR_BADPARAM;
}


RVAPI HTI RVCALLCONV
mtimerSetByHandle(
    IN HAPPTIMER            appHndl,
    IN LPMTIMEREVENTHANDLER eventHandler,
    IN void*                context,
    IN RvUint32             timeOut)
{
    RvH323ApplicationTimers* timers;

    /* First we'll try to find this one */
    timers = mtiFirstApplTimers;
    while (timers != NULL)
    {
        if (timers->applicationHandle == appHndl)
        {
            /* Found it! */
            return mtimerSet((HSTIMER)timers, eventHandler, context, timeOut);
        }

        timers = timers->next;
    }

    return HTI_NULL_TIMER;
}


RVAPI int RVCALLCONV
mtimerResetByValue(
    IN HSTIMER              timer,
    IN LPMTIMEREVENTHANDLER eventHandler,
    IN void*                context)
{
    RvH323ApplicationTimers* timers = (RvH323ApplicationTimers *)timer;
    RvH323ApplicationTimer* tm;
    int curElem = -1;
    int result = RV_ERROR_BADPARAM;
    RvBool found = RV_FALSE;

    if (timers == NULL)
        return RV_ERROR_NULLPTR;

    RvLockGet(&timers->lock);

    while (!found)
    {
        curElem = raGetNext(timers->timers, curElem);
        if (curElem >= 0)
        {
            tm = (RvH323ApplicationTimer *)raGet(timers->timers, curElem);
            if (tm != NULL)
            {
                found = (tm->context == context) && (tm->eventHandler == eventHandler);
            }
        }
        else
        {
            /* Looks like we're done */
            break;
        }
    }

    RvLockRelease(&timers->lock);

    if (found)
    {
        /* We found one to reset */
        result = mtimerReset(timer, (HTI)curElem);
    }

    return result;
}


RVAPI int RVCALLCONV
mtimerResetByHandle(
    IN HAPPTIMER    appHndl,
    IN HTI          tElem)
{
    RvH323ApplicationTimers* timers;

    /* First we'll try to find this one */
    timers = mtiFirstApplTimers;
    while (timers != NULL)
    {
        if (timers->applicationHandle == appHndl)
        {
            /* Found it! */
            return mtimerReset((HSTIMER)timers, tElem);
        }

        timers = timers->next;
    }

    return RV_ERROR_BADPARAM;
}



/************************************************************************
 * mtimerSetMaxTimerSets
 * purpose: To change the maximum number of timer sets (mtimerInit calls)
 *          allowed per thread (the default is 16)
 * input  : timerSets   - the maximum number of timer sets
 * output : none
 * return : none
 ************************************************************************/
RVAPI void RVCALLCONV mtimerSetMaxTimerSets(IN int timerSets)
{
    /* Empty function. It's not actually needed anymore */
    RV_UNUSED_ARG(timerSets);
}

#endif /* RV_H323_COMPILE_WITH_DEAD_FUNCTIONS */



#ifdef __cplusplus
}
#endif

⌨️ 快捷键说明

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