This is a collection of code that shows the use of the SIP Client API.
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);
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
Once the CSIPRegistrationBinding
object has been
created, a REGISTER
transaction can be initiated.
iRegisterTransaction = iRegistration->RegisterL();
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;
}
}
}
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;
}
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);
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;
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
}
}
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);
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
}
}