Symbian3/SDK/Source/GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 13 Aug 2010 16:47:46 +0100
changeset 14 578be2adaf3e
parent 13 48780e181b38
permissions -rw-r--r--
Week 32 contribution of PDK documentation content. See release notes for details. Fixes bug Bug 3582

<?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 xml:lang="en" id="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693"><title>How to use the SIP Client API</title><prolog><metadata><keywords/></metadata></prolog><conbody><section id="GUID-DC93FFFF-1981-5EA1-9B88-E3CC56CCCEB7"><title>Protocols</title> <p>The following sections describe how to do the following: </p> <ul><li id="GUID-7E5B3D7B-45E4-543A-8219-A5C1C0D25913"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-AFD6AB5D-1B1B-53CB-ABC7-4585D9A91CE8">Starting the SIP Client</xref>  </p> </li> <li id="GUID-39810F58-A7EB-5F1C-96C6-4A2E62B263EB"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-42784C1C-600A-53AE-9AEB-463EBF34C636">Closing SIP Client</xref>  </p> </li> <li id="GUID-544748CF-463C-546B-A291-08D1C2887C01"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-AC90094E-BF4E-5C2B-81B2-EF9BF5603BA2"> Sending a SIP request</xref>  </p> </li> <li id="GUID-F71538DD-111C-5DFE-88A3-2E025E05429C"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-5E5EC61F-5AB3-55F6-9AB0-463D5D0876DA">Receiving a SIP request</xref>  </p> </li> <li id="GUID-CC881957-ACE4-597F-85B4-1859886B61E7"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-820D689F-6404-5E40-AAC2-A45ABECDBADC">Receiving a SIP request and creating a session</xref>  </p> </li> <li id="GUID-5FBBC17B-D4B7-51F3-8560-13F6730010B6"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-109B933C-1063-577F-9A58-BA809869A0DF">Registration</xref>  </p> </li> <li id="GUID-8E35F949-CC67-546C-9899-3A2C1BF8BBC1"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-E683488B-B7EA-5215-8476-8C39950AC21B">Creating a dialog with INVITE</xref>  </p> </li> <li id="GUID-3246EFA2-48AB-5D54-9E5C-E8095886FCCD"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-E4E6E0C2-7B0F-51AA-B1E3-282E8F728EDC"> Generating a '100 SIP response'</xref>  </p> </li> <li id="GUID-6E4E101D-8638-5AD8-B105-D5FD5D9ED6E5"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-C1ED4FC7-5DEB-5C5B-AE82-549D4577A9A9">Responding to a CANCEL request</xref>  </p> </li> <li id="GUID-010BA345-B521-54AC-8208-B0C5969BA87D"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-CB27D3C3-D28B-5081-B201-8C10DE60CF25">Sending a SIP request and responding to a HTTP Digest challenge</xref>  </p> </li> <li id="GUID-4A8CF777-7379-5AF6-90A9-B15480B2E67E"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-B882D001-CDE9-579F-8DDE-C087D8707C2E">Notification of a failed refresh</xref>  </p> </li> <li id="GUID-79F2A3B3-2CC0-52ED-903B-3D4855E4A274"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-DDD7FDBD-FBC9-5111-BE71-A71E6CCEFB2A">Error handling</xref>  </p> </li> <li id="GUID-AB416C57-9986-54AD-BB8A-7240D8FBCD7D"><p><xref href="GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693.dita#GUID-B0EF8500-0A49-5EA8-B7FF-8149E5F03693/GUID-0FC8038A-64AE-5E98-A9F9-ADBC6F05DF2B">Refreshing a Connection</xref>  </p> </li> </ul> </section> <section id="GUID-AFD6AB5D-1B1B-53CB-ABC7-4585D9A91CE8"><title>Starting the SIP Client</title> <p>To start the SIP Client: </p> <ol id="GUID-62B966F0-272C-5A03-9364-7685412436B0"><li id="GUID-626ACA6E-6CA9-5A3C-8582-EDEE7AE823D0"><p>Create an instance of the <xref href="GUID-AFB2603A-8A35-3E70-8EC2-229C9726F00B.dita"><apiname>CSIP</apiname></xref> class. The <xref href="GUID-AFB2603A-8A35-3E70-8EC2-229C9726F00B.dita"><apiname>CSIP</apiname></xref> class creates a <xref href="GUID-AFB2603A-8A35-3E70-8EC2-229C9726F00B.dita"><apiname>CSIP</apiname></xref> object and implements the callback functions defined by <xref href="GUID-C6FF4A83-0097-3A82-B4ED-802E1FEA05D1.dita"><apiname>MSIPObserver</apiname></xref>. The <xref href="GUID-AFB2603A-8A35-3E70-8EC2-229C9726F00B.dita"><apiname>CSIP</apiname></xref> object connects the client to a shared server. </p> <p> <b>Note:</b> The server is started if it is not active. This may take a short time while the server side resources are created and initialised. </p> </li> <li id="GUID-BEE4CC97-50C6-5681-ACEB-180CA59B0CD3"><p>Create an instance of the <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> class to use an IAP. The <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> class must implement the callback functions defined by <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita"><apiname>MSIPConnectionObserver</apiname></xref>. The <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> class creates <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> object. The <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> object forms a sub-session between the client and the server. </p> </li> <li id="GUID-1B0B51F8-37DF-5495-AEEC-F49A6C7EE947"><p>Call the <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita#GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94/GUID-7F3A8623-2989-3CCE-BF0C-BA4717D29D64"><apiname>CSIPConnection::NewL()</apiname></xref> function to create an active connection. The <codeph>CSIPConnection::EActive</codeph> state indicates that the object can be used to send SIP messages and create registrations and dialogs. The current state is asked by calling <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita#GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94/GUID-A1A6D679-936C-3156-BA7D-5CBC3E2DEF7F"><apiname>CSIPConnection::State()</apiname></xref>. The <codeph>MSIPConnectionObserver::ConnectionStateChanged(CSIPConnection::
                EActive)</codeph> callback function is called. </p> </li> </ol> <p>The following illustration shows the sequence of events involved in starting the SIP Client API. </p> <fig id="GUID-86E80D26-544B-587A-B2FD-B15CF44E47B4"><image href="GUID-15CAB5AF-CAA5-5D1B-9236-7874BF944484_d0e339678_href.png" placement="inline"/></fig> </section> <section id="GUID-42784C1C-600A-53AE-9AEB-463EBF34C636"><title>Closing the SIP Client</title> <p>To close the SIP Client: </p> <ul><li id="GUID-9FA5F4F3-9403-5256-9B80-939042BB2A8A"><p>Delete the <xref href="GUID-AFB2603A-8A35-3E70-8EC2-229C9726F00B.dita"><apiname>CSIP</apiname></xref> object to close the connection to the SIP server. </p> </li> <li id="GUID-2C9F26A2-D5D1-585A-87C8-222A57D05F2F"><p>Delete the <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> object to close the sub-session between the client and the server. </p> </li> <li id="GUID-78A46553-52E1-57E3-BB0A-AEC70FC36F0F"><p>When the connection has been closed, operations on objects that depend on the connection fail with the <codeph>KErrSIPResourceNotAvailable</codeph> error code. </p> </li> </ul> <p>For example, if an application has <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> and <xref href="GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4.dita"><apiname>CSIPRegistrationBinding</apiname></xref> objects, and it deletes the <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> object, then subsequent attempts to use the <codeph>CSIPRegistrationBinding</codeph> object fails. This is because <codeph>CSIPRegistrationBinding</codeph> cannot communicate with the server side of the SIP stack without the <codeph>CSIPConnection</codeph> object. </p> <p>The following illustration shows the order for deleting SIP Client API objects. </p> <fig id="GUID-5C5F0C8E-76BD-56CC-AA9E-BECF035D1A9F"><image href="GUID-A9BFB95C-E2B0-5CD0-8B39-C448E3C81400_d0e339744_href.png" placement="inline"/></fig> </section> <section id="GUID-AC90094E-BF4E-5C2B-81B2-EF9BF5603BA2"><title> Sending a SIP request</title> <p>To send a SIP request: </p> <ul><li id="GUID-C92F9ADF-1BF5-5057-8851-0940E67A3C6A"><p>Create a <xref href="GUID-19FB031A-CFA7-3C67-A627-CFF501060AA5.dita"><apiname>CSIPRequestElements</apiname></xref> object and enter the required fields of the request. </p> </li> <li id="GUID-E69DA3E7-5C13-5D10-BD82-1D37AEE0EE8A"><p>Call the <codeph>CSIPConnection::SendRequestL(CSIPRequestElements*)</codeph> function to take control of the <xref href="GUID-19FB031A-CFA7-3C67-A627-CFF501060AA5.dita"><apiname>CSIPRequestElements</apiname></xref> objects and communicate the request to the server side of the SIP stack. </p> <p> <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname> CSIPConnection</apiname></xref> creates a <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref> object and returns it to the application. </p> </li> </ul> <p> <b>Note:</b>  <codeph>SendRequestL()</codeph> starts the server side processing of sending the MESSAGE request. This task takes time as address resolving and socket operations are done only after the <codeph>SendRequestL()</codeph> call is returned. If an error occurs after <codeph>SendRequestL()</codeph> returns, then the error is communicated to the application through one of the <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-E4E56635-42BB-351A-8356-DB12B5BE24CC"><apiname>MSIPConnectionObserver::ErrorOccured()</apiname></xref> callback functions. An example of such a failure is failure to resolve the address. When <codeph>SendRequestL()</codeph> returns, the MESSAGE request is not yet sent to the network, and is being processed on the server side of the SIP stack. </p> <p>After <codeph>SendRequestL()</codeph> returns and the sending of a MESSAGE request is in progress on the shared server, there is no way for the application to cancel that operation. This also applies to other operation types. However the <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita#GUID-059F9C3A-EA04-3295-912F-50444F073CE7/GUID-8F7BF1A8-75C4-39A1-BCB3-4E1F7CDE59CC"><apiname>CSIPClientTransaction::CancelL()</apiname></xref> function is used to send a CANCEL request after the application sends an INVITE request. </p> <p>When the SIP response is received from the server side, the <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> object: </p> <ol id="GUID-0DB00054-27E8-57BF-8BB0-7F8231C7627B"><li id="GUID-D207CF42-5B04-5625-8CF8-4EEAD3451542"><p>creates a <xref href="GUID-13F32052-70BE-3B4D-9F8B-DF2DABB896B0.dita"><apiname>CSIPResponseElements</apiname></xref> object to represent the SIP response </p> </li> <li id="GUID-7131D953-EFF6-5D31-B20F-64B56C968368"><p>attaches it to the <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref> object </p> </li> <li id="GUID-72C682B2-05BE-58ED-B743-0554C9476CC2"><p>notifies the application through a call to one of the <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-EE7CC7B8-CC03-3814-9177-CFBFBB043426"><apiname>MSIPConnectionObserver:: IncomingResponse()</apiname></xref> callback functions. </p> </li> </ol> <p>The application determines the kind of response received by accessing the <xref href="GUID-13F32052-70BE-3B4D-9F8B-DF2DABB896B0.dita"><apiname>CSIPResponseElements</apiname></xref> object through <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref>. As the response is provisional, the application does not delete the <codeph>CSIPClientTransaction</codeph> object. A '200 response' is received later, and the application then deletes the <codeph>CSIPClientTransaction</codeph> object. </p> <p>Then, create a <xref href="GUID-13F32052-70BE-3B4D-9F8B-DF2DABB896B0.dita"><apiname>CSIPResponseElements</apiname></xref> object to represent the SIP response, attach it to <codeph>CSIPClientTransaction</codeph> and notify the application with <codeph>MSIPConnectionObserver::
          IncomingResponse</codeph>. </p> <p>The following illustration shows the sequence of events involved in sending a MESSAGE request and receiving two responses to it. </p> <fig id="GUID-6724EF0B-9B98-5225-BABA-3967A5065711"><image href="GUID-7712BAB3-5F48-5A28-9EA9-104D8B4A0431_d0e339890_href.png" placement="inline"/></fig> </section> <section id="GUID-5E5EC61F-5AB3-55F6-9AB0-463D5D0876DA"><title>Receiving a SIP request</title> <p>A standalone SIP request is received through an existing <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> object. The <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> creates <xref href="GUID-19FB031A-CFA7-3C67-A627-CFF501060AA5.dita"><apiname>CSIPRequestElements</apiname></xref> and <xref href="GUID-7E54C95E-5155-30B1-8169-A59778774403.dita"><apiname>CSIPServerTransaction</apiname></xref> objects before notifying the application through the <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-2DF68D26-9787-3D00-B86F-1999D20E4981"><apiname>MSIPConnectionObserver::IncomingRequest()</apiname></xref> callback function. The <xref href="GUID-19FB031A-CFA7-3C67-A627-CFF501060AA5.dita"><apiname>CSIPRequestElements</apiname></xref> and <xref href="GUID-7E54C95E-5155-30B1-8169-A59778774403.dita"><apiname>CSIPServerTransaction</apiname></xref> represent the incoming SIP request </p> <p>The <xref href="GUID-7E54C95E-5155-30B1-8169-A59778774403.dita"><apiname>CSIPServerTransaction</apiname></xref> object is passed to the <xref href="GUID-19FB031A-CFA7-3C67-A627-CFF501060AA5.dita"><apiname>CSIPRequestElements</apiname></xref> object through the callback function. The application retrieves information about the request from the <xref href="GUID-7E54C95E-5155-30B1-8169-A59778774403.dita"><apiname>CSIPServerTransaction</apiname></xref> object. </p> <p>To send a response, the application creates a <xref href="GUID-13F32052-70BE-3B4D-9F8B-DF2DABB896B0.dita"><apiname>CSIPResponseElements</apiname></xref> object and passes it to <xref href="GUID-7E54C95E-5155-30B1-8169-A59778774403.dita#GUID-7E54C95E-5155-30B1-8169-A59778774403/GUID-2D5A77B6-114D-3A22-B622-5342BF235B67"><apiname>CSIPServerTransaction::SendResponseL()</apiname></xref>. This passes the response to the server side for further processing. When <codeph>SendResponseL()</codeph> is returned, the application no longer needs the <xref href="GUID-7E54C95E-5155-30B1-8169-A59778774403.dita"><apiname>CSIPServerTransaction</apiname></xref> object and deletes it. </p> <p>The following illustration shows the sequence of events involved in receiving a MESSAGE request and sending a response to it. </p> <fig id="GUID-8C9A8944-1150-52E2-A031-BA65F16191F4"><image href="GUID-1158BDD3-69F7-5892-9887-FAE30110E33C_d0e339965_href.png" placement="inline"/></fig> </section> <section id="GUID-820D689F-6404-5E40-AAC2-A45ABECDBADC"><title>Receiving a SIP request and creating a session</title> <p>The SIP stack receives a SIP INVITE request from the network acting as a User Agent Server (UAS) and creates an invite server transaction for the received request. The SIP stack sends a '100 SIP response' to the remote UA. After comparing the received request with the stored application capabilities, the SIP stack routes the received INVITE request to the chosen application. </p> <p>The application creates a <xref href="GUID-B4A2FBBD-2B5F-3E64-800D-C4E9203679A8.dita"><apiname>CSIPInviteDialogAssoc</apiname></xref> object and the SIP stack creates an instance of <xref href="GUID-382BC1BE-3CF3-3E81-B1FF-341EEF2B67EA.dita"><apiname>CSIPDialog</apiname></xref>. The application sends a '200 SIP response' to the remote UA. The remote UA acknowledges the '200 SIP' response with ACK and creates a SIP session is between the local and remote UA. </p> <p>The following illustration shows the sequence of events involved in receiving a SIP request and creating a SIP dialog. </p> <fig id="GUID-8A8D96E1-99DC-5F11-847A-9D407212CA6E"><image href="GUID-C64D200D-32A9-5F50-ACF1-4D93DDD0B0A4_d0e339990_href.png" placement="inline"/></fig> </section> <section id="GUID-109B933C-1063-577F-9A58-BA809869A0DF"><title>Registration</title> <p>An application creates a <xref href="GUID-3C166C85-6E17-323B-9CD3-B3E2836DC1C3.dita"><apiname>CSIPRefresh</apiname></xref> object to initiate a registration. It then creates a <xref href="GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4.dita"><apiname>CSIPRegistrationBinding</apiname></xref> object, passing <codeph>CSIPRefresh</codeph> to it. </p> <p> <b>Note:</b> It is not mandatory to create a <codeph>CSIPRefresh</codeph> object. It is required if the registration is to be refreshed by the SIP stack. </p> <p>After the <codeph>CSIPRegistrationBinding</codeph> object exists, the application initiates the registration process by calling <codeph>RegisterL()</codeph> on the <codeph>CSIPRegistrationBinding</codeph> object. <codeph/>  <codeph>CSIPRegistrationBinding</codeph> forms a REGISTER request and communicates it to the server side of the SIP stack, it instantiates the <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref> object and returns it to the application. </p> <p>When the '200 SIP response' is received from the server side, <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> creates the <xref href="GUID-13F32052-70BE-3B4D-9F8B-DF2DABB896B0.dita"><apiname>CSIPResponseElements</apiname></xref> object to contain the response, and then routes the response to <xref href="GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4.dita"><apiname>CSIPRegistrationBinding</apiname></xref>. <xref href="GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4.dita"><apiname>CSIPRegistrationBinding</apiname></xref> attaches the response to <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref>. The application is informed about the response through one of the <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-7DE6337F-4EAA-3AE4-B573-1F7E59EDCFE5"><apiname>MSIPConnectionObserver::IncomingResponse()</apiname></xref> callback functions. </p> <p>The application does not require the <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref> object and can delete it. The <codeph>IsContextActive()</codeph> finds out if the registration is successful. </p> <p>The following illustration shows the sequence of events involved in registering with a refresh and receiving a '200 OK response'. </p> <fig id="GUID-7F489E97-2ADE-5753-A03B-5600E4BD1C55"><image href="GUID-02521DB0-53C4-55D5-856F-BD478E134B73_d0e340082_href.png" placement="inline"/></fig> </section> <section id="GUID-45BEF04F-64A3-5B29-8CE4-8B1F5CA0E64F"><title>Configuring the registration</title> <p>When registering an SIP connection, applications have two options to configure the registration : outbound proxy caching and expiration value removal. To set each of these options, call <xref href="GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4.dita#GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4/GUID-B3C68013-AF24-3529-8595-5CC9497F2E98"><apiname>CSIPRegistrationBinding::SetProperty()</apiname></xref> with the corresponding property constant, as explained below. </p> <p>The SIP stack resolves the IP address of the outbound proxy during registration. The default behavior is to resolve the address again for each SIP message sent using this registration context. However, you can also cache the address to optimise network traffic. If you set <xref href="GUID-9A7A7547-76EB-3CC7-9C3D-7F1C08A160D0.dita"><apiname>KSIPCacheOutboundProxyIP</apiname></xref> property to <codeph>ETrue</codeph>, the SIP stack reuses the proxy address that was resolved during registration. The proxy address is refreshed by successful REGISTER transactions, which always perform a DNS query. </p> <p>By default, the SIP stack sends the expiration value in the REGISTER request. In the '200 OK' answer to a REGISTER message, the registrar returns an expiration value that may be different from the value that was sent. The SIP stack validates the returned expiration value against the minimum and maximum expiration values: if the returned expiration value is out of range, the SIP stack uses the minimum value or the maximum value. </p> <ul><li id="GUID-478291AE-D709-5AF1-AE4A-F1C115F8BE7C"><p>The minimum expiration value is 30 seconds, to reduce network activity and battery consumption. </p> </li> <li id="GUID-A0C7C631-F4CF-5CC0-BAA7-236C939E87C8"><p>The maximum expiration value is the expiration value that you specify for the REGISTER request. By default, the maximum expiration value is 3600 seconds, to protect the application from DOS attacks that provide '200 OK' responses with a very high expiration value. </p> </li> </ul> <p>If you set <xref href="GUID-C0920ECB-95CC-3152-8D6F-C4751AA8271E.dita"><apiname>KSIPSendWithExpires</apiname></xref> to <codeph>EFalse</codeph>, the SIP stack does not send the application's expiration value in the REGISTER message. </p> </section> <section id="GUID-E683488B-B7EA-5215-8476-8C39950AC21B"><title>Creating a dialog with INVITE</title> <p>To create a dialog with INVITE an application creates <xref href="GUID-B4A2FBBD-2B5F-3E64-800D-C4E9203679A8.dita"><apiname>CSIPInviteDialogAssoc</apiname></xref> and <xref href="GUID-77CFD812-7238-3B84-80FF-475BD73C3506.dita"><apiname>CSIPMessageElements</apiname></xref> objects. The application must enter the relevant SIP headers in the <xref href="GUID-77CFD812-7238-3B84-80FF-475BD73C3506.dita"><apiname>CSIPMessageElements </apiname></xref> object before passing it to <xref href="GUID-B4A2FBBD-2B5F-3E64-800D-C4E9203679A8.dita"><apiname>CSIPInviteDialogAssoc</apiname></xref> using the <xref href="GUID-B4A2FBBD-2B5F-3E64-800D-C4E9203679A8.dita#GUID-B4A2FBBD-2B5F-3E64-800D-C4E9203679A8/GUID-D587F38B-3631-3399-9A82-04EA473E7694"><apiname>CSIPInviteDialogAssoc::SendInviteL()</apiname></xref> function. </p> <p> <xref href="GUID-B4A2FBBD-2B5F-3E64-800D-C4E9203679A8.dita"><apiname>CSIPInviteDialogAssoc</apiname></xref> then forms an INVITE request and communicates it to the server side of the SIP stack. It then creates a <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref> object, and returns it to the application. </p> <p>When the server sends '180 response', the <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> creates a <xref href="GUID-13F32052-70BE-3B4D-9F8B-DF2DABB896B0.dita"><apiname>CSIPResponseElements</apiname></xref> object to contain the response, and then routes the response to <xref href="GUID-382BC1BE-3CF3-3E81-B1FF-341EEF2B67EA.dita"><apiname>CSIPDialog</apiname></xref>. <codeph>CSIPDialog</codeph> attaches the response to <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref>. The application is informed about the receipt of the '180 response' through a call to one of the <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-EE7CC7B8-CC03-3814-9177-CFBFBB043426"><apiname>MSIPConnectionObserver:: IncomingResponse()</apiname></xref> callback functions. </p> <p>When the '200 response' is received, processing similar to '180 response' occurs. Then the application responds by sending an ACK request. This is done by invoking the <xref href="GUID-B4A2FBBD-2B5F-3E64-800D-C4E9203679A8.dita#GUID-B4A2FBBD-2B5F-3E64-800D-C4E9203679A8/GUID-DBA0B06D-EC23-3458-9397-402E6CA17106"><apiname>CSIPInviteDialogAssoc::SendAckL()</apiname></xref> function, which forms the ACK request and sends it to the server side of the SIP stack. </p> <p>The INVITE request might fork at a proxy, so the server side of the SIP stack waits for several possible responses. When the forking is does not happen, the server side of the SIP stack sends an <codeph>InviteCompleted</codeph> event. The SIP Client API forwards the <codeph>InviteCompleted</codeph> event to the application, indicating that the application can now delete the <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref>. </p> <p>The following figure shows the sequence of events involved in sending an INVITE, receiving a response and sending an ACK. </p> <fig id="GUID-3AE23155-63D4-5948-855E-9D44F48E4D11"><image href="GUID-C8D04D54-D391-5505-9E80-596589410179_d0e340220_href.png" placement="inline"/></fig> </section> <section id="GUID-E4E6E0C2-7B0F-51AA-B1E3-282E8F728EDC"><title> Generating a '100 SIP response'</title> <p>The SIP stack generates a '100 response' automatically when it receives an <codeph>INVITE</codeph> request from the network. Applications are not allowed to send '100 responses'. </p> </section> <section id="GUID-C1ED4FC7-5DEB-5C5B-AE82-549D4577A9A9"><title>Responding to a CANCEL request</title> <p>When the SIP stack receives a CANCEL request from the network, it automatically responds to it. CANCEL requests are never passed to an application. </p> <p>If the SIP stack: </p> <ul><li id="GUID-05B62303-9453-5E42-8E2A-6D50A5857312"><p>does not find a matching transaction for a CANCEL request, it automatically generates a '481 response'. </p> </li> <li id="GUID-69DBD19D-1871-57C5-AF95-8858A92BE6C5"><p>finds a matching transaction for a CANCEL request, it automatically generates a '200 response'. </p> </li> <li id="GUID-C806FF70-7EBD-5D06-989E-971E2E7589DD"><p>finds a matching INVITE server transaction that is in the <codeph>Proceeding</codeph> state (that is a final response is not yet sent), it also automatically generates a '487 response' to the INVITE transaction. </p> </li> </ul> <p>After these actions are complete, the SIP stack informs the application by calling the <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-500F0C1D-6FCF-32DB-B9CC-4F7CEC1A9053"><apiname>MSIPConnectionObserver::InviteCanceled()</apiname></xref> callback function. </p> </section> <section id="GUID-CB27D3C3-D28B-5081-B201-8C10DE60CF25"><title>Sending a SIP request and responding to a HTTP Digest challenge</title> <p>A SIP server in the signalling chain challenges any SIP request initiated by the application with an HTTP Digest challenge by responding with a '401 SIP response', '407 SIP response' or a '494 SIP response'. The responses contain details of the challenge. These responses are never passed directly to the application. Instead, they are passed to the application through a call to the callback function <xref href="GUID-FA0A893D-E3E3-33F8-9C63-B2A6A2A053EF.dita#GUID-FA0A893D-E3E3-33F8-9C63-B2A6A2A053EF/GUID-D12ED59B-FF9F-3AAD-9740-1108B1091421"><apiname>MSIPHttpDigestChallengeObserver::ChallengeReceived()</apiname></xref>. </p> <p>To enable an application to respond to a challenge, it must: </p> <ul><li id="GUID-69B100E7-A67F-5F0C-B886-1B0FAE9DBEB4"><p>create a <xref href="GUID-F9FBAFBE-A895-3FD3-A526-604A6C9E035D.dita"><apiname>CSIPHttpDigest</apiname></xref> object </p> </li> <li id="GUID-A58199C3-57A0-536F-8EC2-76A29F3003DA"><p>provide an implementation of the callback function <xref href="GUID-FA0A893D-E3E3-33F8-9C63-B2A6A2A053EF.dita#GUID-FA0A893D-E3E3-33F8-9C63-B2A6A2A053EF/GUID-D12ED59B-FF9F-3AAD-9740-1108B1091421"><apiname>MSIPHttpDigestChallengeObserver::ChallengeReceived()</apiname></xref> . </p> </li> </ul> <p>The application can either accept or reject the challenge: </p> <ul><li id="GUID-8EFD6F96-73E8-594E-9971-95DB3DA5B5ED"><p>If it accepts the challenge, the callback function must call <xref href="GUID-F9FBAFBE-A895-3FD3-A526-604A6C9E035D.dita#GUID-F9FBAFBE-A895-3FD3-A526-604A6C9E035D/GUID-FBDFE260-789F-3FB1-9884-D958B82E3734"><apiname>CSIPHttpDigest::SetCredentialsL()</apiname></xref>, specifying the username, password, and the realm passed to the callback function. </p> <p>Then, SIP stack re-sends the original SIP request with the HTTP Digest response. </p> </li> <li id="GUID-C1A1BCCC-7E0C-5B4F-A0D9-EDC52F081D59"><p>If it rejects the challenge, the callback function must call <xref href="GUID-F9FBAFBE-A895-3FD3-A526-604A6C9E035D.dita#GUID-F9FBAFBE-A895-3FD3-A526-604A6C9E035D/GUID-2F3A2A6D-B825-30A5-A133-EEBBFCD3F52B"><apiname>CSIPHttpDigest::IgnoreChallenge()</apiname></xref>, specifying the realm passed to the callback function. </p> <p>Then, SIP stack calls the callback function <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-E4E56635-42BB-351A-8356-DB12B5BE24CC"><apiname>MSIPConnectionObserver::ErrorOccured()</apiname></xref>, by passing the error code <xref href="GUID-FF8BB656-99F5-369E-A6CE-56684D329AD5.dita"><apiname>KErrSIPForbidden</apiname></xref>. </p> </li> </ul> <p>If an application does not want to receive the HTTP Digest challenge then it must not create a <xref href="GUID-F9FBAFBE-A895-3FD3-A526-604A6C9E035D.dita"><apiname>CSIPHttpDigest</apiname></xref> object. In this event, the SIP stack calls the callback function <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-E4E56635-42BB-351A-8356-DB12B5BE24CC"><apiname>MSIPConnectionObserver::ErrorOccured()</apiname></xref>, passing the error code <xref href="GUID-FF8BB656-99F5-369E-A6CE-56684D329AD5.dita"><apiname>KErrSIPForbidden</apiname></xref>. </p> <p> <b>Note:</b>  </p> <ul><li id="GUID-A028B39A-292E-5556-B4A0-AF801F6131F3"><p>If an application uses the SIP Profile Agent for SIP registration, the SIP Profile Agent handles the HTTP Digest challenges related to the registration procedure according to the SIP profile information. </p> </li> <li id="GUID-19A777A8-E8D0-54F4-A59E-53550B6A802C"><p>The SIP stack maintains a HTTP Digest cache which stores username and password pairs for realms. If the username and password have been configured for a proxy, or if the application has already provided them after being asked through a <xref href="GUID-FA0A893D-E3E3-33F8-9C63-B2A6A2A053EF.dita#GUID-FA0A893D-E3E3-33F8-9C63-B2A6A2A053EF/GUID-D12ED59B-FF9F-3AAD-9740-1108B1091421"><apiname>MSIPHttpDigestChallengeObserver::ChallengeReceived()</apiname></xref> call, then the SIP stack uses them to answer subsequent challenges for a matching realm automatically. </p> <p>For example, if the application uses a SIP Profile whose proxy is configured with HTTP Digest passwords and then sends an INVITE, it does not need to provide the passwords for the proxy as the SIP stack gets it from the HTTP Digest cache. </p> </li> </ul> </section> <section id="GUID-B882D001-CDE9-579F-8DDE-C087D8707C2E"><title>Notification of a failed refresh</title> <p>The following example shows how an application is notified when a refresh request within a dialog terminates after an error occurs. In this example the application sends a SUBSCRIBE request with refresh, and receives a <codeph>2xx</codeph> class response. The SIP stack periodically sends a refreshed SUBSCRIBE message. After successfully refreshed SUBSCRIBE requests, the remote server responds with a '481 response', and the application receives the following callback: </p> <codeblock id="GUID-A7F94C80-1224-5A70-B757-98FFAAD92B3B" xml:space="preserve">MSIPConnectionObserver::ErrorOccured(TInt aError, CSIPDialogAssocBase&amp; aDialogAssoc)</codeblock> <p>If the value of <codeph>aError</codeph> is <xref href="GUID-D711A918-6BCE-3A6A-988C-1B1917CD19A6.dita"><apiname>KErrSIPTerminatedWithResponse</apiname></xref>, then the actual SIP response causing the refresh to end can be found as follows: </p> <ul><li id="GUID-76291322-B9F0-55D3-A019-73A9040F2652"><p>Check that <codeph>aDialogAssoc.Type()</codeph> returns <codeph>"SUBSCRIBE"</codeph>. </p> </li> <li id="GUID-52B18DCF-2308-52A9-AB13-5920042C2E5D"><p>Call the function with the following signature to get the refresh instance (<xref href="GUID-3C166C85-6E17-323B-9CD3-B3E2836DC1C3.dita"><apiname>CSIPRefresh</apiname></xref> object): </p> <codeblock id="GUID-F0E7DFDA-506F-5377-9F87-CE9775436133" xml:space="preserve">const CSIPRefresh* CSIPSubscribeDialogAssoc::SIPRefresh() const</codeblock> </li> <li id="GUID-6AB4677A-19F9-5CD3-8DAB-E1A242A98D54"><p>Use the <xref href="GUID-3C166C85-6E17-323B-9CD3-B3E2836DC1C3.dita"><apiname>CSIPRefresh</apiname></xref> object to get the associated transaction by calling the following function: </p> <codeblock id="GUID-D4889AC1-1281-5367-B19B-2136AE9DA707" xml:space="preserve">const CSIPClientTransaction* CSIPRefresh::SIPTransaction() const</codeblock> <p> <b>Note:</b> The returned <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref> object is not similar to the one returned from the call to <codeph>SendSubscribeL(),</codeph> that the application originally used to send the SUBSCRIBE request. </p> </li> <li id="GUID-D1B61B14-7B99-59EA-9FDD-5ECEB839C4DA"><p>Call the following function to get the SIP response: </p> <codeblock id="GUID-04849100-2F81-5B03-9B1A-2797AF7F96DD" xml:space="preserve">const CSIPResponseElements* CSIPClientTransaction::ResponseElements() const</codeblock> </li> </ul> </section> <section id="GUID-DDD7FDBD-FBC9-5111-BE71-A71E6CCEFB2A"><title>Error handling</title> <p>Errors are passed to an application by calling the callback functions or by leaving. For more information, see <xref href="GUID-E5A83EF3-948B-5729-A2CD-3644E803520B.dita">Cleanup support overview</xref>. If an error occurs during the synchronous part of an operation is initiated by the application, functions leave with an error code. If an error occurs during the asynchronous processing stage, the error is passed to the application through one of the <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-E4E56635-42BB-351A-8356-DB12B5BE24CC"><apiname>MSIPConnectionObserver::ErrorOccured()</apiname></xref> callback functions. </p> <p>There are several overloaded variants of <codeph>ErrorOccured()</codeph> functions. Each of them takes the error code and reference to the SIP Client API object that encountered the error: </p> <ul><li id="GUID-2734ECF0-1751-5AB8-BFE3-425965D01CF0"><p>A call to the variants of <codeph>ErrorOccured()</codeph> taking a <xref href="GUID-93256B64-49C9-37F1-9A4E-72C521759749.dita"><apiname>CSIPTransactionBase</apiname></xref> or <xref href="GUID-059F9C3A-EA04-3295-912F-50444F073CE7.dita"><apiname>CSIPClientTransaction</apiname></xref> parameter means that transaction has entered the state <xref href="GUID-8E445232-29A0-3EED-94C3-43BFDD328358.dita#GUID-8E445232-29A0-3EED-94C3-43BFDD328358/GUID-288F503D-3EEA-3B4B-8D31-B58E3777F875"><apiname>CTransactionBase::ETerminated</apiname></xref>. </p> </li> <li id="GUID-C45D4A2D-F175-542B-92BF-211E1673F3F1"><p>A call to the variant of <codeph>ErrorOccured()</codeph> taking a <xref href="GUID-48AA01D5-CE7B-3C22-B2E0-529261121EC4.dita"><apiname>CSIPRegistrationBinding</apiname></xref> parameter means that the registration context is no longer active, that is <codeph>CSIPRegistrationBinding::IsContextActive() == EFalse</codeph>. </p> <p>If the registration was being refreshed, then the refresh has also ended and its state is <xref href="GUID-3C166C85-6E17-323B-9CD3-B3E2836DC1C3.dita#GUID-3C166C85-6E17-323B-9CD3-B3E2836DC1C3/GUID-EFEDCA93-E338-32A1-B005-8BA316B3C172"><apiname>CSIPRefresh::ETerminated</apiname></xref>. </p> </li> </ul> <p>If the callback function <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-27DE00DC-5572-3B55-B92B-5325794EE663"><apiname>MSIPConnectionObserver::ConnectionStateChanged()</apiname></xref> is called and the <codeph>aState</codeph> parameter is either <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita#GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94/GUID-68DD22DC-67E4-387B-BBE9-B9B96D9C9016"><apiname>CSIPConnection::EInactive</apiname></xref> or <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita#GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94/GUID-5963A947-BD5C-3B34-9D10-2CB5DC413774"><apiname>CSIPConnection::EUnavailable</apiname></xref>, then all dialogs, registrations, and standalone transactions using the <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita"><apiname>CSIPConnection</apiname></xref> are terminated. </p> <p>To avoid an overload of callback calls in this type of situation, calls to <codeph>ErrorOccured()</codeph> for the individual dialog, registration and transaction objects are not sent to the application. </p> <p>When the connection state changes, the <codeph>MSIPConnectionObserver::ConnectionStateChanged()</codeph> callback function does not provide a reason. Call <xref href="GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94.dita#GUID-2A070F4D-A35B-3505-BE86-E6C7A2F27B94/GUID-B9D5319D-D569-3D4A-AF73-66F057ACF88D"><apiname>CSIPConnection::GetConnectionError()</apiname></xref> to get details about the connection error that caused the change. </p> </section> <section id="GUID-0FC8038A-64AE-5E98-A9F9-ADBC6F05DF2B"><title>Refreshing a Connection</title> <p>To refresh a connection, do the following steps: </p> <ol id="GUID-368431B7-E9FB-56E7-A45F-01B686DBECAA"><li id="GUID-97E972C7-E839-5942-A487-48A9FD1EEC0E"><p>Start the connection on the desired IAP. </p> </li> <li id="GUID-35157131-E6EA-5EB2-8773-33832C45F46E"><p>Monitor the status of the connection using the <xref href="GUID-64C272AA-5727-3AB9-A131-68303E5A75D6.dita#GUID-64C272AA-5727-3AB9-A131-68303E5A75D6/GUID-7984D221-06F6-3F4B-B373-11C96D0A17F3"><apiname>MSIPConnectionObserver::ConnectionStateChanged(CSIPConnection::TState
                aState)</apiname></xref> function. </p> </li> <li id="GUID-85CDAB12-933A-5748-B2B8-33971F58B7B4"><p>If the connection is inactive, notify the <codeph>EInactive</codeph> state to the application through <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-27DE00DC-5572-3B55-B92B-5325794EE663"><apiname>MSIPConnectionObserver::ConnectionStateChanged()</apiname></xref> function that is, if <xref href="GUID-8239C16D-74EC-3B97-ADB0-B6AE57D30C89.dita#GUID-8239C16D-74EC-3B97-ADB0-B6AE57D30C89/GUID-3380638E-B5BA-3C88-82CB-9E52385F6A38"><apiname>(CSIPConnection::TState == EInactive)</apiname></xref>, then send a <xref href="GUID-7FBF47FB-7D1F-3F20-BBCA-A195BB540D67.dita"><apiname>RefreshConnection()</apiname></xref> function to make it active. </p> <p> <b>Note:</b> This requires a bearer monitor on that IAP to which a refresh request is sent. </p> </li> <li id="GUID-49A770C0-0992-5D27-B8A6-4D68E4B90E09"><p>Any changes to the state of the connection is notified through <xref href="GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4.dita#GUID-B889A3FD-3B14-3785-90AE-3546F0C9A5D4/GUID-27DE00DC-5572-3B55-B92B-5325794EE663"><apiname>MSIPConnectionObserver::ConnectionStateChanged()</apiname></xref>. </p> </li> </ol> <p>The following sequence diagram shows how a client refreshes a connection. </p> <fig id="GUID-B3D9E694-31F8-59AA-A722-BE6F9C0D5E89"><image href="GUID-A50BBBE2-2E23-5AEE-BF53-9EF54FD7F00E_d0e340631_href.jpg" placement="inline"/></fig> <p>The following example code describes how to refresh a connection. </p> <codeblock id="GUID-B14ADDEF-1E3C-5B21-8426-4D0FE65FBC28" xml:space="preserve">// It is assumed that the connection is started and is in an Inactive state that is, 
// (CSIPConnection::TState == EInactive)

// Refresh the IAP ID of the connection by sending a Refresh Request to the Bearer monitor of the IAP
CSIPConnection:: RefreshConnection()

// Note: The application is notified of the changes in the state of the connection through the 
// ConnectionStateChanged() function of MSIPConnectionObserver Interface.</codeblock> </section> </conbody></concept>