Example of a SIP Client Resolver Plug-in

This is an example of a SIP Client Resolver plug-in called CSimpleAppLauncher.

In this example, the plug-in capabilities are not defined in a resource file but are defined in the implementation as the KCapabilities literal descriptor.

If capabilities are defined in the resource file instead of within the implementation, they are defined in the opaque_data field in XML format. See Example of capabilities definition in XML format.

Implementation of CSimpleAppLauncher using CSIPResolvedClient interface

CSimpleAppLauncher.H

#include "SipResolvedClient.h"

class CSimpleAppLauncher : public CSIPResolvedClient
{
public:    // Constructors and destructor
/**
 * Static constructor
 * @return An initialized instance of this class.
 */
static CSimpleAppLauncher* NewL();

/// Destructor
~CSimpleAppLauncher();

public: // from CSIPResolvedClient
TUid ChannelL(RStringF aMethod, 
      const TDesC8& aRequestUri,
      const RPointerArray<CSIPHeaderBase>& aHeaders,
      const TDesC8& aContent,
      const CSIPContentTypeHeader* aContentType=0);

void ConnectL(TUid aUid);

const TDesC8& Capabilities();

private: // Constructors

inline CSimpleAppLauncher() {}

// Second phase constructor
void ConstructL(); 
};

CSimpleAppLauncher.CPP

#include "CSimpleAppLauncher.h"

const TUid KMyApplicationUid = { 0x101F5D45 }; 

_LIT8(KCapabilities,
"<SIP_CLIENT ALLOW_STARTING=\"YES\"><SIP_HEADERS>\
<ACCEPT value=\"text/plain\"/></SIP_HEADERS></SIP_CLIENT>");

// -----------------------------------------------------------------------------
// CSimpleAppLauncher::NewL
// -----------------------------------------------------------------------------
//
CSimpleAppLauncher* CSimpleAppLauncher::NewL()
{
CSimpleAppLauncher* self = new( ELeave ) CSimpleAppLauncher;
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}

// -----------------------------------------------------------------------------
// CSimpleAppLauncher::ConstructL
// -----------------------------------------------------------------------------
//
void CSimpleAppLauncher::ConstructL()
{
}

// -----------------------------------------------------------------------------
// CSimpleAppLauncher::~CSimpleAppLauncher
// -----------------------------------------------------------------------------
//
CSimpleAppLauncher::~CSimpleAppLauncher()
{
}

// -----------------------------------------------------------------------------
// CSimpleAppLauncher::ChannelL
// -----------------------------------------------------------------------------
//
TUid CSimpleAppLauncher::ChannelL(RStringF /*aMethod*/,
const TDesC8& /*aRequestUri*/,
const RPointerArray<CSIPHeaderBase>& /*aHeaders*/,
const TDesC8& /*aContent*/,
const CSIPContentTypeHeader* /*aContentType*/)
{
// In the basic case application wants all the requests to itself
return KMyApplicationUid;

}

// -----------------------------------------------------------------------------
// CSimpleAppLauncher::ConnectL
// -----------------------------------------------------------------------------
//
void CSimpleAppLauncher::ConnectL(TUid aUid)
{
// application specific starting logic that leads to 
// the connection with the SIP. The same UID must be
// provided to SIP while invoking CSIP::NewL().
}
    

// -----------------------------------------------------------------------------
// CSimpleAppLauncher::Capabilities
// -----------------------------------------------------------------------------
//
const TDesC8& CSimpleAppLauncher::Capabilities()
{
// if an application did not provide capabilities in the
// ECOM rsc-file this function will be invoked by the 
// resolution logic implementation.
return KCapabilities;
}

00000001.RSS

00000001.RSS 
#include <RegistryInfo.rh>

RESOURCE REGISTRY_INFO theInfo
   {
   // UID for the DLL
   dll_uid = 0x00000001;
   // Declare array of interface info
   interfaces = 
      {
      INTERFACE_INFO
         {
         // UID of interface that is implemented
         interface_uid = 0x102010DD;
         implementations = 
            {
            IMPLEMENTATION_INFO
               {
               implementation_uid = 0x00000001;
               version_no = 1;
               default_data = "101F5D45"; // SIP client application UID SIPTestUI in this case)
               }
            };
         }
     };
 }

Example of capabilities definition in XML format

This is an example of defining capabilities in XML format.

<SIP_CLIENT ALLOW_STARTING="YES">
<SIP_HEADERS>
<ACCEPT_CONTACT value="*;mobility="mobile";media="audio"" /> 
<ALLOW_EVENTS value="presence" /> 
<ACCEPT value="somecontent/type" /> 
<ACCEPT value="application/sdp" /> 
</SIP_HEADERS>
<SDP_LINES>
<LINE name="m" value="audio 30000 RTP/AVP 98" /> 
</SDP_LINES>
</SIP_CLIENT>

