Add Call Completion Suppplementary Service

Call Completion Supplementary Service (CCSS) added for the following 
switch types: ETSI PTMP, ETSI PTP, Q.SIG.  

Specifications:
ETS 300 359 CCBS for PTMP and PTP
ETS 301 065 CCNR for PTMP and PTP
ECMA-186 Call Completion for Q.SIG

Several support services were added to support CC:
Dummy Call Reference.
Q.931 REGISTER message.
Dynamic expansion of the number of available timers (up to 8192).
Enhanced facility message handling.

Current implementation limitations preclude the following:
CC service retention is not supported.
Q.SIG path reservation is not supported.

(closes issue #14292)
Reported by: tomaso
Tested by: rmudgett

JIRA SWP-1493

Review:	https://reviewboard.asterisk.org/r/522/


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1714 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
Richard Mudgett 2010-05-26 16:01:10 +00:00
parent 07b3f1dc45
commit 6829faae06
28 changed files with 17327 additions and 312 deletions

View File

@ -47,16 +47,19 @@ STATIC_OBJS= \
q921.o \
prisched.o \
q931.o \
pri_cc.o \
pri_facility.o \
asn1_primitive.o \
rose.o \
rose_address.o \
rose_etsi_aoc.o \
rose_etsi_cc.o \
rose_etsi_diversion.o \
rose_etsi_ect.o \
rose_other.o \
rose_q931.o \
rose_qsig_aoc.o \
rose_qsig_cc.o \
rose_qsig_ct.o \
rose_qsig_diversion.o \
rose_qsig_mwi.o \
@ -68,16 +71,19 @@ DYNAMIC_OBJS= \
q921.lo \
prisched.lo \
q931.lo \
pri_cc.lo \
pri_facility.lo \
asn1_primitive.lo \
rose.lo \
rose_address.lo \
rose_etsi_aoc.lo \
rose_etsi_cc.lo \
rose_etsi_diversion.lo \
rose_etsi_ect.lo \
rose_other.lo \
rose_q931.lo \
rose_qsig_aoc.lo \
rose_qsig_cc.lo \
rose_qsig_ct.lo \
rose_qsig_diversion.lo \
rose_qsig_mwi.lo \

366
doc/cc_ptmp_agent.fsm Normal file
View File

@ -0,0 +1,366 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTMP agent.
*/
FSM CC_PTMP_Agent
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_PENDING_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_PENDING_AVAILABLE {
Stimulus CC_EVENT_MSG_ALERTING {
Action Send_CC_Available(Q931_ALERTING);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_MSG_DISCONNECT {
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_AVAILABLE {
Epilog {
Action Stop_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Epilog {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
}
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
/*
* Pass_Up_A_Status passes up the current final status of A.
* Does nothing if status is invalid.
*
* Pass_Up_A_Status_Indirect is the same as Pass_Up_A_Status but
* sets a timer to expire immediately to pass up the event.
* Does nothing if status is invalid.
*
* Pass_Up_Status_Rsp_A passes up the current accumulated status of A.
* Does nothing if status is invalid.
*
* Pass_Up_Status_Rsp_A_Indirect is the same as Pass_Up_Status_Rsp_A but
* sets a timer to expire immediately to pass up the event.
* Does nothing if status is invalid.
*/
State CC_STATE_ACTIVATED {
Prolog {
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
}
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_B_FREE {
Action Send_CCBSBFree;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
Test = Get_A_Status;
Test == Invalid {
Next_State CC_STATE_B_AVAILABLE;
}
Test == Busy {
Action Pass_Up_A_Status_Indirect;
Action Send_CCBSBFree;
Next_State CC_STATE_SUSPENDED;
}
Test == Free {
//Action Pass_Up_A_Status_Indirect;
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
}
Stimulus CC_EVENT_A_STATUS {
Test = Get_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A_Indirect;
Next_State $;
}
Test != Active {
Action Reset_A_Status;
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Next_State $;
}
}
Stimulus CC_EVENT_A_FREE {
Action Raw_Status_Count_Reset;
Action Set_Raw_A_Status_Free;
Action Promote_Raw_A_Status;
Action Pass_Up_Status_Rsp_A;
Action Stop_T_CCBS1;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Action Pass_Up_Status_Rsp_A;
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Action Promote_Raw_A_Status;
Test = Get_A_Status;
Test != Invalid {
/* Only received User A busy. */
Action Raw_Status_Count_Reset;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
}
Stimulus CC_EVENT_TIMEOUT_EXTENDED_T_CCBS1 {
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
}
}
State CC_STATE_B_AVAILABLE {
/* A status is always invalid on entry. */
Prolog {
Test = Get_T_CCBS1_Status;
Test != Active {
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_A_FREE {
Action Send_RemoteUserFree;
Action Set_Raw_A_Status_Free;
//Action Promote_Raw_A_Status;
//Action Pass_Up_A_Status;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Test = Get_Raw_A_Status;
Test != Invalid {
/* Only received User A is busy. */
Action Raw_Status_Count_Reset;
Action Send_CCBSBFree;
Action Promote_Raw_A_Status;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
//Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
}
State CC_STATE_SUSPENDED {
Prolog {
Test = Get_T_CCBS1_Status;
Test != Active {
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_A_FREE {
Action Set_Raw_A_Status_Free;
Action Promote_Raw_A_Status;
Action Pass_Up_A_Status;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Test = Get_Raw_A_Status;
Test != Invalid {
/* Only received User A is busy. */
Action Raw_Status_Count_Reset;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
State CC_STATE_WAIT_CALLBACK {
Prolog {
/* Start T_CCBS3 */
Action Start_T_RECALL;
}
Epilog {
Action Stop_T_RECALL;
}
Stimulus CC_EVENT_TIMEOUT_T_RECALL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS3_TIMEOUT);
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_STOP_ALERTING {
/*
* If an earlier link can send us this event then we
* really should be configured for globalRecall like
* the earlier link.
*/
Test = Get_Recall_Mode;
Test == globalRecall {
Action Send_CCBSStopAlerting;
}
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
Test = Get_Recall_Mode;
Test == globalRecall {
Action Send_CCBSStopAlerting;
}
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_A_STATUS {
Action Set_Raw_A_Status_Free;
Action Pass_Up_Status_Rsp_A_Indirect;
}
}
State CC_STATE_CALLBACK {
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_AlreadyAccepted);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Set_Raw_A_Status_Free;
Action Pass_Up_Status_Rsp_A_Indirect;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_B_AVAILABLE, CC_STATE_SUSPENDED, CC_STATE_WAIT_CALLBACK, CC_STATE_CALLBACK) {
Prolog {
/* Start T_CCBS2 or T_CCNR2 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Next_State CC_STATE_IDLE;
}
}
Superstate CC_STATUS(CC_STATE_ACTIVATED, CC_STATE_B_AVAILABLE, CC_STATE_SUSPENDED) {
Epilog {
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
}
}
}

View File

@ -0,0 +1,483 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTMP agent.
*/
FSM CC_PTMP_Agent
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_PENDING_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_PENDING_AVAILABLE {
Stimulus CC_EVENT_MSG_ALERTING {
Action Send_CC_Available(Q931_ALERTING);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_MSG_DISCONNECT {
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_AVAILABLE {
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
/* Start T_CCBS2 or T_CCNR2 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CANCEL {
Action Send_EraseCallLinkageID;
Action Relese_LinkID;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
/*
* Pass_Up_A_Status passes up the current final status of A.
* Does nothing if status is invalid.
*
* Pass_Up_A_Status_Indirect is the same as Pass_Up_A_Status but
* sets a timer to expire immediately to pass up the event.
* Does nothing if status is invalid.
*
* Pass_Up_Status_Rsp_A passes up the current accumulated status of A.
* Does nothing if status is invalid.
*
* Pass_Up_Status_Rsp_A_Indirect is the same as Pass_Up_Status_Rsp_A but
* sets a timer to expire immediately to pass up the event.
* Does nothing if status is invalid.
*/
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_B_FREE {
Action Send_CCBSBFree;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
Test = Get_A_Status;
Test == Invalid {
Test = Get_T_CCBS1_Status;
Test != Active {
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
Next_State CC_STATE_B_AVAILABLE;
}
Test == Busy {
Action Pass_Up_A_Status_Indirect;
Action Send_CCBSBFree;
Test = Get_T_CCBS1_Status;
Test != Active {
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
Next_State CC_STATE_SUSPENDED;
}
Test == Free {
//Action Pass_Up_A_Status_Indirect;
Action Send_RemoteUserFree;
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
/* Start T_CCBS3 */
Action Start_T_RECALL;
Next_State CC_STATE_WAIT_CALLBACK;
}
}
Stimulus CC_EVENT_A_STATUS {
Test = Get_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A_Indirect;
Next_State $;
}
Test != Active {
Action Reset_A_Status;
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Next_State $;
}
}
Stimulus CC_EVENT_A_FREE {
Action Raw_Status_Count_Reset;
Action Set_Raw_A_Status_Free;
Action Promote_Raw_A_Status;
Action Pass_Up_Status_Rsp_A;
Action Stop_T_CCBS1;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Action Pass_Up_Status_Rsp_A;
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Action Promote_Raw_A_Status;
Test = Get_A_Status;
Test != Invalid {
/* Only received User A busy. */
Action Raw_Status_Count_Reset;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}
Stimulus CC_EVENT_TIMEOUT_EXTENDED_T_CCBS1 {
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_B_AVAILABLE {
/* A status is always invalid on entry. */
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_A_FREE {
Action Send_RemoteUserFree;
Action Set_Raw_A_Status_Free;
//Action Promote_Raw_A_Status;
//Action Pass_Up_A_Status;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
/* Start T_CCBS3 */
Action Start_T_RECALL;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Test = Get_Raw_A_Status;
Test != Invalid {
/* Only received User A is busy. */
Action Raw_Status_Count_Reset;
Action Send_CCBSBFree;
Action Promote_Raw_A_Status;
Action Pass_Up_A_Status;
/* Optimization due to flattening */
//Test = Get_T_CCBS1_Status;
//Test != Active
{
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
Next_State CC_STATE_SUSPENDED;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
//Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_NotReadyForCall);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Stop_Extended_T_CCBS1;
Action Start_Extended_T_CCBS1;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_A_FREE {
Action Set_Raw_A_Status_Free;
Action Promote_Raw_A_Status;
Action Pass_Up_A_Status;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_A_BUSY {
Action Add_Raw_A_Status_Busy;
Test = Get_Extended_T_CCBS1_Status;
Test == Active {
Action Pass_Up_Status_Rsp_A;
}
}
Stimulus CC_EVENT_TIMEOUT_T_CCBS1 {
Test = Get_Raw_A_Status;
Test != Invalid {
/* Only received User A is busy. */
Action Raw_Status_Count_Reset;
}
Test == Invalid {
/* Did not get any responses. */
Action Raw_Status_Count_Increment;
Test = Get_Raw_Status_Count;
Test >= RAW_STATUS_COUNT_MAX {
/* User A no longer present. */
Action Send_CCBSErase(Normal_Unspecified);
Action Pass_Up_CC_Cancel;
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
Action Reset_Raw_A_Status;
Action Send_CCBSStatusRequest;
Action Start_T_CCBS1;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_CCBS1;
Action Stop_Extended_T_CCBS1;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_TIMEOUT_T_RECALL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS3_TIMEOUT);
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_STOP_ALERTING {
/*
* If an earlier link can send us this event then we
* really should be configured for globalRecall like
* the earlier link.
*/
Test = Get_Recall_Mode;
Test == globalRecall {
Action Send_CCBSStopAlerting;
}
Action Stop_T_RECALL;
Action Reset_A_Status;
Action Raw_Status_Count_Reset;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
Test = Get_Recall_Mode;
Test == globalRecall {
Action Send_CCBSStopAlerting;
}
Action Stop_T_RECALL;
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_A_STATUS {
Action Set_Raw_A_Status_Free;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_CALLBACK {
Stimulus CC_EVENT_RECALL {
Action Send_Error_Recall(ROSE_ERROR_CCBS_AlreadyAccepted);
Action Set_Call_To_Hangup;
}
Stimulus CC_EVENT_A_STATUS {
Action Set_Raw_A_Status_Free;
Action Pass_Up_Status_Rsp_A_Indirect;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(T_CCBS2_TIMEOUT);
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
Action Pass_Up_CC_Cancel;
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CCBSErase(Normal_Unspecified);
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

181
doc/cc_ptmp_monitor.fsm Normal file
View File

@ -0,0 +1,181 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTMP monitor.
*
* The CCBSStatusRequest messages are handled independently from this FSM.
*
* The CCBSInterrogate/CCNRInterrogate messages are initiated by a dialplan
* application/AMI/CLI (future) and are handled outside of this FSM.
*/
FSM CC_PTMP_Monitor
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
/*
* Before event is posted:
* Received CallInfoRetain
* Created cc_record
* Saved CallLinkageID
*/
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering as a safeguard in case the network cable is disconnected.
* The timer should be set much longer than the network T_RETENTION
* timer so normally the CC records will be cleaned up by network
* activity.
*/
Stimulus CC_EVENT_CC_REQUEST {
/* cc_record->is_ccnr is set before event posted. */
Action Queue_CC_Request;
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
/*
* Received EraseCallLinkageID
* T_RETENTION expired on the network side so we will pretend
* that it expired on our side.
*/
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Before event is posted:
* Received CCBSRequest/CCNRRequest response
* Saved CCBSReference
*/
Action Relese_LinkID;
Action Pass_Up_CC_Req_Rsp_Success;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_WAIT_DESTRUCTION;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/* We were in the middle of a cc-request when we were asked to cancel. */
Epilog {
Action Stop_T_ACTIVATE;
}
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Before event is posted:
* Received CCBSRequest/CCNRRequest response
* Saved CCBSReference
*/
Action Send_CC_Deactivate_Req;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_B_FREE {
/* Received CCBSBFree */
Action Pass_Up_B_Free;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received CCBSRemoteUserFree */
Action Pass_Up_Remote_User_Free;
Next_State CC_STATE_WAIT_CALLBACK;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_STOP_ALERTING {
Action Pass_Up_Stop_Alerting;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
Next_State CC_STATE_CALLBACK;
}
}
State CC_STATE_CALLBACK {
/*
* We are waiting for the CC records to be torn down because
* CC is complete.
* This state is mainly to block CC_EVENT_STOP_ALERTING since
* we are the one doing the CC recall so we do not need to stop
* alerting.
*/
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_CALLBACK) {
Prolog {
/*
* Start T_CCBS2 or T_CCNR2 depending upon CC mode.
* For PTMP TE mode these timers are not defined. However,
* we will use them anyway to protect our resources from leaks
* caused by the network cable being disconnected. These
* timers should be set much longer than the network
* so normally the CC records will be cleaned up by network
* activity.
*/
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Send_CC_Deactivate_Req;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Deactivate_Req;
Next_State CC_STATE_IDLE;
}
}
}

View File

@ -0,0 +1,225 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTMP monitor.
*
* The CCBSStatusRequest messages are handled independently from this FSM.
*
* The CCBSInterrogate/CCNRInterrogate messages are initiated by a dialplan
* application/AMI/CLI (future) and are handled outside of this FSM.
*/
FSM CC_PTMP_Monitor
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
/*
* Before event is posted:
* Received CallInfoRetain
* Created cc_record
* Saved CallLinkageID
*/
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering as a safeguard in case the network cable is disconnected.
* The timer should be set much longer than the network T_RETENTION
* timer so normally the CC records will be cleaned up by network
* activity.
*/
Stimulus CC_EVENT_CC_REQUEST {
/* cc_record->is_ccnr is set before event posted. */
Action Queue_CC_Request;
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
/*
* Received EraseCallLinkageID
* T_RETENTION expired on the network side so we will pretend
* that it expired on our side.
*/
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Before event is posted:
* Received CCBSRequest/CCNRRequest response
* Saved CCBSReference
*/
Action Relese_LinkID;
Action Pass_Up_CC_Req_Rsp_Success;
Action Stop_T_ACTIVATE;
/*
* Start T_CCBS2 or T_CCNR2 depending upon CC mode.
* For PTMP TE mode these timers are not defined. However,
* we will use them anyway to protect our resources from leaks
* caused by the network cable being disconnected. These
* timers should be set much longer than the network
* so normally the CC records will be cleaned up by network
* activity.
*/
Action Start_T_SUPERVISION;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_WAIT_DESTRUCTION;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/* We were in the middle of a cc-request when we were asked to cancel. */
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Before event is posted:
* Received CCBSRequest/CCNRRequest response
* Saved CCBSReference
*/
Action Send_CC_Deactivate_Req;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_B_FREE {
/* Received CCBSBFree */
Action Pass_Up_B_Free;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received CCBSRemoteUserFree */
Action Pass_Up_Remote_User_Free;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Send_CC_Deactivate_Req;
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Deactivate_Req;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_STOP_ALERTING {
Action Pass_Up_Stop_Alerting;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Send_CC_Deactivate_Req;
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Deactivate_Req;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_CALLBACK {
/*
* We are waiting for the CC records to be torn down because
* CC is complete.
* This state is mainly to block CC_EVENT_STOP_ALERTING since
* we are the one doing the CC recall so we do not need to stop
* alerting.
*/
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Send_CC_Deactivate_Req;
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received CCBSErase */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Deactivate_Req;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

144
doc/cc_ptp_agent.fsm Normal file
View File

@ -0,0 +1,144 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTP agent.
*/
FSM CC_PTP_Agent
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_PENDING_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_PENDING_AVAILABLE {
Stimulus CC_EVENT_MSG_ALERTING {
Action Send_CC_Available(Q931_ALERTING);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_MSG_DISCONNECT {
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_AVAILABLE {
/*
* For PTP mode the T_RETENTION timer is not defined. However,
* we will use it anyway in this state to protect our resources
* from leaks caused by user A not requesting CC. This timer
* should be set much longer than the PTMP network link to
* allow for variations in user A's CC offer timer.
*/
Epilog {
Action Stop_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Prolog {
Action Reset_A_Status;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
Action Pass_Up_A_Status_Indirect;
Test = Get_A_Status;
Test == Busy {
Next_State CC_STATE_SUSPENDED;
}
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
/* Received CCBS_T_Suspend */
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
/* Received CCBS_T_Resume */
Action Reset_A_Status;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
/* Received CCBS_T_Suspend */
Action Set_A_Status_Busy;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
/* Received CCBS_T_Resume */
Action Set_A_Status_Free;
Action Pass_Up_A_Status;
Next_State CC_STATE_ACTIVATED;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_SUSPENDED) {
Prolog {
/* Start T_CCBS5/T_CCNR5 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_RECALL {
/* Received CCBS_T_Call */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
}

View File

@ -0,0 +1,191 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTP agent.
*/
FSM CC_PTP_Agent
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_PENDING_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_PENDING_AVAILABLE {
Stimulus CC_EVENT_MSG_ALERTING {
Action Send_CC_Available(Q931_ALERTING);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_MSG_DISCONNECT {
Action Send_CC_Available(Q931_DISCONNECT);
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_AVAILABLE {
/*
* For PTP mode the T_RETENTION timer is not defined. However,
* we will use it anyway in this state to protect our resources
* from leaks caused by user A not requesting CC. This timer
* should be set much longer than the PTMP network link to
* allow for variations in user A's CC offer timer.
*/
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/* Start T_CCBS5/T_CCNR5 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
Action Pass_Up_A_Status_Indirect;
Test = Get_A_Status;
Test == Busy {
Next_State CC_STATE_SUSPENDED;
}
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
/* Received CCBS_T_Suspend */
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
/* Received CCBS_T_Resume */
Action Reset_A_Status;
}
Stimulus CC_EVENT_RECALL {
/* Received CCBS_T_Call */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
/* Received CCBS_T_Suspend */
Action Set_A_Status_Busy;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_RECALL {
/* Received CCBS_T_Call */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
/* Received CCBS_T_Resume */
Action Set_A_Status_Free;
Action Pass_Up_A_Status;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
/* Received CCBS_T_Call */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

168
doc/cc_ptp_monitor.fsm Normal file
View File

@ -0,0 +1,168 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTP monitor.
*/
FSM CC_PTP_Monitor
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
/* Received CCBS-T-Aailable */
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering.
*/
Stimulus CC_EVENT_CC_REQUEST {
/*
* Before event is posted:
* cc_record->is_ccnr is set.
* The signaling connection call record is created.
*/
Action Queue_CC_Request;
/*
* For PTP mode the T_ACTIVATE timer is not defined. However,
* we will use it to protect our resources from leaks caused
* by the network cable being disconnected.
* This timer should be set longer than normal so the
* CC records will normally be cleaned up by network activity.
*/
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Epilog {
Action Stop_T_ACTIVATE;
}
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received CCBS-T-Request/CCNR-T-Request response
* Before event is posted:
* Negotiated CC retention setting saved
*/
Action Pass_Up_CC_Req_Rsp_Success;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
/*
* If this request fail comes in with the RELEASE_COMPLETE
* message then the post action will never get a chance to
* run. It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Prolog {
Action Reset_A_Status;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received CCBS_T_RemoteUserFree */
Action Pass_Up_Remote_User_Free;
Test = Get_A_Status;
Test == Busy {
Next_State CC_STATE_SUSPENDED;
}
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
Action Reset_A_Status;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
Next_State CC_STATE_SUSPENDED;
}
}
State CC_STATE_SUSPENDED {
Prolog {
Action Send_CC_Suspend;
}
Stimulus CC_EVENT_RESUME {
Action Send_CC_Resume;
Next_State CC_STATE_ACTIVATED;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_SUSPENDED) {
Prolog {
/* Start T_CCBS6/T_CCNR6 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
}

View File

@ -0,0 +1,217 @@
/*
* FSM pseudo code used in the design/implementation of the CC PTP monitor.
*/
FSM CC_PTP_Monitor
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
/* Received CCBS-T-Aailable */
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering.
*/
Stimulus CC_EVENT_CC_REQUEST {
/*
* Before event is posted:
* cc_record->is_ccnr is set.
* The signaling connection call record is created.
*/
Action Queue_CC_Request;
/*
* For PTP mode the T_ACTIVATE timer is not defined. However,
* we will use it to protect our resources from leaks caused
* by the network cable being disconnected.
* This timer should be set longer than normal so the
* CC records will normally be cleaned up by network activity.
*/
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received CCBS-T-Request/CCNR-T-Request response
* Before event is posted:
* Negotiated CC retention setting saved
*/
Action Pass_Up_CC_Req_Rsp_Success;
Action Stop_T_ACTIVATE;
/* Start T_CCBS6/T_CCNR6 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
/*
* If this request fail comes in with the RELEASE_COMPLETE
* message then the post action will never get a chance to
* run. It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
Action Stop_T_ACTIVATE;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received CCBS_T_RemoteUserFree */
Action Pass_Up_Remote_User_Free;
Test = Get_A_Status;
Test == Busy {
Action Send_CC_Suspend;
Next_State CC_STATE_SUSPENDED;
}
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
Action Reset_A_Status;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
Action Send_CC_Suspend;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
Action Send_CC_Resume;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

136
doc/cc_qsig_agent.fsm Normal file
View File

@ -0,0 +1,136 @@
/*
* FSM pseudo code used in the design/implementation of the CC Q.SIG agent.
*/
FSM CC_QSIG_Agent
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* For Q.SIG mode the T_RETENTION timer is not defined. However,
* we will use it anyway in this state to protect our resources
* from leaks caused by user A not requesting CC. This timer
* should be set much longer than the PTMP network link to
* allow for variations in user A's CC offer timer.
*/
Epilog {
Action Stop_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
/* Send Q931_CALL_PROCEEDING message on signaling link. */
Action Send_Call_Proceeding;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Send ccExecPossible in FACILITY or SETUP. */
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
/* Received ccSuspend */
Action Set_A_Status_Busy;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_RECALL {
/* Received ccRingout */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
/* Received ccResume */
Action Set_A_Status_Free;
Action Pass_Up_A_Status;
Next_State CC_STATE_ACTIVATED;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_SUSPENDED) {
Prolog {
/* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
}

View File

@ -0,0 +1,183 @@
/*
* FSM pseudo code used in the design/implementation of the CC Q.SIG agent.
*/
FSM CC_QSIG_Agent
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* For Q.SIG mode the T_RETENTION timer is not defined. However,
* we will use it anyway in this state to protect our resources
* from leaks caused by user A not requesting CC. This timer
* should be set much longer than the PTMP network link to
* allow for variations in user A's CC offer timer.
*/
Stimulus CC_EVENT_MSG_RELEASE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_MSG_RELEASE_COMPLETE {
Action Stop_T_RETENTION;
Action Start_T_RETENTION;
}
Stimulus CC_EVENT_CC_REQUEST {
Action Pass_Up_CC_Request;
/* Send Q931_CALL_PROCEEDING message on signaling link. */
Action Send_Call_Proceeding;
Action Stop_T_RETENTION;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_TIMEOUT_T_RETENTION {
Action Pass_Up_CC_Cancel;
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Stop_T_RETENTION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
Action Start_T_SUPERVISION;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Send ccExecPossible in FACILITY or SETUP. */
Action Send_RemoteUserFree;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_SUSPEND {
/* Received ccSuspend */
Action Set_A_Status_Busy;
Action Pass_Up_A_Status;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_RECALL {
/* Received ccRingout */
Action Pass_Up_CC_Call;
Action Set_Original_Call_Parameters;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
/* Received ccResume */
Action Set_A_Status_Free;
Action Pass_Up_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

249
doc/cc_qsig_monitor.fsm Normal file
View File

@ -0,0 +1,249 @@
/*
* FSM pseudo code used in the design/implementation of the CC Q.SIG monitor.
*/
FSM CC_QSIG_Monitor
{
State CC_STATE_IDLE {
Init {
}
Prolog {
Action Set_Selfdestruct;
}
Stimulus CC_EVENT_AVAILABLE {
/*
* LibPRI will determine if CC will be offered based upon
* if it is even possible.
* Essentially:
* 1) The call must not have been redirected in this link's
* setup.
* 2) Received an ALERTING or received a
* DISCONNECT(busy/congestion).
*/
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering.
*/
Stimulus CC_EVENT_CC_REQUEST {
/*
* Before event is posted:
* cc_record->is_ccnr is set.
* The signaling connection call record is created.
*/
Action Queue_CC_Request;
/* Start QSIG_CC_T1. */
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received ccbsRequest/ccnrRequest response
* Before event is posted:
* Negotiated CC retention setting saved
* Negotiated signaling link retention setting saved
*/
Action Stop_T_ACTIVATE;
Test = Get_msgtype;
Test == Q931_RELEASE {
Action Disassociate_Signaling_Link;
Test = Get_Retain_Signaling_Link;
Test == TRUE {
/*
* The far end did not honor the
* signaling link retention requirement.
* ECMA-186 Section 6.5.2.2.1
*/
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
Action Pass_Up_CC_Req_Rsp_Success;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
/*
* If this request fail comes in with the RELEASE message
* then the post action will never get a chance to run.
* It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
Action Stop_T_ACTIVATE;
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_WAIT_DESTRUCTION;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received ccbsRequest/ccnrRequest response
* Before event is posted:
* Negotiated CC retention setting saved
* Negotiated signaling link retention setting saved
*/
Action Stop_T_ACTIVATE;
Test = Get_msgtype;
Test == Q931_RELEASE {
Action Disassociate_Signaling_Link;
}
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
/*
* If this request fail comes in with the RELEASE message
* then the post action will never get a chance to run.
* It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Stop_T_ACTIVATE;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
//Action Stop_T_ACTIVATE;
Action Hangup_Signaling_Link;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Prolog {
Action Reset_A_Status;
}
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received ccExecPossible */
Action Pass_Up_Remote_User_Free;
/*
* ECMA-186 Section 6.5.2.1.7
* Implied switch to retain-signaling-link.
*/
Action Set_Retain_Signaling_Link;
Test = Get_msgtype;
Test == Q931_SETUP {
/* Send Q931_CALL_PROCEEDING message on signaling link. */
Action Send_Call_Proceeding;
}
Test = Get_A_Status;
Test == Busy {
Next_State CC_STATE_SUSPENDED;
}
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
Action Reset_A_Status;
}
}
State CC_STATE_WAIT_CALLBACK {
Prolog {
/* Start QSIG_CC_T3 */
Action Start_T_RECALL;
}
Epilog {
Action Stop_T_RECALL;
}
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_TIMEOUT_T_RECALL {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_CALLBACK {
}
State CC_STATE_SUSPENDED {
Prolog {
/*
* The ccSuspend will be sent in a FACILITY or CONNECT
* message depending upon the CIS call state.
*/
Action Send_CC_Suspend;
}
Stimulus CC_EVENT_RESUME {
Action Send_CC_Resume;
Next_State CC_STATE_ACTIVATED;
}
}
Superstate CC_ACTIVE(CC_STATE_ACTIVATED, CC_STATE_WAIT_CALLBACK, CC_STATE_CALLBACK, CC_STATE_SUSPENDED) {
Prolog {
/* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
Action Start_T_SUPERVISION;
}
Epilog {
Action Stop_T_SUPERVISION;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Next_State CC_STATE_IDLE;
}
}
}

View File

@ -0,0 +1,327 @@
/*
* FSM pseudo code used in the design/implementation of the CC Q.SIG monitor.
*/
FSM CC_QSIG_Monitor
{
State CC_STATE_IDLE {
Stimulus CC_EVENT_AVAILABLE {
/*
* LibPRI will determine if CC will be offered based upon
* if it is even possible.
* Essentially:
* 1) The call must not have been redirected in this link's
* setup.
* 2) Received an ALERTING or received a
* DISCONNECT(busy/congestion).
*/
Action Pass_Up_CC_Available;
Next_State CC_STATE_AVAILABLE;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
}
}
State CC_STATE_AVAILABLE {
/*
* The upper layer is responsible for canceling the CC available
* offering.
*/
Stimulus CC_EVENT_CC_REQUEST {
/*
* Before event is posted:
* cc_record->is_ccnr is set.
* The signaling connection call record is created.
*/
Action Queue_CC_Request;
/* Start QSIG_CC_T1. */
Action Start_T_ACTIVATE;
Next_State CC_STATE_REQUESTED;
}
Stimulus CC_EVENT_CANCEL {
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_REQUESTED {
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received ccbsRequest/ccnrRequest response
* Before event is posted:
* Negotiated CC retention setting saved
* Negotiated signaling link retention setting saved
*/
Action Stop_T_ACTIVATE;
Test = Get_msgtype;
Test == Q931_RELEASE {
Action Disassociate_Signaling_Link;
Test = Get_Retain_Signaling_Link;
Test == TRUE {
/*
* The far end did not honor the
* signaling link retention requirement.
* ECMA-186 Section 6.5.2.2.1
*/
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
Action Pass_Up_CC_Req_Rsp_Success;
/* Start QSIG_CCBS_T2/QSIG_CCNR_T2 depending upon CC mode. */
Action Start_T_SUPERVISION;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
Action Pass_Up_CC_Req_Rsp_Fail(error/reject, code);
Action Pass_Up_CC_Cancel;
/*
* If this request fail comes in with the RELEASE message
* then the post action will never get a chance to run.
* It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
Action Stop_T_ACTIVATE;
/* Claim it was a timeout */
Action Pass_Up_CC_Req_Rsp_Timeout;
Action Pass_Up_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CANCEL {
Next_State CC_STATE_WAIT_DESTRUCTION;
}
}
State CC_STATE_WAIT_DESTRUCTION {
/*
* Delayed disconnect of the signaling link to allow subcmd events
* from the signaling link to be passed up.
*/
Stimulus CC_EVENT_CC_REQUEST_ACCEPT {
/*
* Received ccbsRequest/ccnrRequest response
* Before event is posted:
* Negotiated CC retention setting saved
* Negotiated signaling link retention setting saved
*/
Action Stop_T_ACTIVATE;
Test = Get_msgtype;
Test == Q931_RELEASE {
Action Disassociate_Signaling_Link;
}
Action Send_CC_Cancel;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_CC_REQUEST_FAIL {
Action Stop_T_ACTIVATE;
/*
* If this request fail comes in with the RELEASE message
* then the post action will never get a chance to run.
* It will be aborted because the CC_EVENT_SIGNALING_GONE
* will be processed first.
*/
Action Post_HANGUP_SIGNALING;
}
Stimulus CC_EVENT_TIMEOUT_T_ACTIVATE {
Action Stop_T_ACTIVATE;
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Stop_T_ACTIVATE;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_HANGUP_SIGNALING {
//Action Stop_T_ACTIVATE;
Action Hangup_Signaling_Link;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_ACTIVATED {
Stimulus CC_EVENT_REMOTE_USER_FREE {
/* Received ccExecPossible */
Action Pass_Up_Remote_User_Free;
/*
* ECMA-186 Section 6.5.2.1.7
* Implied switch to retain-signaling-link.
*/
Action Set_Retain_Signaling_Link;
Test = Get_msgtype;
Test == Q931_SETUP {
/* Send Q931_CALL_PROCEEDING message on signaling link. */
Action Send_Call_Proceeding;
}
Test = Get_A_Status;
Test == Busy {
/*
* The ccSuspend will be sent in a FACILITY or CONNECT
* message depending upon the CIS call state.
*/
Action Send_CC_Suspend;
Next_State CC_STATE_SUSPENDED;
}
/* Start QSIG_CC_T3 */
Action Start_T_RECALL;
Next_State CC_STATE_WAIT_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Set_A_Status_Busy;
}
Stimulus CC_EVENT_RESUME {
Action Reset_A_Status;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_WAIT_CALLBACK {
Stimulus CC_EVENT_RECALL {
/* The original call parameters have already been set. */
Action Queue_SETUP_Recall;
Action Stop_T_RECALL;
Next_State CC_STATE_CALLBACK;
}
Stimulus CC_EVENT_SUSPEND {
Action Stop_T_RECALL;
/*
* The ccSuspend will be sent in a FACILITY or CONNECT
* message depending upon the CIS call state.
*/
Action Send_CC_Suspend;
Next_State CC_STATE_SUSPENDED;
}
Stimulus CC_EVENT_TIMEOUT_T_RECALL {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_RECALL;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_CALLBACK {
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
State CC_STATE_SUSPENDED {
Stimulus CC_EVENT_RESUME {
Action Send_CC_Resume;
Action Reset_A_Status;
Next_State CC_STATE_ACTIVATED;
}
Stimulus CC_EVENT_TIMEOUT_T_SUPERVISION {
Action Pass_Up_CC_Cancel;
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
Stimulus CC_EVENT_SIGNALING_GONE {
/* Signaling link cleared. */
Action Disassociate_Signaling_Link;
}
Stimulus CC_EVENT_LINK_CANCEL {
/* Received ccCancel */
Action Pass_Up_CC_Cancel;
Action Post_HANGUP_SIGNALING;
Action Stop_T_SUPERVISION;
Next_State CC_STATE_WAIT_DESTRUCTION;
}
Stimulus CC_EVENT_CANCEL {
Action Send_CC_Cancel;
Action Stop_T_SUPERVISION;
Action Set_Selfdestruct;
Next_State CC_STATE_IDLE;
}
}
}

250
libpri.h
View File

@ -51,6 +51,7 @@
#define PRI_DEBUG_Q931_ANOMALY (1 << 7) /* Show unexpected events */
#define PRI_DEBUG_APDU (1 << 8) /* Debug of APDU components such as ROSE */
#define PRI_DEBUG_AOC (1 << 9) /* Debug of Advice of Charge ROSE Messages */
#define PRI_DEBUG_CC (1 << 10) /* Debug call-completion. */
#define PRI_DEBUG_ALL (0xffff) /* Everything */
@ -439,6 +440,14 @@ struct pri_party_subaddress {
unsigned char data[32];
};
/*! \brief Addressing information needed to identify an endpoint in a call. */
struct pri_party_address {
/*! \brief Subscriber phone number */
struct pri_party_number number;
/*! \brief Subscriber subaddress */
struct pri_party_subaddress subaddress;
};
/*! \brief Information needed to identify an endpoint in a call. */
struct pri_party_id {
/*! \brief Subscriber name */
@ -503,11 +512,127 @@ struct pri_rerouting_data {
int invoke_id;
};
/* Subcommands derived from supplementary services. */
#define PRI_SUBCMD_REDIRECTING 1
#define PRI_SUBCMD_CONNECTED_LINE 2
#define PRI_SUBCMD_REROUTING 3
/*
* NOTE:
* The code surrounded by STATUS_REQUEST_PLACE_HOLDER is not implemented.
* The STATUS_REQUEST_PLACE_HOLDER code will be made unconditional if support
* for the messages is ever needed (and gets written).
*/
/* Subcommands derived from supplementary services. */
#define PRI_SUBCMD_REDIRECTING 1 /*!< Redirecting information update */
#define PRI_SUBCMD_CONNECTED_LINE 2 /*!< Connected line information update */
#define PRI_SUBCMD_REROUTING 3 /*!< CallRerouting/CallDeflection received. */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
#define PRI_SUBCMD_STATUS_REQ 4 /*!< Determine the status of the given party. */
#define PRI_SUBCMD_STATUS_REQ_RSP 5 /*!< Status request response */
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#define PRI_SUBCMD_CC_AVAILABLE 6 /*!< Indicate that CC is available */
#define PRI_SUBCMD_CC_REQ 7 /*!< CC activation request */
#define PRI_SUBCMD_CC_REQ_RSP 8 /*!< CC activation request response */
#define PRI_SUBCMD_CC_REMOTE_USER_FREE 9 /*!< Indicate that CC party B is available, party A is considered free. */
#define PRI_SUBCMD_CC_B_FREE 10 /*!< Indicate that CC party B is available, party A is considered busy. */
#define PRI_SUBCMD_CC_STATUS_REQ 11 /*!< Request/prod to receive updates of CC party A status */
#define PRI_SUBCMD_CC_STATUS_REQ_RSP 12 /*!< Requested update of CC party A status */
#define PRI_SUBCMD_CC_STATUS 13 /*!< Unsolicited update of CC party A status */
#define PRI_SUBCMD_CC_CALL 14 /*!< Indicate that this call is a CC callback */
#define PRI_SUBCMD_CC_CANCEL 15 /*!< Unsolicited indication that CC is canceled */
#define PRI_SUBCMD_CC_STOP_ALERTING 16 /*!< Indicate that someone else has responed to remote user free */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
struct pri_subcmd_status_request {
/*!
* \brief Invoke id in case there are multiple outstanding requests.
* \note Used to match any responses with the original invoke in case
* there are several requests active.
*/
int invoke_id;
/*! \brief Party address requesting status about. */
struct pri_party_address party;
};
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
struct pri_subcmd_status_request_rsp {
/*!
* \brief Request id in case there are multiple outstanding requests.
* \note Used to match any responses with the request in case there
* are several requests active.
*/
int request_id;
/*!
* \brief Response status to the status request.
* \details
* free(0),
* busy(1),
* incompatible(2)
* timeout(3),
*/
int status;
};
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
struct pri_subcmd_cc_id {
/*! \brief Call-Completion record id */
long cc_id;
};
struct pri_subcmd_cc_request {
/*! \brief Call-Completion record id */
long cc_id;
/*!
* \brief Mode of call-completion requested.
* \details
* ccbs(0),
* ccnr(1)
*/
int mode;
};
struct pri_subcmd_cc_request_rsp {
/*! \brief Call-Completion record id */
long cc_id;
/*!
* \brief Status of the requested call-completion activation.
* \details
* success(0),
* timeout(1),
* error(2),
* reject(3)
*/
int status;
/*!
* \brief Failure code that can be converted to a string to further
* explain the non-timeout failure.
* \note Valid when status is error or reject.
* \note Use pri_facility_error2str() to convert the error_code.
* \note Use pri_facility_reject2str() to convert the reject_code.
*/
int fail_code;
};
struct pri_subcmd_cc_status {
/*! \brief Call-Completion record id */
long cc_id;
/*!
* \brief Party A status.
* \details
* free(0),
* busy(1)
*/
int status;
};
struct pri_subcmd_cc_cancel {
/*! \brief Call-Completion record id */
long cc_id;
/*!
* \brief TRUE if the cc_id is for an agent.
* \note This is a convenience value so the upper layer can know which
* list it should search for the cc_id.
*/
int is_agent;
};
struct pri_subcommand {
/*! PRI_SUBCMD_xxx defined values */
@ -518,6 +643,21 @@ struct pri_subcommand {
struct pri_party_connected_line connected_line;
struct pri_party_redirecting redirecting;
struct pri_rerouting_data rerouting;
#if defined(STATUS_REQUEST_PLACE_HOLDER)
struct pri_subcmd_status_request status_request;
struct pri_subcmd_status_request_rsp status_request_rsp;
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
struct pri_subcmd_cc_id cc_available;
struct pri_subcmd_cc_request cc_request;
struct pri_subcmd_cc_request_rsp cc_request_rsp;
struct pri_subcmd_cc_id cc_remote_user_free;
struct pri_subcmd_cc_id cc_b_free;
struct pri_subcmd_cc_id cc_stop_alerting;
struct pri_subcmd_cc_id cc_status_req;
struct pri_subcmd_cc_status cc_status_req_rsp;
struct pri_subcmd_cc_status cc_status;
struct pri_subcmd_cc_id cc_call;
struct pri_subcmd_cc_cancel cc_cancel;
} u;
};
@ -867,6 +1007,24 @@ char *pri_plan2str(int plan);
/* Turn cause into a string */
char *pri_cause2str(int cause);
/*!
* \brief Convert the given facility error code to a descriptive string.
*
* \param facility_error_code Error code to convert to a string.
*
* \return Descriptive error string.
*/
const char *pri_facility_error2str(int facility_error_code);
/*!
* \brief Convert the given facility reject code to a descriptive string.
*
* \param facility_reject_code Error code to convert to a string.
*
* \return Descriptive reject string.
*/
const char *pri_facility_reject2str(int facility_reject_code);
/* Acknowledge a call and place it on the given channel. Set info to non-zero if there
is in-band data available on the channel */
int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
@ -1262,6 +1420,65 @@ int pri_retrieve_ack(struct pri *ctrl, q931_call *call, int channel);
*/
int pri_retrieve_rej(struct pri *ctrl, q931_call *call, int cause);
#if defined(STATUS_REQUEST_PLACE_HOLDER)
int pri_status_req(struct pri *ctrl, int request_id, const struct pri_sr *req);
void pri_status_req_rsp(struct pri *ctrl, int invoke_id, int status);
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
/*!
* \brief Set the call completion feature enable flag.
*
* \param ctrl D channel controller.
* \param enable TRUE to enable call completion feature.
*
* \return Nothing
*/
void pri_cc_enable(struct pri *ctrl, int enable);
/*!
* \brief Set the PTMP NT call completion recall mode.
*
* \param ctrl D channel controller.
* \param mode globalRecall(0), specificRecall(1)
*
* \return Nothing
*/
void pri_cc_recall_mode(struct pri *ctrl, int mode);
/*!
* \brief Set the Q.SIG call completion signaling link retention mode.
* (Requestor/Initiator/Originator/Party-A)
*
* \param ctrl D channel controller.
* \param signaling_retention release(0), retain(1), do-not-care(2).
*
* \return Nothing
*/
void pri_cc_retain_signaling_req(struct pri *ctrl, int signaling_retention);
/*!
* \brief Set the Q.SIG call completion signaling link retention mode.
* (Responder/Answerer/Party-B)
*
* \param ctrl D channel controller.
* \param signaling_retention release(0), retain(1).
*
* \return Nothing
*/
void pri_cc_retain_signaling_rsp(struct pri *ctrl, int signaling_retention);
long pri_cc_available(struct pri *ctrl, q931_call *call);
int pri_cc_req(struct pri *ctrl, long cc_id, int mode);
int pri_cc_req_rsp(struct pri *ctrl, long cc_id, int status);
void pri_cc_remote_user_free(struct pri *ctrl, long cc_id);
void pri_cc_b_free(struct pri *ctrl, long cc_id);
void pri_cc_stop_alerting(struct pri *ctrl, long cc_id);
void pri_cc_status_req(struct pri *ctrl, long cc_id);
void pri_cc_status_req_rsp(struct pri *ctrl, long cc_id, int status);
void pri_cc_status(struct pri *ctrl, long cc_id, int status);
int pri_cc_call(struct pri *ctrl, long cc_id, q931_call *call, struct pri_sr *req);
void pri_cc_cancel(struct pri *ctrl, long cc_id);
/* Get/Set PRI Timers */
#define PRI_GETSET_TIMERS
int pri_set_timer(struct pri *pri, int timer, int value);
@ -1309,6 +1526,31 @@ enum PRI_TIMERS_AND_COUNTERS {
PRI_TIMER_T_RESPONSE, /*!< Maximum time to wait for a typical APDU response. */
PRI_TIMER_T_STATUS, /*!< Max time to wait for all replies to check for compatible terminals */
PRI_TIMER_T_ACTIVATE, /*!< Request supervision timeout. */
PRI_TIMER_T_DEACTIVATE, /*!< Deactivate supervision timeout. */
PRI_TIMER_T_INTERROGATE,/*!< Interrogation supervision timeout. */
/* ETSI call-completion timers */
PRI_TIMER_T_RETENTION, /*!< Max time to wait for user A to activate call-completion. */
PRI_TIMER_T_CCBS1, /*!< T-STATUS timer equivalent for CC user A status. */
PRI_TIMER_T_CCBS2, /*!< Max time the CCBS service will be active */
PRI_TIMER_T_CCBS3, /*!< Max time to wait for user A to respond to user B availability. */
PRI_TIMER_T_CCBS4, /*!< CC user B guard time before sending CC recall indication. */
PRI_TIMER_T_CCBS5, /*!< Network B CCBS supervision timeout. */
PRI_TIMER_T_CCBS6, /*!< Network A CCBS supervision timeout. */
PRI_TIMER_T_CCNR2, /*!< Max time the CCNR service will be active */
PRI_TIMER_T_CCNR5, /*!< Network B CCNR supervision timeout. */
PRI_TIMER_T_CCNR6, /*!< Network A CCNR supervision timeout. */
/* Q.SIG call-completion timers */
PRI_TIMER_QSIG_CC_T1, /*!< CC request supervision timeout. */
PRI_TIMER_QSIG_CCBS_T2, /*!< CCBS supervision timeout. */
PRI_TIMER_QSIG_CCNR_T2, /*!< CCNR supervision timeout. */
PRI_TIMER_QSIG_CC_T3, /*!< Max time to wait for user A to respond to user B availability. */
PRI_TIMER_QSIG_CC_T4, /*!< Path reservation supervision timeout. */
/* Must be last in the enum list */
PRI_MAX_TIMERS
};

134
pri.c
View File

@ -40,11 +40,10 @@
#include "libpri.h"
#include "pri_internal.h"
#include "pri_facility.h"
#include "pri_q921.h"
#include "pri_q931.h"
#define PRI_BIT(a_bit) (1UL << (a_bit))
#define PRI_ALL_SWITCHES 0xFFFFFFFF
#define PRI_ETSI_SWITCHES (PRI_BIT(PRI_SWITCH_EUROISDN_E1) | PRI_BIT(PRI_SWITCH_EUROISDN_T1))
struct pri_timer_table {
const char *name;
@ -89,6 +88,27 @@ static const struct pri_timer_table pri_timer[] = {
{ "T-HOLD", PRI_TIMER_T_HOLD, PRI_ALL_SWITCHES },
{ "T-RETRIEVE", PRI_TIMER_T_RETRIEVE, PRI_ALL_SWITCHES },
{ "T-RESPONSE", PRI_TIMER_T_RESPONSE, PRI_ALL_SWITCHES },
{ "T-STATUS", PRI_TIMER_T_STATUS, PRI_ETSI_SWITCHES },
{ "T-ACTIVATE", PRI_TIMER_T_ACTIVATE, PRI_ETSI_SWITCHES },
{ "T-DEACTIVATE", PRI_TIMER_T_DEACTIVATE, PRI_ETSI_SWITCHES },
{ "T-INTERROGATE", PRI_TIMER_T_INTERROGATE, PRI_ETSI_SWITCHES },
{ "T-RETENTION", PRI_TIMER_T_RETENTION, PRI_ETSI_SWITCHES | PRI_BIT(PRI_SWITCH_QSIG) },
{ "T-CCBS1", PRI_TIMER_T_CCBS1, PRI_ETSI_SWITCHES },
{ "T-CCBS2", PRI_TIMER_T_CCBS2, PRI_ETSI_SWITCHES },
{ "T-CCBS3", PRI_TIMER_T_CCBS3, PRI_ETSI_SWITCHES },
{ "T-CCBS4", PRI_TIMER_T_CCBS4, PRI_ETSI_SWITCHES },
{ "T-CCBS5", PRI_TIMER_T_CCBS5, PRI_ETSI_SWITCHES },
{ "T-CCBS6", PRI_TIMER_T_CCBS6, PRI_ETSI_SWITCHES },
{ "T-CCNR2", PRI_TIMER_T_CCNR2, PRI_ETSI_SWITCHES },
{ "T-CCNR5", PRI_TIMER_T_CCNR5, PRI_ETSI_SWITCHES },
{ "T-CCNR6", PRI_TIMER_T_CCNR6, PRI_ETSI_SWITCHES },
{ "CC-T1", PRI_TIMER_QSIG_CC_T1, PRI_BIT(PRI_SWITCH_QSIG) },
{ "CCBS-T2", PRI_TIMER_QSIG_CCBS_T2, PRI_BIT(PRI_SWITCH_QSIG) },
{ "CCNR-T2", PRI_TIMER_QSIG_CCNR_T2, PRI_BIT(PRI_SWITCH_QSIG) },
{ "CC-T3", PRI_TIMER_QSIG_CC_T3, PRI_BIT(PRI_SWITCH_QSIG) },
#if defined(QSIG_PATH_RESERVATION_SUPPORT)
{ "CC-T4", PRI_TIMER_QSIG_CC_T4, PRI_BIT(PRI_SWITCH_QSIG) },
#endif /* defined(QSIG_PATH_RESERVATION_SUPPORT) */
/* *INDENT-ON* */
};
@ -166,6 +186,33 @@ static void pri_default_timers(struct pri *ctrl, int switchtype)
ctrl->timers[PRI_TIMER_T_RESPONSE] = 4 * 1000; /* Maximum time to wait for a typical APDU response. */
/* ETSI timers */
ctrl->timers[PRI_TIMER_T_STATUS] = 4 * 1000; /* Max time to wait for all replies to check for compatible terminals */
ctrl->timers[PRI_TIMER_T_ACTIVATE] = 10 * 1000; /* Request supervision timeout. */
ctrl->timers[PRI_TIMER_T_DEACTIVATE] = 4 * 1000;/* Deactivate supervision timeout. */
ctrl->timers[PRI_TIMER_T_INTERROGATE] = 4 * 1000;/* Interrogation supervision timeout. */
/* ETSI call-completion timers */
ctrl->timers[PRI_TIMER_T_RETENTION] = 30 * 1000;/* Max time to wait for user A to activate call-completion. */
ctrl->timers[PRI_TIMER_T_CCBS1] = 4 * 1000; /* T-STATUS timer equivalent for CC user A status. */
ctrl->timers[PRI_TIMER_T_CCBS2] = 45 * 60 * 1000;/* Max time the CCBS service will be active */
ctrl->timers[PRI_TIMER_T_CCBS3] = 20 * 1000; /* Max time to wait for user A to respond to user B availability. */
ctrl->timers[PRI_TIMER_T_CCBS4] = 5 * 1000; /* CC user B guard time before sending CC recall indication. */
ctrl->timers[PRI_TIMER_T_CCBS5] = 60 * 60 * 1000;/* Network B CCBS supervision timeout. */
ctrl->timers[PRI_TIMER_T_CCBS6] = 60 * 60 * 1000;/* Network A CCBS supervision timeout. */
ctrl->timers[PRI_TIMER_T_CCNR2] = 180 * 60 * 1000;/* Max time the CCNR service will be active */
ctrl->timers[PRI_TIMER_T_CCNR5] = 195 * 60 * 1000;/* Network B CCNR supervision timeout. */
ctrl->timers[PRI_TIMER_T_CCNR6] = 195 * 60 * 1000;/* Network A CCNR supervision timeout. */
/* Q.SIG call-completion timers */
ctrl->timers[PRI_TIMER_QSIG_CC_T1] = 30 * 1000;/* CC request supervision timeout. */
ctrl->timers[PRI_TIMER_QSIG_CCBS_T2] = 60 * 60 * 1000;/* CCBS supervision timeout. */
ctrl->timers[PRI_TIMER_QSIG_CCNR_T2] = 195 * 60 * 1000;/* CCNR supervision timeout. */
ctrl->timers[PRI_TIMER_QSIG_CC_T3] = 30 * 1000;/* Max time to wait for user A to respond to user B availability. */
#if defined(QSIG_PATH_RESERVATION_SUPPORT)
ctrl->timers[PRI_TIMER_QSIG_CC_T4] = 40 * 1000;/* Path reservation supervision timeout. */
#endif /* defined(QSIG_PATH_RESERVATION_SUPPORT) */
/* Set any switch specific override default values */
switch (switchtype) {
default:
@ -246,6 +293,7 @@ void __pri_free_tei(struct pri * p)
pri_call_apdu_queue_cleanup(call);
}
free(p->msg_line);
free(p->sched.timer);
free(p);
}
}
@ -903,6 +951,52 @@ int pri_redirecting_update(struct pri *ctrl, q931_call *call, const struct pri_p
return 0;
}
#if defined(STATUS_REQUEST_PLACE_HOLDER)
/*!
* \brief Poll/ping for the status of any "called" party.
*
* \param ctrl D channel controller.
* \param request_id The upper layer's ID number to match with the response in case
* there are several requests at the same time.
* \param req Setup request for "called" party to determine the status.
*
* \note
* There could be one or more PRI_SUBCMD_STATUS_REQ_RSP to the status request
* depending upon how many endpoints respond to the request.
* (This includes the timeout termination response.)
* \note
* Could be used to poll for the status of call-completion party B.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int pri_status_req(struct pri *ctrl, int request_id, const struct pri_sr *req)
{
return -1;
}
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#if defined(STATUS_REQUEST_PLACE_HOLDER)
/*!
* \brief Response to a poll/ping request for status of any "called" party by libpri.
*
* \param ctrl D channel controller.
* \param invoke_id ID given by libpri when it requested the party status.
* \param status free(0)/busy(1)/incompatible(2)
*
* \note
* There could be zero, one, or more responses to the original
* status request depending upon how many endpoints respond to the request.
* \note
* Could be used to poll for the status of call-completion party B.
*
* \return Nothing
*/
void pri_status_req_rsp(struct pri *ctrl, int invoke_id, int status)
{
}
#endif /* defined(STATUS_REQUEST_PLACE_HOLDER) */
#if 0
/* deprecated routines, use pri_hangup */
int pri_release(struct pri *pri, q931_call *call, int cause)
@ -930,7 +1024,7 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2)
return -1;
/* Check for bearer capability */
if (call1->transcapability != call2->transcapability)
if (call1->bc.transcapability != call2->bc.transcapability)
return -1;
/* Check to see if we're on the same PRI */
@ -1040,7 +1134,7 @@ void pri_dump_event(struct pri *pri, pri_event *e)
}
}
static void pri_sr_init(struct pri_sr *req)
void pri_sr_init(struct pri_sr *req)
{
memset(req, 0, sizeof(struct pri_sr));
q931_party_redirecting_init(&req->redirecting);
@ -1618,3 +1712,35 @@ int pri_reroute_call(struct pri *ctrl, q931_call *call, const struct pri_party_i
return send_reroute_request(ctrl, call, caller_id, &reroute, subscription_option);
}
void pri_cc_enable(struct pri *ctrl, int enable)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->cc_support = enable ? 1 : 0;
}
}
void pri_cc_recall_mode(struct pri *ctrl, int mode)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->cc.option.recall_mode = mode ? 1 : 0;
}
}
void pri_cc_retain_signaling_req(struct pri *ctrl, int signaling_retention)
{
if (ctrl && 0 <= signaling_retention && signaling_retention < 3) {
ctrl = PRI_MASTER(ctrl);
ctrl->cc.option.signaling_retention_req = signaling_retention;
}
}
void pri_cc_retain_signaling_rsp(struct pri *ctrl, int signaling_retention)
{
if (ctrl) {
ctrl = PRI_MASTER(ctrl);
ctrl->cc.option.signaling_retention_rsp = signaling_retention ? 1 : 0;
}
}

7872
pri_cc.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -30,13 +30,7 @@
#ifndef _PRI_FACILITY_H
#define _PRI_FACILITY_H
#include "pri_q931.h"
/* Forward declare some structs */
struct fac_extension_header;
struct rose_msg_invoke;
struct rose_msg_result;
struct rose_msg_error;
struct rose_msg_reject;
#include "rose.h"
/* Protocol Profile field */
#define Q932_PROTOCOL_MASK 0x1F
@ -75,7 +69,7 @@ struct rose_msg_reject;
/*! Reasons an APDU callback is called. */
enum APDU_CALLBACK_REASON {
/*!
* \brief Send setup error. Abort and cleanup.
* \brief Transmit facility ie setup error. Abort and cleanup.
* \note The message may or may not actually get sent.
* \note The callback cannot generate an event subcmd.
* \note The callback should not send messages. Out of order messages will result.
@ -114,10 +108,15 @@ enum APDU_CALLBACK_REASON {
APDU_CALLBACK_REASON_MSG_REJECT,
};
union apdu_msg_data {
const struct rose_msg_result *result;
const struct rose_msg_error *error;
const struct rose_msg_reject *reject;
struct apdu_msg_data {
/*! Decoded response message contents. */
union {
const struct rose_msg_result *result;
const struct rose_msg_error *error;
const struct rose_msg_reject *reject;
} response;
/*! Q.931 message type the response came in with. */
int type;
};
union apdu_callback_param {
@ -126,6 +125,9 @@ union apdu_callback_param {
char pad[8];
};
/* So calls to pri_call_apdu_find() will not find an aliased event. */
#define APDU_INVALID_INVOKE_ID 0x10000
struct apdu_callback_data {
/*! APDU invoke id to match with any response messages. (Result/Error/Reject) */
int invoke_id;
@ -149,7 +151,7 @@ struct apdu_callback_data {
*
* \return TRUE if no more responses are expected.
*/
int (*callback)(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const union apdu_msg_data *msg);
int (*callback)(enum APDU_CALLBACK_REASON reason, struct pri *ctrl, struct q931_call *call, struct apdu_event *apdu, const struct apdu_msg_data *msg);
/*! \brief Sender data for the callback function to identify the particular APDU. */
union apdu_callback_param user;
};
@ -173,6 +175,29 @@ struct apdu_event {
unsigned char apdu[255];
};
void rose_copy_number_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePartyNumber *rose_number);
void rose_copy_subaddress_to_q931(struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, const struct rosePartySubaddress *rose_subaddress);
void rose_copy_address_to_q931(struct pri *ctrl, struct q931_party_address *q931_address, const struct roseAddress *rose_address);
void rose_copy_address_to_id_q931(struct pri *ctrl, struct q931_party_id *q931_address, const struct roseAddress *rose_address);
void rose_copy_presented_number_screened_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePresentedNumberScreened *rose_presented);
void rose_copy_presented_number_unscreened_to_q931(struct pri *ctrl, struct q931_party_number *q931_number, const struct rosePresentedNumberUnscreened *rose_presented);
void rose_copy_presented_address_screened_to_id_q931(struct pri *ctrl, struct q931_party_id *q931_address, const struct rosePresentedAddressScreened *rose_presented);
void rose_copy_name_to_q931(struct pri *ctrl, struct q931_party_name *qsig_name, const struct roseQsigName *rose_name);
void q931_copy_number_to_rose(struct pri *ctrl, struct rosePartyNumber *rose_number, const struct q931_party_number *q931_number);
void q931_copy_subaddress_to_rose(struct pri *ctrl, struct rosePartySubaddress *rose_subaddress, const struct q931_party_subaddress *q931_subaddress);
void q931_copy_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address, const struct q931_party_address *q931_address);
void q931_copy_id_address_to_rose(struct pri *ctrl, struct roseAddress *rose_address, const struct q931_party_id *q931_address);
void q931_copy_presented_number_screened_to_rose(struct pri *ctrl, struct rosePresentedNumberScreened *rose_presented, const struct q931_party_number *q931_number);
void q931_copy_presented_number_unscreened_to_rose(struct pri *ctrl, struct rosePresentedNumberUnscreened *rose_presented, const struct q931_party_number *q931_number);
void q931_copy_presented_id_address_screened_to_rose(struct pri *ctrl, struct rosePresentedAddressScreened *rose_presented, const struct q931_party_id *q931_address);
void q931_copy_name_to_rose(struct pri *ctrl, struct roseQsigName *rose_name, const struct q931_party_name *qsig_name);
int rose_error_msg_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id, enum rose_error_code code);
int send_facility_error(struct pri *ctrl, q931_call *call, int invoke_id, enum rose_error_code code);
int rose_result_ok_encode(struct pri *ctrl, q931_call *call, int msgtype, int invoke_id);
int send_facility_result_ok(struct pri *ctrl, q931_call *call, int invoke_id);
/* Queues an MWI apdu on a the given call */
int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
@ -197,6 +222,8 @@ int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
int pri_call_apdu_queue(q931_call *call, int messagetype, const unsigned char *apdu, int apdu_len, struct apdu_callback_data *response);
void pri_call_apdu_queue_cleanup(q931_call *call);
struct apdu_event *pri_call_apdu_find(struct q931_call *call, int invoke_id);
int pri_call_apdu_extract(struct q931_call *call, struct apdu_event *extract);
void pri_call_apdu_delete(struct q931_call *call, struct apdu_event *doomed);
/* Adds the "standard" APDUs to a call */
@ -209,4 +236,11 @@ void rose_handle_result(struct pri *ctrl, q931_call *call, int msgtype, q931_ie
void rose_handle_error(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_error *error);
void rose_handle_reject(struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
int pri_cc_interrogate_rsp(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
void pri_cc_ptmp_request(struct pri *ctrl, q931_call *call, const struct rose_msg_invoke *invoke);
void pri_cc_ptp_request(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
void pri_cc_qsig_request(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
void pri_cc_qsig_cancel(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
void pri_cc_qsig_exec_possible(struct pri *ctrl, q931_call *call, int msgtype, const struct rose_msg_invoke *invoke);
#endif /* _PRI_FACILITY_H */

View File

@ -42,6 +42,7 @@
/* Forward declare some structs */
struct apdu_event;
struct pri_cc_record;
struct pri_sched {
struct timeval when;
@ -49,8 +50,12 @@ struct pri_sched {
void *data;
};
/*! Maximum number of scheduled events active at the same time. */
#define MAX_SCHED 128
/*
* libpri needs to be able to allocate B channels to support Q.SIG path reservation.
* Until that happens, path reservation is not possible. Fortunately,
* path reservation is optional with a fallback to what we can implement.
*/
//#define QSIG_PATH_RESERVATION_SUPPORT 1
/*! Maximum number of facility ie's to handle per incoming message. */
#define MAX_FACILITY_IES 8
@ -73,7 +78,14 @@ struct pri {
struct pri_msg_line *msg_line;
struct pri *subchannel; /* Sub-channel if appropriate */
struct pri *master; /* Master channel if appropriate */
struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */
struct {
/*! Dynamically allocated array of timers that can grow as needed. */
struct pri_sched *timer;
/*! Numer of timer slots in the allocated array of timers. */
unsigned num_slots;
/*! Maximum timer slots currently needed. */
unsigned max_used;
} sched;
int debug; /* Debug stuff */
int state; /* State of D-channel */
int switchtype; /* Switch type */
@ -93,6 +105,7 @@ struct pri {
unsigned int hold_support:1;/* TRUE if upper layer supports call hold. */
unsigned int deflection_support:1;/* TRUE if upper layer supports call deflection/rerouting. */
unsigned int hangup_fix_enabled:1;/* TRUE if should follow Q.931 Section 5.3.2 instead of blindly sending RELEASE_COMPLETE for certain causes */
unsigned int cc_support:1;/* TRUE if upper layer supports call completion. */
/* MDL variables */
int mdl_error;
@ -156,6 +169,31 @@ struct pri {
short last_invoke; /* Last ROSE invoke ID (Valid in master record only) */
/*! Call completion (Valid in master record only) */
struct {
/*! Active CC records */
struct pri_cc_record *pool;
/*! Last CC record id allocated. */
unsigned short last_record_id;
/*! Last CC PTMP reference id allocated. (0-127) */
unsigned char last_reference_id;
/*! Last CC PTMP linkage id allocated. (0-127) */
unsigned char last_linkage_id;
/*! Configured CC options. */
struct {
/*! PTMP recall mode: globalRecall(0), specificRecall(1) */
unsigned char recall_mode;
/*! Q.SIG Request signaling link retention: release(0), retain(1), do-not-care(2) */
unsigned char signaling_retention_req;
/*! Q.SIG Response request signaling link retention: release(0), retain(1) */
unsigned char signaling_retention_rsp;
#if defined(QSIG_PATH_RESERVATION_SUPPORT)
/*! Q.SIG TRUE if response request can support path reservation. */
unsigned char allow_path_reservation;
#endif /* defined(QSIG_PATH_RESERVATION_SUPPORT) */
} option;
} cc;
/*! For delayed processing of facility ie's. */
struct {
/*! Array of facility ie locations in the current received message. */
@ -370,6 +408,38 @@ enum Q931_HOLD_STATE {
Q931_HOLD_STATE_RETRIEVE_IND,
};
/* Only save the first of each BC, HLC, and LLC from the initial SETUP. */
#define CC_SAVED_IE_BC (1 << 0) /*!< BC has already been saved. */
#define CC_SAVED_IE_HLC (1 << 1) /*!< HLC has already been saved. */
#define CC_SAVED_IE_LLC (1 << 2) /*!< LLC has already been saved. */
/*! Saved ie contents for BC, HLC, and LLC. (Only the first of each is saved.) */
struct q931_saved_ie_contents {
/*! Length of saved ie contents. */
unsigned char length;
/*! Saved ie contents data. */
unsigned char data[
/* Bearer Capability has a max length of 12. */
12
/* High Layer Compatibility has a max length of 5. */
+ 5
/* Low Layer Compatibility has a max length of 18. */
+ 18
/* Room for null terminator just in case. */
+ 1];
};
/*! Digested BC parameters. */
struct decoded_bc {
int transcapability;
int transmoderate;
int transmultiple;
int userl1;
int userl2;
int userl3;
int rateadaption;
};
/* q931_call datastructure */
struct q931_call {
struct pri *pri; /* PRI */
@ -394,20 +464,21 @@ struct q931_call {
int ri; /* Restart Indicator (Restart Indicator IE) */
/* Bearer Capability */
int transcapability;
int transmoderate;
int transmultiple;
int userl1;
int userl2;
int userl3;
int rateadaption;
/*! Bearer Capability */
struct decoded_bc bc;
/*!
* \brief TRUE if the call is a Call Independent Signalling connection.
* \note The call has no B channel associated with it. (Just signalling)
*/
int cis_call;
/*!
* \brief TRUE if we have recognized a use for this CIS call.
* \note An incoming CIS call will be immediately disconnected if not set.
* This is a safeguard against unhandled incoming CIS calls to protect the
* call reference pool.
*/
int cis_recognized;
/*! \brief TRUE if we will auto disconnect the cis_call we originated. */
int cis_auto_disconnect;
@ -530,6 +601,261 @@ struct q931_call {
/* These valid in master call only */
struct q931_call *subcalls[Q931_MAX_TEI];
int pri_winner;
/* Call completion */
struct {
/*!
* \brief CC record associated with this call.
* \note
* CC signaling link or original call when cc-available indicated.
*/
struct pri_cc_record *record;
/*! Original calling party. */
struct q931_party_id party_a;
/*! Saved BC, HLC, and LLC from initial SETUP */
struct q931_saved_ie_contents saved_ie_contents;
/*! Only save the first of each BC, HLC, and LLC from the initial SETUP. */
unsigned char saved_ie_flags;
/*! TRUE if call needs to be hung up. */
unsigned char hangup_call;
/*! TRUE if we originated this call. */
unsigned char originated;
/*! TRUE if outgoing call was already redirected. */
unsigned char initially_redirected;
} cc;
};
enum CC_STATES {
/*! CC is not active. */
CC_STATE_IDLE,
// /*! CC has recorded call information in anticipation of CC availability. */
// CC_STATE_RECORD_RETENTION,
/*! CC is available and waiting on ALERTING or DISCONNECT to go out. */
CC_STATE_PENDING_AVAILABLE,
/*! CC is available and waiting on possible CC request. */
CC_STATE_AVAILABLE,
/*! CC is requested to be activated and waiting on party B to acknowledge. */
CC_STATE_REQUESTED,
/*! CC is activated and waiting for party B to become available. */
CC_STATE_ACTIVATED,
/*! CC party B is available and waiting for status of party A. */
CC_STATE_B_AVAILABLE,
/*! CC is suspended because party A is not available. (Monitor party A.) */
CC_STATE_SUSPENDED,
/*! CC is waiting for party A to initiate CC callback. */
CC_STATE_WAIT_CALLBACK,
/*! CC callback in progress. */
CC_STATE_CALLBACK,
/*! CC is waiting for signaling link to be cleared before destruction. */
CC_STATE_WAIT_DESTRUCTION,
/*! Number of CC states. Must be last in enum. */
CC_STATE_NUM
};
enum CC_EVENTS {
/*! CC is available for the current call. */
CC_EVENT_AVAILABLE,
/*! Requesting CC activation. */
CC_EVENT_CC_REQUEST,
/*! Requesting CC activation accepted. */
CC_EVENT_CC_REQUEST_ACCEPT,
/*! Requesting CC activation failed (error/reject received). */
CC_EVENT_CC_REQUEST_FAIL,
/*! CC party B is available, party A is considered free. */
CC_EVENT_REMOTE_USER_FREE,
/*! CC party B is available, party A is busy or CCBS busy. */
CC_EVENT_B_FREE,
/*! Someone else responded to the CC recall. */
CC_EVENT_STOP_ALERTING,
/*! CC poll/prompt for party A status. */
CC_EVENT_A_STATUS,
/*! CC party A is free/available for recall. */
CC_EVENT_A_FREE,
/*! CC party A is busy/not-available for recall. */
CC_EVENT_A_BUSY,
/*! Suspend monitoring party B because party A is busy. */
CC_EVENT_SUSPEND,
/*! Resume monitoring party B because party A is now available. */
CC_EVENT_RESUME,
/*! This is the CC recall call attempt. */
CC_EVENT_RECALL,
/*! Link request to cancel/deactivate CC received. */
CC_EVENT_LINK_CANCEL,
/*! Tear down CC request from upper layer. */
CC_EVENT_CANCEL,
/*! Received message indicating tear down of CC signaling link completed. */
CC_EVENT_SIGNALING_GONE,
/*! Delayed hangup request for the signaling link to allow subcmd events to be passed up. */
CC_EVENT_HANGUP_SIGNALING,
/*! Sent ALERTING message. */
CC_EVENT_MSG_ALERTING,
/*! Sent DISCONNECT message. */
CC_EVENT_MSG_DISCONNECT,
/*! Sent RELEASE message. */
CC_EVENT_MSG_RELEASE,
/*! Sent RELEASE_COMPLETE message. */
CC_EVENT_MSG_RELEASE_COMPLETE,
/*! T_ACTIVATE timer timed out. */
CC_EVENT_TIMEOUT_T_ACTIVATE,
#if 0
/*! T_DEACTIVATE timer timed out. */
CC_EVENT_TIMEOUT_T_DEACTIVATE,
/*! T_INTERROGATE timer timed out. */
CC_EVENT_TIMEOUT_T_INTERROGATE,
#endif
/*! T_RETENTION timer timed out. */
CC_EVENT_TIMEOUT_T_RETENTION,
/*! T-STATUS timer equivalent for CC user A status timed out. */
CC_EVENT_TIMEOUT_T_CCBS1,
/*! Timeout for valid party A status. */
CC_EVENT_TIMEOUT_EXTENDED_T_CCBS1,
/*! Max time the CCBS/CCNR service will be active. */
CC_EVENT_TIMEOUT_T_SUPERVISION,
/*! Max time to wait for user A to respond to user B availability. */
CC_EVENT_TIMEOUT_T_RECALL,
};
enum CC_PARTY_A_AVAILABILITY {
CC_PARTY_A_AVAILABILITY_INVALID,
CC_PARTY_A_AVAILABILITY_BUSY,
CC_PARTY_A_AVAILABILITY_FREE,
};
/* Invalid PTMP call completion reference and linkage id value. */
#define CC_PTMP_INVALID_ID 0xFF
/*! \brief Call-completion record */
struct pri_cc_record {
/*! Next call-completion record in the list */
struct pri_cc_record *next;
/*! Master D channel control structure. */
struct pri *master;
/*! Original call that is offered CC availability. (NULL if no longer exists.) */
struct q931_call *original_call;
/*!
* \brief Associated signaling link. (NULL if not established.)
* \note
* PTMP - Broadcast dummy call reference call.
* (If needed, the TE side could use this pointer to locate its specific
* dummy call reference call.)
* \note
* PTP - REGISTER signaling link.
* \note
* Q.SIG - SETUP signaling link.
*/
struct q931_call *signaling;
/*! Call-completion record id (0 - 65535) */
long record_id;
/*! Call-completion state */
enum CC_STATES state;
/*! Original calling party. */
struct q931_party_id party_a;
/*! Original called party. */
struct q931_party_address party_b;
/*! Saved BC, HLC, and LLC from initial SETUP */
struct q931_saved_ie_contents saved_ie_contents;
/*! Saved decoded BC */
struct decoded_bc bc;
/*! FSM parameters. */
union {
/*! PTMP FSM parameters. */
struct {
/*! Extended T_CCBS1 timer id for CCBSStatusRequest handling. */
int extended_t_ccbs1;
/*! Invoke id for the CCBSStatusRequest message to find if T_CCBS1 still running. */
int t_ccbs1_invoke_id;
/*! Number of times party A status request got no responses. */
int party_a_status_count;
/*! Accumulating party A availability status */
enum CC_PARTY_A_AVAILABILITY party_a_status_acc;
} ptmp;
/*! PTP FSM parameters. */
struct {
} ptp;
struct {
/*! Q.931 message type the current message event came in on. */
int msgtype;
} qsig;
} fsm;
/*! Received message parameters of interest. */
union {
/*! cc-request error/reject response */
struct {
/*! enum APDU_CALLBACK_REASON reason */
int reason;
/*! MSG_ERROR/MSG_REJECT fail code. */
int code;
} cc_req_rsp;
} msg;
/*! Party A availability status */
enum CC_PARTY_A_AVAILABILITY party_a_status;
/*! Indirect timer id to abort indirect action events. */
int t_indirect;
/*!
* \brief PTMP T_RETENTION timer id.
* \note
* This timer is used by all CC agents to implement
* the Asterisk CC core offer timer.
*/
int t_retention;
/*!
* \brief CC service supervision timer.
*
* \details
* This timer is one of the following timer id's depending upon
* switch type and CC mode:
* PTMP - T_CCBS2/T_CCNR2,
* PTP - T_CCBS5/T_CCNR5/T_CCBS6/T_CCNR6,
* Q.SIG - QSIG_CCBS_T2/QSIG_CCNR_T2
*/
int t_supervision;
/*!
* \brief Party A response to B availability for recall timer.
* \details
* This timer is one of the following timer id's:
* PTMP - T_CCBS3
* Q.SIG - QSIG_CC_T3
*/
int t_recall;
/*! Invoke id for the cc-request message to find if T_ACTIVATE/QSIG_CC_T1 still running. */
int t_activate_invoke_id;
/*! Pending response information. */
struct {
/*!
* \brief Send response on this signaling link.
* \note Used by PTMP for CCBSRequest/CCNRRequest/CCBSCall responses.
* \note Used by Q.SIG for ccRingout responses.
*/
struct q931_call *signaling;
/*! Invoke operation code */
int invoke_operation;
/*! Invoke id to use in the pending response. */
short invoke_id;
} response;
/*! TRUE if the call-completion FSM has completed and this record needs to be destroyed. */
unsigned char fsm_complete;
/*! TRUE if we are a call completion agent. */
unsigned char is_agent;
/*! TRUE if active cc mode is CCNR. */
unsigned char is_ccnr;
/*! PTMP pre-activation reference id. (0-127) */
unsigned char call_linkage_id;
/*! PTMP active CCBS reference id. (0-127) */
unsigned char ccbs_reference_id;
/*! Negotiated options */
struct {
/*! PTMP recall mode: globalRecall(0), specificRecall(1) */
unsigned char recall_mode;
/*! TRUE if negotiated for Q.SIG signaling link to be retained. */
unsigned char retain_signaling_link;
#if defined(QSIG_PATH_RESERVATION_SUPPORT)
/*! Q.SIG TRUE if can do path reservation. */
unsigned char do_path_reservation;
#endif /* defined(QSIG_PATH_RESERVATION_SUPPORT) */
} option;
};
/*! D channel control structure with associated dummy call reference record. */
@ -558,6 +884,8 @@ void __pri_free_tei(struct pri *p);
void q931_init_call_record(struct pri *ctrl, struct q931_call *call, int cr);
void pri_sr_init(struct pri_sr *req);
void q931_party_name_init(struct q931_party_name *name);
void q931_party_number_init(struct q931_party_number *number);
void q931_party_subaddress_init(struct q931_party_subaddress *subaddr);
@ -565,20 +893,32 @@ void q931_party_address_init(struct q931_party_address *address);
void q931_party_id_init(struct q931_party_id *id);
void q931_party_redirecting_init(struct q931_party_redirecting *redirecting);
static inline void q931_party_address_to_id(struct q931_party_id *id, struct q931_party_address *address)
static inline void q931_party_address_to_id(struct q931_party_id *id, const struct q931_party_address *address)
{
id->number = address->number;
id->subaddress = address->subaddress;
}
static inline void q931_party_id_to_address(struct q931_party_address *address, const struct q931_party_id *id)
{
address->number = id->number;
address->subaddress = id->subaddress;
}
int q931_party_name_cmp(const struct q931_party_name *left, const struct q931_party_name *right);
int q931_party_number_cmp(const struct q931_party_number *left, const struct q931_party_number *right);
int q931_party_subaddress_cmp(const struct q931_party_subaddress *left, const struct q931_party_subaddress *right);
int q931_party_address_cmp(const struct q931_party_address *left, const struct q931_party_address *right);
int q931_party_id_cmp(const struct q931_party_id *left, const struct q931_party_id *right);
int q931_party_id_cmp_address(const struct q931_party_id *left, const struct q931_party_id *right);
int q931_cmp_party_id_to_address(const struct q931_party_id *id, const struct q931_party_address *address);
void q931_party_id_copy_to_address(struct q931_party_address *address, const struct q931_party_id *id);
void q931_party_name_copy_to_pri(struct pri_party_name *pri_name, const struct q931_party_name *q931_name);
void q931_party_number_copy_to_pri(struct pri_party_number *pri_number, const struct q931_party_number *q931_number);
void q931_party_subaddress_copy_to_pri(struct pri_party_subaddress *pri_subaddress, const struct q931_party_subaddress *q931_subaddress);
void q931_party_address_copy_to_pri(struct pri_party_address *pri_address, const struct q931_party_address *q931_address);
void q931_party_id_copy_to_pri(struct pri_party_id *pri_id, const struct q931_party_id *q931_id);
void q931_party_redirecting_copy_to_pri(struct pri_party_redirecting *pri_redirecting, const struct q931_party_redirecting *q931_redirecting);
@ -598,6 +938,15 @@ struct pri_subcommand *q931_alloc_subcommand(struct pri *ctrl);
int q931_notify_redirection(struct pri *ctrl, q931_call *call, int notify, const struct q931_party_number *number);
struct pri_cc_record *pri_cc_find_by_reference(struct pri *ctrl, unsigned reference_id);
struct pri_cc_record *pri_cc_find_by_linkage(struct pri *ctrl, unsigned linkage_id);
struct pri_cc_record *pri_cc_find_by_addressing(struct pri *ctrl, const struct q931_party_address *party_a, const struct q931_party_address *party_b, unsigned length, const unsigned char *q931_ies);
struct pri_cc_record *pri_cc_new_record(struct pri *ctrl, q931_call *call);
void pri_cc_qsig_determine_available(struct pri *ctrl, q931_call *call);
int pri_cc_event(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record, enum CC_EVENTS event);
int q931_cc_timeout(struct pri *ctrl, struct pri_cc_record *cc_record, enum CC_EVENTS event);
void q931_cc_indirect(struct pri *ctrl, struct pri_cc_record *cc_record, void (*func)(struct pri *ctrl, q931_call *call, struct pri_cc_record *cc_record));
/*!
* \brief Get the master PRI control structure.
*
@ -731,4 +1080,10 @@ static inline int q931_is_dummy_call(const q931_call *call)
return (call->cr == Q931_DUMMY_CALL_REFERENCE) ? 1 : 0;
}
static inline short get_invokeid(struct pri *ctrl)
{
ctrl = PRI_MASTER(ctrl);
return ++ctrl->last_invoke;
}
#endif

View File

@ -82,6 +82,9 @@ typedef struct q931_ie {
/* Q.931 / National ISDN Message Types */
/*! Send this facility APDU on the next message to go out. */
#define Q931_ANY_MESSAGE -1
/* Call Establishment Messages */
#define Q931_ALERTING 0x01
#define Q931_CALL_PROCEEDING 0x02
@ -106,6 +109,7 @@ typedef struct q931_ie {
#define Q931_CONGESTION_CONTROL 0x79
#define Q931_INFORMATION 0x7b
#define Q931_FACILITY 0x62
#define Q931_REGISTER 0x64 /* Q.932 */
#define Q931_NOTIFY 0x6e
/* Call Management Messages */
@ -490,6 +494,9 @@ struct q931_call *q931_find_call(struct pri *ctrl, int cr);
struct q931_call *q931_new_call(struct pri *pri);
extern int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req);
int q931_register(struct pri *ctrl, q931_call *call);
void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx);
void q931_destroycall(struct pri *pri, q931_call *c);

View File

@ -28,16 +28,73 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libpri.h"
#include "pri_internal.h"
/*! Initial number of scheduled timer slots. */
#define SCHED_EVENTS_INITIAL 128
/*!
* Maximum number of scheduled timer slots.
* Should be a power of 2 multiple of SCHED_EVENTS_INITIAL.
*/
#define SCHED_EVENTS_MAX 8192
/*! \brief The maximum number of timers that were active at once. */
static int maxsched = 0;
static unsigned maxsched = 0;
/* Scheduler routines */
/*!
* \internal
* \brief Increase the number of scheduler timer slots available.
*
* \param ctrl D channel controller.
*
* \retval 0 on success.
* \retval -1 on error.
*/
static int pri_schedule_grow(struct pri *ctrl)
{
unsigned num_slots;
struct pri_sched *timers;
/* Determine how many slots in the new timer table. */
if (ctrl->sched.num_slots) {
if (SCHED_EVENTS_MAX <= ctrl->sched.num_slots) {
/* Cannot grow the timer table any more. */
return -1;
}
num_slots = ctrl->sched.num_slots * 2;
if (SCHED_EVENTS_MAX < num_slots) {
num_slots = SCHED_EVENTS_MAX;
}
} else {
num_slots = SCHED_EVENTS_INITIAL;
}
/* Get and initialize the new timer table. */
timers = calloc(num_slots, sizeof(struct pri_sched));
if (!timers) {
/* Could not get a new timer table. */
return -1;
}
if (ctrl->sched.timer) {
/* Copy over the old timer table. */
memcpy(timers, ctrl->sched.timer,
ctrl->sched.num_slots * sizeof(struct pri_sched));
free(ctrl->sched.timer);
}
/* Put the new timer table in place. */
ctrl->sched.timer = timers;
ctrl->sched.num_slots = num_slots;
return 0;
}
/*!
* \brief Start a timer to schedule an event.
*
@ -51,22 +108,26 @@ static int maxsched = 0;
*/
int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), void *data)
{
int x;
unsigned max_used;
unsigned x;
struct timeval tv;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (!ctrl->pri_sched[x].callback) {
ctrl = PRI_MASTER(ctrl);
max_used = ctrl->sched.max_used;
for (x = 0; x < max_used; ++x) {
if (!ctrl->sched.timer[x].callback) {
break;
}
}
if (x == MAX_SCHED) {
if (x == ctrl->sched.num_slots && pri_schedule_grow(ctrl)) {
pri_error(ctrl, "No more room in scheduler\n");
return 0;
}
if (ctrl->sched.max_used <= x) {
ctrl->sched.max_used = x + 1;
}
if (x >= maxsched) {
maxsched = x + 1;
}
@ -77,9 +138,9 @@ int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), v
tv.tv_usec -= 1000000;
tv.tv_sec += 1;
}
ctrl->pri_sched[x].when = tv;
ctrl->pri_sched[x].callback = function;
ctrl->pri_sched[x].data = data;
ctrl->sched.timer[x].when = tv;
ctrl->sched.timer[x].callback = function;
ctrl->sched.timer[x].data = data;
return x + 1;
}
@ -93,20 +154,29 @@ int pri_schedule_event(struct pri *ctrl, int ms, void (*function)(void *data), v
struct timeval *pri_schedule_next(struct pri *ctrl)
{
struct timeval *closest = NULL;
int x;
unsigned x;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (ctrl->pri_sched[x].callback && (!closest
|| (closest->tv_sec > ctrl->pri_sched[x].when.tv_sec)
|| ((closest->tv_sec == ctrl->pri_sched[x].when.tv_sec)
&& (closest->tv_usec > ctrl->pri_sched[x].when.tv_usec)))) {
closest = &ctrl->pri_sched[x].when;
ctrl = PRI_MASTER(ctrl);
/* Scan the scheduled timer slots backwards so we can update the max_used value. */
for (x = ctrl->sched.max_used; x--;) {
if (ctrl->sched.timer[x].callback) {
if (!closest) {
/* This is the highest sheduled timer slot in use. */
closest = &ctrl->sched.timer[x].when;
ctrl->sched.max_used = x + 1;
} else if ((closest->tv_sec > ctrl->sched.timer[x].when.tv_sec)
|| ((closest->tv_sec == ctrl->sched.timer[x].when.tv_sec)
&& (closest->tv_usec > ctrl->sched.timer[x].when.tv_usec))) {
closest = &ctrl->sched.timer[x].when;
}
}
}
if (!closest) {
/* No scheduled timer slots are active. */
ctrl->sched.max_used = 0;
}
return closest;
}
@ -121,23 +191,25 @@ struct timeval *pri_schedule_next(struct pri *ctrl)
*/
static pri_event *__pri_schedule_run(struct pri *ctrl, struct timeval *tv)
{
int x;
unsigned x;
unsigned max_used;
void (*callback)(void *);
void *data;
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
for (x = 0; x < MAX_SCHED; ++x) {
if (ctrl->pri_sched[x].callback && ((ctrl->pri_sched[x].when.tv_sec < tv->tv_sec)
|| ((ctrl->pri_sched[x].when.tv_sec == tv->tv_sec)
&& (ctrl->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
ctrl = PRI_MASTER(ctrl);
max_used = ctrl->sched.max_used;
for (x = 0; x < max_used; ++x) {
if (ctrl->sched.timer[x].callback
&& ((ctrl->sched.timer[x].when.tv_sec < tv->tv_sec)
|| ((ctrl->sched.timer[x].when.tv_sec == tv->tv_sec)
&& (ctrl->sched.timer[x].when.tv_usec <= tv->tv_usec)))) {
/* This timer has expired. */
ctrl->schedev = 0;
callback = ctrl->pri_sched[x].callback;
data = ctrl->pri_sched[x].data;
ctrl->pri_sched[x].callback = NULL;
callback = ctrl->sched.timer[x].callback;
data = ctrl->sched.timer[x].data;
ctrl->sched.timer[x].callback = NULL;
callback(data);
if (ctrl->schedev) {
return &ctrl->ev;
@ -175,12 +247,12 @@ pri_event *pri_schedule_run(struct pri *ctrl)
void pri_schedule_del(struct pri *ctrl, int id)
{
/* Scheduling runs on master channels only */
while (ctrl->master) {
ctrl = ctrl->master;
}
if (0 < id && id <= MAX_SCHED) {
ctrl->pri_sched[id - 1].callback = NULL;
ctrl = PRI_MASTER(ctrl);
if (0 < id && id <= ctrl->sched.num_slots) {
ctrl->sched.timer[id - 1].callback = NULL;
} else if (id) {
pri_error(ctrl, "Asked to delete sched id %d???\n", id);
pri_error(ctrl, "Asked to delete sched id %d??? num_slots=%d\n", id,
ctrl->sched.num_slots);
}
}

690
q931.c

File diff suppressed because it is too large Load Diff

350
rose.c
View File

@ -200,6 +200,46 @@ static const struct asn1_oid rose_etsi_ect = {
/* *INDENT-ON* */
};
/*! \brief ETSI Status Request OID prefix. */
static const struct asn1_oid rose_etsi_status_request = {
/* *INDENT-OFF* */
/* {itu-t(0) identified-organization(4) etsi(0) 196 status-request-procedure(9)} */
4, { 4, 0, 196, 9 }
/* *INDENT-ON* */
};
/*! \brief ETSI Call Completion Busy Status OID prefix. */
static const struct asn1_oid rose_etsi_ccbs = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 359 operations-and-errors(1)} */
4, { 4, 0, 359, 1 }
/* *INDENT-ON* */
};
/*! \brief ETSI Call Completion Busy Status public-private interworking OID prefix. */
static const struct asn1_oid rose_etsi_ccbs_t = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 359 private-networks-operations-and-errors(2)} */
4, { 4, 0, 359, 2 }
/* *INDENT-ON* */
};
/*! \brief ETSI Call Completion No Reply OID prefix. */
static const struct asn1_oid rose_etsi_ccnr = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 1065 operations-and-errors(1)} */
4, { 4, 0, 1065, 1 }
/* *INDENT-ON* */
};
/*! \brief ETSI Call Completion No Reply public-private interworking OID prefix. */
static const struct asn1_oid rose_etsi_ccnr_t = {
/* *INDENT-OFF* */
/* {ccitt(0) identified-organization(4) etsi(0) 1065 private-networks-operations-and-errors(2)} */
4, { 4, 0, 1065, 2 }
/* *INDENT-ON* */
};
/*! \brief ETSI specific invoke/result encode/decode message table */
static const struct rose_convert_msg rose_etsi_msgs[] = {
/* *INDENT-OFF* */
@ -361,6 +401,136 @@ static const struct rose_convert_msg rose_etsi_msgs[] = {
rose_enc_etsi_EctLoopTest_ARG, rose_enc_etsi_EctLoopTest_RES,
rose_dec_etsi_EctLoopTest_ARG, rose_dec_etsi_EctLoopTest_RES
},
/*
* globalValue's (OIDs) from Status-Request-Procedure
* {itu-t identified-organization etsi(0) 196 status-request-procedure(9)}
*/
{
ROSE_ETSI_StatusRequest, &rose_etsi_status_request, 1,
rose_enc_etsi_StatusRequest_ARG, rose_enc_etsi_StatusRequest_RES,
rose_dec_etsi_StatusRequest_ARG, rose_dec_etsi_StatusRequest_RES
},
/*
* globalValue's (OIDs) from CCBS-Operations-and-Errors
* {ccitt identified-organization etsi(0) 359 operations-and-errors(1)}
*/
{
ROSE_ETSI_CallInfoRetain, &rose_etsi_ccbs, 1,
rose_enc_etsi_CallInfoRetain_ARG, NULL,
rose_dec_etsi_CallInfoRetain_ARG, NULL
},
{
ROSE_ETSI_CCBSRequest, &rose_etsi_ccbs, 2,
rose_enc_etsi_CCBSRequest_ARG, rose_enc_etsi_CCBSRequest_RES,
rose_dec_etsi_CCBSRequest_ARG, rose_dec_etsi_CCBSRequest_RES
},
{
ROSE_ETSI_CCBSDeactivate, &rose_etsi_ccbs, 3,
rose_enc_etsi_CCBSDeactivate_ARG, NULL,
rose_dec_etsi_CCBSDeactivate_ARG, NULL
},
{
ROSE_ETSI_CCBSInterrogate, &rose_etsi_ccbs, 4,
rose_enc_etsi_CCBSInterrogate_ARG, rose_enc_etsi_CCBSInterrogate_RES,
rose_dec_etsi_CCBSInterrogate_ARG, rose_dec_etsi_CCBSInterrogate_RES
},
{
ROSE_ETSI_CCBSErase, &rose_etsi_ccbs, 5,
rose_enc_etsi_CCBSErase_ARG, NULL,
rose_dec_etsi_CCBSErase_ARG, NULL
},
{
ROSE_ETSI_CCBSRemoteUserFree, &rose_etsi_ccbs, 6,
rose_enc_etsi_CCBSRemoteUserFree_ARG, NULL,
rose_dec_etsi_CCBSRemoteUserFree_ARG, NULL
},
{
ROSE_ETSI_CCBSCall, &rose_etsi_ccbs, 7,
rose_enc_etsi_CCBSCall_ARG, NULL,
rose_dec_etsi_CCBSCall_ARG, NULL
},
{
ROSE_ETSI_CCBSStatusRequest, &rose_etsi_ccbs, 8,
rose_enc_etsi_CCBSStatusRequest_ARG, rose_enc_etsi_CCBSStatusRequest_RES,
rose_dec_etsi_CCBSStatusRequest_ARG, rose_dec_etsi_CCBSStatusRequest_RES
},
{
ROSE_ETSI_CCBSBFree, &rose_etsi_ccbs, 9,
rose_enc_etsi_CCBSBFree_ARG, NULL,
rose_dec_etsi_CCBSBFree_ARG, NULL
},
{
ROSE_ETSI_EraseCallLinkageID, &rose_etsi_ccbs, 10,
rose_enc_etsi_EraseCallLinkageID_ARG, NULL,
rose_dec_etsi_EraseCallLinkageID_ARG, NULL
},
{
ROSE_ETSI_CCBSStopAlerting, &rose_etsi_ccbs, 11,
rose_enc_etsi_CCBSStopAlerting_ARG, NULL,
rose_dec_etsi_CCBSStopAlerting_ARG, NULL
},
/*
* globalValue's (OIDs) from CCBS-private-networks-Operations-and-Errors
* {ccitt identified-organization etsi(0) 359 private-networks-operations-and-errors(2)}
*/
{
ROSE_ETSI_CCBS_T_Request, &rose_etsi_ccbs_t, 1,
rose_enc_etsi_CCBS_T_Request_ARG, rose_enc_etsi_CCBS_T_Request_RES,
rose_dec_etsi_CCBS_T_Request_ARG, rose_dec_etsi_CCBS_T_Request_RES
},
{
ROSE_ETSI_CCBS_T_Call, &rose_etsi_ccbs_t, 2,
NULL, NULL,
NULL, NULL
},
{
ROSE_ETSI_CCBS_T_Suspend, &rose_etsi_ccbs_t, 3,
NULL, NULL,
NULL, NULL
},
{
ROSE_ETSI_CCBS_T_Resume, &rose_etsi_ccbs_t, 4,
NULL, NULL,
NULL, NULL
},
{
ROSE_ETSI_CCBS_T_RemoteUserFree, &rose_etsi_ccbs_t, 5,
NULL, NULL,
NULL, NULL
},
{
ROSE_ETSI_CCBS_T_Available, &rose_etsi_ccbs_t, 6,
NULL, NULL,
NULL, NULL
},
/*
* globalValue's (OIDs) from CCNR-Operations-and-Errors
* {ccitt identified-organization etsi(0) 1065 operations-and-errors(1)}
*/
{
ROSE_ETSI_CCNRRequest, &rose_etsi_ccnr, 1,
rose_enc_etsi_CCNRRequest_ARG, rose_enc_etsi_CCNRRequest_RES,
rose_dec_etsi_CCNRRequest_ARG, rose_dec_etsi_CCNRRequest_RES
},
{
ROSE_ETSI_CCNRInterrogate, &rose_etsi_ccnr, 2,
rose_enc_etsi_CCNRInterrogate_ARG, rose_enc_etsi_CCNRInterrogate_RES,
rose_dec_etsi_CCNRInterrogate_ARG, rose_dec_etsi_CCNRInterrogate_RES
},
/*
* globalValue's (OIDs) from CCNR-private-networks-Operations-and-Errors
* {ccitt identified-organization etsi(0) 1065 private-networks-operations-and-errors(2)}
*/
{
ROSE_ETSI_CCNR_T_Request, &rose_etsi_ccnr_t, 1,
rose_enc_etsi_CCNR_T_Request_ARG, rose_enc_etsi_CCNR_T_Request_RES,
rose_dec_etsi_CCNR_T_Request_ARG, rose_dec_etsi_CCNR_T_Request_RES
},
/* *INDENT-ON* */
};
@ -463,6 +633,60 @@ static const struct rose_convert_error rose_etsi_errors[] = {
ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork, &rose_etsi_ect, 21,
NULL, NULL
},
/*
* globalValue Errors (OIDs) from CCBS-Operations-and-Errors
* {ccitt identified-organization etsi(0) 359 operations-and-errors(1)}
*/
{
ROSE_ERROR_CCBS_InvalidCallLinkageID, &rose_etsi_ccbs, 20,
NULL, NULL
},
{
ROSE_ERROR_CCBS_InvalidCCBSReference, &rose_etsi_ccbs, 21,
NULL, NULL
},
{
ROSE_ERROR_CCBS_LongTermDenial, &rose_etsi_ccbs, 22,
NULL, NULL
},
{
ROSE_ERROR_CCBS_ShortTermDenial, &rose_etsi_ccbs, 23,
NULL, NULL
},
{
ROSE_ERROR_CCBS_IsAlreadyActivated, &rose_etsi_ccbs, 24,
NULL, NULL
},
{
ROSE_ERROR_CCBS_AlreadyAccepted, &rose_etsi_ccbs, 25,
NULL, NULL
},
{
ROSE_ERROR_CCBS_OutgoingCCBSQueueFull, &rose_etsi_ccbs, 26,
NULL, NULL
},
{
ROSE_ERROR_CCBS_CallFailureReasonNotBusy, &rose_etsi_ccbs, 27,
NULL, NULL
},
{
ROSE_ERROR_CCBS_NotReadyForCall, &rose_etsi_ccbs, 28,
NULL, NULL
},
/*
* globalValue Errors (OIDs) from CCBS-private-networks-Operations-and-Errors
* {ccitt identified-organization etsi(0) 359 private-networks-operations-and-errors(2)}
*/
{
ROSE_ERROR_CCBS_T_LongTermDenial, &rose_etsi_ccbs_t, 20,
NULL, NULL
},
{
ROSE_ERROR_CCBS_T_ShortTermDenial, &rose_etsi_ccbs_t, 21,
NULL, NULL
},
/* *INDENT-ON* */
};
@ -649,6 +873,51 @@ static const struct rose_convert_msg rose_qsig_msgs[] = {
rose_dec_qsig_DummyArg_ARG, NULL
},
/*
* localValue's from Q.SIG SS-CC-Operations
* { iso(1) standard(0) pss1-call-completion(13870) operations(0) }
*/
{
ROSE_QSIG_CcbsRequest, NULL, 40,
rose_enc_qsig_CcbsRequest_ARG, rose_enc_qsig_CcbsRequest_RES,
rose_dec_qsig_CcbsRequest_ARG, rose_dec_qsig_CcbsRequest_RES
},
{
ROSE_QSIG_CcnrRequest, NULL, 27,
rose_enc_qsig_CcnrRequest_ARG, rose_enc_qsig_CcnrRequest_RES,
rose_dec_qsig_CcnrRequest_ARG, rose_dec_qsig_CcnrRequest_RES
},
{
ROSE_QSIG_CcCancel, NULL, 28,
rose_enq_qsig_CcCancel_ARG, NULL,
rose_dec_qsig_CcCancel_ARG, NULL
},
{
ROSE_QSIG_CcExecPossible, NULL, 29,
rose_enq_qsig_CcExecPossible_ARG, NULL,
rose_dec_qsig_CcExecPossible_ARG, NULL
},
{
ROSE_QSIG_CcPathReserve, NULL, 30,
rose_enc_qsig_CcPathReserve_ARG, rose_enc_qsig_CcPathReserve_RES,
rose_dec_qsig_CcPathReserve_ARG, rose_dec_qsig_CcPathReserve_RES
},
{
ROSE_QSIG_CcRingout, NULL, 31,
rose_enc_qsig_CcRingout_ARG, NULL,
rose_dec_qsig_CcRingout_ARG, NULL
},
{
ROSE_QSIG_CcSuspend, NULL, 32,
rose_enc_qsig_CcSuspend_ARG, NULL,
rose_dec_qsig_CcSuspend_ARG, NULL
},
{
ROSE_QSIG_CcResume, NULL, 33,
rose_enc_qsig_CcResume_ARG, NULL,
rose_dec_qsig_CcResume_ARG, NULL
},
/*
* localValue's from Q.SIG SS-MWI-Operations
* { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
@ -800,6 +1069,31 @@ static const struct rose_convert_error rose_qsig_errors[] = {
NULL, NULL
},
/*
* localValue's from Q.SIG SS-CC-Operations
* { iso(1) standard(0) pss1-call-completion(13870) operations(0) }
*/
{
ROSE_ERROR_QSIG_ShortTermRejection, NULL, 1010,
NULL, NULL
},
{
ROSE_ERROR_QSIG_LongTermRejection, NULL, 1011,
NULL, NULL
},
{
ROSE_ERROR_QSIG_RemoteUserBusyAgain, NULL, 1012,
NULL, NULL
},
{
ROSE_ERROR_QSIG_FailureToMatch, NULL, 1013,
NULL, NULL
},
{
ROSE_ERROR_QSIG_FailedDueToInterworking, NULL, 1014,
NULL, NULL
},
/*
* localValue's from Q.SIG SS-MWI-Operations
* { iso(1) standard(0) pss1-message-waiting-indication(15506) message-waiting-operations(0) }
@ -1069,6 +1363,34 @@ const char *rose_operation2str(enum rose_operation operation)
{ ROSE_ETSI_AOCECurrency, "ROSE_ETSI_AOCECurrency" },
{ ROSE_ETSI_AOCEChargingUnit, "ROSE_ETSI_AOCEChargingUnit" },
{ ROSE_ETSI_StatusRequest, "ROSE_ETSI_StatusRequest" },
{ ROSE_ETSI_CallInfoRetain, "ROSE_ETSI_CallInfoRetain" },
{ ROSE_ETSI_EraseCallLinkageID, "ROSE_ETSI_EraseCallLinkageID" },
{ ROSE_ETSI_CCBSDeactivate, "ROSE_ETSI_CCBSDeactivate" },
{ ROSE_ETSI_CCBSErase, "ROSE_ETSI_CCBSErase" },
{ ROSE_ETSI_CCBSRemoteUserFree, "ROSE_ETSI_CCBSRemoteUserFree" },
{ ROSE_ETSI_CCBSCall, "ROSE_ETSI_CCBSCall" },
{ ROSE_ETSI_CCBSStatusRequest, "ROSE_ETSI_CCBSStatusRequest" },
{ ROSE_ETSI_CCBSBFree, "ROSE_ETSI_CCBSBFree" },
{ ROSE_ETSI_CCBSStopAlerting, "ROSE_ETSI_CCBSStopAlerting" },
{ ROSE_ETSI_CCBSRequest, "ROSE_ETSI_CCBSRequest" },
{ ROSE_ETSI_CCBSInterrogate, "ROSE_ETSI_CCBSInterrogate" },
{ ROSE_ETSI_CCNRRequest, "ROSE_ETSI_CCNRRequest" },
{ ROSE_ETSI_CCNRInterrogate, "ROSE_ETSI_CCNRInterrogate" },
{ ROSE_ETSI_CCBS_T_Call, "ROSE_ETSI_CCBS_T_Call" },
{ ROSE_ETSI_CCBS_T_Suspend, "ROSE_ETSI_CCBS_T_Suspend" },
{ ROSE_ETSI_CCBS_T_Resume, "ROSE_ETSI_CCBS_T_Resume" },
{ ROSE_ETSI_CCBS_T_RemoteUserFree, "ROSE_ETSI_CCBS_T_RemoteUserFree" },
{ ROSE_ETSI_CCBS_T_Available, "ROSE_ETSI_CCBS_T_Available" },
{ ROSE_ETSI_CCBS_T_Request, "ROSE_ETSI_CCBS_T_Request" },
{ ROSE_ETSI_CCNR_T_Request, "ROSE_ETSI_CCNR_T_Request" },
{ ROSE_QSIG_CallingName, "ROSE_QSIG_CallingName" },
{ ROSE_QSIG_CalledName, "ROSE_QSIG_CalledName" },
{ ROSE_QSIG_ConnectedName, "ROSE_QSIG_ConnectedName" },
@ -1103,6 +1425,15 @@ const char *rose_operation2str(enum rose_operation operation)
{ ROSE_QSIG_DivertingLegInformation3, "ROSE_QSIG_DivertingLegInformation3" },
{ ROSE_QSIG_CfnrDivertedLegFailed, "ROSE_QSIG_CfnrDivertedLegFailed" },
{ ROSE_QSIG_CcbsRequest, "ROSE_QSIG_CcbsRequest" },
{ ROSE_QSIG_CcnrRequest, "ROSE_QSIG_CcnrRequest" },
{ ROSE_QSIG_CcCancel, "ROSE_QSIG_CcCancel" },
{ ROSE_QSIG_CcExecPossible, "ROSE_QSIG_CcExecPossible" },
{ ROSE_QSIG_CcPathReserve, "ROSE_QSIG_CcPathReserve" },
{ ROSE_QSIG_CcRingout, "ROSE_QSIG_CcRingout" },
{ ROSE_QSIG_CcSuspend, "ROSE_QSIG_CcSuspend" },
{ ROSE_QSIG_CcResume, "ROSE_QSIG_CcResume" },
{ ROSE_QSIG_MWIActivate, "ROSE_QSIG_MWIActivate" },
{ ROSE_QSIG_MWIDeactivate, "ROSE_QSIG_MWIDeactivate" },
{ ROSE_QSIG_MWIInterrogate, "ROSE_QSIG_MWIInterrogate" },
@ -1161,6 +1492,19 @@ const char *rose_error2str(enum rose_error_code code)
{ ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
{ ROSE_ERROR_CCBS_InvalidCallLinkageID, "CCBS: Invalid Call Linkage ID" },
{ ROSE_ERROR_CCBS_InvalidCCBSReference, "CCBS: Invalid CCBS Reference" },
{ ROSE_ERROR_CCBS_LongTermDenial, "CCBS: Long Term Denial" },
{ ROSE_ERROR_CCBS_ShortTermDenial, "CCBS: Short Term Denial" },
{ ROSE_ERROR_CCBS_IsAlreadyActivated, "CCBS: Is Already Activated" },
{ ROSE_ERROR_CCBS_AlreadyAccepted, "CCBS: Already Accepted" },
{ ROSE_ERROR_CCBS_OutgoingCCBSQueueFull, "CCBS: Outgoing CCBS Queue Full" },
{ ROSE_ERROR_CCBS_CallFailureReasonNotBusy, "CCBS: Call Failure Reason Not Busy" },
{ ROSE_ERROR_CCBS_NotReadyForCall, "CCBS: Not Ready For Call" },
{ ROSE_ERROR_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
{ ROSE_ERROR_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
/* Q.SIG specific errors */
{ ROSE_ERROR_QSIG_Unspecified, "Unspecified" },
@ -1173,6 +1517,12 @@ const char *rose_error2str(enum rose_error_code code)
{ ROSE_ERROR_QSIG_Div_TemporarilyUnavailable, "Diversion: Temporarily Unavailable" },
{ ROSE_ERROR_QSIG_Div_NotAuthorized, "Diversion: Not Authorized" },
{ ROSE_ERROR_QSIG_ShortTermRejection, "CC: Short Term Rejection" },
{ ROSE_ERROR_QSIG_LongTermRejection, "CC: Long Term Rejection" },
{ ROSE_ERROR_QSIG_RemoteUserBusyAgain, "CC: Remote User Busy Again" },
{ ROSE_ERROR_QSIG_FailureToMatch, "CC: Failure To Match" },
{ ROSE_ERROR_QSIG_FailedDueToInterworking, "CC: Failed Due To Interworking" },
{ ROSE_ERROR_QSIG_InvalidMsgCentreId, "MWI: Invalid Message Center ID" },
/* DMS-100 specific errors */

606
rose.h
View File

@ -103,6 +103,37 @@ enum rose_operation {
ROSE_ETSI_EctInform, /*!< Invoke only */
ROSE_ETSI_EctLoopTest, /*!< Invoke/Result */
/* ETSI Status-Request-Procedure */
ROSE_ETSI_StatusRequest, /*!< Invoke/Result */
/* ETSI CCBS-Operations-and-Errors */
ROSE_ETSI_CallInfoRetain, /*!< Invoke only */
ROSE_ETSI_CCBSRequest, /*!< Invoke/Result */
ROSE_ETSI_CCBSDeactivate, /*!< Invoke/Result */
ROSE_ETSI_CCBSInterrogate, /*!< Invoke/Result */
ROSE_ETSI_CCBSErase, /*!< Invoke only */
ROSE_ETSI_CCBSRemoteUserFree, /*!< Invoke only */
ROSE_ETSI_CCBSCall, /*!< Invoke only */
ROSE_ETSI_CCBSStatusRequest, /*!< Invoke/Result */
ROSE_ETSI_CCBSBFree, /*!< Invoke only */
ROSE_ETSI_EraseCallLinkageID, /*!< Invoke only */
ROSE_ETSI_CCBSStopAlerting, /*!< Invoke only */
/* ETSI CCBS-private-networks-Operations-and-Errors */
ROSE_ETSI_CCBS_T_Request, /*!< Invoke/Result */
ROSE_ETSI_CCBS_T_Call, /*!< Invoke only */
ROSE_ETSI_CCBS_T_Suspend, /*!< Invoke only */
ROSE_ETSI_CCBS_T_Resume, /*!< Invoke only */
ROSE_ETSI_CCBS_T_RemoteUserFree, /*!< Invoke only */
ROSE_ETSI_CCBS_T_Available, /*!< Invoke only */
/* ETSI CCNR-Operations-and-Errors */
ROSE_ETSI_CCNRRequest, /*!< Invoke/Result */
ROSE_ETSI_CCNRInterrogate, /*!< Invoke/Result */
/* ETSI CCNR-private-networks-Operations-and-Errors */
ROSE_ETSI_CCNR_T_Request, /*!< Invoke/Result */
/* Q.SIG Name-Operations */
ROSE_QSIG_CallingName, /*!< Invoke only */
ROSE_QSIG_CalledName, /*!< Invoke only */
@ -141,6 +172,16 @@ enum rose_operation {
ROSE_QSIG_DivertingLegInformation3, /*!< Invoke only */
ROSE_QSIG_CfnrDivertedLegFailed, /*!< Invoke only */
/* Q.SIG SS-CC-Operations */
ROSE_QSIG_CcbsRequest, /*!< Invoke/Result */
ROSE_QSIG_CcnrRequest, /*!< Invoke/Result */
ROSE_QSIG_CcCancel, /*!< Invoke only */
ROSE_QSIG_CcExecPossible, /*!< Invoke only */
ROSE_QSIG_CcPathReserve, /*!< Invoke/Result */
ROSE_QSIG_CcRingout, /*!< Invoke only */
ROSE_QSIG_CcSuspend, /*!< Invoke only */
ROSE_QSIG_CcResume, /*!< Invoke only */
/* Q.SIG SS-MWI-Operations */
ROSE_QSIG_MWIActivate, /*!< Invoke/Result */
ROSE_QSIG_MWIDeactivate, /*!< Invoke/Result */
@ -198,6 +239,21 @@ enum rose_error_code {
/* ETSI Explicit-Call-Transfer-Operations-and-Errors */
ROSE_ERROR_ECT_LinkIdNotAssignedByNetwork,
/* ETSI CCBS-Operations-and-Errors */
ROSE_ERROR_CCBS_InvalidCallLinkageID,
ROSE_ERROR_CCBS_InvalidCCBSReference,
ROSE_ERROR_CCBS_LongTermDenial,
ROSE_ERROR_CCBS_ShortTermDenial,
ROSE_ERROR_CCBS_IsAlreadyActivated,
ROSE_ERROR_CCBS_AlreadyAccepted,
ROSE_ERROR_CCBS_OutgoingCCBSQueueFull,
ROSE_ERROR_CCBS_CallFailureReasonNotBusy,
ROSE_ERROR_CCBS_NotReadyForCall,
/* ETSI CCBS-private-networks-Operations-and-Errors */
ROSE_ERROR_CCBS_T_LongTermDenial,
ROSE_ERROR_CCBS_T_ShortTermDenial,
/* Q.SIG from various specifications */
ROSE_ERROR_QSIG_Unspecified,
@ -213,6 +269,13 @@ enum rose_error_code {
ROSE_ERROR_QSIG_Div_TemporarilyUnavailable,
ROSE_ERROR_QSIG_Div_NotAuthorized,
/* Q.SIG SS-CC-Operations */
ROSE_ERROR_QSIG_ShortTermRejection,
ROSE_ERROR_QSIG_LongTermRejection,
ROSE_ERROR_QSIG_RemoteUserBusyAgain,
ROSE_ERROR_QSIG_FailureToMatch,
ROSE_ERROR_QSIG_FailedDueToInterworking,
/* Q.SIG SS-MWI-Operations */
ROSE_ERROR_QSIG_InvalidMsgCentreId,
@ -1671,6 +1734,351 @@ struct roseEtsiEctLoopTest_RES {
/* ------------------------------------------------------------------- */
/*
* ARGUMENT SEQUENCE {
* compatibilityMode CompatibilityMode,
*
* -- The BC, HLC (optional) and LLC (optional) information
* -- elements shall be embedded in q931InfoElement
* q931InformationElement Q931InformationElement
* }
*/
struct roseEtsiStatusRequest_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \details allBasicServices(0), oneOrMoreBasicServices(1) */
u_int8_t compatibility_mode;
};
/*
* RESULT StatusResult
*/
struct roseEtsiStatusRequest_RES {
/*! \details compatibleAndFree(0), compatibleAndBusy(1), incompatible(2) */
u_int8_t status;
};
/* ------------------------------------------------------------------- */
/*
* CallLinkageID ::= INTEGER (0..127)
* CCBSReference ::= INTEGER (0..127)
*/
/*
* ARGUMENT callLinkageID CallLinkageID
*/
struct roseEtsiCallInfoRetain_ARG {
/*! \brief Call Linkage Record ID */
u_int8_t call_linkage_id;
};
/*
* ARGUMENT callLinkageID CallLinkageID
*/
struct roseEtsiEraseCallLinkageID_ARG {
/*! \brief Call Linkage Record ID */
u_int8_t call_linkage_id;
};
/*
* ARGUMENT callLinkageID CallLinkageID
*/
struct roseEtsiCCBSRequest_ARG {
/*! \brief Call Linkage Record ID */
u_int8_t call_linkage_id;
};
/*
* RESULT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference
* }
*/
struct roseEtsiCCBSRequest_RES {
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT cCBSReference CCBSReference
*/
struct roseEtsiCCBSDeactivate_ARG {
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT SEQUENCE {
* cCBSReference CCBSReference OPTIONAL,
* partyNumberOfA PartyNumber OPTIONAL
* }
*/
struct roseEtsiCCBSInterrogate_ARG {
/*! \brief Party A number (Optional) */
struct rosePartyNumber a_party_number;
/*! \brief TRUE if CCBSReference present */
u_int8_t ccbs_reference_present;
/*! \brief CCBS Record ID (optional) */
u_int8_t ccbs_reference;
};
/*
* -- The Bearer capability, High layer compatibility (optional)
* -- and Low layer compatibility (optional) information elements
* -- shall be embedded in q931InfoElement.
* CallInformation ::= SEQUENCE {
* addressOfB Address,
* q931InfoElement Q931InformationElement,
* cCBSReference CCBSReference,
* subAddressOfA PartySubaddress OPTIONAL
* }
*/
struct roseEtsiCallInformation {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress address_of_b;
/*! \brief Subaddress of A (Optional) */
struct rosePartySubaddress subaddress_of_a;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* CallDetails ::= SEQUENCE SIZE(1..5) OF CallInformation
*/
struct roseEtsiCallDetailsList {
struct roseEtsiCallInformation list[5];
/*! \brief Number of CallDetails records present */
u_int8_t num_records;
};
/*
* RESULT SEQUENCE {
* recallMode RecallMode,
* callDetails CallDetails OPTIONAL
* }
*/
struct roseEtsiCCBSInterrogate_RES {
struct roseEtsiCallDetailsList call_details;
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
};
/*
* ARGUMENT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference,
* addressOfB Address,
* q931InfoElement Q931InformationElement,
* eraseReason CCBSEraseReason
* }
*/
struct roseEtsiCCBSErase_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress address_of_b;
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
/*!
* \brief CCBS Erase reason
* \details
* normal-unspecified(0),
* t-CCBS2-timeout(1),
* t-CCBS3-timeout(2),
* basic-call-failed(3)
*/
u_int8_t reason;
};
/*
* ARGUMENT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference,
* addressOfB Address,
* q931InfoElement Q931InformationElement
* }
*/
struct roseEtsiCCBSRemoteUserFree_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress address_of_b;
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT cCBSReference CCBSReference
*/
struct roseEtsiCCBSCall_ARG {
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference,
* q931InfoElement Q931InformationElement
* }
*/
struct roseEtsiCCBSStatusRequest_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* RESULT BOOLEAN -- free=TRUE, busy=FALSE
*/
struct roseEtsiCCBSStatusRequest_RES {
/*! \brief TRUE if User A is free */
u_int8_t free;
};
/*
* ARGUMENT SEQUENCE {
* recallMode RecallMode,
* cCBSReference CCBSReference,
* addressOfB Address,
* q931InfoElement Q931InformationElement
* }
*/
struct roseEtsiCCBSBFree_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress address_of_b;
/*! \details globalRecall(0), specificRecall(1) */
u_int8_t recall_mode;
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/*
* ARGUMENT cCBSReference CCBSReference
*/
struct roseEtsiCCBSStopAlerting_ARG {
/*! \brief CCBS Record ID */
u_int8_t ccbs_reference;
};
/* ------------------------------------------------------------------- */
/*
* ARGUMENT SEQUENCE {
* destinationAddress Address,
*
* -- contains HLC, LLC and BC information
* q931InfoElement Q931InformationElement,
*
* retentionSupported [1] IMPLICIT BOOLEAN DEFAULT FALSE,
*
* -- The use of this parameter is specified in
* -- EN 300 195-1 for interaction of CCBS with CLIP
* presentationAllowedIndicator [2] IMPLICIT BOOLEAN OPTIONAL,
*
* -- The use of this parameter is specified in
* -- EN 300 195-1 for interaction of CCBS with CLIP
* originatingAddress Address OPTIONAL
* }
*/
struct roseEtsiCCBS_T_Request_ARG {
/*! \brief The BC, HLC (optional) and LLC (optional) information */
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief Address of B */
struct roseAddress destination;
/*! \brief Caller-ID Address (Present if Originating.Party.LengthOfNumber is nonzero) */
struct roseAddress originating;
/*! \brief TRUE if the PresentationAllowedIndicator is present */
u_int8_t presentation_allowed_indicator_present;
/*! \brief TRUE if presentation is allowed for the originating address (optional) */
u_int8_t presentation_allowed_indicator;
/*! \brief TRUE if User A's CCBS request is continued if user B is busy again. */
u_int8_t retention_supported;
};
/*
* RESULT retentionSupported BOOLEAN -- Default False
*/
struct roseEtsiCCBS_T_Request_RES {
/*! \brief TRUE if User A's CCBS request is continued if user B is busy again. */
u_int8_t retention_supported;
};
/* ------------------------------------------------------------------- */
/*
* Name ::= CHOICE {
* -- iso8859-1 is implied in namePresentationAllowedSimple.
@ -2835,6 +3243,146 @@ struct roseQsigDivertingLegInformation3_ARG {
/* ------------------------------------------------------------------- */
/*
* CcExtension ::= CHOICE {
* none NULL,
* single [14] IMPLICIT Extension,
* multiple [15] IMPLICIT SEQUENCE OF Extension
* }
*/
/*
* CcRequestArg ::= SEQUENCE {
* numberA PresentedNumberUnscreened,
* numberB PartyNumber,
*
* -- permitted information elements are:
* -- Bearer capability;
* -- Low layer compatibility;
* -- High layer compatibility
* service PSS1InformationElement,
* subaddrA [10] EXPLICIT PartySubaddress OPTIONAL,
* subaddrB [11] EXPLICIT PartySubaddress OPTIONAL,
* can-retain-service [12] IMPLICIT BOOLEAN DEFAULT FALSE,
*
* -- TRUE: signalling connection to be retained;
* -- FALSE: signalling connection to be released;
* -- omission: release or retain signalling connection
* retain-sig-connection [13] IMPLICIT BOOLEAN OPTIONAL,
* extension CcExtension OPTIONAL
* }
*/
struct roseQsigCcRequestArg {
struct rosePresentedNumberUnscreened number_a;
struct rosePartyNumber number_b;
/*!
* \brief subaddrA (optional)
* The subaddress is present if the length is nonzero.
*/
struct rosePartySubaddress subaddr_a;
/*!
* \brief subaddrB (optional)
* The subaddress is present if the length is nonzero.
*/
struct rosePartySubaddress subaddr_b;
/*!
* \brief The BC, HLC (optional) and LLC (optional) information.
* \note The ASN.1 field name is service.
*/
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
/*! \brief TRUE if can retain service (DEFAULT FALSE) */
u_int8_t can_retain_service;
/*!
* \brief TRUE if retain_sig_connection present
* \note If not present then the signaling connection could be
* released or retained.
*/
u_int8_t retain_sig_connection_present;
/*!
* \brief Determine if the signalling connection should be retained.
* \note TRUE if signalling connection to be retained.
* \note FALSE if signalling connection to be released.
*/
u_int8_t retain_sig_connection;
};
/*
* CcRequestRes ::= SEQUENCE {
* no-path-reservation [0] IMPLICIT BOOLEAN DEFAULT FALSE,
* retain-service [1] IMPLICIT BOOLEAN DEFAULT FALSE,
* extension CcExtension OPTIONAL
* }
*/
struct roseQsigCcRequestRes {
/*! \brief TRUE if no path reservation. (DEFAULT FALSE) */
u_int8_t no_path_reservation;
/*! \brief TRUE if agree to retain service (DEFAULT FALSE) */
u_int8_t retain_service;
};
/*
* CcOptionalArg ::= CHOICE {
* fullArg [0] IMPLICIT SEQUENCE {
* numberA PartyNumber,
* numberB PartyNumber,
*
* -- permitted information elements are:
* -- Bearer capability;
* -- Low layer compatibility;
* -- High layer compatibility.
* service PSS1InformationElement,
* subaddrA [10] EXPLICIT PartySubaddress OPTIONAL,
* subaddrB [11] EXPLICIT PartySubaddress OPTIONAL,
* extension CcExtension OPTIONAL
* },
* extArg CcExtension
* }
*/
struct roseQsigCcOptionalArg {
#if 1 /* The conditional is here to indicate fullArg values grouping. */
struct rosePartyNumber number_a;
struct rosePartyNumber number_b;
/*!
* \brief subaddrA (optional)
* The subaddress is present if the length is nonzero.
*/
struct rosePartySubaddress subaddr_a;
/*!
* \brief subaddrB (optional)
* The subaddress is present if the length is nonzero.
*/
struct rosePartySubaddress subaddr_b;
/*!
* \brief The BC, HLC (optional) and LLC (optional) information.
* \note The ASN.1 field name is service.
*/
struct roseQ931ie q931ie;
/*! \brief q931ie.contents "allocated" after the stucture. */
unsigned char q931ie_contents[ROSE_Q931_MAX_BC + ROSE_Q931_MAX_HLC +
ROSE_Q931_MAX_LLC + 1];
#endif /* end fullArg values */
/*! \brief TRUE if the fullArg values are present. */
u_int8_t full_arg_present;
};
/* ------------------------------------------------------------------- */
/*
* MsgCentreId ::= CHOICE {
* integer [0] IMPLICIT INTEGER (0..65535),
@ -3283,6 +3831,34 @@ union rose_msg_invoke_etsi_args {
struct roseEtsiSubaddressTransfer_ARG SubaddressTransfer;
struct roseEtsiEctInform_ARG EctInform;
struct roseEtsiEctLoopTest_ARG EctLoopTest;
/* ETSI Status Request (CCBS/CCNR support) */
struct roseEtsiStatusRequest_ARG StatusRequest;
/* ETSI CCBS/CCNR support */
struct roseEtsiCallInfoRetain_ARG CallInfoRetain;
struct roseEtsiEraseCallLinkageID_ARG EraseCallLinkageID;
struct roseEtsiCCBSDeactivate_ARG CCBSDeactivate;
struct roseEtsiCCBSErase_ARG CCBSErase;
struct roseEtsiCCBSRemoteUserFree_ARG CCBSRemoteUserFree;
struct roseEtsiCCBSCall_ARG CCBSCall;
struct roseEtsiCCBSStatusRequest_ARG CCBSStatusRequest;
struct roseEtsiCCBSBFree_ARG CCBSBFree;
struct roseEtsiCCBSStopAlerting_ARG CCBSStopAlerting;
/* ETSI CCBS */
struct roseEtsiCCBSRequest_ARG CCBSRequest;
struct roseEtsiCCBSInterrogate_ARG CCBSInterrogate;
/* ETSI CCNR */
struct roseEtsiCCBSRequest_ARG CCNRRequest;
struct roseEtsiCCBSInterrogate_ARG CCNRInterrogate;
/* ETSI CCBS-T */
struct roseEtsiCCBS_T_Request_ARG CCBS_T_Request;
/* ETSI CCNR-T */
struct roseEtsiCCBS_T_Request_ARG CCNR_T_Request;
};
/*! \brief Facility ie result etsi messages with arguments. */
@ -3297,6 +3873,26 @@ union rose_msg_result_etsi_args {
/* ETSI Explicit Call Transfer (ECT) */
struct roseEtsiEctLinkIdRequest_RES EctLinkIdRequest;
struct roseEtsiEctLoopTest_RES EctLoopTest;
/* ETSI Status Request (CCBS/CCNR support) */
struct roseEtsiStatusRequest_RES StatusRequest;
/* ETSI CCBS/CCNR support */
struct roseEtsiCCBSStatusRequest_RES CCBSStatusRequest;
/* ETSI CCBS */
struct roseEtsiCCBSRequest_RES CCBSRequest;
struct roseEtsiCCBSInterrogate_RES CCBSInterrogate;
/* ETSI CCNR */
struct roseEtsiCCBSRequest_RES CCNRRequest;
struct roseEtsiCCBSInterrogate_RES CCNRInterrogate;
/* ETSI CCBS-T */
struct roseEtsiCCBS_T_Request_RES CCBS_T_Request;
/* ETSI CCNR-T */
struct roseEtsiCCBS_T_Request_RES CCNR_T_Request;
};
/*! \brief Facility ie invoke qsig messages with arguments. */
@ -3333,6 +3929,12 @@ union rose_msg_invoke_qsig_args {
struct roseQsigDivertingLegInformation2_ARG DivertingLegInformation2;
struct roseQsigDivertingLegInformation3_ARG DivertingLegInformation3;
/* Q.SIG SS-CC-Operations */
struct roseQsigCcRequestArg CcbsRequest;
struct roseQsigCcRequestArg CcnrRequest;
struct roseQsigCcOptionalArg CcCancel;
struct roseQsigCcOptionalArg CcExecPossible;
/* Q.SIG SS-MWI-Operations */
struct roseQsigMWIActivateArg MWIActivate;
struct roseQsigMWIDeactivateArg MWIDeactivate;
@ -3351,6 +3953,10 @@ union rose_msg_result_qsig_args {
/* Q.SIG Call-Diversion-Operations */
struct roseQsigForwardingList InterrogateDiversionQ;
/* Q.SIG SS-CC-Operations */
struct roseQsigCcRequestRes CcbsRequest;
struct roseQsigCcRequestRes CcnrRequest;
/* Q.SIG SS-MWI-Operations */
struct roseQsigMWIInterrogateRes MWIInterrogate;
};

1853
rose_etsi_cc.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -238,6 +238,135 @@ const unsigned char *rose_dec_etsi_EctLoopTest_RES(struct pri *ctrl, unsigned ta
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* ETSI Status Request */
unsigned char *rose_enc_etsi_StatusRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_StatusRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_StatusRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_StatusRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* ETSI Call-Completion Busy Status (CCBS) / Call-Completion No Reply (CCNR) */
unsigned char *rose_enc_etsi_CallInfoRetain_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_EraseCallLinkageID_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSDeactivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSErase_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSRemoteUserFree_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSCall_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSBFree_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSStopAlerting_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSStatusRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSStatusRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCBSRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCNRRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCNRRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCBSInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCNRInterrogate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBSInterrogate_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCNRInterrogate_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CallInfoRetain_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_EraseCallLinkageID_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSDeactivate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSErase_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSRemoteUserFree_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSCall_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSBFree_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSStopAlerting_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSStatusRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSStatusRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCBSRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCNRRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCNRRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCBSInterrogate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCNRInterrogate_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBSInterrogate_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCNRInterrogate_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* ETSI CCBS-T/CCNR-T */
unsigned char *rose_enc_etsi_CCBS_T_Request_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCNR_T_Request_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_etsi_CCBS_T_Request_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_etsi_CCNR_T_Request_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCBS_T_Request_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCNR_T_Request_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_etsi_CCBS_T_Request_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_etsi_CCNR_T_Request_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
/* Q.SIG Name-Operations */
unsigned char *rose_enc_qsig_Name(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseQsigName *name);
@ -416,6 +545,64 @@ const unsigned char *rose_dec_qsig_SubaddressTransfer_ARG(struct pri *ctrl, unsi
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG SS-CC-Operations */
unsigned char *rose_enc_qsig_CcbsRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcnrRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcbsRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_qsig_CcnrRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enq_qsig_CcCancel_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enq_qsig_CcExecPossible_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcPathReserve_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcPathReserve_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args);
unsigned char *rose_enc_qsig_CcRingout_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcSuspend_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
unsigned char *rose_enc_qsig_CcResume_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcbsRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcnrRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcbsRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_CcnrRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_CcCancel_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcExecPossible_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcPathReserve_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcPathReserve_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_result_args *args);
const unsigned char *rose_dec_qsig_CcRingout_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcSuspend_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
const unsigned char *rose_dec_qsig_CcResume_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end,
union rose_msg_invoke_args *args);
/* Q.SIG SS-MWI-Operations */
unsigned char *rose_enc_qsig_MWIActivate_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args);

984
rose_qsig_cc.c Normal file
View File

@ -0,0 +1,984 @@
/*
* libpri: An implementation of Primary Rate ISDN
*
* Copyright (C) 2009 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*
* In addition, when this program is distributed with Asterisk in
* any form that would qualify as a 'combined work' or as a
* 'derivative work' (but not mere aggregation), you can redistribute
* and/or modify the combination under the terms of the license
* provided with that copy of Asterisk, instead of the license
* terms granted here.
*/
/*!
* \file
* \brief Q.SIG ROSE SS-CC-Operations (CC)
*
* SS-CC-Operations ECMA-186 Annex F Table F.1
*
* \author Richard Mudgett <rmudgett@digium.com>
*/
#include "compat.h"
#include "libpri.h"
#include "pri_internal.h"
#include "rose.h"
#include "rose_internal.h"
#include "asn1.h"
/* ------------------------------------------------------------------- */
/*!
* \internal
* \brief Encode the CcExtension type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*
* \details
* CcExtension ::= CHOICE {
* none NULL,
* single [14] IMPLICIT Extension,
* multiple [15] IMPLICIT SEQUENCE OF Extension
* }
*/
static unsigned char *rose_enc_qsig_CcExtension(struct pri *ctrl, unsigned char *pos,
unsigned char *end)
{
return asn1_enc_null(pos, end, ASN1_TYPE_NULL);
}
/*!
* \internal
* \brief Encode the CcRequestArg type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param cc_request_arg Call-completion request arguments to encode.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_CcRequestArg(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseQsigCcRequestArg *cc_request_arg)
{
unsigned char *seq_len;
unsigned char *exp_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
ASN1_CALL(pos, rose_enc_PresentedNumberUnscreened(ctrl, pos, end,
&cc_request_arg->number_a));
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &cc_request_arg->number_b));
ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
&cc_request_arg->q931ie));
if (cc_request_arg->subaddr_a.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 10);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&cc_request_arg->subaddr_a));
ASN1_CONSTRUCTED_END(exp_len, pos, end);
}
if (cc_request_arg->subaddr_b.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 11);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&cc_request_arg->subaddr_b));
ASN1_CONSTRUCTED_END(exp_len, pos, end);
}
if (cc_request_arg->can_retain_service) {
/* Not the DEFAULT value */
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 12,
cc_request_arg->can_retain_service));
}
if (cc_request_arg->retain_sig_connection_present) {
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 13,
cc_request_arg->retain_sig_connection));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CcbsRequest invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcbsRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcRequestArg(ctrl, pos, end, ASN1_TAG_SEQUENCE,
&args->qsig.CcbsRequest);
}
/*!
* \brief Encode the Q.SIG CcnrRequest invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcnrRequest_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcRequestArg(ctrl, pos, end, ASN1_TAG_SEQUENCE,
&args->qsig.CcnrRequest);
}
/*!
* \internal
* \brief Encode the CcRequestRes type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param tag Component tag to identify the encoded component.
* The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
* tags it otherwise.
* \param cc_request_res Call-completion request result to encode.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_CcRequestRes(struct pri *ctrl, unsigned char *pos,
unsigned char *end, unsigned tag, const struct roseQsigCcRequestRes *cc_request_res)
{
unsigned char *seq_len;
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
if (cc_request_res->no_path_reservation) {
/* Not the DEFAULT value */
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0,
cc_request_res->no_path_reservation));
}
if (cc_request_res->retain_service) {
/* Not the DEFAULT value */
ASN1_CALL(pos, asn1_enc_boolean(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
cc_request_res->retain_service));
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CcbsRequest result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcbsRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return rose_enc_qsig_CcRequestRes(ctrl, pos, end, ASN1_TAG_SEQUENCE,
&args->qsig.CcbsRequest);
}
/*!
* \brief Encode the Q.SIG CcnrRequest result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcnrRequest_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return rose_enc_qsig_CcRequestRes(ctrl, pos, end, ASN1_TAG_SEQUENCE,
&args->qsig.CcnrRequest);
}
/*!
* \internal
* \brief Encode the CcOptionalArg type.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param cc_optional_arg Call-completion optional arguments to encode.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
static unsigned char *rose_enc_qsig_CcOptionalArg(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const struct roseQsigCcOptionalArg *cc_optional_arg)
{
unsigned char *seq_len;
unsigned char *exp_len;
if (!cc_optional_arg->full_arg_present) {
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &cc_optional_arg->number_a));
ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &cc_optional_arg->number_b));
ASN1_CALL(pos, rose_enc_Q931ie(ctrl, pos, end, ASN1_CLASS_APPLICATION | 0,
&cc_optional_arg->q931ie));
if (cc_optional_arg->subaddr_a.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 10);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&cc_optional_arg->subaddr_a));
ASN1_CONSTRUCTED_END(exp_len, pos, end);
}
if (cc_optional_arg->subaddr_b.length) {
/* EXPLICIT tag */
ASN1_CONSTRUCTED_BEGIN(exp_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 11);
ASN1_CALL(pos, rose_enc_PartySubaddress(ctrl, pos, end,
&cc_optional_arg->subaddr_b));
ASN1_CONSTRUCTED_END(exp_len, pos, end);
}
/* No extension to encode */
ASN1_CONSTRUCTED_END(seq_len, pos, end);
return pos;
}
/*!
* \brief Encode the Q.SIG CcCancel invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enq_qsig_CcCancel_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcOptionalArg(ctrl, pos, end, &args->qsig.CcCancel);
}
/*!
* \brief Encode the Q.SIG CcExecPossible invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enq_qsig_CcExecPossible_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcOptionalArg(ctrl, pos, end, &args->qsig.CcExecPossible);
}
/*!
* \brief Encode the Q.SIG CcPathReserve invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcPathReserve_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \brief Encode the Q.SIG CcPathReserve result facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcPathReserve_RES(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_result_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \brief Encode the Q.SIG CcRingout invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcRingout_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \brief Encode the Q.SIG CcSuspend invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcSuspend_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \brief Encode the Q.SIG CcResume invoke facility ie arguments.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param pos Starting position to encode ASN.1 component.
* \param end End of ASN.1 encoding data buffer.
* \param args Arguments to encode in the buffer.
*
* \retval Start of the next ASN.1 component to encode on success.
* \retval NULL on error.
*/
unsigned char *rose_enc_qsig_CcResume_ARG(struct pri *ctrl, unsigned char *pos,
unsigned char *end, const union rose_msg_invoke_args *args)
{
return rose_enc_qsig_CcExtension(ctrl, pos, end);
}
/*!
* \internal
* \brief Decode the CcExtension argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*
* \details
* CcExtension ::= CHOICE {
* none NULL,
* single [14] IMPLICIT Extension,
* multiple [15] IMPLICIT SEQUENCE OF Extension
* }
*/
static const unsigned char *rose_dec_qsig_CcExtension(struct pri *ctrl, const char *name,
unsigned tag, const unsigned char *pos, const unsigned char *end)
{
int length;
int ext_offset;
const unsigned char *ext_end;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s CcExtension\n", name);
}
switch (tag & ~ASN1_PC_MASK) {
case ASN1_TYPE_NULL:
/* Must not be constructed but we will not check for it for simplicity. */
return asn1_dec_null(ctrl, "none", tag, pos, end);
case ASN1_CLASS_CONTEXT_SPECIFIC | 14:
name = "single";
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 15:
name = "multiple";
break;
default:
ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
return NULL;
}
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(ext_end, ext_offset, length, pos, end);
/* Fixup will skip over the manufacturer extension information */
ASN1_END_FIXUP(ctrl, pos, ext_offset, ext_end, end);
return pos;
}
/*!
* \internal
* \brief Decode the CcRequestArg argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param cc_request_arg Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_CcRequestArg(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigCcRequestArg *cc_request_arg)
{
int32_t value;
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s CcRequestArg %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PresentedNumberUnscreened(ctrl, "numberA", tag, pos, seq_end,
&cc_request_arg->number_a));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "numberB", tag, pos, seq_end,
&cc_request_arg->number_b));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_CLASS_APPLICATION | 0);
ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "service", tag, pos, seq_end,
&cc_request_arg->q931ie, sizeof(cc_request_arg->q931ie_contents)));
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
cc_request_arg->subaddr_a.length = 0;
cc_request_arg->subaddr_b.length = 0;
cc_request_arg->can_retain_service = 0; /* DEFAULT FALSE */
cc_request_arg->retain_sig_connection_present = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "subaddrA", tag, pos,
explicit_end, &cc_request_arg->subaddr_a));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 11:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "subaddrB", tag, pos,
explicit_end, &cc_request_arg->subaddr_b));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 12:
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "can-retain-service", tag, pos,
seq_end, &value));
cc_request_arg->can_retain_service = value;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 13:
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "retain-sig-connection", tag, pos,
seq_end, &value));
cc_request_arg->retain_sig_connection = value;
cc_request_arg->retain_sig_connection_present = 1;
break;
case ASN1_TYPE_NULL:
case ASN1_CLASS_CONTEXT_SPECIFIC | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | 15:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 15:
ASN1_CALL(pos, rose_dec_qsig_CcExtension(ctrl, "extension", tag, pos,
seq_end));
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CcbsRequest invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcbsRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
return rose_dec_qsig_CcRequestArg(ctrl, "CcbsRequest", tag, pos, end,
&args->qsig.CcbsRequest);
}
/*!
* \brief Decode the Q.SIG CcnrRequest invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcnrRequest_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
return rose_dec_qsig_CcRequestArg(ctrl, "CcnrRequest", tag, pos, end,
&args->qsig.CcnrRequest);
}
/*!
* \internal
* \brief Decode the CcRequestRes argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param cc_request_res Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_CcRequestRes(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigCcRequestRes *cc_request_res)
{
int32_t value;
int length;
int seq_offset;
const unsigned char *seq_end;
const unsigned char *save_pos;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s CcRequestRes %s\n", name, asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
cc_request_res->no_path_reservation = 0; /* DEFAULT FALSE */
cc_request_res->retain_service = 0; /* DEFAULT FALSE */
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | 0:
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "no-path-reservation", tag, pos,
seq_end, &value));
cc_request_res->no_path_reservation = value;
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
ASN1_CALL(pos, asn1_dec_boolean(ctrl, "retain-service", tag, pos, seq_end,
&value));
cc_request_res->retain_service = value;
break;
case ASN1_TYPE_NULL:
case ASN1_CLASS_CONTEXT_SPECIFIC | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | 15:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 15:
ASN1_CALL(pos, rose_dec_qsig_CcExtension(ctrl, "extension", tag, pos,
seq_end));
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CcbsRequest result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcbsRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
return rose_dec_qsig_CcRequestRes(ctrl, "CcbsRequest", tag, pos, end,
&args->qsig.CcbsRequest);
}
/*!
* \brief Decode the Q.SIG CcnrRequest result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcnrRequest_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
return rose_dec_qsig_CcRequestRes(ctrl, "CcnrRequest", tag, pos, end,
&args->qsig.CcnrRequest);
}
/*!
* \internal
* \brief Decode the CcOptionalArg argument parameters.
*
* \param ctrl D channel controller for any diagnostic messages.
* \param name Field name
* \param tag Component tag that identified this production.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param cc_optional_arg Parameter storage to fill.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
static const unsigned char *rose_dec_qsig_CcOptionalArg(struct pri *ctrl,
const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
struct roseQsigCcOptionalArg *cc_optional_arg)
{
int length;
int seq_offset;
int explicit_offset;
const unsigned char *explicit_end;
const unsigned char *seq_end;
const unsigned char *save_pos;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " %s CcOptionalArg\n", name);
}
if (tag != (ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0)) {
cc_optional_arg->full_arg_present = 0;
return rose_dec_qsig_CcExtension(ctrl, "extArg", tag, pos, end);
}
cc_optional_arg->full_arg_present = 1;
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " fullArg %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "numberA", tag, pos, seq_end,
&cc_optional_arg->number_a));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "numberB", tag, pos, seq_end,
&cc_optional_arg->number_b));
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
ASN1_CHECK_TAG(ctrl, tag, tag & ~ASN1_PC_MASK, ASN1_CLASS_APPLICATION | 0);
ASN1_CALL(pos, rose_dec_Q931ie(ctrl, "service", tag, pos, seq_end,
&cc_optional_arg->q931ie, sizeof(cc_optional_arg->q931ie_contents)));
/*
* A sequence specifies an ordered list of component types.
* However, for simplicity we are not checking the order of
* the remaining optional components.
*/
cc_optional_arg->subaddr_a.length = 0;
cc_optional_arg->subaddr_b.length = 0;
while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
save_pos = pos;
ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
switch (tag) {
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 10:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "subaddrA", tag, pos,
explicit_end, &cc_optional_arg->subaddr_a));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 11:
/* Remove EXPLICIT tag */
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
}
ASN1_CALL(pos, asn1_dec_length(pos, seq_end, &length));
ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, seq_end);
ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
ASN1_CALL(pos, rose_dec_PartySubaddress(ctrl, "subaddrB", tag, pos,
explicit_end, &cc_optional_arg->subaddr_b));
ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, seq_end);
break;
case ASN1_TYPE_NULL:
case ASN1_CLASS_CONTEXT_SPECIFIC | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 14:
case ASN1_CLASS_CONTEXT_SPECIFIC | 15:
case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 15:
ASN1_CALL(pos, rose_dec_qsig_CcExtension(ctrl, "extension", tag, pos,
seq_end));
break;
default:
pos = save_pos;
goto cancel_options;
}
}
cancel_options:;
ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
return pos;
}
/*!
* \brief Decode the Q.SIG CcCancel invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcCancel_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcOptionalArg(ctrl, "CcCancel", tag, pos, end,
&args->qsig.CcCancel);
}
/*!
* \brief Decode the Q.SIG CcExecPossible invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcExecPossible_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcOptionalArg(ctrl, "CcExecPossible", tag, pos, end,
&args->qsig.CcCancel);
}
/*!
* \brief Decode the Q.SIG CcPathReserve invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcPathReserve_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcPathReserve", tag, pos, end);
}
/*!
* \brief Decode the Q.SIG CcPathReserve result argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcPathReserve_RES(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcPathReserve", tag, pos, end);
}
/*!
* \brief Decode the Q.SIG CcRingout invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcRingout_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcRingout", tag, pos, end);
}
/*!
* \brief Decode the Q.SIG CcSuspend invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcSuspend_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcSuspend", tag, pos, end);
}
/*!
* \brief Decode the Q.SIG CcResume invoke argument parameters.
*
* \param ctrl D channel controller for diagnostic messages or global options.
* \param tag Component tag that identified this structure.
* \param pos Starting position of the ASN.1 component length.
* \param end End of ASN.1 decoding data buffer.
* \param args Arguments to fill in from the decoded buffer.
*
* \retval Start of the next ASN.1 component on success.
* \retval NULL on error.
*/
const unsigned char *rose_dec_qsig_CcResume_ARG(struct pri *ctrl, unsigned tag,
const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
{
return rose_dec_qsig_CcExtension(ctrl, "CcResume", tag, pos, end);
}
/* ------------------------------------------------------------------- */
/* end rose_qsig_cc.c */

View File

@ -951,6 +951,444 @@ static const struct rose_message rose_etsi_msgs[] = {
.component.result.invoke_id = 66,
.component.result.args.etsi.EctLoopTest.loop_result = 2,
},
/* Status Request */
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_StatusRequest,
.component.invoke.invoke_id = 13,
.component.invoke.args.etsi.StatusRequest.q931ie.length = 5,
.component.invoke.args.etsi.StatusRequest.q931ie_contents = "CDEZY",
.component.invoke.args.etsi.StatusRequest.compatibility_mode = 1,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_StatusRequest,
.component.result.invoke_id = 14,
.component.result.args.etsi.StatusRequest.status = 2,
},
/* CCBS support */
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CallInfoRetain,
.component.invoke.invoke_id = 15,
.component.invoke.args.etsi.CallInfoRetain.call_linkage_id = 115,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_EraseCallLinkageID,
.component.invoke.invoke_id = 16,
.component.invoke.args.etsi.EraseCallLinkageID.call_linkage_id = 105,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSDeactivate,
.component.invoke.invoke_id = 17,
.component.invoke.args.etsi.CCBSDeactivate.ccbs_reference = 2,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCBSDeactivate,
.component.result.invoke_id = 18,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSErase,
.component.invoke.invoke_id = 19,
.component.invoke.args.etsi.CCBSErase.q931ie.length = 2,
.component.invoke.args.etsi.CCBSErase.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSErase.address_of_b.number.plan = 0,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.length = 5,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.str = "33403",
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.type = 0,
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.length = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.u.user_specified.information = "3748",
.component.invoke.args.etsi.CCBSErase.recall_mode = 1,
.component.invoke.args.etsi.CCBSErase.ccbs_reference = 102,
.component.invoke.args.etsi.CCBSErase.reason = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSErase,
.component.invoke.invoke_id = 20,
.component.invoke.args.etsi.CCBSErase.q931ie.length = 2,
.component.invoke.args.etsi.CCBSErase.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSErase.address_of_b.number.plan = 1,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.length = 11,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.ton = 1,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.str = "18003020102",
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.type = 0,
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.length = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.u.user_specified.odd_count_present = 1,
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.u.user_specified.odd_count = 1,
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.u.user_specified.information = "3748",
.component.invoke.args.etsi.CCBSErase.recall_mode = 1,
.component.invoke.args.etsi.CCBSErase.ccbs_reference = 102,
.component.invoke.args.etsi.CCBSErase.reason = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSErase,
.component.invoke.invoke_id = 21,
.component.invoke.args.etsi.CCBSErase.q931ie.length = 2,
.component.invoke.args.etsi.CCBSErase.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSErase.address_of_b.number.plan = 2,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.length = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.str = "1803",
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.type = 1,
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.length = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.subaddress.u.nsap = "6492",
.component.invoke.args.etsi.CCBSErase.recall_mode = 1,
.component.invoke.args.etsi.CCBSErase.ccbs_reference = 102,
.component.invoke.args.etsi.CCBSErase.reason = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSErase,
.component.invoke.invoke_id = 22,
.component.invoke.args.etsi.CCBSErase.q931ie.length = 2,
.component.invoke.args.etsi.CCBSErase.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSErase.address_of_b.number.plan = 3,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.length = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.str = "1803",
.component.invoke.args.etsi.CCBSErase.recall_mode = 1,
.component.invoke.args.etsi.CCBSErase.ccbs_reference = 102,
.component.invoke.args.etsi.CCBSErase.reason = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSErase,
.component.invoke.invoke_id = 23,
.component.invoke.args.etsi.CCBSErase.q931ie.length = 2,
.component.invoke.args.etsi.CCBSErase.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSErase.address_of_b.number.plan = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.length = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.str = "1803",
.component.invoke.args.etsi.CCBSErase.recall_mode = 1,
.component.invoke.args.etsi.CCBSErase.ccbs_reference = 102,
.component.invoke.args.etsi.CCBSErase.reason = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSErase,
.component.invoke.invoke_id = 24,
.component.invoke.args.etsi.CCBSErase.q931ie.length = 2,
.component.invoke.args.etsi.CCBSErase.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSErase.address_of_b.number.plan = 5,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.length = 11,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.ton = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.str = "18003020102",
.component.invoke.args.etsi.CCBSErase.recall_mode = 1,
.component.invoke.args.etsi.CCBSErase.ccbs_reference = 102,
.component.invoke.args.etsi.CCBSErase.reason = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSErase,
.component.invoke.invoke_id = 25,
.component.invoke.args.etsi.CCBSErase.q931ie.length = 2,
.component.invoke.args.etsi.CCBSErase.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSErase.address_of_b.number.plan = 8,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.length = 4,
.component.invoke.args.etsi.CCBSErase.address_of_b.number.str = "1803",
.component.invoke.args.etsi.CCBSErase.recall_mode = 1,
.component.invoke.args.etsi.CCBSErase.ccbs_reference = 102,
.component.invoke.args.etsi.CCBSErase.reason = 3,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSRemoteUserFree,
.component.invoke.invoke_id = 26,
.component.invoke.args.etsi.CCBSRemoteUserFree.q931ie.length = 2,
.component.invoke.args.etsi.CCBSRemoteUserFree.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSRemoteUserFree.address_of_b.number.plan = 8,
.component.invoke.args.etsi.CCBSRemoteUserFree.address_of_b.number.length = 4,
.component.invoke.args.etsi.CCBSRemoteUserFree.address_of_b.number.str = "1803",
.component.invoke.args.etsi.CCBSRemoteUserFree.recall_mode = 1,
.component.invoke.args.etsi.CCBSRemoteUserFree.ccbs_reference = 102,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSCall,
.component.invoke.invoke_id = 27,
.component.invoke.args.etsi.CCBSCall.ccbs_reference = 115,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSStatusRequest,
.component.invoke.invoke_id = 28,
.component.invoke.args.etsi.CCBSStatusRequest.q931ie.length = 2,
.component.invoke.args.etsi.CCBSStatusRequest.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSStatusRequest.recall_mode = 1,
.component.invoke.args.etsi.CCBSStatusRequest.ccbs_reference = 102,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCBSStatusRequest,
.component.result.invoke_id = 29,
.component.result.args.etsi.CCBSStatusRequest.free = 1,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSBFree,
.component.invoke.invoke_id = 30,
.component.invoke.args.etsi.CCBSBFree.q931ie.length = 2,
.component.invoke.args.etsi.CCBSBFree.q931ie_contents = "JK",
.component.invoke.args.etsi.CCBSBFree.address_of_b.number.plan = 8,
.component.invoke.args.etsi.CCBSBFree.address_of_b.number.length = 4,
.component.invoke.args.etsi.CCBSBFree.address_of_b.number.str = "1803",
.component.invoke.args.etsi.CCBSBFree.recall_mode = 1,
.component.invoke.args.etsi.CCBSBFree.ccbs_reference = 14,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSStopAlerting,
.component.invoke.invoke_id = 31,
.component.invoke.args.etsi.CCBSStopAlerting.ccbs_reference = 37,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSRequest,
.component.invoke.invoke_id = 32,
.component.invoke.args.etsi.CCBSRequest.call_linkage_id = 57,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCBSRequest,
.component.result.invoke_id = 33,
.component.result.args.etsi.CCBSRequest.recall_mode = 1,
.component.result.args.etsi.CCBSRequest.ccbs_reference = 102,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSInterrogate,
.component.invoke.invoke_id = 34,
.component.invoke.args.etsi.CCBSInterrogate.a_party_number.plan = 8,
.component.invoke.args.etsi.CCBSInterrogate.a_party_number.length = 4,
.component.invoke.args.etsi.CCBSInterrogate.a_party_number.str = "1803",
.component.invoke.args.etsi.CCBSInterrogate.ccbs_reference_present = 1,
.component.invoke.args.etsi.CCBSInterrogate.ccbs_reference = 76,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSInterrogate,
.component.invoke.invoke_id = 35,
.component.invoke.args.etsi.CCBSInterrogate.a_party_number.plan = 8,
.component.invoke.args.etsi.CCBSInterrogate.a_party_number.length = 4,
.component.invoke.args.etsi.CCBSInterrogate.a_party_number.str = "1803",
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSInterrogate,
.component.invoke.invoke_id = 36,
.component.invoke.args.etsi.CCBSInterrogate.ccbs_reference_present = 1,
.component.invoke.args.etsi.CCBSInterrogate.ccbs_reference = 76,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBSInterrogate,
.component.invoke.invoke_id = 37,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCBSInterrogate,
.component.result.invoke_id = 38,
.component.result.args.etsi.CCBSInterrogate.recall_mode = 1,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCBSInterrogate,
.component.result.invoke_id = 39,
.component.result.args.etsi.CCBSInterrogate.recall_mode = 1,
.component.result.args.etsi.CCBSInterrogate.call_details.num_records = 1,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].ccbs_reference = 12,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].q931ie.length = 2,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].q931ie_contents = "JK",
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].address_of_b.number.plan = 8,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].address_of_b.number.length = 4,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].address_of_b.number.str = "1803",
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].subaddress_of_a.type = 1,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].subaddress_of_a.length = 4,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].subaddress_of_a.u.nsap = "6492",
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCBSInterrogate,
.component.result.invoke_id = 40,
.component.result.args.etsi.CCBSInterrogate.recall_mode = 1,
.component.result.args.etsi.CCBSInterrogate.call_details.num_records = 2,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].ccbs_reference = 12,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].q931ie.length = 2,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].q931ie_contents = "JK",
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].address_of_b.number.plan = 8,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].address_of_b.number.length = 4,
.component.result.args.etsi.CCBSInterrogate.call_details.list[0].address_of_b.number.str = "1803",
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].ccbs_reference = 102,
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].q931ie.length = 2,
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].q931ie_contents = "LM",
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].address_of_b.number.plan = 8,
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].address_of_b.number.length = 4,
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].address_of_b.number.str = "6229",
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].address_of_b.subaddress.type = 1,
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].address_of_b.subaddress.length = 4,
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].address_of_b.subaddress.u.nsap = "8592",
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].subaddress_of_a.type = 1,
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].subaddress_of_a.length = 4,
.component.result.args.etsi.CCBSInterrogate.call_details.list[1].subaddress_of_a.u.nsap = "6492",
},
/* CCNR support */
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCNRRequest,
.component.invoke.invoke_id = 512,
.component.invoke.args.etsi.CCNRRequest.call_linkage_id = 57,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCNRRequest,
.component.result.invoke_id = 150,
.component.result.args.etsi.CCNRRequest.recall_mode = 1,
.component.result.args.etsi.CCNRRequest.ccbs_reference = 102,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCNRInterrogate,
.component.invoke.invoke_id = -129,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCNRInterrogate,
.component.result.invoke_id = -3,
.component.result.args.etsi.CCNRInterrogate.recall_mode = 1,
},
/* CCBS-T */
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Call,
.component.invoke.invoke_id = 41,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Suspend,
.component.invoke.invoke_id = 42,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Resume,
.component.invoke.invoke_id = 43,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_RemoteUserFree,
.component.invoke.invoke_id = 44,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Available,
.component.invoke.invoke_id = 45,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Request,
.component.invoke.invoke_id = 46,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.plan = 8,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.length = 4,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.str = "6229",
.component.invoke.args.etsi.CCBS_T_Request.q931ie.length = 2,
.component.invoke.args.etsi.CCBS_T_Request.q931ie_contents = "LM",
.component.invoke.args.etsi.CCBS_T_Request.retention_supported = 1,
.component.invoke.args.etsi.CCBS_T_Request.presentation_allowed_indicator_present = 1,
.component.invoke.args.etsi.CCBS_T_Request.presentation_allowed_indicator = 1,
.component.invoke.args.etsi.CCBS_T_Request.originating.number.plan = 8,
.component.invoke.args.etsi.CCBS_T_Request.originating.number.length = 4,
.component.invoke.args.etsi.CCBS_T_Request.originating.number.str = "9864",
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Request,
.component.invoke.invoke_id = 47,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.plan = 8,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.length = 4,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.str = "6229",
.component.invoke.args.etsi.CCBS_T_Request.q931ie.length = 2,
.component.invoke.args.etsi.CCBS_T_Request.q931ie_contents = "LM",
.component.invoke.args.etsi.CCBS_T_Request.presentation_allowed_indicator_present = 1,
.component.invoke.args.etsi.CCBS_T_Request.presentation_allowed_indicator = 1,
.component.invoke.args.etsi.CCBS_T_Request.originating.number.plan = 8,
.component.invoke.args.etsi.CCBS_T_Request.originating.number.length = 4,
.component.invoke.args.etsi.CCBS_T_Request.originating.number.str = "9864",
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Request,
.component.invoke.invoke_id = 48,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.plan = 8,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.length = 4,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.str = "6229",
.component.invoke.args.etsi.CCBS_T_Request.q931ie.length = 2,
.component.invoke.args.etsi.CCBS_T_Request.q931ie_contents = "LM",
.component.invoke.args.etsi.CCBS_T_Request.originating.number.plan = 8,
.component.invoke.args.etsi.CCBS_T_Request.originating.number.length = 4,
.component.invoke.args.etsi.CCBS_T_Request.originating.number.str = "9864",
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Request,
.component.invoke.invoke_id = 49,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.plan = 8,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.length = 4,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.str = "6229",
.component.invoke.args.etsi.CCBS_T_Request.q931ie.length = 2,
.component.invoke.args.etsi.CCBS_T_Request.q931ie_contents = "LM",
.component.invoke.args.etsi.CCBS_T_Request.presentation_allowed_indicator_present = 1,
.component.invoke.args.etsi.CCBS_T_Request.presentation_allowed_indicator = 1,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCBS_T_Request,
.component.invoke.invoke_id = 50,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.plan = 8,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.length = 4,
.component.invoke.args.etsi.CCBS_T_Request.destination.number.str = "6229",
.component.invoke.args.etsi.CCBS_T_Request.q931ie.length = 2,
.component.invoke.args.etsi.CCBS_T_Request.q931ie_contents = "LM",
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCBS_T_Request,
.component.result.invoke_id = 51,
.component.result.args.etsi.CCBS_T_Request.retention_supported = 1,
},
/* CCNR-T */
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_ETSI_CCNR_T_Request,
.component.invoke.invoke_id = 52,
.component.invoke.args.etsi.CCNR_T_Request.destination.number.plan = 8,
.component.invoke.args.etsi.CCNR_T_Request.destination.number.length = 4,
.component.invoke.args.etsi.CCNR_T_Request.destination.number.str = "6229",
.component.invoke.args.etsi.CCNR_T_Request.q931ie.length = 2,
.component.invoke.args.etsi.CCNR_T_Request.q931ie_contents = "LM",
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_ETSI_CCNR_T_Request,
.component.result.invoke_id = 53,
.component.result.args.etsi.CCNR_T_Request.retention_supported = 1,
},
/* *INDENT-ON* */
};
@ -1975,6 +2413,143 @@ static const struct rose_message rose_qsig_msgs[] = {
.component.invoke.invoke_id = 86,
},
/* Q.SIG SS-CC-Operations */
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcbsRequest,
.component.invoke.invoke_id = 87,
.component.invoke.args.qsig.CcbsRequest.number_a.presentation = 1,
.component.invoke.args.qsig.CcbsRequest.number_b.plan = 4,
.component.invoke.args.qsig.CcbsRequest.number_b.length = 4,
.component.invoke.args.qsig.CcbsRequest.number_b.str = "8347",
.component.invoke.args.qsig.CcbsRequest.q931ie.length = 2,
.component.invoke.args.qsig.CcbsRequest.q931ie_contents = "AB",
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcbsRequest,
.component.invoke.invoke_id = 88,
.component.invoke.args.qsig.CcbsRequest.number_a.presentation = 1,
.component.invoke.args.qsig.CcbsRequest.number_b.plan = 4,
.component.invoke.args.qsig.CcbsRequest.number_b.length = 4,
.component.invoke.args.qsig.CcbsRequest.number_b.str = "8347",
.component.invoke.args.qsig.CcbsRequest.q931ie.length = 2,
.component.invoke.args.qsig.CcbsRequest.q931ie_contents = "AB",
.component.invoke.args.qsig.CcbsRequest.subaddr_a.type = 1,
.component.invoke.args.qsig.CcbsRequest.subaddr_a.length = 4,
.component.invoke.args.qsig.CcbsRequest.subaddr_a.u.nsap = "8765",
.component.invoke.args.qsig.CcbsRequest.subaddr_b.type = 1,
.component.invoke.args.qsig.CcbsRequest.subaddr_b.length = 4,
.component.invoke.args.qsig.CcbsRequest.subaddr_b.u.nsap = "8765",
.component.invoke.args.qsig.CcbsRequest.can_retain_service = 1,
.component.invoke.args.qsig.CcbsRequest.retain_sig_connection_present = 1,
.component.invoke.args.qsig.CcbsRequest.retain_sig_connection = 1,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_QSIG_CcbsRequest,
.component.result.invoke_id = 89,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_QSIG_CcbsRequest,
.component.result.invoke_id = 90,
.component.result.args.qsig.CcbsRequest.no_path_reservation = 1,
.component.result.args.qsig.CcbsRequest.retain_service = 1,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcnrRequest,
.component.invoke.invoke_id = 91,
.component.invoke.args.qsig.CcnrRequest.number_a.presentation = 1,
.component.invoke.args.qsig.CcnrRequest.number_b.plan = 4,
.component.invoke.args.qsig.CcnrRequest.number_b.length = 4,
.component.invoke.args.qsig.CcnrRequest.number_b.str = "8347",
.component.invoke.args.qsig.CcnrRequest.q931ie.length = 2,
.component.invoke.args.qsig.CcnrRequest.q931ie_contents = "AB",
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_QSIG_CcnrRequest,
.component.result.invoke_id = 92,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcCancel,
.component.invoke.invoke_id = 93,
.component.invoke.args.qsig.CcCancel.full_arg_present = 0,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcCancel,
.component.invoke.invoke_id = 94,
.component.invoke.args.qsig.CcCancel.full_arg_present = 1,
.component.invoke.args.qsig.CcCancel.number_a.plan = 4,
.component.invoke.args.qsig.CcCancel.number_a.length = 4,
.component.invoke.args.qsig.CcCancel.number_a.str = "8347",
.component.invoke.args.qsig.CcCancel.number_b.plan = 4,
.component.invoke.args.qsig.CcCancel.number_b.length = 4,
.component.invoke.args.qsig.CcCancel.number_b.str = "8347",
.component.invoke.args.qsig.CcCancel.q931ie.length = 2,
.component.invoke.args.qsig.CcCancel.q931ie_contents = "AB",
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcCancel,
.component.invoke.invoke_id = 95,
.component.invoke.args.qsig.CcCancel.full_arg_present = 1,
.component.invoke.args.qsig.CcCancel.number_a.plan = 4,
.component.invoke.args.qsig.CcCancel.number_a.length = 4,
.component.invoke.args.qsig.CcCancel.number_a.str = "8347",
.component.invoke.args.qsig.CcCancel.number_b.plan = 4,
.component.invoke.args.qsig.CcCancel.number_b.length = 4,
.component.invoke.args.qsig.CcCancel.number_b.str = "8347",
.component.invoke.args.qsig.CcCancel.q931ie.length = 2,
.component.invoke.args.qsig.CcCancel.q931ie_contents = "AB",
.component.invoke.args.qsig.CcCancel.subaddr_a.type = 1,
.component.invoke.args.qsig.CcCancel.subaddr_a.length = 4,
.component.invoke.args.qsig.CcCancel.subaddr_a.u.nsap = "8765",
.component.invoke.args.qsig.CcCancel.subaddr_b.type = 1,
.component.invoke.args.qsig.CcCancel.subaddr_b.length = 4,
.component.invoke.args.qsig.CcCancel.subaddr_b.u.nsap = "8765",
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcExecPossible,
.component.invoke.invoke_id = 96,
.component.invoke.args.qsig.CcExecPossible.full_arg_present = 0,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcPathReserve,
.component.invoke.invoke_id = 97,
},
{
.type = ROSE_COMP_TYPE_RESULT,
.component.result.operation = ROSE_QSIG_CcPathReserve,
.component.result.invoke_id = 98,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcRingout,
.component.invoke.invoke_id = 99,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcSuspend,
.component.invoke.invoke_id = 100,
},
{
.type = ROSE_COMP_TYPE_INVOKE,
.component.invoke.operation = ROSE_QSIG_CcResume,
.component.invoke.invoke_id = 101,
},
/* Q.SIG SS-MWI-Operations */
{
.type = ROSE_COMP_TYPE_INVOKE,
@ -2455,6 +3030,8 @@ int main(int argc, char *argv[])
(unsigned) sizeof(struct roseEtsiForwardingList));
pri_message(&dummy_ctrl, "sizeof(struct roseEtsiServedUserNumberList) = %u\n",
(unsigned) sizeof(struct roseEtsiServedUserNumberList));
pri_message(&dummy_ctrl, "sizeof(struct roseEtsiCallDetailsList) = %u\n",
(unsigned) sizeof(struct roseEtsiCallDetailsList));
pri_message(&dummy_ctrl, "\n");
pri_message(&dummy_ctrl, "sizeof(struct roseEtsiCallRerouting_ARG) = %u\n",