Before calling any SCCP service functions, the application must:
Refer to the Natural Access Developer's Reference Manual for more information about Natural Access.
The Natural Access environment is initialized by calling ctaInitialize. Initialize Natural Access only once per application, regardless of the number of queues and contexts created.
CTA_INIT_PARMS sccpInitparms = {0};
CTA_SERVICE_NAME sccpServiceNames[] = {{"SCCP", "SCCPMGR"}};
...
sccpInitparms.size = sizeof(CTA_INIT_PARMS);
sccpInitparms.traceflags = CTA_TRACE_ENABLE;
sccpInitparms.parmflags = CTA_PARM_MGMT_SHARED;
sccpInitparms.ctacompatlevel = CTA_COMPATLEVEL;
Ret = ctaInitialize(sccpServiceNames, 1, &sccpInitparms);
if (Ret != SUCCESS) {
printf("ERROR code 0x%08x initializing Natural Access.", Ret);
exit( 1 );
}
The application creates the required Natural Access queues and contexts. The queue must always be created before any associated context is created.
CTAHD ctaHd; /* CTA context handle */
CTAQUEUEHD ctaQueue; /* Queue */
...
Ret = ctaCreateQueue( NULL, 0, &ctaQueue );
if ( Ret != SUCCESS )
{
ctaGetText( NULL_CTAHD, Ret, sErr, sizeof( sErr ) );
printf( "*ERROR : ctaCreateQueue failed( %s )\n", sErr );
...
}
sprintf( contextName, "SccpSAP-%d", spId ); /* context name is optional */
Ret = ctaCreateContext( ctaQueue, spId, contextName, &ctaHd );
if ( Ret != SUCCESS )
{
ctaGetText( NULL_CTAHD, Ret, sErr, sizeof( sErr ) );
printf( "ERROR : ctaCreateContext failed( %s )\n", sErr );
ctaDestroyQueue( pSap->ctaQueue );
...
}
Once the queues and contexts are created, the application must bind to each desired SCCP user service access point by calling ctaOpenServices once for each binding. The binding operation specifies the following parameters:
Parameter |
Description |
board |
TX board number. |
srcEnt |
Calling application entity ID. |
srcInst |
Calling application instance ID. |
suId |
Calling application service user ID. |
spId |
SCCP service access point ID on which to bind. |
ssn |
SCCP subsystem number associated with the service access point. |
poolsize |
Number of messages allowed to be queued to the TX board. Default value is 128. Maximum value of 1024. |
In Natural Access, these parameters are specified in the CTA_SERVICE_ARGS structure, contained in the CTA_SERVICE_DESC structure. An example of the parameter specification is provided:
CTA_SERVICE_DESC sccpOpenSvcLst[] = {{{"SCCP", "SCCPMGR"}, {0}, {0}, {0}}};
sccpOpenSvcLst[0].svcargs.args[0] = board; /* board number */
sccpOpenSvcLst[0].svcargs.args[1] = INST_ID; /* srcInst */
sccpOpenSvcLst[0].svcargs.args[2] = ENT_ID; /* srcEnt */
sccpOpenSvcLst[0].svcargs.args[3] = 0; /* reserved for future use */
sccpOpenSvcLst[0].svcargs.args[4] = SAP_ID; /* spId */
sccpOpenSvcLst[0].svcargs.args[5] = SAP_ID; /* suId */
sccpOpenSvcLst[0].svcargs.args[6] = DST_SSN; /* subsystem number */
sccpOpenSvcLst[0].svcargs.args[7] = 0; /* reserved for future use */
sccpOpenSvcLst[0].svcargs.args[7] = poolsize /* number of queued msgs. */
ctaOpenServices is an asynchronous function. The return from the function indicates that the bind operation initiated. Once completed, a CTAEVN_OPEN_SERVICES_DONE event is returned to the application.
If multiple contexts are assigned to the same queue, all of the contexts must use the same entity ID in the service arguments parameter. Conversely, contexts bound to different queues must specify unique entity IDs.
CTA_EVENT event; /* Event structure to wait for SCCP events */
...
Ret = ctaOpenServices( ctaHd, sccpOpenSvcLst, 1 );
if ( Ret != SUCCESS )
{
ctaGetText( NULL_CTAHD, Ret, sErr, sizeof( sErr ) );
printf( "ERROR : ctaOpenServices failed( %s )\n", sErr );
ctaDestroyQueue( ctaQueue ); /* destroys context too */
return(...)
}
/* Wait for "open services" to complete; note: this loop
* assumes no other contexts are already active on the queue
* we're waiting on, so no other events will be received that
* need handling
*/
event.id = CTAEVN_NULL_EVENT;
do
{
ctaWaitEvent( ctaQueue, &event, 5000 );
}
while( (event.id != CTAEVN_OPEN_SERVICES_DONE) &&
(event.id != CTAEVN_WAIT_TIMEOUT) );
/* check if binding succeeded */
if( (pSap->event.id != CTAEVN_OPEN_SERVICES_DONE) ||
(pSap->event.value != CTA_REASON_FINISHED) )
{
ctaGetText( event.ctahd, event.value, sErr, sizeof( sErr ) );
printf( "ERROR opening SCCP service [%s]\n", sErr );
ctaDestroyQueue( pSap->ctaQueue ); /* destroys context too */
return( ... );
}
The previous example is only correct if the application uses a separate queue for each context/service instance. If the application opens multiple service instances against the same queue, either multiple SAPs on the same board or on multiple boards (in a redundant configuration), it must process events (call SCCPRetrieveMessage) for other contexts while waiting for the CTAEVN_OPEN_SERVICES_DONE event. Failure to do so can result in an infinite loop.
It is also recommended that the application call SCCPStateRqst and mark the subsystem in service as soon as it is ready to handle data traffic, in case the subsystem was previously left out of service by an application unbinding from the same SCCP service access point.