📄 gc_basic_call_model.c
字号:
/* assumes caller of gc_ResetLinedev() set dropcall_time = 0 */
for (index = 0; index < num_devices; index++) {
pline = &port[index];
/* check if time tripped */
if (pline->dropcall_time && (pline->dropcall_time <= current_time)) {
/* drop call is no longer required */
pline->dropcall_time = 0;
/* Retrieve CRN - assumes only 1 call is active */
callindex = existCRN(-1, pline);
if (callindex == OUT_OF_RANGE) {
/* CRN not found, so log error and return from function. */
sprintf(str, "CRN not found");
printandlog(pline->index, MISC_WITH_NL, NULL, str, 0);
return;
}
if (gc_DropCall(pline->call[callindex].crn, GC_NORMAL_CLEARING, EV_ASYNC) != GC_SUCCESS) {
sprintf(str, "gc_DropCall(crn=0x%lx, cause=GC_NORMAL_CLEARING, mode=EV_ASYNC) Failed", pline->call[callindex].crn);
printandlog(pline->index, GC_APIERR, NULL, str, 0);
printandlog(pline->index, STATE, NULL, " ", callindex);
exitdemo(1);
}
printandlog(index, MISC_WITH_NL, NULL, "********* Dropping outbound call from drop_outbound_calls_if_required() *********", 0);
sprintf(str, "gc_DropCall(crn=0x%lx, cause=GC_NORMAL_CLEARING, mode=EV_ASYNC) Success", pline->call[callindex].crn);
printandlog(pline->index, GC_APICALL, NULL, str, 0);
/* Set the dropcall flag to YES on the related channel */
pline->call[callindex].dropcall_active = YES;
}
}
}
/****************************************************************
* NAME: make_calls_if_required(void)
* DESCRIPTION: This procedure sees if there are any calls that need to be made
* handles some makecall error conditions
* RETURNS: NA
* CAUTIONS: none
****************************************************************/
static void make_calls_if_required(void)
{
int index;
struct channel *pline;
time_t current_time; /* in seconds */
time(¤t_time); /* get the current time in seconds */
/* check all devices for an "expired" make call time */
for (index = 0; index < num_devices; index++) {
pline = &port[index];
if (pline->makecall_time && (pline->makecall_time <= current_time)) { /* check if time tripped */
printandlog(index, MISC, NULL, "makecall timer tripped - will retry the makecall", 0);
pline->makecall_time = 0; /* makecall request will now be met */
gc_demo_makecall(index); /* attempt to make the call again */
}
if (pline->intercall_time && (pline->intercall_time <= current_time)) { /* check if time tripped */
printandlog(index, MISC, NULL, "Inter-Call timer tripped - New call will now be attempted", 0);
pline->intercall_time = 0; /* makecall request will now be met */
gc_demo_makecall(index); /* attempt to make the call again */
}
}
}
/****************************************************************
* NAME: process_event(void)
* DESCRIPTION: Function to handle the GlobalCall Events
* RETURNS: NA
* CAUTIONS: none
****************************************************************/
static void process_event(void)
{
METAEVENT metaevent;
struct channel *pline;
char str[MAX_STRING_SIZE];
int index; /* Device index */
int evttype;
GC_INFO t_info; /* Structure which stores information about GC related errors */
int callindex; /* CAUTION: once initialized, do not change */
/* the value in this subroutine! */
int temp_callindex; /* use the temporary callindex instead */
int channum; /* Channel Number for Index */
/* Populate the metaEvent structure */
if(gc_GetMetaEvent(&metaevent) != GC_SUCCESS)
{
/* serious problem - should never fail */
printandlog(ALL_DEVICES, GC_APIERR, NULL, "gc_GetMetaEvent() failed", 0);
exitdemo(1);
}
/* process GlobalCall events */
if ((metaevent.flags & GCME_GC_EVENT) == 0) {
/*********************************************************************/
/* Your application might have non-GC events , e.g. voice or fax */
/* events that need to be processed. That would be done here. */
/* However for the purposes of the demo, non_GC events are only */
/* logged. Most likely you will need to do some sort of a */
/* search of the port array to find the associated data structure */
/* for this event. Since the event is not a GC event, */
/* gc_GetUsrAttr() cannot help find the associated GC data structure */
/*********************************************************************/
sr_getparm(metaevent.evtdev, SR_USERCONTEXT, &channum);
sprintf(str, "Received a non-GC Event 0x%lx\n channel number %d", metaevent.evttype, channum);
printandlog(channum, MISC, NULL, str, 0);
//return;
process_voice_event(channum);
return;
}
/**************************************/
/* when here => processing a GC event */
/**************************************/
/* initialize pline to port[index],
The pointer to this structure was stored in GC
during gc_OpenEx() */
pline = (struct channel *) metaevent.usrattr;
/* Retrieve device index */
index = pline->index;
evttype = metaevent.evttype;
/* skip checks if no crn for this event */
if ((metaevent.crn != 0) && (pline->resetlinedev_active == NO)) {
/* Assumption: Only GCEV_DETECTED/GCEV_OFFERED will require the CRN
to be inserted into the array. */
callindex = existCRN(metaevent.crn, pline);
if (callindex == OUT_OF_RANGE) {
/* CRN was not found, so insert CRN into the array.
* Should only occurs when GCEV_DETECTED or GCEV_OFFERED event is received.
* Note: GCEV_DETECTED is not enabled, but this code will support it if
* if you enable this event */
if ((evttype == GCEV_DETECTED) || (evttype == GCEV_OFFERED)) {
for (callindex = 0; callindex < MAX_CALLS; callindex++) {
if (pline->call[callindex].crn == 0) {
/* crn is not found, insert into crn array. */
pline->call[callindex].crn = metaevent.crn;
break;
}
}
} else {
/* Error case: should not happen */
sprintf(str, " Received an event(0x%x) with an invalid CRN(0x%lx)", evttype, metaevent.crn);
printandlog(index, MISC_WITH_NL, NULL, str, 0);
return;
}
}
} else {
callindex = 0; /* some printing routines use callindex */
}
/**********************************************************************/
/* CAUTION: at this point callindex is initialized, do not change it! */
/**********************************************************************/
printandlog(index, MISC_WITH_NL, NULL, "********* Received a GC event *********", 0);
printandlog(index, EVENT, NULL, GCEV_MSG(evttype), 0);
printandlog(index, STATE, NULL, " is the current GC call state ", callindex);
/* 1st handle the generic events */
switch (evttype)
{
case GCEV_OPENEX:
printandlog(index, MISC, NULL, "GCEV_OPENEX received", 0);
/* Although this demo currently only opens H.323 and SIP devices asynchronously */
if ((pline->techtype == H323) || (pline->techtype == SIP)) {
routevoice(index);
/* Enable alarm notification for H.323 or SIP devices which were opened ASYNC */
enable_alarm_notification(pline);
/* Set DTMF mode to inband for SIP as default of Alphanumeric mode
* valid only for H.323 devices
*/
if (pline->techtype == SIP) {
GC_PARM_BLK *parmblkp = NULL;
gc_util_insert_parm_val(&parmblkp, IPSET_DTMF, IPPARM_SUPPORT_DTMF_BITMASK,
sizeof(char), IP_DTMF_TYPE_INBAND_RTP);
if (gc_SetUserInfo(GCTGT_GCLIB_CHAN, port[index].ldev, parmblkp, GC_ALLCALLS) != GC_SUCCESS) {
sprintf(str, "gc_SetUserInfo(linedev=%ld) Failed configuring DTMF mode", port[index].ldev);
printandlog(index, GC_APIERR, NULL, str, 0);
exitdemo(1);
}
sprintf(str, "gc_SetUserInfo(linedev=%ld) Success - DTMF mode is inband", port[index].ldev);
printandlog(index, GC_APICALL, NULL, str, 0);
gc_util_delete_parm_blk(parmblkp);
}
}
break;
/* This demo only opens H.323 and SIP devices asynchronously */
case GCEV_OPENEX_FAIL:
printandlog(index, MISC, NULL, "GCEV_OPENEX_FAIL received", 0);
printandlog(index, GC_RESULT_INFO, &metaevent, "Reason for GCEV_OPENEX_FAIL ", 0);
exitdemo(1);
break;
case GCEV_ALARM:
print_alarm_info(&metaevent, pline);
break;
case GCEV_FATALERROR:
printandlog(index, GC_RESULT_INFO, &metaevent, "Reason for fatalerror ", 0);
printandlog(index, STATE, NULL, " ", callindex);
if (gc_ResultInfo(&metaevent, &t_info) < 0) {
sprintf(str, "gc_ResultInfo() call failed");
printandlog(index, GC_APIERR, NULL, str, 0);
exitdemo(1);
}
if (t_info.gcValue == GCRV_RESETABLE_FATALERROR) {
pline->dropcall_time = 0; /* in case on */
pline->resetlinedev_active = YES; /* reset linedevice is on as a background process */
/* do nothing else= wait till the GCEV_RESETLINEDEV completion event arrives */
} else if (t_info.gcValue == GCRV_RECOVERABLE_FATALERROR) {
/* do a close and open on recoverable, fatal errors */
printandlog(index, MISC, NULL, " Recoverable fatal error occurred - closing device and re-opening it", 0);
if (gc_Close(port[index].ldev) < 0) {
printandlog(index, GC_APIERR, NULL, "gc_Close() failed", 0);
exitdemo(1);
}
open_device(index);
} else {
printandlog(index, MISC, NULL, " Non-recoverable fatal error occurred", 0);
exitdemo(1);
}
break;
case GCEV_BLOCKED:
pline->blocked = YES; /* Nothing to do when a blocked event occurs */
break;
case GCEV_UNBLOCKED:
/* blocked/unblocked do not cause state transitions */
pline->blocked = NO;
if (pline->resetlinedev_required_after_unblocked == YES) {
pline->resetlinedev_required_after_unblocked = NO;
if (gc_ResetLineDev(port[index].ldev, EV_ASYNC) != GC_SUCCESS) {
sprintf(str, "gc_ResetLineDev(linedev=%ld, mode=EV_ASYNC) Failed", port[index].ldev);
printandlog(index, GC_APIERR, NULL, str, 0);
exitdemo(1);
}
pline->resetlinedev_active = YES;
sprintf(str, "gc_ResetLineDev(linedev=%ld, mode=EV_ASYNC) Success", port[index].ldev);
printandlog(index, GC_APICALL, NULL, str, 0);
/* nothing more can do until the completion event arrives */
break;
}
if (pline->waitcall_active == YES) {
break;
}
if (pline->resetlinedev_active == YES) {
break;
}
/* FALL THROUGH ON PURPOSE */
case GCEV_RESETLINEDEV:
if (evttype == GCEV_RESETLINEDEV) {
/* Reset call related flags and variables */
pline->waitcall_active = NO;
pline->makecall_active = NO;
pline->resetlinedev_active = NO;
for (temp_callindex = 0; temp_callindex < MAX_CALLS; temp_callindex++) {
/* reset internal variables to that of beginning */
pline->call[temp_callindex].call_state = GCST_NULL;
pline->call[temp_callindex].crn = 0;
pline->call[temp_callindex].dropcall_active = NO;
}
}
if ((evttype == GCEV_RESETLINEDEV)
&& (reset_linedevs_left_to_complete != 0)) { /* tests if processing shutdown request */
reset_linedevs_left_to_complete--;
sprintf(str, "One less GCEV_RESETLINEDEV to wait for, %d left",
reset_linedevs_left_to_complete);
printandlog(ALL_DEVICES, MISC, NULL, str, 0);
}
/* must further process the event if unblocked */
if ((interrupted == NO) && (pline->blocked == NO)) {
if (pline->direction == DIR_IN) {
/* Note: by definition, waitcall is not active at this point */
if (pline->blocked == NO) {
if (gc_WaitCall(pline->ldev, NULL, NULL, -1, EV_ASYNC) != GC_SUCCESS) {
sprintf(str, "gc_WaitCall(linedev=%ld, crnp=NULL, waittime=0, mode=EV_ASYNC) Failed", pline->ldev);
printandlog(index, GC_APIERR, NULL, str, 0);
exitdemo(1);
}
pline->waitcall_active = YES;
sprintf(str, "gc_WaitCall(linedev=%ld, crnp=NULL, waittime=0, mode=EV_ASYNC) Success", pline->ldev);
printandlog(index, GC_APICALL, NULL, str, 0);
}
} else {
/* Make another call if possible */
gc_demo_makecall(index);
}
}
break;
case GCEV_TASKFAIL:
printandlog(index, GC_RESULT_INFO, &metaevent, "Reason for taskfail ", 0);
printandlog(index, STATE, NULL, " ", callindex);
/* best can do is a reset linedevice */
/* if reset lindevice is already active, then retry it */
if (gc_ResetLineDev(port[index].ldev, EV_ASYNC) == GC_SUCCESS) {
pline->dropcall_time = 0; /* in case on */
pline->call[callindex].dropcall_active = NO; /* in case on */
pline->makecall_active = NO; /* in case on */
pline->resetlinedev_active = YES;
sprintf(str, "gc_ResetLineDev(linedev=%ld, mode=EV_ASYNC) Success", port[index].ldev);
printandlog(index, GC_APICALL, NULL, str, 0);
} else {
sprintf(str, "gc_ResetLineDev(linedev=%ld, mode=EV_ASYNC) Failed", port[index].ldev);
printandlog(index, GC_APIERR, NULL, str, 0);
if (pline->blocked == NO) { /* If no alarms are active */
exitdemo(1); /* Then should never get here */
}
/* when here, resetlinedev failed and in the blocked state */
/* most likely due to an alarm being active */
if (pline->call[callindex].crn) { /* is there an active call? */
if (pline->call[callindex].dropcall_active == NO) { /* drop and release the call if can */
if (gc_DropCall(pline->call[callindex].crn, GC_NORMAL_CLEARING, EV_ASYNC) == GC_SUCCESS)
{
sprintf(str, "gc_DropCall(crn=0x%lx, cause=GC_NORMAL_CLEARING, mode=EV_ASYNC) Success", pline->call[callindex].crn);
printandlog(pline->index, GC_APICALL, NULL, str, 0);
pline->call[callindex].dropcall_active = YES;
} else {
sprintf(str, "gc_DropCall(crn=0x%lx, cause=GC_NORMAL_CLEARING, mode=EV_ASYNC) Failed", pline->call[callindex].crn);
printandlog(pline->index, GC_APIERR, NULL, str, 0);
printandlog(pline->index, STATE, NULL, " ", callindex);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -