/************************************************************************** *** COPYRIGHT (c) 2002 by TransNexus, Inc. *** *** *** *** This software is property of TransNexus, Inc. *** *** This software is freely available under license from TransNexus. *** *** The license terms and conditions for free use of this software by *** *** third parties are defined in the OSP Toolkit Software License *** *** Agreement (LICENSE.txt). Any use of this software by third *** *** parties, which does not comply with the terms and conditions of the *** *** OSP Toolkit Software License Agreement is prohibited without *** *** the prior, express, written consent of TransNexus, Inc. *** *** *** *** Thank you for using the OSP ToolKit(TM). Please report any bugs, *** *** suggestions or feedback to support@transnexus.com *** *** *** **************************************************************************/ /* * nonblocking.c - NonBlockingMonitor object funcions. */ #include "nonblocking.h" #include "osp/osptrans.h" OSPTTHREADRETURN WorkThread(void *); void NonBlockingQueueMonitorIncrementActiveWorkThreadCounter(NBMONITOR *); void NonBlockingQueueMonitorDecrementActiveWorkThreadCounter(NBMONITOR *); unsigned NonBlockingQueueMonitorGetActiveWorkThreadCounter(NBMONITOR *); OSPTUINT64 GetDeltaMS(OSPTTIME FromTimeSec, unsigned int FromTimeMS, OSPTTIME ToTimeSec, unsigned int ToTimeMS); typedef struct _NBAUTHREQ { OSPTTRANHANDLE ospvTransaction; /* In - Transaction Handle */ const char *ospvSource; /* In - Source of call */ const char *ospvSourceDevice; /* In - SourceDevice of call */ const char *ospvCallingNumber; /* In - Calling number */ OSPE_NUMBER_FORMAT ospvCallingNumberFormat; /* In - Calling number Format */ const char *ospvCalledNumber; /* In - Called number */ OSPE_NUMBER_FORMAT ospvCalledNumberFormat; /* In - Called number Format */ const char *ospvUser; /* In - End user (optional) */ unsigned ospvNumberOfCallIds; /* In - Number of call identifiers */ OSPT_CALL_ID **ospvCallIds; /* In - List of call identifiers */ const char **ospvPreferredDestinations; /* In - List of preferred destinations for call */ unsigned *ospvNumberOfDestinations; /* In\Out - Max number of destinations \ Actual number of dests authorised */ unsigned *ospvSizeOfDetailLog; /* In\Out - Max size of detail log \ Actual size of detail log */ void *ospvDetailLog; /* In\Out - Location of detail log storage */ } NBAUTHREQ; typedef struct _NBUSEIND { OSPTTRANHANDLE ospvTransaction; /* In - Transaction handle */ unsigned ospvDuration; /* In - Length of call */ OSPTTIME ospvStartTime; /* In - StartTime of call */ OSPTTIME ospvEndTime; /* In - EndTime of call */ OSPTTIME ospvAlertTime; /* In - AlertTime of call */ OSPTTIME ospvConnectTime; /* In - ConnectTime of call */ OSPTBOOL ospvHasPDDInfo; /* In - Is PDD info present */ unsigned ospvPostDialDelay; /* In - PDD in milliseconds */ unsigned ospvReleaseSource; /* In - Rel Src */ char ospvConferenceId[OSPC_SIZE_CONFID]; /* In - ConferenceId */ int ospvLossPacketsSent; /* In - Packets not received by peer */ int ospvLossFractionSent; /* In - Fraction of packets not received by peer */ int ospvLossPacketsReceived; /* In - Packets not received that were expected */ int ospvLossFractionReceived; /* In - Fraction of packets expected but not received */ unsigned *ospvSizeOfDetailLog; /* In\Out - Max size of detail log \ Actual size of detail log */ void *ospvDetailLog; /* In\Out - Location of detail log storage */ } NBUSEIND; typedef struct _NBCAPIND { OSPTTRANHANDLE ospvTransaction; /* In - Transaction Handle */ const char *ospvSource; /* In - Source of call */ const char *ospvSourceDevice; /* In - SourceDevice of call */ const char *ospvSourceNetworkId; /* In - NetworkId of call */ unsigned ospvAlmostOutOfResources; /* In - A Boolean flag indicating device's availability */ unsigned *ospvSizeOfDetailLog; /* In\Out - Max size of detail log \ Actual size of detail log */ void *ospvDetailLog; /* In\Out - Location of detail log storage */ } NBCAPIND; typedef struct _NBVALIDATEAUTH { OSPTTRANHANDLE ospvTransaction; /* In - Transaction Handle */ const char *ospvSource; /* In - Source of call */ const char *ospvDestination; /* In - Dest of call */ const char *ospvSourceDevice; /* In - SourceDevice of call */ const char *ospvDestinationDevice; /* In - DestDevice of call */ const char *ospvCallingNumber; /* In - Calling number */ OSPE_NUMBER_FORMAT ospvCallingNumberFormat; /* In - Calling number Format */ const char *ospvCalledNumber; /* In - Called number */ OSPE_NUMBER_FORMAT ospvCalledNumberFormat; /* In - Called number Format */ unsigned ospvSizeOfCallId; /* In - Size of call id value */ const void *ospvCallId; /* In - Call Id for this call */ unsigned ospvSizeOfToken; /* In - Size of authorization token */ const void *ospvToken; /* In - Authorization token */ unsigned *ospvAuthorised; /* Out - Call authorization indicator */ unsigned *ospvTimeLimit; /* Out - Number of seconds call is authorized for */ unsigned *ospvSizeOfDetailLog; /* In\Out - Max size of detail log \ Actual size of detail log */ void *ospvDetailLog; /* In\Out - Location of detail log storage */ unsigned ospvTokenAlgo; /* In - Algorithm to be used for Validating Token */ } NBVALIDATEAUTH; typedef union _OSPMESSAGE { NBAUTHREQ AuthReq; NBUSEIND UseInd; NBCAPIND CapInd; NBVALIDATEAUTH ValidateAuth; } OSPMESSAGE; #define MESSAGE_TYPE_INVALID 0 #define MESSAGE_TYPE_AUTH_REQ 1 #define MESSAGE_TYPE_USE_IND 2 #define MESSAGE_TYPE_CAP_IND 3 #define MESSAGE_TYPE_VALIDATE_AUTH 4 #define MESSAGE_TYPE_TIME_TO_EXIT 10 typedef struct _NBDATA { OSPTLISTLINK NextItem; int MessageType; int *ErrorCode; union { NBAUTHREQ AuthReq; NBUSEIND UseInd; NBCAPIND CapInd; NBVALIDATEAUTH ValidateAuth; } Message; int ShouldBlock; /* Ussed to indicate if the caller is blocked */ OSPTMUTEX Mutex; /* Used to wake up blocked call */ OSPTCONDVAR CondVar; /* Used to wake up blocked call */ /* Stats */ OSPTTIME InQuequeTime; unsigned int InQuequeTimeMS; OSPTTIME OutQuequeTime; unsigned int OutQuequeTimeMS; OSPTTIME OutToolKitTime; unsigned int OutToolKitTimeMS; } NBDATA; int newNBDATA(NBDATA **nbData, int MessageType); int deleteNBDATA(NBDATA *nbData); /* * Allocate memory * Set MessageType * Init Mutex and CondVar */ int newNBDATA(NBDATA **nbData, int MessageType) { int errorcode = OSPC_ERR_NO_ERROR; OSPM_MALLOC((*nbData), NBDATA, sizeof(NBDATA)); if ((*nbData) != OSPC_OSNULL) { OSPM_MEMSET((*nbData), 0, sizeof(NBDATA)); (*nbData)->MessageType = MessageType; OSPM_MUTEX_INIT((*nbData)->Mutex, OSPC_OSNULL, errorcode); if (OSPC_ERR_NO_ERROR == errorcode) { OSPM_CONDVAR_INIT((*nbData)->CondVar, OSPC_OSNULL, errorcode); } } else { errorcode = OSPC_ERR_MSGQ_NO_MEMORY; } return errorcode; } /* * Destroy Mutex and CondVar * De-allocate memory */ int deleteNBDATA(NBDATA * nbData) { int errorcode = OSPC_ERR_NO_ERROR; // check input if (nbData == OSPC_OSNULL) { errorcode = OSPC_ERR_UTIL_INVALID_ARG; } else { OSPM_MUTEX_DESTROY(nbData->Mutex, errorcode); OSPM_CONDVAR_DESTROY(nbData->CondVar, errorcode); OSPM_FREE(nbData); } return errorcode; } int NonBlockingQueueMonitorNew(NBMONITOR **nbMonitor, unsigned NumberOfWorkThreads, unsigned MaxQueSize, unsigned MaxQueWaitMS) { int errorcode = OSPC_ERR_NO_ERROR; unsigned int i = 0; // check input if ((nbMonitor == OSPC_OSNULL) || (NumberOfWorkThreads > MAX_WORK_THREAD_NUM)) { errorcode = OSPC_ERR_UTIL_INVALID_ARG; } // allocate space if (errorcode == OSPC_ERR_NO_ERROR) { OSPM_MALLOC(*nbMonitor, NBMONITOR, sizeof(NBMONITOR)); if (*nbMonitor != OSPC_OSNULL) { // Zero out newly allocated space OSPM_MEMSET(*nbMonitor, 0, sizeof(NBMONITOR)); // Init memeber variables (*nbMonitor)->NumberOfWorkThreads = NumberOfWorkThreads; (*nbMonitor)->MaxQueSize = MaxQueSize; (*nbMonitor)->MaxQueWaitMS = MaxQueWaitMS; (*nbMonitor)->NumberOfActiveWorkThreads = 0; (*nbMonitor)->TimeToShutDown = 0; // Init mutex variable OSPM_MUTEX_INIT((*nbMonitor)->Mutex, OSPC_OSNULL, errorcode); assert(errorcode == OSPC_ERR_NO_ERROR); // Init conditional variable OSPM_CONDVAR_INIT((*nbMonitor)->CondVarNoActiveWorkThreads, OSPC_OSNULL, errorcode); assert(errorcode == OSPC_ERR_NO_ERROR); } else { errorcode = OSPC_ERR_MSGQ_NO_MEMORY; } } // start sync queue if (errorcode == OSPC_ERR_NO_ERROR) { errorcode = SyncQueueNew(&((*nbMonitor)->SyncQue)); } // start work threads queue if (errorcode == OSPC_ERR_NO_ERROR) { for (i = 0; i < (*nbMonitor)->NumberOfWorkThreads; i++) { OSPM_CREATE_THREAD((*nbMonitor)->WorkThreadIDs[i], NULL, WorkThread, (*nbMonitor), errorcode); if (errorcode != OSPC_ERR_NO_ERROR) { break; } } } return errorcode; } int NonBlockingQueueMonitorDelete(NBMONITOR **nbMonitor) { int errorcode = OSPC_ERR_NO_ERROR; unsigned int i = 0; // check input if ((nbMonitor == OSPC_OSNULL) || (*nbMonitor == OSPC_OSNULL)) { errorcode = OSPC_ERR_UTIL_INVALID_ARG; } // Signal that no more requests should be processed (*nbMonitor)->TimeToShutDown = 1; // Wait for all current transactions to stop errorcode = NonBlockingQueueMonitorBlockWhileQueueNotEmpty(*nbMonitor); if (errorcode == OSPC_ERR_NO_ERROR) { // For every work thread / put TIME_TO_EXIT message for (i = 0; i < (*nbMonitor)->NumberOfWorkThreads; i++) { NBDATA *nbData = OSPC_OSNULL; errorcode = newNBDATA(&nbData, MESSAGE_TYPE_TIME_TO_EXIT); if (errorcode == OSPC_ERR_NO_ERROR) { errorcode = SyncQueueAddTransaction((*nbMonitor)->SyncQue, nbData); } else { errorcode = OSPC_ERR_MSGQ_NO_MEMORY; } // break on any ERROR if (errorcode != OSPC_ERR_NO_ERROR) { break; } } } // delete the queu if (errorcode == OSPC_ERR_NO_ERROR) { NonBlockingQueueMonitorBlockWhileQueueNotEmpty(*nbMonitor); SyncQueueDelete(&((*nbMonitor)->SyncQue)); for (i = 0; i < (*nbMonitor)->NumberOfWorkThreads; i++) { OSPM_THR_JOIN((*nbMonitor)->WorkThreadIDs[i], NULL); } } // release memory OSPM_FREE((*nbMonitor)); *nbMonitor = OSPC_OSNULL; return errorcode; } void NonBlockingQueueMonitorIncrementActiveWorkThreadCounter(NBMONITOR *nbMonitor) { unsigned errcode = OSPC_ERR_NO_ERROR; OSPM_MUTEX_LOCK(nbMonitor->Mutex, errcode); assert(errcode == OSPC_ERR_NO_ERROR); nbMonitor->NumberOfActiveWorkThreads++; OSPM_MUTEX_UNLOCK(nbMonitor->Mutex, errcode); assert(errcode == OSPC_ERR_NO_ERROR); } void NonBlockingQueueMonitorDecrementActiveWorkThreadCounter(NBMONITOR *nbMonitor) { unsigned errcode = OSPC_ERR_NO_ERROR; OSPM_MUTEX_LOCK(nbMonitor->Mutex, errcode); assert(errcode == OSPC_ERR_NO_ERROR); nbMonitor->NumberOfActiveWorkThreads--; // there are no more active work threads if (nbMonitor->NumberOfActiveWorkThreads == 0) { OSPM_CONDVAR_SIGNAL(nbMonitor->CondVarNoActiveWorkThreads, errcode); assert(errcode == OSPC_ERR_NO_ERROR); } OSPM_MUTEX_UNLOCK(nbMonitor->Mutex, errcode); assert(errcode == OSPC_ERR_NO_ERROR); } unsigned NonBlockingQueueMonitorGetActiveWorkThreadCounter(NBMONITOR *nbMonitor) { return nbMonitor->NumberOfActiveWorkThreads; } int NonBlockingQueueMonitorBlockWhileQueueNotEmpty(NBMONITOR *nbMonitor) { unsigned errcode = OSPC_ERR_NO_ERROR; errcode = SyncQueueBlockWhileNotEmpty(nbMonitor->SyncQue); if (errcode == OSPC_ERR_NO_ERROR) { OSPM_MUTEX_LOCK(nbMonitor->Mutex, errcode); assert(errcode == OSPC_ERR_NO_ERROR); while (NonBlockingQueueMonitorGetActiveWorkThreadCounter(nbMonitor) > 0) { OSPM_CONDVAR_WAIT(nbMonitor->CondVarNoActiveWorkThreads, nbMonitor->Mutex, errcode); assert(errcode == OSPC_ERR_NO_ERROR); } OSPM_MUTEX_UNLOCK(nbMonitor->Mutex, errcode); assert(errcode == OSPC_ERR_NO_ERROR); } return errcode; } OSPTTHREADRETURN WorkThread(void *arg) { NBMONITOR *nbMonitor = (NBMONITOR *)arg; NBDATA *transaction = NULL; int TimeToExit = 0; int errcode = 0; OSPTUINT64 QTime = 0; OSPTUINT64 TKTime = 0; while (TimeToExit == 0) { /* * block waiting for a message to process */ if (OSPC_ERR_NO_ERROR == SyncQueueRemoveTransaction(nbMonitor->SyncQue, (void **)&transaction)) { NonBlockingQueueMonitorIncrementActiveWorkThreadCounter(nbMonitor); // Time stamp OUT QUEUE OSPPOSTimeGetTime(&transaction->OutQuequeTime, &transaction->OutQuequeTimeMS); // Calculate Queue time QTime = GetDeltaMS(transaction->InQuequeTime, transaction->InQuequeTimeMS, transaction->OutQuequeTime, transaction->OutQuequeTimeMS); /* * What kind of message is it? (AuthReq or UseInd) */ switch (transaction->MessageType) { case MESSAGE_TYPE_TIME_TO_EXIT: TimeToExit = 1; break; case MESSAGE_TYPE_AUTH_REQ: // AuthorisationRequest /* * Make sure that the request has not expired */ if (QTime < nbMonitor->MaxQueWaitMS) { *(transaction->ErrorCode) = OSPPTransactionRequestAuthorisation(transaction->Message.AuthReq.ospvTransaction, transaction->Message.AuthReq.ospvSource, transaction->Message.AuthReq.ospvSourceDevice, transaction->Message.AuthReq.ospvCallingNumber, transaction->Message.AuthReq.ospvCallingNumberFormat, transaction->Message.AuthReq.ospvCalledNumber, transaction->Message.AuthReq.ospvCalledNumberFormat, transaction->Message.AuthReq.ospvUser, transaction->Message.AuthReq.ospvNumberOfCallIds, transaction->Message.AuthReq.ospvCallIds, transaction->Message.AuthReq.ospvPreferredDestinations, transaction->Message.AuthReq.ospvNumberOfDestinations, transaction->Message.AuthReq.ospvSizeOfDetailLog, transaction->Message.AuthReq.ospvDetailLog); } else { /* * AuthRequest has expired */ OSPM_DBGPRINTF("AUTH REQ EXPIRED\n"); *(transaction->ErrorCode) = -1; } break; case MESSAGE_TYPE_USE_IND: // UseageReport *(transaction->ErrorCode) = OSPPTransactionReportUsage(transaction->Message.UseInd.ospvTransaction, transaction->Message.UseInd.ospvDuration, transaction->Message.UseInd.ospvStartTime, transaction->Message.UseInd.ospvEndTime, transaction->Message.UseInd.ospvAlertTime, transaction->Message.UseInd.ospvConnectTime, transaction->Message.UseInd.ospvHasPDDInfo, transaction->Message.UseInd.ospvPostDialDelay, transaction->Message.UseInd.ospvReleaseSource, transaction->Message.UseInd.ospvConferenceId, transaction->Message.UseInd.ospvLossPacketsSent, transaction->Message.UseInd.ospvLossFractionSent, transaction->Message.UseInd.ospvLossPacketsReceived, transaction->Message.UseInd.ospvLossFractionReceived, transaction->Message.UseInd.ospvSizeOfDetailLog, transaction->Message.UseInd.ospvDetailLog); break; case MESSAGE_TYPE_CAP_IND: // CapabilitiesIndication *(transaction->ErrorCode) = OSPPTransactionIndicateCapabilities(transaction->Message.CapInd.ospvTransaction, transaction->Message.CapInd.ospvSource, transaction->Message.CapInd.ospvSourceDevice, transaction->Message.CapInd.ospvSourceNetworkId, transaction->Message.CapInd.ospvAlmostOutOfResources, transaction->Message.CapInd.ospvSizeOfDetailLog, transaction->Message.CapInd.ospvDetailLog); break; case MESSAGE_TYPE_VALIDATE_AUTH: // ValidationRequest /* * Make sure that the request has not expired */ if (QTime < nbMonitor->MaxQueWaitMS) { *(transaction->ErrorCode) = OSPPTransactionValidateAuthorisation(transaction->Message.ValidateAuth.ospvTransaction, transaction->Message.ValidateAuth.ospvSource, transaction->Message.ValidateAuth.ospvDestination, transaction->Message.ValidateAuth.ospvSourceDevice, transaction->Message.ValidateAuth.ospvDestinationDevice, transaction->Message.ValidateAuth.ospvCallingNumber, transaction->Message.ValidateAuth.ospvCallingNumberFormat, transaction->Message.ValidateAuth.ospvCalledNumber, transaction->Message.ValidateAuth.ospvCalledNumberFormat, transaction->Message.ValidateAuth.ospvSizeOfCallId, transaction->Message.ValidateAuth.ospvCallId, transaction->Message.ValidateAuth.ospvSizeOfToken, transaction->Message.ValidateAuth.ospvToken, transaction->Message.ValidateAuth.ospvAuthorised, transaction->Message.ValidateAuth.ospvTimeLimit, transaction->Message.ValidateAuth.ospvSizeOfDetailLog, transaction->Message.ValidateAuth.ospvDetailLog, transaction->Message.ValidateAuth.ospvTokenAlgo); } else { /* * Validate Req has expired */ OSPM_DBGPRINTF("VALIDATE REQ EXPIRED\n"); *(transaction->ErrorCode) = -1; } break; default: break; } /* * Log a message */ if (MESSAGE_TYPE_TIME_TO_EXIT != transaction->MessageType) { // Time stamp OUT ToolKit OSPPOSTimeGetTime(&transaction->OutToolKitTime, &transaction->OutToolKitTimeMS); // Calculate TK time TKTime = GetDeltaMS(transaction->OutQuequeTime, transaction->OutQuequeTimeMS, transaction->OutToolKitTime, transaction->OutToolKitTimeMS); OSPM_DBGPRINTF ("InQ[%llu:%3llu] OutQ[%llu:%3llu] OutTK[%llu:%3llu] QTime[%7llu] TKTime[%7llu] QSize[%5u] MsgType[%d]\n", (OSPTUINT64) transaction->InQuequeTime, (OSPTUINT64) transaction->InQuequeTimeMS, (OSPTUINT64) transaction->OutQuequeTime, (OSPTUINT64) transaction->OutQuequeTimeMS, (OSPTUINT64) transaction->OutToolKitTime, (OSPTUINT64) transaction->OutToolKitTimeMS, QTime, TKTime, SyncQueueGetNumberOfTransactions(nbMonitor->SyncQue), transaction->MessageType); } /* * This is a bit odd. If the caller wants to wait, * it is responsible for deleting nbData. * Oterwise, the work thread will clean up */ if (1 == transaction->ShouldBlock) { /* * Yes, wake it up */ OSPM_CONDVAR_SIGNAL(transaction->CondVar, errcode); } else { /* * No, we are responsible for cleaning up */ deleteNBDATA(transaction); } NonBlockingQueueMonitorDecrementActiveWorkThreadCounter(nbMonitor); } else { /* * Error removing transaction for the queue */ } } OSPTTHREADRETURN_NULL(); } int OSPPTransactionValidateAuthorisation_nb(NBMONITOR *nbMonitor, /* In - NBMonitor Pointer */ int ShouldBlock, /* In - 1 WILL block, 0 - will NOT block */ int *OSPErrorCode, /* Out- Error code returned by the blocking function */ OSPTTRANHANDLE ospvTransaction, /* In - Transaction handle */ const char *ospvSource, /* In - Source of call */ const char *ospvDestination, /* In - Destination for call */ const char *ospvSourceDevice, /* In - SourceDevice of call */ const char *ospvDestinationDevice, /* In - DestinationDevice for call */ const char *ospvCallingNumber, /* In - Calling number string */ OSPE_NUMBER_FORMAT ospvCallingNumberFormat, /* In - Calling number Format */ const char *ospvCalledNumber, /* In - Called number string */ OSPE_NUMBER_FORMAT ospvCalledNumberFormat, /* In - Calling number Format */ unsigned ospvSizeOfCallId, /* In - Size of call id value */ const void *ospvCallId, /* In - Call Id for this call */ unsigned ospvSizeOfToken, /* In - Size of authorization token */ const void *ospvToken, /* In - Authorization token */ unsigned *ospvAuthorised, /* Out - Call authorization indicator */ unsigned *ospvTimeLimit, /* Out - Number of seconds call is authorized for */ unsigned *ospvSizeOfDetailLog, /* In\Out - Max size of detail log \ Actual size of detail log */ void *ospvDetailLog, /* In\Out - Location of detail log storage */ unsigned ospvTokenAlgo) /* In - Algorithm to be used for Validating Token */ { int errorcode = OSPC_ERR_NO_ERROR; NBDATA *nbData = OSPC_OSNULL; if (nbMonitor->TimeToShutDown == 1) { /* * Q is shutting down */ errorcode = -1; } else if (SyncQueueGetNumberOfTransactions(nbMonitor->SyncQue) > nbMonitor->MaxQueSize) { /* * There are already to many requests in the Q */ errorcode = -1; } else { /* * allocate space * the space will be deallocated by one of the working thread */ errorcode = newNBDATA(&nbData, MESSAGE_TYPE_VALIDATE_AUTH); if (OSPC_ERR_NO_ERROR == errorcode) { // fill out the data structure nbData->ShouldBlock = ShouldBlock; nbData->ErrorCode = OSPErrorCode; nbData->Message.ValidateAuth.ospvTransaction = ospvTransaction; nbData->Message.ValidateAuth.ospvSource = ospvSource; nbData->Message.ValidateAuth.ospvDestination = ospvDestination; nbData->Message.ValidateAuth.ospvSourceDevice = ospvSourceDevice; nbData->Message.ValidateAuth.ospvDestinationDevice = ospvDestinationDevice; nbData->Message.ValidateAuth.ospvCallingNumber = ospvCallingNumber; nbData->Message.ValidateAuth.ospvCallingNumberFormat = ospvCallingNumberFormat; nbData->Message.ValidateAuth.ospvCalledNumber = ospvCalledNumber; nbData->Message.ValidateAuth.ospvCalledNumberFormat = ospvCalledNumberFormat; nbData->Message.ValidateAuth.ospvSizeOfCallId = ospvSizeOfCallId; nbData->Message.ValidateAuth.ospvCallId = ospvCallId; nbData->Message.ValidateAuth.ospvSizeOfToken = ospvSizeOfToken; nbData->Message.ValidateAuth.ospvToken = ospvToken; nbData->Message.ValidateAuth.ospvAuthorised = ospvAuthorised; nbData->Message.ValidateAuth.ospvTimeLimit = ospvTimeLimit; nbData->Message.ValidateAuth.ospvSizeOfDetailLog = ospvSizeOfDetailLog; nbData->Message.ValidateAuth.ospvDetailLog = ospvDetailLog; nbData->Message.ValidateAuth.ospvTokenAlgo = ospvTokenAlgo; // time stamp (AuthReq) IN QUEUE event OSPPOSTimeGetTime(&nbData->InQuequeTime, &nbData->InQuequeTimeMS); // put a new message to the non-blocking queue *(nbData->ErrorCode) = OSPC_AUTH_REQUEST_BLOCK; errorcode = SyncQueueAddTransaction(nbMonitor->SyncQue, nbData); if (OSPC_ERR_NO_ERROR == errorcode) { /* * This is a bit odd. If the caller wants to wait, * it is responsible for deleting nbData. * Oterwise, the work thread will clean up */ if (1 == nbData->ShouldBlock) { /* * SHOULD wait */ OSPM_MUTEX_LOCK(nbData->Mutex, errorcode); while ((*(nbData->ErrorCode) == OSPC_AUTH_REQUEST_BLOCK) && (OSPC_ERR_NO_ERROR == errorcode)) { OSPM_CONDVAR_WAIT(nbData->CondVar, nbData->Mutex, errorcode); } OSPM_MUTEX_UNLOCK(nbData->Mutex, errorcode); deleteNBDATA(nbData); } else { /* * should NOT wait */ } } } else { errorcode = OSPC_ERR_MSGQ_NO_MEMORY; } } return errorcode; } int OSPPTransactionRequestAuthorisation_nb(NBMONITOR *nbMonitor, /* In - NBMonitor Pointer */ int ShouldBlock, /* In - 1 WILL block, 0 - will NOT block */ int *OSPErrorCode, /* Out- Error code returned by the blocking function */ OSPTTRANHANDLE ospvTransaction, /* In - Transaction Handle */ const char *ospvSource, /* In - Source of call */ const char *ospvSourceDevice, /* In - SourceDevice of call */ const char *ospvCallingNumber, /* In - Calling number */ OSPE_NUMBER_FORMAT ospvCallingNumberFormat, /* In - Calling number Format */ const char *ospvCalledNumber, /* In - Called number */ OSPE_NUMBER_FORMAT ospvCalledNumberFormat, /* In - Called number Format */ const char *ospvUser, /* In - End user (optional) */ unsigned ospvNumberOfCallIds, /* In - Number of call identifiers */ OSPT_CALL_ID *ospvCallIds[], /* In - List of call identifiers */ const char *ospvPreferredDestinations[], /* In - List of preferred destinations for call */ unsigned *ospvNumberOfDestinations, /* In\Out - Max number of destinations \ Actual number of dests authorised */ unsigned *ospvSizeOfDetailLog, /* In\Out - Max size of detail log \ Actual size of detail log */ void *ospvDetailLog) /* In\Out - Location of detail log storage */ { int errorcode = OSPC_ERR_NO_ERROR; NBDATA *nbData = OSPC_OSNULL; if (nbMonitor->TimeToShutDown == 1) { /* * Q is shutting down */ errorcode = -1; } else if (SyncQueueGetNumberOfTransactions(nbMonitor->SyncQue) > nbMonitor->MaxQueSize) { /* * There are already to many requests in the Q */ errorcode = -1; } else { /* * allocate space * the space will be deallocated by one of the working thread */ errorcode = newNBDATA(&nbData, MESSAGE_TYPE_AUTH_REQ); if (OSPC_ERR_NO_ERROR == errorcode) { // fill out the data structure nbData->ShouldBlock = ShouldBlock; nbData->ErrorCode = OSPErrorCode; nbData->Message.AuthReq.ospvTransaction = ospvTransaction; nbData->Message.AuthReq.ospvSource = ospvSource; nbData->Message.AuthReq.ospvSourceDevice = ospvSourceDevice; nbData->Message.AuthReq.ospvCallingNumber = ospvCallingNumber; nbData->Message.AuthReq.ospvCallingNumberFormat = ospvCallingNumberFormat; nbData->Message.AuthReq.ospvCalledNumber = ospvCalledNumber; nbData->Message.AuthReq.ospvCalledNumberFormat = ospvCalledNumberFormat; nbData->Message.AuthReq.ospvUser = ospvUser; nbData->Message.AuthReq.ospvNumberOfCallIds = ospvNumberOfCallIds; nbData->Message.AuthReq.ospvCallIds = ospvCallIds; nbData->Message.AuthReq.ospvPreferredDestinations = ospvPreferredDestinations; nbData->Message.AuthReq.ospvNumberOfDestinations = ospvNumberOfDestinations; nbData->Message.AuthReq.ospvSizeOfDetailLog = ospvSizeOfDetailLog; nbData->Message.AuthReq.ospvDetailLog = ospvDetailLog; // time stamp (AuthReq) IN QUEUE event OSPPOSTimeGetTime(&nbData->InQuequeTime, &nbData->InQuequeTimeMS); // put a new message to the non-blocking queue *(nbData->ErrorCode) = OSPC_AUTH_REQUEST_BLOCK; errorcode = SyncQueueAddTransaction(nbMonitor->SyncQue, nbData); if (OSPC_ERR_NO_ERROR == errorcode) { /* * This is a bit odd. If the caller wants to wait, * it is responsible for deleting nbData. * Oterwise, the work thread will clean up */ if (1 == nbData->ShouldBlock) { /* * SHOULD wait */ OSPM_MUTEX_LOCK(nbData->Mutex, errorcode); while ((*(nbData->ErrorCode) == OSPC_AUTH_REQUEST_BLOCK) && (OSPC_ERR_NO_ERROR == errorcode)) { OSPM_CONDVAR_WAIT(nbData->CondVar, nbData->Mutex, errorcode); } OSPM_MUTEX_UNLOCK(nbData->Mutex, errorcode); deleteNBDATA(nbData); } else { /* * should NOT wait */ } } } else { errorcode = OSPC_ERR_MSGQ_NO_MEMORY; } } return errorcode; } int OSPPTransactionReportUsage_nb( NBMONITOR *nbMonitor, /* In - NBMonitor Pointer */ int ShouldBlock, /* In - 1 WILL block, 0 - will NOT block */ int *OSPErrorCode, /* Out- Error code returned by the blocking function */ OSPTTRANHANDLE ospvTransaction, /* In - Transaction handle */ unsigned ospvDuration, /* In - Length of call */ OSPTTIME ospvStartTime, /* In - StartTime of call */ OSPTTIME ospvEndTime, /* In - EndTime of call */ OSPTTIME ospvAlertTime, /* In - AlertTime of call */ OSPTTIME ospvConnectTime, /* In - ConnectTime of call */ OSPTBOOL ospvHasPDDInfo, /* In - Is PDD info available */ unsigned ospvPostDialDelay, /* In - PDD in milliseconds */ unsigned ospvReleaseSource, /* In - Release Src */ const char *ospvConferenceId, /* In - ConferenceId */ int ospvLossPacketsSent, /* In - Packets not received by peer */ int ospvLossFractionSent, /* In - Fraction of packets not received by peer */ int ospvLossPacketsReceived, /* In - Packets not received that were expected */ int ospvLossFractionReceived, /* In - Fraction of packets expected but not received */ unsigned *ospvSizeOfDetailLog, /* In/Out - Max size of detail log \ Actual size of detail log */ void *ospvDetailLog) /* Out - Pointer to detail log storage */ { int errorcode = OSPC_ERR_NO_ERROR; NBDATA *nbData = OSPC_OSNULL; if (nbMonitor->TimeToShutDown == 0) { /* * allocate space * the space will be deallocated by one of the working thread */ errorcode = newNBDATA(&nbData, MESSAGE_TYPE_USE_IND); if (OSPC_ERR_NO_ERROR == errorcode) { // fill out the data structure nbData->ShouldBlock = ShouldBlock; nbData->ErrorCode = OSPErrorCode; nbData->Message.UseInd.ospvTransaction = ospvTransaction; nbData->Message.UseInd.ospvDuration = ospvDuration; nbData->Message.UseInd.ospvStartTime = ospvStartTime; nbData->Message.UseInd.ospvEndTime = ospvEndTime; nbData->Message.UseInd.ospvAlertTime = ospvAlertTime; nbData->Message.UseInd.ospvConnectTime = ospvConnectTime; nbData->Message.UseInd.ospvHasPDDInfo = ospvHasPDDInfo; nbData->Message.UseInd.ospvPostDialDelay = ospvPostDialDelay; nbData->Message.UseInd.ospvReleaseSource = ospvReleaseSource; if (ospvConferenceId) { OSPM_STRCPY(nbData->Message.UseInd.ospvConferenceId, (const char *)ospvConferenceId); } nbData->Message.UseInd.ospvLossPacketsSent = ospvLossPacketsSent; nbData->Message.UseInd.ospvLossFractionSent = ospvLossFractionSent; nbData->Message.UseInd.ospvLossPacketsReceived = ospvLossPacketsReceived; nbData->Message.UseInd.ospvLossFractionReceived = ospvLossFractionReceived; nbData->Message.UseInd.ospvSizeOfDetailLog = ospvSizeOfDetailLog; nbData->Message.UseInd.ospvDetailLog = ospvDetailLog; // time stamp (UseInd) IN QUEUE event OSPPOSTimeGetTime(&nbData->InQuequeTime, &nbData->InQuequeTimeMS); // put a new message to the non-blocking queue *(nbData->ErrorCode) = OSPC_REPORT_USAGE_BLOCK; errorcode = SyncQueueAddTransaction(nbMonitor->SyncQue, nbData); if (OSPC_ERR_NO_ERROR == errorcode) { /* * This is a bit odd. If the caller wants to wait, * it is responsible for deleting nbData. * Oterwise, the work thread will clean up */ if (1 == ShouldBlock) { /* * SHOULD wait */ OSPM_MUTEX_LOCK(nbData->Mutex, errorcode); while ((*(nbData->ErrorCode) == OSPC_REPORT_USAGE_BLOCK) && (OSPC_ERR_NO_ERROR == errorcode)) { OSPM_CONDVAR_WAIT(nbData->CondVar, nbData->Mutex, errorcode); } OSPM_MUTEX_UNLOCK(nbData->Mutex, errorcode); deleteNBDATA(nbData); } else { /* * should NOT wait */ } } } else { errorcode = OSPC_ERR_MSGQ_NO_MEMORY; } } else { errorcode = -1; } return errorcode; } int OSPPTransactionIndicateCapabilities_nb(NBMONITOR *nbMonitor, /* In - NBMonitor Pointer */ int ShouldBlock, /* In - 1 WILL block, 0 - will NOT block */ int *OSPErrorCode, /* Out- Error code returned by the blocking function */ OSPTTRANHANDLE ospvTransaction, /* In - Transaction Handle */ const char *ospvSource, /* In - Source of call */ const char *ospvSourceDevice, /* In - SourceDevice of call */ const char *ospvSourceNetworkId, /* In - NetworkId of call */ unsigned ospvAlmostOutOfResource, /* In - A Boolean flag indicating device's availability */ unsigned *ospvSizeOfDetailLog, /* In\Out - Max size of detail log \ Actual size of detail log */ void *ospvDetailLog) /* In\Out - Location of detail log storage */ { int errorcode = OSPC_ERR_NO_ERROR; NBDATA *nbData = OSPC_OSNULL; if (nbMonitor->TimeToShutDown == 1) { /* * Q is shutting down */ errorcode = -1; } else if (SyncQueueGetNumberOfTransactions(nbMonitor->SyncQue) > nbMonitor->MaxQueSize) { /* * There are already to many requests in the Q */ errorcode = -1; } else { /* * allocate space * the space will be deallocated by one of the working thread */ errorcode = newNBDATA(&nbData, MESSAGE_TYPE_CAP_IND); if (OSPC_ERR_NO_ERROR == errorcode) { // fill out the data structure nbData->ShouldBlock = ShouldBlock; nbData->ErrorCode = OSPErrorCode; nbData->Message.CapInd.ospvTransaction = ospvTransaction; nbData->Message.CapInd.ospvSource = ospvSource; nbData->Message.CapInd.ospvSourceDevice = ospvSourceDevice; nbData->Message.CapInd.ospvAlmostOutOfResources = ospvAlmostOutOfResource; nbData->Message.CapInd.ospvSourceNetworkId = ospvSourceNetworkId; nbData->Message.CapInd.ospvSizeOfDetailLog = ospvSizeOfDetailLog; nbData->Message.CapInd.ospvDetailLog = ospvDetailLog; // time stamp (AuthReq) IN QUEUE event OSPPOSTimeGetTime(&nbData->InQuequeTime, &nbData->InQuequeTimeMS); // put a new message to the non-blocking queue *(nbData->ErrorCode) = OSPC_AUTH_REQUEST_BLOCK; errorcode = SyncQueueAddTransaction(nbMonitor->SyncQue, nbData); if (OSPC_ERR_NO_ERROR == errorcode) { /* * This is a bit odd. If the caller wants to wait, * it is responsible for deleting nbData. * Oterwise, the work thread will clean up */ if (1 == nbData->ShouldBlock) { /* * SHOULD wait */ OSPM_MUTEX_LOCK(nbData->Mutex, errorcode); while ((*(nbData->ErrorCode) == OSPC_CAP_IND_BLOCK) && (OSPC_ERR_NO_ERROR == errorcode)) { OSPM_CONDVAR_WAIT(nbData->CondVar, nbData->Mutex, errorcode); } OSPM_MUTEX_UNLOCK(nbData->Mutex, errorcode); deleteNBDATA(nbData); } else { /* * should NOT wait */ } } } else { errorcode = OSPC_ERR_MSGQ_NO_MEMORY; } } return errorcode; } OSPTUINT64 GetDeltaMS(OSPTTIME FromTimeSec, unsigned int FromTimeMS, OSPTTIME ToTimeSec, unsigned int ToTimeMS) { return(1000 * (ToTimeSec - FromTimeSec) + (ToTimeMS - FromTimeMS)); }