📄 gc_basic_call_model.c
字号:
if ((port[index].log_fp = fopen(temp_filename, "w")) == NULL) {
printf("\nCannot open log file %s for write\n", temp_filename);
perror("Reason is: ");
exitdemo(1);
}
printf("%s successfully opened\n", temp_filename);
} /* End of for loop */
return 1;
}
/****************************************************************
* NAME: inbound_application(struct channel *pline)
* DESCRIPTION: Place holder for your inbound application code in the connected state
* INPUT: pline - pointer to port data structure
* RETURNS: NA
* CAUTIONS: none
****************************************************************/
static void inbound_application(struct channel *pline)
{
/* Place holder - your app code goes here */
}
/****************************************************************
* NAME: outbound_application(struct channel *pline)
* DESCRIPTION: Place holder for your outbound application code in the connected state
* INPUT: pline - pointer to port data structure
* RETURNS: NA
* CAUTIONS: none
****************************************************************/
static void outbound_application(struct channel *pline)
{
/*************************************************************************/
/* YOUR APP WOULD PUT ITS WORK HERE */
/* however for purposes of the demo, stay in the connected state */
/* at least one second. This is because not all technologies and all */
/* protocols support dropcall immediately after connected in the default */
/* shipped configuration */
/*************************************************************************/
time(&pline->dropcall_time);
pline->dropcall_time += 2; /* stay connected at least one second */
/* 2 is chosen because the granularity is 1 sec */
printandlog(pline->index, MISC, NULL, "gc_DropCall() will be issued in 1-2 seconds");
}
/****************************************************************
* NAME: drop_outbound_calls_if_required(void)
* DESCRIPTION: This drops outbound side calls if required
* For purposes of the demo, a call stays in the connected
* state state for a second or two, then is dropped by the outbound side
* Your application does not need this code
* and hence it is not optimized
* RETURNS: NA
* CAUTIONS: none
****************************************************************/
static void drop_outbound_calls_if_required(void)
{
int index;
struct channel *pline;
time_t current_time; /* in seconds */
char str[MAX_STRING_SIZE];
time(¤t_time); /* get the current time in seconds */
/* check all devices for an "expired" drop call time */
/* assumes caller of gc_ResetLinedev() set dropcall_time = 0 */
for (index = 0; index < num_devices; index++) {
pline = &port[index];
if (pline->dropcall_time && (pline->dropcall_time <= current_time)) { /* check if time tripped */
pline->dropcall_time = 0; /* drop call is no longer required */
if (gc_DropCall(pline->crn, GC_NORMAL_CLEARING, EV_ASYNC) != GC_SUCCESS) {
sprintf(str, "gc_DropCall(crn=0x%lx, cause=GC_NORMAL_CLEARING, mode=EV_ASYNC) Failed", pline->crn);
printandlog(pline->index, GC_APIERR, NULL, str);
printandlog(pline->index, STATE, NULL, " ");
exitdemo(1);
}
printandlog(index, MISC_WITH_NL, NULL, "********* Dropping outbound call from drop_outbound_calls_if_required() *********");
sprintf(str, "gc_DropCall(crn=0x%lx, cause=GC_NORMAL_CLEARING, mode=EV_ASYNC) Success", pline->crn);
printandlog(pline->index, GC_APICALL, NULL, str);
/* Set the dropcall flag to YES on the related channel */
pline->dropcall_active = YES;
}
}
}
/****************************************************************
* NAME: process_event(void)
* DESCRIPTION: Function to handle the GlobalCall Events
* RETURNS: NA
* CAUTIONS: none
****************************************************************/
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 */
/* Populate the metaEvent structure */
if(gc_GetMetaEvent(&metaevent) != GC_SUCCESS)
{
printandlog(ALL_DEVICES, GC_APIERR, NULL, "gc_GetMetaEvent() failed");
exitdemo(1); /* serious problem - should never fail */
}
/* 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 */
/*********************************************************************/
sprintf(str, "Received a non-GC Event 0x%lx\n", metaevent.evttype);
printandlog(ALL_DEVICES, MISC, NULL, str);
return; /* RETURN POINT */
}
/**************************************/
/* 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;
printandlog(index, MISC_WITH_NL, NULL, "********* Received a GC event *********");
printandlog(index, EVENT, NULL, GCEV_MSG(evttype));
printandlog(index, STATE, NULL, " is the current GC call state ");
/* 1st handle the generic events */
switch (evttype)
{
case GCEV_FATALERROR:
printandlog(index, GC_RESULT_INFO, &metaevent, "Reason for fatalerror ");
printandlog(index, STATE, NULL, " ");
if (gc_ResultInfo(&metaevent, &t_info) < 0) {
sprintf(str, "gc_ResultInfo() call failed");
printandlog(index, GC_APIERR, NULL, str);
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");
if (gc_Close(port[index].ldev) < 0) {
printandlog(index, GC_APIERR, NULL, "gc_Close() failed");
exitdemo(1);
}
open_device(index);
} else {
printandlog(index, MISC, NULL, " Non-recoverable fatal error occurred");
exitdemo(1);
}
break;
case GCEV_BLOCKED:
pline->blocked = YES; /* Nothing to do when a blocked event occurs */
break;
case GCEV_RESETLINEDEV:
pline->call_state = GCST_NULL; /* reset internal variables to that of beginning */
pline->crn = 0; /* except blocked/unblocked which are not affected by */
pline->waitcall_active = NO; /* GCEV_RESETLINEDEV */
pline->dropcall_active = NO;
pline->makecall_active = NO;
pline->resetlinedev_active = NO;
if (pline->blocked == NO) { /* must further process the event if unblocked */
if (pline->direction == DIR_IN) {
process_inbound_event(pline, &metaevent);
} else {
process_outbound_event(pline, &metaevent);
}
}
break;
/* Note: for purposes of the demo, we will assume that gc_ResetLineDev() */
/* does not fail or if it fails the 1st time, it will recover the 2nd time */
case GCEV_TASKFAIL:
printandlog(index, GC_RESULT_INFO, &metaevent, "Reason for taskfail ");
printandlog(index, STATE, NULL, " ");
/* best can do is a reset linedevice */
pline->dropcall_time = 0; /* in case on */
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);
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);
break; /* nothing more can do until the completion event arrives */
case GCEV_DISCONNECTED:
if (pline->resetlinedev_active == NO) {
process_disconnected_event(pline); /* process the disconnected event */
}
break;
case GCEV_UNBLOCKED:
pline->blocked = NO; /* blocked/unblocked do not cause state transitions */
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);
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);
break; /* nothing more can do until the completion event arrives */
}
/* fall through on purpose so the unblocked event will be handled */
default:
if (pline->resetlinedev_active == NO) { /* ignore all call related events with reset linedevice active */
if (pline->direction == DIR_IN) {
process_inbound_event(pline, &metaevent);
} else {
process_outbound_event(pline, &metaevent);
}
}
break;
}
printandlog(index, STATE, NULL, " is the new GC call state after processing the event");
}
/****************************************************************
* NAME: process_disconnected_event(struct channel *pline)
* DESCRIPTION: Function to process a disconnected event
* INPUTS: pline - pointer to entry in port table
* RETURNS: NA
* CAUTIONS: Assumes event logging already done
****************************************************************/
static void process_disconnected_event(struct channel *pline)
{
char str[MAX_STRING_SIZE];
switch (pline->call_state)
{
case GCST_IDLE:
/*************************************************************/
/* this represents a simultaneous disconnect */
/* do nothing as gc_DropCall() must have already been issued */
/* to reach this point! */
/*************************************************************/
break;
case GCST_NULL:
/* In case have a disconnect before dialing is reached */
if (pline->makecall_active == NO) {
/* this represents an error */
printandlog(pline->index, MISC, NULL, "Received GCEV_DISCONNECTED in null call state");
break;
}
/* fall through on purpose - need to do a dropcall and release call since there is a call active */
/* may have reached this condition if there is a problem before dialing */
default:
/* GCEV_DISCONNECTED is allowed in all other call states */
/* If dropcall is already active, don't reissue it */
/* this represents a simultaneous disconnect */
if(pline->dropcall_active == NO)
{
if (gc_DropCall(pline->crn, GC_NORMAL_CLEARING, EV_ASYNC) != GC_SUCCESS)
{
sprintf(str, "gc_DropCall(crn=0x%lx, cause=GC_NORMAL_CLEARING, mode=EV_ASYNC) Failed", pline->crn);
printandlog(pline->index, GC_APIERR, NULL, str);
printandlog(pline->index, STATE, NULL, " ");
exitdemo(1);
}
sprintf(str, "gc_DropCall(crn=0x%lx, cause=GC_NORMAL_CLEARING, mode=EV_ASYNC) Success", pline->crn);
printandlog(pline->index, GC_APICALL, NULL, str);
pline->dropcall_active = YES;
}
pline->call_state = GCST_DISCONNECTED;
break;
}
}
/****************************************************************
* NAME: process_inbound_event(struct channel *pline, METAEVENT *metaeventp)
* DESCRIPTION: Function to process inbound GlobalCall event
* INPUTS: pline - pointer to entry in port table
* metaeventp - pointer to the metaevent structure
* RETURNS: NA
* CAUTIONS: Tightly coupled with process_event() for pre-processing
* Assumes event logging already done
* Disconnected event already handled
****************************************************************/
static void process_inbound_event(struct channel *pline, METAEVENT *metaeventp)
{
int evttype, index, call_state;
char str[MAX_STRING_SIZE];
int unexpected_event = 0; /*assume not till proven otherwise */
/* May be overridden for GCEV_UNBLOCKED */
evttype = metaeventp->evttype;
index = pline->index;
call_state = pline->call_state;
/* Implement the state machine */
switch (pline->call_state)
{
/************************************/
/* first come the call setup states */
/************************************/
case GCST_NULL:
{
switch (evttype)
{
case GCEV_UNBLOCKED:
if (pline->waitcall_active == YES) {
break; /* waitcall already done - don't do again */
}
/* FALL THROUGH ON PURPOSE */
case GCEV_RESETLINEDEV:
/* 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);
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -