mirror of
https://github.com/moparisthebest/xeps
synced 2024-11-24 10:12:19 -05:00
0392f0dfcb
git-svn-id: file:///home/ksmith/gitmigration/svn/xmpp/trunk@49 4b5297f7-1745-476d-ba37-a9c6900126ab
308 lines
24 KiB
XML
308 lines
24 KiB
XML
<?xml version='1.0' encoding='UTF-8'?>
|
|
<!DOCTYPE xep SYSTEM 'xep.dtd' [
|
|
<!ENTITY % ents SYSTEM 'xep.ent'>
|
|
%ents;
|
|
]>
|
|
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
|
|
<xep>
|
|
<header>
|
|
<title>Link-Local Messaging</title>
|
|
<abstract>This document describes how to establish XMPP-like communications over local networks using zero-configuration networking.</abstract>
|
|
&LEGALNOTICE;
|
|
<number>0174</number>
|
|
<status>Experimental</status>
|
|
<type>Standards Track</type>
|
|
<jig>Standards JIG</jig>
|
|
<approver>Council</approver>
|
|
<dependencies>
|
|
<spec>XMPP Core</spec>
|
|
<spec>XMPP IM</spec>
|
|
<spec>RFC 3927</spec>
|
|
<spec>draft-cheshire-dnsext-dns-sd</spec>
|
|
<spec>draft-cheshire-dnsext-multicastdns</spec>
|
|
</dependencies>
|
|
<supersedes/>
|
|
<supersededby/>
|
|
<shortname>N/A</shortname>
|
|
&stpeter;
|
|
<revision>
|
|
<version>0.8</version>
|
|
<date>2006-07-31</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Recommended use of TLS and SASL for stream security.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.7</version>
|
|
<date>2006-06-06</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Further clarified internationalization considerations.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.6</version>
|
|
<date>2006-06-05</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Clarified internationalization considerations and use of mDNS in unicast mode for avatar retrieval.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.5</version>
|
|
<date>2006-04-14</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Specified presence name conflict resolution procedure, offline procedure, use of DNS NULL record for icons, and handling of multiple network interfaces.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.4</version>
|
|
<date>2006-03-16</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Corrected PTR format and client discovery process.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.3</version>
|
|
<date>2006-02-23</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Added more details about DNS setup and stream initiation; specified internationalization considerations.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.2</version>
|
|
<date>2006-02-22</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Corrected information about Service Instance Name format, p2pj port, and presence discovery process.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.1</version>
|
|
<date>2006-02-09</date>
|
|
<initials>psa</initials>
|
|
<remark><p>Initial version; changed title to Link-Local Messaging.</p></remark>
|
|
</revision>
|
|
<revision>
|
|
<version>0.0.1</version>
|
|
<date>2006-02-07</date>
|
|
<initials>psa</initials>
|
|
<remark><p>First draft.</p></remark>
|
|
</revision>
|
|
</header>
|
|
<section1 topic='Introduction' anchor='intro'>
|
|
<p>XMPP as defined in &rfc3920; does not support direct client-to-client interactions, since it requires authentication with a server: an XMPP client is allowed access to the network only once it has authenticated with a server, and the server must not grant access if authentication fails for any reason. If an unauthenticated client attempts to communicate directly with another client, such communication will fail because all XMPP communications are sent through one or more servers and a client cannot inject messages onto the network without first authenticating with a server.</p>
|
|
<p>However, it is possible to establish an XMPP-like communications system on a local network using zero-configuration networking. In this situation, the clients obviate the XMPP requirement for authentication with a server by relying on zero-configuration networking to establish link-local communication using the _presence._tcp DNS SRV service type. Once discovery has been completed, the clients are then able to exchange messages and other structured data using the XMPP &MESSAGE; and &IQ; stanzas. Note well that such communications are restricted to the local network because of how zero-configuration networking works. It is impossible for clients that communicate via link-local addresses to insert messages into an XMPP network, which is why this kind of local "mesh" is most accurately referred to as an XMPP-like system that exists outside the context of existing XMPP networks (though see the <link url='#security'>Security Considerations</link> regarding the ability to "forward" messages from a local mech to an XMPP network or vice-versa).</p>
|
|
<p>Such a local "mesh" can be quite valuable in certain circumstances. For instance, participants in a trade show or conference, users of the same WiFi hotspot, or employees on the same local area network can communicate without the need for a pre-configured server. For this reason, support for link-local messaging has been a feature of Apple's iChat client when operating in Bonjour (formerly Rendezvous) mode. Because it is desirable for other Jabber clients to support such functionality, this document describes how to use zero-configuration networking as the basis for link-local communication.</p>
|
|
</section1>
|
|
<section1 topic='Glossary' anchor='glossary'>
|
|
<table caption='Terminology'>
|
|
<tr>
|
|
<th>Term</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td>Bonjour</td>
|
|
<td>Apple Computer's implementation of zero-configuration networking, formerly known as Rendezvous. See <<link url='http://www.apple.com/macosx/features/bonjour/'>http://www.apple.com/macosx/features/bonjour/</link>>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>DNS-SD</td>
|
|
<td>A convention for naming and structuring DNS SRV records such that a client can dynamically discover a domain for a service using only standard DNS queries. See &dnssd;. For a full list of registered DNS-SD records, see <<link url='http://www.dns-sd.org/ServiceTypes.html'>http://www.dns-sd.org/ServiceTypes.html</link>>.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Link-local address</td>
|
|
<td>An IPv4 or IPv6 address that is valid for communication with other devices connected to the same physical or logical link. See &rfc3927;.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Multicast DNS (mDNS)</td>
|
|
<td>A technology that provides the ability to perform DNS-like operations on a local link in the absence of any conventional unicast DNS server. See &mdns;.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Zero-configuration networking</td>
|
|
<td>A set of technologies that enable the use of the Internet Protocol for local communications. See <<link url='http://www.zeroconf.org/'>http://www.zeroconf.org/</link>>.</td>
|
|
</tr>
|
|
</table>
|
|
</section1>
|
|
<section1 topic='DNS Records' anchor='dns'>
|
|
<p>In order to advertise its availability for link-local messaging, a client MUST publish four different kinds of DNS records:</p>
|
|
<ol>
|
|
<li>
|
|
<p>An address ("A") record of the following form:</p>
|
|
<code><![CDATA[
|
|
machine-name.local. A ip-address
|
|
]]></code>
|
|
</li>
|
|
<li>
|
|
<p>An "SRV" record (see &rfc2782;) of the following form:</p>
|
|
<code><![CDATA[
|
|
_presence._tcp <ttl> IN SRV <priority> <weight> port-number username@machine-name.local.
|
|
]]></code>
|
|
</li>
|
|
<li>
|
|
<p>A "PTR" record (see &rfc2317; and &rfc1886;) of the following form:</p>
|
|
<code><![CDATA[
|
|
_presence._tcp.local. port-number IN PTR username@machine-name._presence._tcp.local.
|
|
]]></code>
|
|
</li>
|
|
<li>
|
|
<p>Optionally, various "TXT" records (see &rfc1464;) of the following form, as further described in to the <link url='#txt'>TXT Records</link> section of this document:</p>
|
|
<code><![CDATA[
|
|
<owner> IN <ttl> TXT "1st=user-first-name"
|
|
<owner> IN <ttl> TXT "email=user-email-address"
|
|
<owner> IN <ttl> TXT "jid=user-jabber-id"
|
|
<owner> IN <ttl> TXT "last=user-last-name"
|
|
<owner> IN <ttl> TXT "msg=freeform-availability-status"
|
|
<owner> IN <ttl> TXT "phsh=sha1-hash-of-avatar"
|
|
<owner> IN <ttl> TXT "port.p2pj=5298"
|
|
<owner> IN <ttl> TXT "status=avail-away-or-dnd"
|
|
<owner> IN <ttl> TXT "txtvers=1"
|
|
<owner> IN <ttl> TXT "vc=capabilities-string"
|
|
]]></code>
|
|
</li>
|
|
</ol>
|
|
<p>The "machine-name" is the name of the computer, the "username" is the system username of the principal currently logged into the computer, the "port" may be any unassigned port number, and the "ip-address" is the physical address of the computer on the local network.</p>
|
|
<p>So, for example, if the machine name is "roundabout", the username is "stpeter", the chosen port is "5526", the IP address is "10.2.1.187", and the personal information is that associated with the author of this document, the DNS records would be as follows:</p>
|
|
<code><![CDATA[
|
|
roundabout.local. A 10.2.1.187
|
|
|
|
_presence._tcp IN SRV 5526 stpeter@roundabout.local.
|
|
|
|
_presence._tcp.local. 5526 IN PTR stpeter@roundabout._presence._tcp.local.
|
|
|
|
psa IN TXT "1st=Peter"
|
|
psa IN TXT "email=stpeter@jabber.org"
|
|
psa IN TXT "jid=stpeter@jabber.org"
|
|
psa IN TXT "last=Saint-Andre"
|
|
psa IN TXT "msg=IETF 66 Montreal"
|
|
psa IN TXT "phsh=a3839614e1a382bcfebbcf20464f519e81770813"
|
|
psa IN TXT "port.p2pj=5298"
|
|
psa IN TXT "status=avail"
|
|
psa IN TXT "txtvers=1"
|
|
psa IN TXT "vc=CA!"
|
|
]]></code>
|
|
<p>The IPv4 and IPv6 addresses associated with a machine may vary depending on the local network to which the machine is connected. For example, on an Ethernet connection the physical address might be "10.2.1.187" but when the machine is connected to a wireless network, its physical address might change to "10.10.1.179".</p>
|
|
<p>In the unlikely event that the "presence name" (username@machine-name) asserted by a client is already taken by another entity on the network, the client MUST choose a different presence name, which SHOULD be formed by adding the digit "1" to the end of the username string, adding the digit "2" if the resulting presence name is already taken, and incrementing the digit until a unique presence name is constructed.</p>
|
|
<section2 topic='TXT Records' anchor='txt'>
|
|
<p>DNS-SD enables service definitions to include various TXT keys that specify parameters to be used in the context of the service type. The TXT keys defined for the _presence._tcp service are as follows:</p>
|
|
<table caption='TXT Records'>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
<tr>
|
|
<td>1st</td>
|
|
<td>The given or first name of the user.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>email</td>
|
|
<td>The email address of the user.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>jid</td>
|
|
<td>The Jabber ID of the user.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>last</td>
|
|
<td>The family or last name of the user.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>msg</td>
|
|
<td>Natural-language text describing the user's state. This is equivalent to the XMPP &STATUS; element.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>phsh</td>
|
|
<td>The SHA-1 hash of the user's avatar icon or photo. <note>The client should keep a local cache of icons keyed by hash. If the phsh value is not in the cache, the client should fetch the unknown icon and then cache it. Implementations should also include logic for expiring avatar icons.</note> This SHOULD be requested using mDNS in unicast mode by sending a DNS query to the mDNS multicast address (224.0.0.251 or its IPv6 equivalent FF02::FB).</td>
|
|
</tr>
|
|
<tr>
|
|
<td>port.p2pj</td>
|
|
<td>The (hardcoded) port for link-local communications. Clients MUST use the port discovered via SRV lookups and MUST ignore the value of this TXT field, which is included only for backwards-compatibility with some older, existing implementations.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>status</td>
|
|
<td>The presence availability of the user. Allowable values are "avail", "away", and "dnd", which map to mere XMPP presence (the user is available) and the XMPP &SHOW; values of "away" and "dnd", respectively.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>txtvers</td>
|
|
<td>The version of the TXT fields supported by the client. This document describes txtvers "1".</td>
|
|
</tr>
|
|
<tr>
|
|
<td>vc</td>
|
|
<td>A flag advertising the user's ability to engage in audio or video conferencing. If the user is able to engage in audio conferencing, the string MUST include the "A" character. If the user is able to engage in video conferencing, the string MUST include the "V" character. If the user is able to engage in conferencing with more than one participant, the string MUST include the "C" character. If the user is not currently engaged in an audio or video conference, the string MUST include the "!" character. The order of characters in the string is immaterial.</td>
|
|
</tr>
|
|
</table>
|
|
<p>It is OPTIONAL to include any of these TXT keys, since link-local messaging can be used by non-human entities (e.g., devices) and these keys relate to human users. However, for use by humans, certain keys are of greater interest than others, e.g. the "msg" and "status" keys. See also the <link url='#security'>Security Considerations</link> section of this document regarding the inclusion of information that may have an impact on personal privacy (e.g., the "1st", "last", "email", and "jid" keys).</p>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='Discovering Other Users' anchor='disco'>
|
|
<p>In order to discover other users, a client sends an mDNS request for PTR records that match "_presence_tcp.local.". The client then receives replies from all machines that advertise support for link-local messaging. <note>The replies will include a record corresponding the client itself; the client MUST filter out this result.</note> The client MAY then find out detailed information about each machine by sending SRV and TXT queries to "username@machine-name._presence._tcp.local." for each machine (however, to preserve bandwidth, the client SHOULD NOT send these queries unless it is about to initiate communications with the other user, and it MUST cancel the queries after it has received a response). Note: The presence name to be used for display in a link-local "roster" MUST be obtained from the <Instance> portion of the received PTR record for each user; the client MAY display a name or nickname derived from the TXT records if available.</p>
|
|
</section1>
|
|
<section1 topic='Exchanging Presence' anchor='presence'>
|
|
<p>When the _presence._tcp service is used, presence is exchanged via the format described in the <link url='#txt'>TXT Records</link> section of this document. In particular, presence information is not pushed as in XMPP (see &rfc3921;). Instead, clients listen for presence announcements from other local entities. Recommended rates for sending updates can be found in <cite>Multicast DNS</cite>.</p>
|
|
</section1>
|
|
<section1 topic='Establishing XML Streams' anchor='streams'>
|
|
<p>In order to exchange link-local messages, the sender and recipient MUST first establish XML streams between themselves, as is familiar from <cite>RFC 3920</cite>.</p>
|
|
<p>First, the initating party opens a TCP connection at the IP address and port discovered via the DNS lookup for a local entity and opens an XML stream to the recipient with no 'to' or 'from' address:</p>
|
|
<example caption="Opening a Stream"><![CDATA[
|
|
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
|
|
]]></example>
|
|
<p>The recipient then responds with a stream header as well:</p>
|
|
<example caption="Stream Header Response"><![CDATA[
|
|
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>
|
|
]]></example>
|
|
<p>The exchange of stream headers results in an unencrypted and unauthenticated channel between the two entities. Subject to client configuration and local service policies, two entities MAY accept such a channel. However, it is RECOMMENDED to use Transport Layer Security (TLS) for channel encryption (see &rfc4346;) and the Simple Authentication and Security Layer (SASL) for authentication (see &rfc4422;), in a manner essentially the same as that defined in <cite>RFC 3920</cite>. If the initiating party wishes to TLS and SASL, it MUST include a 'version' attribute with a value of "1.0" in the stream header it sends:</p>
|
|
<example caption="Opening a Stream (Version 1.0)"><![CDATA[
|
|
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
|
|
]]></example>
|
|
<p>If the receiving entity supports TLS and SASL for stream security, it MUST also include the 'version' attribute:</p>
|
|
<example caption="Stream Header Response (Version 1.0)"><![CDATA[
|
|
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>
|
|
]]></example>
|
|
<p>The parties then can complete TLS and SASL negotiation (including stream feature advertisement) as specified in <cite>RFC 3920</cite>. A future version of this specification may include more detailed examples showing the relevant protocol flows. Handling of the 'version' attribute (or lack thereof) MUST follow the rules specified in <cite>RFC 3920</cite>.</p>
|
|
</section1>
|
|
<section1 topic='Exchanging Messages' anchor='comms'>
|
|
<p>Once the streams are established, either entity then can send XMPP message or IQ stanzas by specifying 'to' and 'from' addresses using the logical local addresses: <note>The "JIDs" MUST be of the form "username@machine-name" as discovered via SRV (this is the <Instance> portion of the Service Instance Name).</note></p>
|
|
<example caption="Sending a Message"><![CDATA[
|
|
<message to='hildjj@wolfram' from='stpeter@roundabout'>
|
|
<body>hey, testing out link-local messaging</body>
|
|
</message>
|
|
]]></example>
|
|
</section1>
|
|
<section1 topic='Ending a Chat' anchor='end'>
|
|
<p>To end the chat, either party closes the XML stream:</p>
|
|
<example caption="Ending the Chat"><![CDATA[
|
|
</stream:stream>
|
|
]]></example>
|
|
<p>The other party then closes the stream in the other direction as well:</p>
|
|
<example caption="Closing the Stream"><![CDATA[
|
|
</stream:stream>
|
|
]]></example>
|
|
<p>Both parties then MUST close the TCP connection between them.</p>
|
|
</section1>
|
|
<section1 topic='Going Offline' anchor='offline'>
|
|
<p>In order to go offline, a client MUST send a Multicast DNS "Goodbye" packet for the user's PTR record. As a result, all other entities on the local network will receive a Multicast DNS "Remove" event, at which point they MUST cancel any outstanding TXT, SRV, or NULL record queries for the offline user.</p>
|
|
</section1>
|
|
<section1 topic='Implementation Notes' anchor='impl'>
|
|
<section2 topic='Multiple Network Interfaces' anchor='impl-network'>
|
|
<p>Devices that use link-local messaging may have multiple network interfaces. As a result, it is possible to discover the same entity multiple times. Even if a client discovers the same presence name on multiple network interfaces, it MUST show only one entity in the local roster. In addition, because local IP addresses can be dynamically re-assigned, the client SHOULD NOT store the IP address to be used for communications when it discovers that address in the initial DNS lookup phase; instead, it SHOULD delay sending the Multicast DNS query until the client is ready to communicate with the other entity.</p>
|
|
</section2>
|
|
<section2 topic='Buddy Icons' anchor='impl-icons'>
|
|
<p>If an entity has an associated icon (e.g., a user avatar or photo), its client SHOULD publish the raw binary data for that image via a DNS NULL record of the following form:</p>
|
|
<code><![CDATA[
|
|
_presence._tcp.local. IN NULL raw-binary-data-here
|
|
]]></code>
|
|
<p>Note: In accordance with &rfc1035;, the data MUST be 65535 octets or less.</p>
|
|
<p>After retrieving the "phsh" value from a Buddy's TXT record, a client SHOULD search its local picture database to learn the last recorded picture hash value for an entity and then compare it to the "phsh" value in the TXT record. If the values are equal, the client SHOULD use the local copy of the icon. If the picture hash values are not equal, the client SHOULD issue a Multicast DNS NULL record query to retrieve the new icon. After retrieving the NULL record, the client SHOULD replace the old "phsh" value in the picture database with the new "phsh" value and save the icon to disk. If the client needs to send a Multicast DNS query in order to retrieve the icon, it MUST cancel the NULL record query immediately after receiving a response containing the new picture data.</p>
|
|
<p>If a user changes their picture, the user's client MUST update the NULL record with the contents of the new picture, calculate a new picture hash, and then update the "phsh" value in the TXT record with the new hash value. Since all users logged into local presence are monitoring for TXT record changes, they will see that the "phsh" value was changed; if they wish to view the new icon, their clients SHOULD issue a new Multicast DNS query to retrieve the updated picture.</p>
|
|
</section2>
|
|
</section1>
|
|
<section1 topic='Internationalization Considerations' anchor='i18n'>
|
|
<p><cite>RFC 1035</cite> does not allow characters outside the &ascii; character range in DNS A records. Therefore the "machine-name" portion of an A record as used for link-local messaging MUST NOT contain characters outside the US-ASCII character range.</p>
|
|
<p>Although <cite>RFC 2317</cite> and <cite>RFC 2782</cite> do not allow characters outside the US-ASCII character range in PTR and SRV records respectively, Section 4.1 of <cite>DNS-Based Service Discovery</cite> recommends support for UTF-8-encoded Unicode characters in the <Instance> portion of Service Instance Names, which in link-local messaging is the "username@machine-name" portion of the PTR or SRV record. This document adheres to the recommendation in <cite>DNS-Based Service Discovery</cite>. However, as mentioned above, the "machine-name" portion of the <Instance> portion MUST NOT contain characters outside the US-ASCII range.</p>
|
|
<p>Although <cite>RFC 1464</cite> does not allow characters outside the US-ASCII character range in TXT records, Section 6.5 of <cite>DNS-Based Service Discovery</cite> mentions support for UTF-8-encoded Unicode characters in text record values (e.g., values of the TXT "msg" name). This document adheres to the recommendation in <cite>DNS-Based Service Discovery</cite>.</p>
|
|
</section1>
|
|
<section1 topic='Security Considerations' anchor='security'>
|
|
<p>XMPP networks depend on TLS (&rfc2246;) for channel encryption, SASL (&rfc4422;) for authentication, and the Domain Name System (&rfc1034;) for validation of server hostnames; these technologies help to ensure the identity of sending entities. By contrast, zero-configuration networking uses dynamic discovery and asserted machine names as the basis of sender identity. Therefore, zero-configuration networking does not result in authenticated identities in the same way that XMPP itself does, nor does it provide for an encrypted channel between local entities. (TLS could be negotiated on the local streams, but is out of scope for this specification.)</p>
|
|
<p>Because of fundamental differences between a true XMPP network and a localized XMPP client "mesh", local entities MUST NOT attempt to inject local traffic onto an XMPP network and an XMPP server MUST reject communications until an entity is properly authenticated. However, a client on a local mesh MAY forward traffic to an XMPP network after having properly authenticated on such a network (e.g., to forward a message received on a local client mesh to a contact on an XMPP network).</p>
|
|
<p>The TXT records optionally advertised as part of this protocol MAY result in exposure of privacy-sensitive information about a human user (such as full name, email address, and Jabber ID). A client MUST allow a user to disable publication of this personal information (e.g., via client configuration).</p>
|
|
</section1>
|
|
<section1 topic='IANA Considerations' anchor='iana'>
|
|
<p>The p2pj port number 5298 is not included in the &ianaports; maintained by &IANA;. The author will investigate whether that port number (or some other port number) needs to be registered.</p>
|
|
</section1>
|
|
<section1 topic='XMPP Registrar Considerations' anchor='registrar'>
|
|
<p>This document requires no interaction with the ®ISTRAR;.</p>
|
|
</section1>
|
|
<section1 topic='Acknowledgements' anchor='ack'>
|
|
<p>Thanks to Justin Karneges, Jens Alfke, and Marc Krochmal for their input.</p>
|
|
</section1>
|
|
</xep>
|