Note: This XML file is an example to demonstrate how to define capabilities in XML format. The contents of this file are not related to the CSimpleAppLauncher example plug-in in anyway, as the capabilities for the example plug-in is proved.

Implementation of CSimpleAppLauncher2 using CSIPResolvedClient2 interface

This is an example of SIP Client Resolver plug-in named CSimpleAppLauncher2.

CSimpleAppLauncher2.h

#include "SipResolvedClient2.h"

class CSimpleAppLauncher2 : public CSIPResolvedClient2
      {
      public: // Constructors and destructor

/**
* Static constructor
* @return An initialized instance of this class.
*/
static CSimpleAppLauncher2* NewL();

/// Destructor
~CSimpleAppLauncher2();

       public: // from CSIPResolvedClient2

TBool MatchAcceptContactsL(
            RStringF aMethod,
            const CUri8& aRequestUri,
            const RPointerArray<CSIPHeaderBase>& aHeaders,
            const TDesC8& aContent,
            const CSIPContentTypeHeader* aContentType,
            TUid& aClientUid);

           TBool MatchEventL(
                RStringF aMethod,
                const CUri8& aRequestUri,
                const RPointerArray<CSIPHeaderBase>& aHeaders,
                const TDesC8& aContent,
                const CSIPContentTypeHeader* aContentType,
                TUid& aClientUid);

    TBool MatchRequestL(
                RStringF aMethod,
                const CUri8& aRequestUri,
                const RPointerArray<CSIPHeaderBase>& aHeaders,
                const TDesC8& aContent,
                const CSIPContentTypeHeader* aContentType,
                TUid& aClientUid );

    TBool ConnectSupported() ;

    void ConnectL( const TUid& aClientUid );

    void CancelConnect( const TUid& aClientUid );

    RPointerArray<CSIPContentTypeHeader> SupportedContentTypesL();

    RPointerArray<CSdpMediaField> SupportedSdpMediasL();

    void AddClientSpecificHeadersForOptionsResponseL(
                                        RPointerArray<CSIPHeaderBase>& aHeaders );

       private: // Constructors

inline CSimpleAppLauncher2(){}

// Second phase constructor
void ConstructL(); 
      
       private: //Data

    RPointerArray<CSIPAcceptContactHeader> iAcceptContactHeaders;
    CSIPEventHeader*      iEvent;
    CSIPExtensionHeader*  iExtensionHeader; 
};

CSimpleAppLauncher2.cpp

#include "CSimpleAppLauncher2.h"

const TUid KResolvedClient2PluginUID = { 0x23456789 };


// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::NewL
// -----------------------------------------------------------------------------
//
CSimpleAppLauncher2* CSimpleAppLauncher2::NewL()
    {
    CSimpleAppLauncher2* self = new( ELeave ) CSimpleAppLauncher2;
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;    
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::ConstructL
// -----------------------------------------------------------------------------
//
void CSimpleAppLauncher2::ConstructL()
    {
    _LIT8(KACValue, "*;+resolvedexample2");
    iAcceptContactHeaders = CSIPAcceptContactHeader::DecodeL(KACValue());
    _LIT8(KEventValue,"precense.winfo.jinfo.kinfo");
    iEvent = CSIPEventHeader::DecodeL(KEventValue());
    iExtensionHeader = CSIPExtensionHeader::NewL( _L8("ExtraHeader"),
    _L8("resolvedClient2"));
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::~CSimpleAppLauncher2
// -----------------------------------------------------------------------------
//
CSimpleAppLauncher2::~CSimpleAppLauncher2()
    {
    iAcceptContactHeaders.ResetAndDestroy();
    delete iEvent;
    delete iExtensionHeader;
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::MatchAcceptContactsL
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//
TBool CSimpleAppLauncher2::MatchAcceptContactsL(
    RStringF /*aMethod*/,
    const CUri8& /*aRequestUri*/,
    const RPointerArray<CSIPHeaderBase>& aHeaders,
    const TDesC8& /*aContent*/,
    const CSIPContentTypeHeader* /*aContentType*/,
    TUid& aClientUid)
    {
    
    TBool match = EFalse;
    if ( iAcceptContactHeaders.Count() )
        {
        CSIPAcceptContactHeader* acceptContact = 
           static_cast<CSIPAcceptContactHeader*>(iAcceptContactHeaders[0]);
           for (TInt i = 0;i < aHeaders.Count() && !match;i++)
                {
                CSIPAcceptContactHeader* ac = 
                      static_cast<CSIPAcceptContactHeader*>(aHeaders[i]);
                 if ( ac == acceptContact )
                     {
                     match = ETrue;
                     aClientUid.iUid = 0x23456789;
                     }
                }
        }
    return match;
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::MatchEventL
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//
TBool CSimpleAppLauncher2::MatchEventL(
    RStringF /*aMethod*/,
    const CUri8& /*aRequestUri*/,
    const RPointerArray<CSIPHeaderBase>& aHeaders,
    const TDesC8& /*aContent*/,
    const CSIPContentTypeHeader* /*aContentType*/,
    TUid& aClientUid)
    {
    TBool match = EFalse;
    if ( iEvent )
        {
           for (TInt i = 0;i < aHeaders.Count() && !match;i++)
                {
                CSIPEventHeader* event = 
                        static_cast<CSIPEventHeader*>(aHeaders[i]);
                if ( event == iEvent )
                    {
                    match = ETrue;
                    aClientUid.iUid = 0x23456789;
                    }
                }
        }
    return match;
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::MatchRequestL
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//
TBool CSimpleAppLauncher2::MatchRequestL(
    RStringF /*aMethod*/,
    const CUri8& /*aRequestUri*/,
    const RPointerArray<CSIPHeaderBase>& aHeaders,
    const TDesC8& /*aContent*/,
    const CSIPContentTypeHeader* /*aContentType*/,
    TUid& aClientUid)
    {
    TBool match = EFalse;
    if ( iExtensionHeader )
        {
           for (TInt i = 0;i < aHeaders.Count() && !match;i++)
                 {
                 CSIPExtensionHeader* extension = 
                        static_cast<CSIPExtensionHeader*>(aHeaders[i]);
                 if ( iExtensionHeader->Name() == extension->Name() )
                     {
                     match = ETrue;
                     aClientUid.iUid = 0x23456789;
                    }
                 }
        }
    return match;
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::ConnectSupported
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//
TBool CSimpleAppLauncher2::ConnectSupported()
    {
    return ETrue;
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::ConnectL
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//
void CSimpleAppLauncher2::ConnectL( 
    const TUid& aClientUid )
    {
    // application specific starting logic that leads to 
    // the connection with the SIP. The same UID must be
    // provided to SIP while invoking CSIP::NewL().
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::CancelConnect
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//        
void CSimpleAppLauncher2::CancelConnect(
    const TUid& /*aClientUid*/ )
    {
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::SupportedContentTypesL
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//        
RPointerArray<CSIPContentTypeHeader> 
        CSimpleAppLauncher2::SupportedContentTypesL()
    {
    RPointerArray<CSIPContentTypeHeader> headers;
    _LIT8 (KAppWithSdp, "application/sdp");
    CSIPContentTypeHeader* contentTypeHeader = 
    CSIPContentTypeHeader::DecodeL(KAppWithSdp());
    CleanupStack::PushL( contentTypeHeader );
    headers.AppendL( contentTypeHeader );
    CleanupStack::Pop( contentTypeHeader );
    return headers;
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::SupportedSdpMediasL
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//        
RPointerArray<CSdpMediaField> 
        CSimpleAppLauncher2::SupportedSdpMediasL()
    {
    RStringPool sdpStrPool = SdpCodecStringPool::StringPoolL();
    RStringF media = sdpStrPool.OpenFStringL(_L8("audio"));
    CleanupClosePushL(media);
    RStringF protocol = sdpStrPool.OpenFStringL(_L8("RTP/AVP"));
    CleanupClosePushL(protocol);
    CSdpMediaField* mediafield = 
    CSdpMediaField::NewL(media,0,protocol,_L8("formatlist"));
    CleanupStack::Pop(2);//media,protocol
    media.Close();
    protocol.Close();
    CleanupStack::PushL(mediafield);
    RPointerArray<CSdpMediaField> headers;
    headers.AppendL(mediafield);
    CleanupStack::Pop(mediafield);
    return headers;
    }

// -----------------------------------------------------------------------------
// CSimpleAppLauncher2::AddClientSpecificHeadersForOptionsResponseL
// From CSIPResolvedClient2
// -----------------------------------------------------------------------------
//        
void CSimpleAppLauncher2::AddClientSpecificHeadersForOptionsResponseL( 
                    RPointerArray<CSIPHeaderBase>& aHeaders )
    {
    CSIPExtensionHeader* extHeader =  
        CSIPExtensionHeader::NewL( _L8("ExtraHeader"),   
    _L8("resolvedClient2"));
    CleanupStack::PushL( extHeader );
    TBool found(EFalse);
    for ( TInt i = 0;i < aHeaders.Count() && !found;i++ )
        {
        if ( aHeaders[i]->IsExtensionHeader() )
            {
              //It is plug-ins responsibility to check that the new extension 
              //header is not yet exsisiting in aHeaders array.

            if ( (static_cast <CSIPExtensionHeader*> (aHeaders[i]) )->Value() 
                   == extHeader->Value() &&(static_cast <CSIPExtensionHeader*> 
                             (aHeaders[i]) )->Name() == extHeader->Name() )
                {
                found = ETrue;
                CleanupStack::Pop( extHeader );
                delete extHeader;
                }
            }
        }
    if ( !found )
        {
        aHeaders.AppendL( extHeader );
        CleanupStack::Pop( extHeader );
        }
    }