Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


Example showing the use of the SIP Client API

This is a collection of code that shows the use of the SIP Client API.

1

Use of the SIP Client API is initiated by creating the CSIP and CSIPConnection objects:

iSIP = CSIP::NewL(KAppUid, *iMySIPObserver);
iConnection = CSIPConnection::NewL(*iSIP, KIapIdentifier,*iMyConnectionObserver);

2

To publish a user’s SIP contact address, a SIP registration is created. This requires an AOR, a contact to be registered and, in this example, a CSIPRefresh is created to cause the registration to be automatically refreshed by the SIP stack.

In the code below, localhost indicates the request for the SIP stack to replace it with a local address; i.e. sip:user@localhost means that the SIP stack will replace localhost with the local IP address.

CSIPToHeader* aor = CSIPToHeader::DecodeL(_L8("sip:[email protected]"));
CleanupStack::PushL(aor);

CSIPAddress* addr = CSIPAddress::DecodeL(_L8("sip:user@LOCALHOST"));
CleanupStack::PushL(addr);
CSIPContactHeader* contact = CSIPContactHeader::NewL(addr);
CleanupStack::Pop(addr);
CleanupStack::PushL(contact);

CSIPRefresh* refresh = CSIPRefresh::NewLC();

iRegistration = CSIPRegistrationBinding::NewL(*iConnection, aor, contact, refresh);

CleanupStack::Pop(3); //refresh, contact, aor

3

Once the CSIPRegistrationBinding object has been created, a REGISTER transaction can be initiated.

iRegisterTransaction = iRegistration->RegisterL();

4

When a 2xx response is received, the registration is active. As a final response was received, the transaction can be deleted.

void CMyConnectionObserver::IncomingResponse(CSIPClientTransaction& aTransaction,
                  CSIPRegistrationBinding& aRegistration)
    {
    if (aRegistration.IsContextActive())
        {
        // Registration has succeeded
        }

    if (aTransaction.ResponseElements()->StatusCode() >= 200)
        {
        // Final response received, transaction is no longer needed

        if (aTransaction == *iRegisterTransaction)
            {
            delete iRegisterTransaction;
            iRegisterTransaction = NULL;
            }
        }
    }

5

An INVITE request is received from the network. In this example, it is received through a different IAP than the one for which there already exists a CSIPConnection. A CSIPConnection instance is created also for this IAP.

void CMySIPObserver::IncomingRequest(TUint32 aIapId,                                    CSIPServerTransaction* aTransaction)
    {
    // Create an observer for the new CSIPConnection
    TRAPD(err, iMyOtherConnectionObserver = CMyConnectionObserver::NewL());
    // Handle leave condition

    // Create a new connection for the IAP
    TRAP(err, iOtherConnection = CSIPConnection::NewL(*iSIP, aIapId,
                                   *iMyOtherConnectionObserver));
    // Handle leave condition

    // Application owns the transaction
    iInviteServerTransaction = aTransaction;
    }

6

As the received request is an INVITE, and the application intends to send a response (101-299) that will create a SIP dialog, CSIPInviteDialogAssoc needs to be created before sending the response.

iInviteAssoc = CSIPInviteDialogAssoc::NewL(*iInviteServerTransaction);

CSIPResponseElements* response = CSIPResponseElements::NewLC(180, “Ringing”);

iInviteServerTransaction->SendResponseL(response);
CleanupStack::Pop(response);

7

When the user has accepted the INVITE, a 200 response is sent using the same transaction object. Since sending a 2xx response to an INVITE causes the transaction to enter the CSIPTransactionBase::ETerminated state, the transaction can be deleted.

CSIPResponseElements* response = CSIPResponseElements::NewLC(200, “OK”);
            
iInviteServerTransaction->SendResponseL(response);
CleanupStack::Pop(response);

delete iInviteServerTransaction;
iInviteServerTransaction = NULL;

8

When the ACK request arrives, SIP Client API creates a new CSIPServerTransaction and passes the transaction object to the application using MSIPConnectionObserver of the IAP through which the ACK was received. No response is sent to an ACK, so the transaction object can be deleted.

void CMyConnectionObserver::IncomingRequest(CSIPServerTransaction* aTransaction,
                                     CSIPDialog& aDialog)
    {
    if (aTransaction.Type() == SIPStrings::StringF(SipStrConsts::EAck))
        {
        // Might inspect the Content part of the ACK for SDP etc.

        // No response will be sent to an ACK
        delete aTransaction;
        }
    else
        {
        // Handle other requests
        }
    }

9

The following is an example code of getting transaction timers values from the Central Repository.

#include <centralrepository.h>
#include <SIPSDKCRKeys.h>

TInt timerT1 = 0;
TInt timerT2 = 0;
CRepository* repository = CRepository::NewLC(KCRUidSIP);
User::LeaveIfError(repository->Get(KSIPTransactionTimerT1,timerT1));
User::LeaveIfError(repository->Get(KSIPTransactionTimerT2,timerT2));
CleanupStack::PopAndDestroy(repository);

10

The following is an example of extension headers definition with SIP Client API.

void CMyClass::ExtractHeadersL( CSIPMessageElements& aElements )
    {
    const RPointerArray<CSIPHeaderBase>& userHeaders = 
        aElements.UserHeaders();

    for ( TInt i = 0; i < userHeaders.Count(); i++ )
        {
        const CSIPHeaderBase* header = userHeaders[ i ];
        
        // An example of a known already supported header.
        // This can be casted to the actual class.
        // It will be supported also in the future and does not cause SC/BC
        // problems.
        //
        if ( header->Name() == SIPStrings::StringF( SipStrConsts::ERAckHeader ) )
             {
             iRAckHeader = static_cast<CSIPRAckHeader*>(header->CloneL());
             }
         
        // An example of a SIP header that is currently supported as an exten-
        // sion.
        // The application must NOT make a static cast to CSIPExtensionHeader.
        // Instead it must use CSIPHeaderBase::ToTextValueL and parse the result.
        //
        RStringF extensionName = SIPStrings::Pool().OpenFStringL( L8("Extension") );
        CleanupClosePushL( extensionName ); 
        if ( header->Name() == extensionName )
            {
            HBufC8* headerValue = header->ToTextValueLC();
            
            // Do application specific parsing and handling for the header
 
            CleanupStack::PopAndDestroy( headerValue );
            }
        CleanupStack::PopAndDestroy( 1 ); // extensionName
        }
    }