<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License
"Eclipse Public License v1.0" which accompanies this distribution,
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
Nokia Corporation - initial contribution.
Contributors:
-->
<!DOCTYPE concept
PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-0D579DDC-0A8A-5CFA-8194-CAA955B65A57" xml:lang="en"><title>Example
of a SIP Client Resolver Plug-in</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>This is an example of a SIP Client Resolver plug-in called <codeph>CSimpleAppLauncher</codeph>. </p>
<p>In this example, the plug-in capabilities are not defined in a resource
file but are defined in the implementation as the <codeph>KCapabilities</codeph> literal
descriptor. </p>
<p>If capabilities are defined in the resource file instead of within the
implementation, they are defined in the <codeph>opaque_data</codeph> field
in XML format. See <xref href="GUID-0D579DDC-0A8A-5CFA-8194-CAA955B65A57.dita#GUID-0D579DDC-0A8A-5CFA-8194-CAA955B65A57/GUID-2B6A49E7-B483-59E2-B679-9828B483AB52">Example
of capabilities definition in XML format</xref>. </p>
<section id="GUID-1DF21E5C-9D66-5BBD-A1FD-91B5043D5D72"><title>Implementation
of CSimpleAppLauncher using CSIPResolvedClient interface</title> <p><b> CSimpleAppLauncher.H </b> </p> <codeblock id="GUID-25F9D5DF-0D59-5236-8E04-641F36C0DEF8" xml:space="preserve">#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();
};
</codeblock> <p><b> CSimpleAppLauncher.CPP </b> </p> <codeblock id="GUID-D7CF3E31-D2E1-5CF6-AAD0-6CE028EB9412" xml:space="preserve">#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;
}
</codeblock> <p><b> 00000001.RSS </b> </p> <codeblock id="GUID-BA39D436-55CD-54AC-99F6-0AFDBE825E3F" xml:space="preserve">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)
}
};
}
};
}</codeblock> <p id="GUID-2B6A49E7-B483-59E2-B679-9828B483AB52"><b>Example
of capabilities definition in XML format</b> </p> <p>This is an example of
defining capabilities in XML format. </p> <codeblock id="GUID-AD845CAF-ADC0-5C53-BF4A-E02D9D5E6A15" xml:space="preserve"><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>
</codeblock> <p> <b>Note:</b> 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 <codeph>CSimpleAppLauncher</codeph> example plug-in in anyway, as the
capabilities for the example plug-in is proved. </p> </section>
<section><title>Implementation of CSimpleAppLauncher2 using CSIPResolvedClient2
interface</title> <p>This is an example of SIP Client Resolver plug-in named <codeph>CSimpleAppLauncher2</codeph>. </p> <p><b>CSimpleAppLauncher2.h</b> </p> <codeblock id="GUID-AC545323-9326-506E-984C-CF831A3A6828" xml:space="preserve">#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;
};
</codeblock> <p><b>CSimpleAppLauncher2.cpp</b> </p> <codeblock id="GUID-C65A4DFA-C332-5096-B885-017E9C8E7722" xml:space="preserve">#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 );
}
}
</codeblock> </section>
</conbody></concept>