summaryrefslogtreecommitdiff
path: root/doc/ICElib.ms
diff options
context:
space:
mode:
Diffstat (limited to 'doc/ICElib.ms')
-rw-r--r--doc/ICElib.ms3400
1 files changed, 3400 insertions, 0 deletions
diff --git a/doc/ICElib.ms b/doc/ICElib.ms
new file mode 100644
index 0000000..0c35d60
--- /dev/null
+++ b/doc/ICElib.ms
@@ -0,0 +1,3400 @@
+.\" $Xorg: ICElib.ms,v 1.3 2000/08/17 19:42:09 cpqbld Exp $
+.\" $XdotOrg: xc/doc/specs/ICE/ICElib.ms,v 1.2 2004/04/23 18:42:16 eich Exp $
+.\"
+.\" Use tbl, -ms, and macros.t
+.\"
+.\" macro: start marker
+.de sM
+.ne 4
+.sp 1
+\\h'-0.3i'\\L'-1v'\\v'3p'\\l'1v'\\v'1v-3p'
+.sp -1
+..
+.\" macro: end marker
+.de eM
+.sp -1
+\\h'-0.3i'\\L'-1v'\\v'1v+4p'\\l'1v'\\v'-4p'
+.sp 1
+..
+.EH ''''
+.OH ''''
+.EF ''''
+.OF ''''
+.ad b
+.sp 10
+.TL
+\s+2\fBInter-Client Exchange Library\fP\s-2
+.sp
+Version 1.0
+.sp
+X Consortium Standard
+.sp
+X Version 11, Release 6.8
+.AU
+Ralph Mor
+.AI
+X Consortium
+.LP
+.DS C
+Copyright \(co 1993, 1994, 1996 X Consortium
+.DE
+.LP
+.sp 5
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the ``Software''), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+.LP
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+.LP
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+.LP
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+.sp 5
+X Window System is a trademark of The Open Group.
+.bp
+.EH '\fBInter-Client Exchange Library\fP''\fBX11, Release 6.8\fP'
+.OH '\fBInter-Client Exchange Library\fP''\fBX11, Release 6.8\fP'
+.bp 1
+.EF ''\- \\\\n(PN \-''
+.OF ''\- \\\\n(PN \-''
+.NH 1
+Overview of ICE
+.XS
+\*(SN Overview of ICE
+.XE
+.LP
+There are numerous possible inter-client protocols, with many similarities
+and common needs - authentication, version negotiation, byte
+order negotiation, and so on.
+The Inter-Client Exchange (ICE) protocol is intended to provide a framework
+for building such protocols, allowing them to make use of common negotiation
+mechanisms and to be multiplexed over a single transport connection.
+.NH 1
+The ICE Library - C Language Interface to ICE
+.XS
+\*(SN The ICE Library - C Language Interface to ICE
+.XE
+.LP
+A client that wishes to utilize ICE must first register the protocols it
+understands with the ICE library. Each protocol is dynamically assigned
+a major opcode ranging from 1-255 (two clients can use different
+major opcodes for the same protocol). The next step for the client is either
+to open a connection with another client or to wait for connections made
+by other clients. Authentication may be required. A client can both
+initiate connections with other clients and be
+waiting for clients to connect to itself (a nested session manager is an
+example). Once an ICE connection is established between the two clients, one
+of the clients needs to initiate a
+.PN ProtocolSetup
+in order to
+"activate" a given protocol. Once the other client accepts the
+.PN ProtocolSetup
+(once again, authentication may be required), the
+two clients are ready to start passing messages specific to that protocol to
+each other. Multiple protocols may be active on a single ICE connection.
+Clients are responsible for notifying the ICE library when a protocol is no
+longer active on an ICE connection, although ICE does not define how each
+subprotocol triggers a protocol shutdown.
+.LP
+The ICE library utilizes callbacks to process incoming messages. Using
+callbacks allows
+.PN ProtocolSetup
+messages and authentication to happen
+behind the scenes. An additional benefit is that messages never need
+to be buffered up by the library when the client blocks waiting for a
+particular message.
+.NH 1
+Intended Audience
+.XS
+\*(SN Intended Audience
+.XE
+.LP
+This document is intended primarily for implementors of protocol libraries
+layered on top of ICE. Typically, applications that wish to utilize ICE
+will make calls into individual protocol libraries rather than directly
+make calls into the ICE library. However, some applications will have to
+make some initial calls into the ICE library in order to accept ICE
+connections (for example, a session manager accepting connections from
+clients). But in general, protocol libraries should be designed to hide
+the inner details of ICE from applications.
+.NH 1
+Header Files and Library Name
+.XS
+\*(SN Header Files and Library Name
+.XE
+.LP
+The header file
+.Pn < X11/ICE/ICElib.h >
+defines all of the ICElib data structures and function prototypes.
+.PN ICElib.h
+includes the header file
+.Pn < X11/ICE/ICE.h >,
+which defines all of the ICElib constants.
+Protocol libraries that need to read and write messages should include
+the header file
+.Pn < X11/ICE/ICEmsg.h >.
+.LP
+Applications should link against ICElib using -lICE.
+.NH 1
+Note on Prefixes
+.XS
+\*(SN Note on Prefixes
+.XE
+.LP
+The following name prefixes are used in the library to distinguish between
+a client that initiates a
+.PN ProtocolSetup
+and a client that
+responds with a
+.PN ProtocolReply :
+.IP \(bu 5
+.PN IcePo
+\- Ice Protocol Originator
+.IP \(bu 5
+.PN IcePa
+\- Ice Protocol Acceptor
+.NH 1
+Protocol Registration
+.XS
+\*(SN Protocol Registration
+.XE
+.LP
+In order for two clients to exchange messages for a given protocol, each
+side must register the protocol with the ICE library. The purpose of
+registration is for each side to obtain a major opcode for the protocol
+and to provide callbacks for processing messages and handling authentication.
+There are two separate registration functions:
+.IP \(bu 5
+One to handle the side that does a
+.PN ProtocolSetup
+.IP \(bu 5
+One to handle the side that responds with a
+.PN ProtocolReply
+.LP
+It is recommended that protocol registration occur before the two clients
+establish an ICE connection. If protocol registration occurs after an
+ICE connection is created, there can be a brief interval of time in which
+a
+.PN ProtocolSetup
+is received, but the protocol is not registered.
+If it is not possible to register a protocol before the creation of an
+ICE connection, proper precautions should be taken to avoid the above race
+condition.
+.sp
+.LP
+The
+.PN IceRegisterForProtocolSetup
+function should be called for the client that initiates a
+.PN ProtocolSetup .
+.sM
+.FD 0
+int IceRegisterForProtocolSetup\^(\^\fIprotocol_name\fP, \fIvendor\fP\^, \
+\fIrelease\fP\^, \fIversion_count\fP\^, \fIversion_recs\fP\^,
+.br
+ \fIauth_count\fP\^, \fIauth_names\fP\^, \fIauth_procs\fP\^, \
+\fIio_error_proc\fP\^)
+.br
+ char *\fIprotocol_name\fP\^;
+.br
+ char *\fIvendor\fP\^;
+.br
+ char *\fIrelease\fP\^;
+.br
+ int \fIversion_count\fP\^;
+.br
+ IcePoVersionRec *\fIversion_recs\fP\^;
+.br
+ int \fIauth_count\fP\^;
+.br
+ char **\fIauth_names\fP\^;
+.br
+ IcePoAuthProc *\fIauth_procs\fP\^;
+.br
+ IceIOErrorProc \fIio_error_proc\fP\^;
+.FN
+.IP \fIprotocol_name\fP 1i
+A string specifying the name of the protocol to register.
+.IP \fIvendor\fP 1i
+A vendor string with semantics specified by the protocol.
+.IP \fIrelease\fP 1i
+A release string with semantics specified by the protocol.
+.IP \fIversion_count\fP 1i
+The number of different versions of the protocol supported.
+.IP \fIversion_recs\fP 1i
+List of versions and associated callbacks.
+.IP \fIauth_count\fP 1i
+The number of authentication methods supported.
+.IP \fIauth_names\fP 1i
+The list of authentication methods supported.
+.IP \fIauth_procs\fP 1i
+The list of authentication callbacks, one for each authentication method.
+.IP \fIio_error_proc\fP 1i
+IO error handler, or NULL.
+.LP
+.eM
+.PN IceRegisterForProtocolSetup
+returns the major opcode reserved or -1 if an error occurred. In order
+to actually activate the protocol, the
+.PN IceProtocolSetup
+function needs to be called with this major opcode. Once the protocol is
+activated, all messages for the protocol should be sent using this major
+opcode.
+.LP
+A protocol library may support multiple versions of the same protocol.
+The version_recs argument specifies a list of supported versions of the protocol,
+which are prioritized in decreasing order of preference.
+Each version record consists of a major and minor version of the protocol
+as well as a callback to be used for processing incoming messages.
+.LP
+.sM
+.Ds 0
+.TA .5i
+.ta .5i
+typedef struct {
+ int major_version;
+ int minor_version;
+ IcePoProcessMsgProc process_msg_proc;
+} IcePoVersionRec;
+.De
+.LP
+.eM
+The
+.PN IcePoProcessMsgProc
+callback is responsible for processing the set of messages that can be
+received by the client that initiated the
+.PN ProtocolSetup .
+For further information,
+see section 6.1, ``Callbacks for Processing Messages.''
+.LP
+Authentication may be required before the protocol can become active.
+The protocol library must register the authentication methods that it
+supports with the ICE library.
+The auth_names and auth_procs arguments are a list of authentication names
+and callbacks that are prioritized in decreasing order of preference.
+For information on the
+.PN IcePoAuthProc
+callback, see section 6.2, ``Authentication Methods.''
+.LP
+The
+.PN IceIOErrorProc
+callback is invoked if the ICE connection unexpectedly breaks.
+You should pass NULL for io_error_proc if not interested in being notified.
+For further information,
+see section 13, ``Error Handling.''
+.sp
+.LP
+The
+.PN IceRegisterForProtocolReply
+function should be called for the client that responds to a
+.PN ProtocolSetup
+with a
+.PN ProtocolReply .
+.sM
+.FD 0
+int IceRegisterForProtocolReply\^(\^\fIprotocol_name\fP, \fIvendor\fP\^, \fIrelease\fP\^, \fIversion_count\fP\^, \fIversion_recs\fP\^,
+.br
+ \fIauth_count\fP\^, \fIauth_names\fP\^, \fIauth_procs\fP\^, \fIhost_based_auth_proc\fP\^, \fIprotocol_setup_proc\fP\^,
+.br
+ \fIprotocol_activate_proc\fP\^, \fIio_error_proc\fP\^)
+.br
+ char *\fIprotocol_name\fP\^;
+.br
+ char *\fIvendor\fP\^;
+.br
+ char *\fIrelease\fP\^;
+.br
+ int \fIversion_count\fP\^;
+.br
+ IcePaVersionRec *\fIversion_recs\fP\^;
+.br
+ int \fIauth_count\fP\^;
+.br
+ char **\fIauth_names\fP\^;
+.br
+ IcePaAuthProc *\fIauth_procs\fP\^;
+.br
+ IceHostBasedAuthProc \fIhost_based_auth_proc\fP\^;
+.br
+ IceProtocolSetupProc \fIprotocol_setup_proc\fP\^;
+.br
+ IceProtocolActivateProc \fIprotocol_activate_proc\fP\^;
+.br
+ IceIOErrorProc \fIio_error_proc\fP\^;
+.FN
+.IP \fIprotocol_name\fP 1i
+A string specifying the name of the protocol to register.
+.IP \fIvendor\fP 1i
+A vendor string with semantics specified by the protocol.
+.IP \fIrelease\fP 1i
+A release string with semantics specified by the protocol.
+.IP \fIversion_count\fP 1i
+The number of different versions of the protocol supported.
+.IP \fIversion_recs\fP 1i
+List of versions and associated callbacks.
+.IP \fIauth_count\fP 1i
+The number of authentication methods supported.
+.IP \fIauth_names\fP 1i
+The list of authentication methods supported.
+.IP \fIauth_procs\fP 1i
+The list of authentication callbacks, one for each authentication method.
+.IP \fIhost_based_auth_proc\fP 1i
+Host based authentication callback.
+.IP \fIprotocol_setup_proc\fP 1i
+A callback to be invoked when authentication has succeeded for a
+.PN ProtocolSetup
+but before the
+.PN ProtocolReply
+is sent.
+.IP \fIprotocol_activate_proc\fP 1i
+A callback to be invoked after the
+.PN ProtocolReply
+is sent.
+.IP \fIio_error_proc\fP 1i
+IO error handler, or NULL.
+.LP
+.eM
+.PN IceRegisterForProtocolReply
+returns the major opcode reserved or -1 if an error occurred. The major
+opcode should be used in all subsequent messages sent for this protocol.
+.LP
+A protocol library may support multiple versions of the same protocol.
+The version_recs argument specifies a list of supported versions of the protocol,
+which are prioritized in decreasing order of preference.
+Each version record consists of a major and minor version of the protocol
+as well as a callback to be used for processing incoming messages.
+.LP
+.sM
+.Ds 0
+.TA .5i
+.ta .5i
+typedef struct {
+ int major_version;
+ int minor_version;
+ IcePaProcessMsgProc process_msg_proc;
+} IcePaVersionRec;
+.De
+.LP
+.eM
+The
+.PN IcePaProcessMsgProc
+callback is responsible for processing the set of messages that can be
+received by the client that accepted the
+.PN ProtocolSetup .
+For further information,
+see section 6.1, ``Callbacks for Processing Messages.''
+.LP
+Authentication may be required before the protocol can become active.
+The protocol library must register the authentication methods that it
+supports with the ICE library.
+The auth_names and auth_procs arguments are a list of authentication names
+and callbacks that are prioritized in decreasing order of preference.
+For information on the
+.PN IcePaAuthProc
+callback, see section 6.2, ``Authentication Methods.''
+.LP
+If authentication fails and the client attempting to initiate
+the
+.PN ProtocolSetup
+has not required authentication, the
+.PN IceHostBasedAuthProc
+callback is invoked with the host name of the originating client.
+If the callback returns
+.PN True ,
+the
+.PN ProtocolSetup
+will succeed, even though the original
+authentication failed.
+Note that authentication can effectively be disabled by registering an
+.PN IceHostBasedAuthProc ,
+which always returns
+.PN True .
+If no host based
+authentication is allowed, you should pass NULL for host_based_auth_proc.
+.LP
+.sM
+.FD 0
+typedef Bool (*IceHostBasedAuthProc) ();
+
+Bool HostBasedAuthProc\^(\^\fIhost_name\fP\^)
+.br
+ char *\fIhost_name\fP\^;
+.FN
+.IP \fIhost_name\fP 1i
+The host name of the client that sent the
+.PN ProtocolSetup .
+.LP
+.eM
+The host_name argument is a string of the form \fIprotocol\fP\^/\^\fIhostname\fP,
+where \fIprotocol\fP\^ is one of {tcp, decnet, local}.
+.LP
+Because
+.PN ProtocolSetup
+messages and authentication happen behind the scenes
+via callbacks, the protocol library needs some way of being notified when the
+.PN ProtocolSetup
+has completed.
+This occurs in two phases.
+In the first phase, the
+.PN IceProtocolSetupProc
+callback is invoked after authentication has
+successfully completed but before the ICE library sends a
+.PN ProtocolReply .
+Any resources required for this protocol should be allocated at this time.
+If the
+.PN IceProtocolSetupProc
+returns a successful status, the ICE library will
+send the
+.PN ProtocolReply
+and then invoke the
+.PN IceProtocolActivateProc
+callback. Otherwise, an error will be sent to the
+other client in response to the
+.PN ProtocolSetup .
+.LP
+The
+.PN IceProtocolActivateProc
+is an optional callback and should be registered only if the protocol
+library intends to generate a message immediately following the
+.PN ProtocolReply .
+You should pass NULL for protocol_activate_proc if not interested
+in this callback.
+.if t .bp
+.sM
+.FD 0
+typedef Status (*IceProtocolSetupProc) ();
+
+Status ProtocolSetupProc\^(\^\fIice_conn\fP, \fImajor_version\fP\^, \
+\fIminor_version\fP\^, \fIvendor\fP\^, \fIrelease\fP\^,
+.br
+ \fIclient_data_ret\fP\^, \fIfailure_reason_ret\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fImajor_version\fP\^;
+.br
+ int \fIminor_version\fP\^;
+.br
+ char *\fIvendor\fP\^;
+.br
+ char *\fIrelease\fP\^;
+.br
+ IcePointer *\fIclient_data_ret\fP\^;
+.br
+ char **\fIfailure_reason_ret\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.IP \fImajor_version\fP 1i
+The major version of the protocol.
+.IP \fIminor_version\fP 1i
+The minor version of the protocol.
+.IP \fIvendor\fP 1i
+The vendor string registered by the protocol originator.
+.IP \fIrelease\fP 1i
+The release string registered by the protocol originator.
+.IP \fIclient_data_ret\fP 1i
+Client data to be set by callback.
+.IP \fIfailure_reason_ret\fP 1i
+Failure reason returned.
+.LP
+.eM
+The pointer stored in the client_data_ret argument will be passed
+to the
+.PN IcePaProcessMsgProc
+callback whenever a message has arrived for this protocol on the
+ICE connection.
+.LP
+The vendor and release strings should be freed with
+.PN free
+when they are no longer needed.
+.LP
+If a failure occurs, the
+.PN IceProtocolSetupProc
+should return a zero status as well as allocate and return a failure
+reason string in failure_reason_ret.
+The ICE library will be responsible for freeing this memory.
+.LP
+The
+.PN IceProtocolActivateProc
+callback is defined as follows:
+.sM
+.FD 0
+typedef void (*IceProtocolActivateProc)();
+
+void ProtocolActivateProc\^(\^\fIice_conn\fP, \fIclient_data\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.IP \fIclient_data\fP 1i
+The client data set in the
+.PN IceProtocolSetupProc
+callback.
+.LP
+.eM
+The
+.PN IceIOErrorProc
+callback is invoked if the ICE connection unexpectedly breaks.
+You should pass NULL for io_error_proc if not interested in being notified.
+For further information,
+see section 13, ``Error Handling.''
+.NH 2
+Callbacks for Processing Messages
+.XS
+\*(SN Callbacks for Processing Messages
+.XE
+.LP
+When an application detects that there is new data to read on an ICE
+connection (via
+.PN select ),
+it calls the
+.PN IceProcessMessages
+function (see section 9, ``Processing Messages'').
+When
+.PN IceProcessMessages
+reads an ICE message header with a major opcode other than
+zero (reserved for the ICE protocol), it needs to call a function that will
+read the rest of the message, unpack it, and process it accordingly.
+.LP
+If the message arrives at the client that initiated the
+.PN ProtocolSetup ,
+the
+.PN IcePoProcessMsgProc
+callback is invoked.
+.sM
+.FD 0
+typedef void (*IcePoProcessMsgProc)();
+
+void PoProcessMsgProc\^(\^\fIice_conn\fP, \fIclient_data\fP\^, \fIopcode\fP\^, \fIlength\fP\^, \fIswap\fP\^, \fIreply_wait\fP\^, \fIreply_ready_ret\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.br
+ int \fIopcode\fP\^;
+.br
+ unsigned long \fIlength\fP\^;
+.br
+ Bool \fIswap\fP\^;
+.br
+ IceReplyWaitInfo *\fIreply_wait\fP\^;
+.br
+ Bool *\fIreply_ready_ret\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.IP \fIclient_data\fP 1i
+Client data associated with this protocol on the ICE connection.
+.IP \fIopcode\fP 1i
+The minor opcode of the message.
+.IP \fIlength\fP 1i
+The length (in 8-byte units) of the message beyond the ICE header.
+.IP \fIswap\fP 1i
+A flag that indicates if byte swapping is necessary.
+.IP \fIreply_wait\fP 1i
+Indicates if the invoking client is waiting for a reply.
+.IP \fIreply_ready_ret\fP 1i
+If set to
+.PN True ,
+a reply is ready.
+.LP
+.eM
+If the message arrives at the client that accepted the
+.PN ProtocolSetup ,
+the
+.PN IcePaProcessMsgProc
+callback is invoked.
+.sM
+.FD 0
+typedef void (*IcePaProcessMsgProc)();
+
+void PaProcessMsgProc\^(\^\fIice_conn\fP, \fIclient_data\fP\^, \fIopcode\fP\^, \fIlength\fP\^, \fIswap\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.br
+ int \fIopcode\fP\^;
+.br
+ unsigned long \fIlength\fP\^;
+.br
+ Bool \fIswap\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.IP \fIclient_data\fP 1i
+Client data associated with this protocol on the ICE connection.
+.IP \fIopcode\fP 1i
+The minor opcode of the message.
+.IP \fIlength\fP 1i
+The length (in 8-byte units) of the message beyond the ICE header.
+.IP \fIswap\fP 1i
+A flag that indicates if byte swapping is necessary.
+.LP
+.eM
+In order to read the message, both of these callbacks should use the
+macros defined for this purpose (see section 12.2, ``Reading ICE Messages'').
+Note that byte swapping may be necessary.
+As a convenience, the length field in the ICE header will be swapped by ICElib
+if necessary.
+.LP
+In both of these callbacks, the client_data argument is a pointer to client
+data that was registered at
+.PN ProtocolSetup
+time.
+In the case of
+.PN IcePoProcessMsgProc ,
+the client data was set in the call to
+.PN IceProtocolSetup .
+In the case of
+.PN IcePaProcessMsgProc ,
+the client data was set in the
+.PN IceProtocolSetupProc
+callback.
+.LP
+The
+.PN IcePoProcessMsgProc
+callback needs to check the reply_wait argument.
+If reply_wait is NULL ,
+the ICE library expects the function to
+pass the message to the client via a callback.
+For example, if this is a Session Management ``Save Yourself'' message,
+this function should notify the client of the ``Save Yourself'' via a callback.
+The details of how such a callback would be defined
+are implementation-dependent.
+.LP
+However, if reply_wait is not NULL ,
+then the client is waiting for
+a reply or an error for a message it previously sent.
+The reply_wait is of type
+.PN IceReplyWaitInfo .
+.sM
+.Ds 0
+.TA .5i 2.5i
+.ta .5i 2.5i
+typedef struct {
+ unsigned long sequence_of_request;
+ int major_opcode_of_request;
+ int minor_opcode_of_request;
+ IcePointer reply;
+} IceReplyWaitInfo;
+.De
+.LP
+.eM
+.PN IceReplyWaitInfo
+contains the major/minor opcodes and sequence number of
+the message for which a reply is being awaited.
+It also contains a pointer to the reply message to be filled in
+(the protocol library should cast this
+.PN IcePointer
+to the appropriate reply type).
+In most cases, the reply will have some fixed-size part, and the client waiting
+for the reply will have provided a pointer to a structure to hold
+this fixed-size data. If there is variable-length data, it would be
+expected that the
+.PN IcePoProcessMsgProc
+callback will have to allocate additional
+memory and store pointer(s) to that memory in the fixed-size
+structure. If the entire data is variable length (for example., a single
+variable-length string), then the client waiting for the reply would probably
+just pass a pointer to fixed-size space to hold a pointer, and the
+.PN IcePoProcessMsgProc
+callback would allocate the storage and store the pointer.
+It is the responsibility of the client receiving the reply to
+free any memory allocated on its behalf.
+.LP
+If reply_wait is not NULL and
+.PN IcePoProcessMsgProc
+has a reply or error to return in response to this reply_wait
+(that is, no callback was generated), then the reply_ready_ret argument
+should be set to
+.PN True .
+Note that an error should only be returned
+if it corresponds to the reply being waited for. Otherwise, the
+.PN IcePoProcessMsgProc
+should either handle the error internally or invoke an error handler
+for its library.
+.LP
+If reply_wait is NULL,
+then care must be taken not to store any value in reply_ready_ret,
+because this pointer may also be NULL.
+.LP
+The
+.PN IcePaProcessMsgProc
+callback, on the other hand, should always pass
+the message to the client via a callback. For example, if this is a Session
+Management ``Interact Request'' message, this function should notify the
+client of the ``Interact Request'' via a callback.
+.LP
+The reason the
+.PN IcePaProcessMsgProc
+callback does not have a reply_wait, like
+.PN IcePoProcessMsgProc
+does, is because a process that is acting as
+a server should never block for a reply (infinite blocking can
+occur if the connecting client does not act properly, denying access
+to other clients).
+.NH 2
+Authentication Methods
+.XS
+\*(SN Authentication Methods
+.XE
+.LP
+As already stated, a protocol library must register the authentication
+methods that it supports with the ICE library. For each authentication
+method, there are two callbacks that may be registered:
+.IP \(bu 5
+One to handle the side that initiates a
+.PN ProtocolSetup
+.IP \(bu 5
+One to handle the side that accepts or rejects this request
+.LP
+.PN IcePoAuthProc
+is the callback invoked for the client that initiated the
+.PN ProtocolSetup .
+This callback must be able to respond
+to the initial ``Authentication Required'' message or subsequent
+``Authentication Next Phase'' messages sent by the other client.
+.if t .bp
+.sM
+.FD 0
+typedef IcePoAuthStatus (*IcePoAuthProc)();
+
+IcePoAuthStatus PoAuthProc\^(\^\fIice_conn\fP, \fIauth_state_ptr\fP\^, \fIclean_up\fP\^, \fIswap\fP\^, \fIauth_datalen\fP\^, \fIauth_data\fP\^,
+.br
+ \fIreply_datalen_ret\fP\^, \fIreply_data_ret\fP\^, \fIerror_string_ret\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IcePointer *\fIauth_state_ptr\fP\^;
+.br
+ Bool \fIclean_up\fP\^;
+.br
+ Bool \fIswap\fP\^;
+.br
+ int \fIauth_datalen\fP\^;
+.br
+ IcePointer \fIauth_data\fP\^;
+.br
+ int *\fIreply_datalen_ret\fP\^;
+.br
+ IcePointer *\fIreply_data_ret\fP\^;
+.br
+ char **\fIerror_string_ret\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.IP \fIauth_state_ptr\fP 1i
+A pointer to state for use by the authentication callback procedure.
+.IP \fIclean_up\fP 1i
+If
+.PN True ,
+authentication is over, and the function
+should clean up any state it was maintaining. The
+last 6 arguments should be ignored.
+.IP \fIswap\fP 1i
+If
+.PN True ,
+the auth_data may have to be byte swapped
+(depending on its contents).
+.IP \fIauth_datalen\fP 1i
+The length (in bytes) of the authenticator data.
+.IP \fIauth_data\fP 1i
+The data from the authenticator.
+.IP \fIreply_datalen_ret\fP 1i
+The length (in bytes) of the reply data returned.
+.IP \fIreply_data_ret\fP 1i
+The reply data returned.
+.IP \fIerror_string_ret\fP 1i
+If the authentication procedure encounters an error during
+authentication, it should allocate and return
+an error string.
+.LP
+.eM
+Authentication may require several phases, depending on the authentication
+method. As a result, the
+.PN IcePoAuthProc
+may be called more than once when authenticating a client, and
+some state will have to be maintained between each invocation.
+At the start of each
+.PN ProtocolSetup ,
+*auth_state_ptr is NULL,
+and the function should initialize its state and set
+this pointer. In subsequent invocations of the callback, the pointer
+should be used to get at any state previously stored by the callback.
+.LP
+If needed, the network ID of the client accepting the
+.PN ProtocolSetup
+can be obtained by calling the
+.PN IceConnectionString
+function.
+.LP
+ICElib will be responsible for freeing the reply_data_ret and
+error_string_ret pointers with
+.PN free .
+.LP
+The auth_data pointer may point to a volatile block of memory.
+If the data must be kept beyond this invocation of the callback, be sure
+to make a copy of it.
+.LP
+The
+.PN IcePoAuthProc
+should return one of four values:
+.IP \(bu 5
+.PN IcePoAuthHaveReply
+\- a reply is available.
+.IP \(bu 5
+.PN IcePoAuthRejected
+\- authentication rejected.
+.IP \(bu 5
+.PN IcePoAuthFailed
+\- authentication failed.
+.IP \(bu 5
+.PN IcePoAuthDoneCleanup
+\- done cleaning up.
+.LP
+.PN IcePaAuthProc
+is the callback invoked for the client that received the
+.PN ProtocolSetup .
+.if t .bp
+.sM
+.FD 0
+typedef IcePaAuthStatus (*IcePaAuthProc) ();
+
+IcePaAuthStatus PaAuthProc\^(\^\fIice_conn\fP, \fIauth_state_ptr\fP\^, \fIswap\fP\^, \fIauth_datalen\fP\^, \fIauth_data\fP\^,
+.br
+ \fIreply_datalen_ret\fP\^, \fIreply_data_ret\fP\^, \fIerror_string_ret\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IcePointer *\fIauth_state_ptr\fP\^;
+.br
+ Bool \fIswap\fP\^;
+.br
+ int \fIauth_datalen\fP\^;
+.br
+ IcePointer \fIauth_data\fP\^;
+.br
+ int *\fIreply_datalen_ret\fP\^;
+.br
+ IcePointer *\fIreply_data_ret\fP\^;
+.br
+ char **\fIerror_string_ret\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.IP \fIauth_state_ptr\fP 1i
+A pointer to state for use by the authentication callback procedure.
+.IP \fIswap\fP 1i
+If
+.PN True ,
+auth_data may have to be byte swapped
+(depending on its contents).
+.IP \fIauth_datalen\fP 1i
+The length (in bytes) of the protocol originator authentication data.
+.IP \fIauth_data\fP 1i
+The authentication data from the protocol originator.
+.IP \fIreply_datalen_ret\fP 1i
+The length of the authentication data returned.
+.IP \fIreply_data_ret\fP 1i
+The authentication data returned.
+.IP \fIerror_string_ret\fP 1i
+If authentication is rejected or fails, an error
+string is returned.
+.LP
+.eM
+.LP
+Authentication may require several phases, depending on the authentication
+method. As a result, the
+.PN IcePaAuthProc
+may be called more than once when authenticating a client, and
+some state will have to be maintained between each invocation.
+At the start of each
+.PN ProtocolSetup ,
+auth_datalen is zero,
+*auth_state_ptr is NULL,
+and the function should initialize its state and set
+this pointer. In subsequent invocations of the callback, the pointer
+should be used to get at any state previously stored by the callback.
+.LP
+If needed, the network ID of the client accepting the
+.PN ProtocolSetup
+can be obtained by calling the
+.PN IceConnectionString
+function.
+.LP
+The auth_data pointer may point to a volatile block of memory.
+If the data must be kept beyond this invocation of the callback, be sure
+to make a copy of it.
+.LP
+ICElib will be responsible for transmitting and freeing the reply_data_ret and
+error_string_ret pointers with
+.PN free .
+.LP
+The
+.PN IcePaAuthProc
+should return one of four values:
+.IP \(bu 5
+.PN IcePaAuthContinue
+\- continue (or start) authentication.
+.IP \(bu 5
+.PN IcePaAuthAccepted
+\- authentication accepted.
+.IP \(bu 5
+.PN IcePaAuthRejected
+\- authentication rejected.
+.IP \(bu 5
+.PN IcePaAuthFailed
+\- authentication failed.
+.NH 1
+ICE Connections
+.XS
+\*(SN ICE Connections
+.XE
+.LP
+In order for two clients to establish an ICE connection, one client has
+to be waiting for connections, and the other client has to initiate the
+connection.
+Most clients will initiate connections, so we discuss that first.
+.NH 2
+Opening an ICE Connection
+.XS
+\*(SN Opening an ICE Connection
+.XE
+.LP
+To open an ICE connection with another client (that is, waiting
+for connections), use
+.PN IceOpenConnection .
+.sM
+.FD 0
+IceConn IceOpenConnection\^(\^\fInetwork_ids_list\fP, \fIcontext\fP\^, \fImust_authenticate\fP\^, \fImajor_opcode_check\fP\^,
+.br
+ \fIerror_length\fP\^, \fIerror_string_ret\fP\^)
+.br
+ char *\fInetwork_ids_list\fP\^;
+.br
+ IcePointer \fIcontext\fP\^;
+.br
+ Bool \fImust_authenticate\fP\^;
+.br
+ int \fImajor_opcode_check\fP\^;
+.br
+ int \fIerror_length\fP\^;
+.br
+ char *\fIerror_string_ret\fP\^;
+.FN
+.IP \fInetwork_ids_list\fP 1i
+Specifies the network ID(s) of the other client.
+.IP \fIcontext\fP 1i
+A pointer to an opaque object or NULL. Used to determine if an
+ICE connection can be shared (see below).
+.IP \fImust_authenticate\fP 1i
+If
+.PN True ,
+the other client may not bypass authentication.
+.IP \fImajor_opcode_check\fP 1i
+Used to force a new ICE connection to be created (see below).
+.IP \fIerror_length\fP 1i
+Length of the error_string_ret argument passed in.
+.IP \fIerror_string_ret\fP 1i
+Returns a null-terminated error message, if any.
+The error_string_ret argument points to user supplied memory.
+No more than error_length bytes
+are used.
+.LP
+.eM
+.PN IceOpenConnection
+returns an opaque ICE connection object if it succeeds;
+otherwise, it returns NULL.
+.LP
+The network_ids_list argument contains a list of network IDs separated by commas.
+An attempt will be made to use the first network ID. If that fails,
+an attempt will be made using the second network ID, and so on.
+Each network ID has the following format:
+.TS
+lw(0.25i) lw(2.5i) lw(1i).
+ tcp/<hostname>:<portnumber> or
+ decnet/<hostname>::<objname> or
+ local/<hostname>:<path>
+.TE
+.LP
+Most protocol libraries will have some sort of open function that should
+internally make a call into
+.PN IceOpenConnection .
+When
+.PN IceOpenConnection
+is called, it may be possible to use a previously opened ICE connection (if
+the target client is the same). However, there are cases in which shared
+ICE connections are not desired.
+.LP
+The context argument is used to determine if an ICE connection can
+be shared.
+If context is NULL,
+then the caller is always willing to share the connection.
+If context is not NULL,
+then the caller is not willing to use a previously opened ICE connection
+that has a different non-NULL context associated with it.
+.LP
+In addition, if major_opcode_check contains a nonzero major opcode value,
+a previously created ICE connection will be used only if the major opcode
+is not active on the connection. This can be used to force multiple ICE
+connections between two clients for the same protocol.
+.LP
+Any authentication requirements are handled internally by the ICE library.
+The method by which the authentication data is obtained
+is implementation-dependent.\(dg
+.FS \(dg
+The X Consortium's ICElib implementation uses an \&.ICEauthority file (see
+Appendix A).
+.FE
+.LP
+After
+.PN IceOpenConnection
+is called, the client is ready to send a
+.PN ProtocolSetup
+(provided that
+.PN IceRegisterForProtocolSetup
+was called) or receive a
+.PN ProtocolSetup
+(provided that
+.PN IceRegisterForProtocolReply
+was called).
+.NH 2
+Listening for ICE Connections
+.XS
+\*(SN Listening for ICE Connections
+.XE
+.LP
+Clients wishing to accept ICE connections must first call
+.PN IceListenForConnections
+or
+.PN IceListenForWellKnownConnections
+so that they can listen for connections. A list of opaque "listen" objects are
+returned, one for each type of transport method that is available
+(for example, Unix Domain, TCP, DECnet, and so on).
+.LP
+Normally clients will let ICElib allocate an available name in each
+transport and return listen objects. Such a client will then use
+.PN IceComposeNetworkIdList
+to extract the chosen names and make them
+available to other clients for opening the connection. In certain
+cases it may be necessary for a client to listen for connections
+on pre-arranged transport object names. Such a client may use
+.PN IceListenForWellKnownConnections
+to specify the names for the listen objects.
+.sM
+.FD 0
+Status IceListenForConnections\^(\^\fIcount_ret\fP, \fIlisten_objs_ret\fP\^, \fIerror_length\fP\^, \fIerror_string_ret\fP\^)
+.br
+ int *\fIcount_ret\fP\^;
+.br
+ IceListenObj **\fIlisten_objs_ret\fP\^;
+.br
+ int \fIerror_length\fP\^;
+.br
+ char *\fIerror_string_ret\fP\^;
+.FN
+.IP \fIcount_ret\fP 1i
+Returns the number of listen objects created.
+.IP \fIlisten_objs_ret\fP 1i
+Returns a list of pointers to opaque listen objects.
+.IP \fIerror_length\fP 1i
+The length of the error_string_ret argument passed in.
+.IP \fIerror_string_ret\fP 1i
+Returns a null-terminated error message, if any.
+The error_string_ret points to user supplied memory.
+No more than error_length bytes are used.
+.LP
+.eM
+The return value of
+.PN IceListenForConnections
+is zero for failure and a positive value for success.
+.sp
+.sM
+.FD 0
+Status IceListenForWellKnownConnections\^(\^\fIport_id\fP, \fIcount_ret\fP, \fIlisten_objs_ret\fP\^, \fIerror_length\fP\^, \fIerror_string_ret\fP\^)
+.br
+ char *\fIport_id\fP\^;
+.br
+ int *\fIcount_ret\fP\^;
+.br
+ IceListenObj **\fIlisten_objs_ret\fP\^;
+.br
+ int \fIerror_length\fP\^;
+.br
+ char *\fIerror_string_ret\fP\^;
+.FN
+.IP \fIport_id\fP 1i
+Specifies the port identification for the address(es)
+to be opened. The value must not contain the slash
+(\^``/''\^) or comma (\^``,''\^) character;
+these are reserved for future use.
+.IP \fIcount_ret\fP 1i
+Returns the number of listen objects created.
+.IP \fIlisten_objs_ret\fP 1i
+Returns a list of pointers to opaque listen objects.
+.IP \fIerror_length\fP 1i
+The length of the error_string_ret argument passed in.
+.IP \fIerror_string_ret\fP 1i
+Returns a null-terminated error message, if any.
+The error_string_ret points to user supplied memory.
+No more than error_length bytes are used.
+.LP
+.eM
+.PN IceListenForWellKnownConnections
+constructs a list of network IDs
+by prepending each known transport to port_id and then attempts to
+create listen objects for the result. Port_id is the portnumber,
+objname, or path portion of the ICE network ID. If a listen object for
+a particular network ID cannot be created the network ID is ignored.
+If no listen objects are created
+.PN IceListenForWellKnownConnections
+returns failure.
+.LP
+The return value of
+.PN IceListenForWellKnownConnections
+is zero for failure and a positive value for success.
+.sp
+.LP
+To close and free the listen objects, use
+.PN IceFreeListenObjs .
+.LP
+.sM
+.FD 0
+void IceFreeListenObjs\^(\^\fIcount\fP, \fIlisten_objs\fP\^)
+.br
+ int \fIcount\fP\^;
+.br
+ IceListenObj *\fIlisten_objs\fP\^;
+.FN
+.IP \fIcount\fP 1i
+The number of listen objects.
+.IP \fIlisten_objs\fP 1i
+The listen objects.
+.LP
+.eM
+.LP
+To detect a new connection on a listen object, use
+.PN select
+on the descriptor associated with the listen object.
+.sp
+.LP
+To obtain the descriptor, use
+.PN IceGetListenConnectionNumber .
+.LP
+.sM
+.FD 0
+int IceGetListenConnectionNumber\^(\^\fIlisten_obj\fP\^)
+.br
+ IceListenObj \fIlisten_obj\fP\^;
+.FN
+.IP \fIlisten_obj\fP 1i
+The listen object.
+.LP
+.eM
+.LP
+To obtain the network ID string associated with a listen object, use
+.PN IceGetListenConnectionString .
+.sM
+.FD 0
+char *IceGetListenConnectionString\^(\^\fIlisten_obj\fP\^)
+.br
+ IceListenObj \fIlisten_obj\fP\^;
+.FN
+.IP \fIlisten_obj\fP 1i
+The listen object.
+.LP
+.eM
+.LP
+A network ID has the following format:
+.TS
+lw(0.25i) lw(2.5i) lw(1i).
+ tcp/<hostname>:<portnumber> or
+ decnet/<hostname>::<objname> or
+ local/<hostname>:<path>
+.TE
+.LP
+To compose a string containing a list of network IDs separated by commas
+(the format recognized by
+.PN IceOpenConnection ),
+use
+.PN IceComposeNetworkIdList .
+.LP
+.sM
+.FD 0
+char *IceComposeNetworkIdList\^(\^\fIcount\fP, \fIlisten_objs\fP\^)
+.br
+ int \fIcount\fP\^;
+.br
+ IceListenObj *\fIlisten_objs\fP\^;
+.FN
+.IP \fIcount\fP 1i
+The number of listen objects.
+.IP \fIlisten_objs\fP 1i
+The listen objects.
+.LP
+.eM
+.NH 2
+Host Based Authentication for ICE Connections
+.XS
+\*(SN Host Based Authentication for ICE Connections
+.XE
+.LP
+If authentication fails when a client attempts to open an
+ICE connection and the initiating client has not required authentication,
+a host based authentication procedure may be invoked to provide
+a last chance for the client to connect. Each listen object has such a
+callback associated with it, and this callback is set using the
+.PN IceSetHostBasedAuthProc
+function.
+.sM
+.FD 0
+void IceSetHostBasedAuthProc\^(\^\fIlisten_obj\fP, \fIhost_based_auth_proc\fP\^)
+.br
+ IceListenObj \fIlisten_obj\fP\^;
+.br
+ IceHostBasedAuthProc \fIhost_based_auth_proc\fP\^;
+.FN
+.IP \fIlisten_obj\fP 1i
+The listen object.
+.IP \fIhost_based_auth_proc\fP 1i
+The host based authentication procedure.
+.LP
+.eM
+By default, each listen object has no host based authentication procedure
+associated with it.
+Passing NULL for host_based_auth_proc turns off host based authentication
+if it was previously set.
+.LP
+.sM
+.FD 0
+typedef Bool (*IceHostBasedAuthProc) ();
+
+Bool HostBasedAuthProc\^(\^\fIhost_name\fP\^)
+.br
+ char *\fIhost_name\fP\^;
+.FN
+.IP \fIhost_name\fP 1i
+The host name of the client that tried to open an ICE connection.
+.LP
+.eM
+The host_name argument is a string in the form \fIprotocol\fP\^/\^\fIhostname\fP,
+where \fIprotocol\fP\^ is one of {tcp, decnet, local}.
+.LP
+If
+.PN IceHostBasedAuthProc
+returns
+.PN True ,
+access will be granted, even though the original
+authentication failed. Note that authentication can effectively be
+disabled by registering an
+.PN IceHostBasedAuthProc ,
+which always returns
+.PN True .
+.LP
+Host based authentication is also allowed at
+.PN ProtocolSetup
+time.
+The callback is specified in the
+.PN IceRegisterForProtocolReply
+function (see section 6, ``Protocol Registration'').
+.NH 2
+Accepting ICE Connections
+.XS
+\*(SN Accepting ICE Connections
+.XE
+.LP
+After a connection attempt is detected on a listen object returned by
+.PN IceListenForConnections ,
+you should call
+.PN IceAcceptConnection .
+This returns a new opaque ICE connection object.
+.sM
+.FD 0
+IceConn IceAcceptConnection\^(\^\fIlisten_obj\fP, \fI\^status_ret\fP\^)
+.br
+ IceListenObj \fIlisten_obj\fP\^;
+.br
+ IceAcceptStatus *\fIstatus_ret\fP\^;
+.FN
+.IP \fIlisten_obj\fP 1i
+The listen object on which a new connection was detected.
+.IP \fIstatus_ret\fP 1i
+Return status information.
+.LP
+.eM
+The status_ret argument is set to one of the following values:
+.IP \(bu 5
+.PN IceAcceptSuccess
+\- the accept operation succeeded,
+and the function returns a new connection object.
+.IP \(bu 5
+.PN IceAcceptFailure
+\- the accept operation failed, and the function returns NULL.
+.IP \(bu 5
+.PN IceAcceptBadMalloc
+\- a memory allocation failed, and the function returns NULL.
+.LP
+In general, to detect new connections, you should call
+.PN select
+on the file descriptors associated with the listen objects.
+When a new connection is detected, the
+.PN IceAcceptConnection
+function should be called.
+.PN IceAcceptConnection
+may return a new ICE connection that is in a pending state. This is because
+before the connection can become valid, authentication may be necessary.
+Because the ICE library cannot block and wait for the connection to
+become valid (infinite blocking can occur if the connecting client
+does not act properly), the application must wait for the connection status
+to become valid.
+.LP
+The following pseudo-code demonstrates how connections are accepted:
+.if t .bp
+.LP
+.Ds 0
+.TA .5i 1i 1.5i 2i
+.ta .5i 1i 1.5i 2i
+new_ice_conn = IceAcceptConnection (listen_obj, &accept_status);
+if (accept_status != IceAcceptSuccess)
+{
+ close the file descriptor and return
+}
+
+status = IceConnectionStatus (new_ice_conn);
+time_start = time_now;
+
+while (status == IceConnectPending)
+{
+ select() on {new_ice_conn, all open connections}
+
+ for (each ice_conn in the list of open connections)
+ if (data ready on ice_conn)
+ {
+ status = IceProcessMessages (ice_conn, NULL, NULL);
+ if (status == IceProcessMessagesIOError)
+ IceCloseConnection (ice_conn);
+ }
+
+ if (data ready on new_ice_conn)
+ {
+ /*
+ * IceProcessMessages is called until the connection
+ * is non-pending. Doing so handles the connection
+ * setup request and any authentication requirements.
+ */
+
+ IceProcessMessages (new_ice_conn, NULL, NULL);
+ status = IceConnectionStatus (new_ice_conn);
+ }
+ else
+ {
+ if (time_now - time_start > MAX_WAIT_TIME)
+ status = IceConnectRejected;
+ }
+}
+
+if (status == IceConnectAccepted)
+{
+ Add new_ice_conn to the list of open connections
+}
+else
+{
+ IceCloseConnection (new_ice_conn);
+}
+.De
+.LP
+After
+.PN IceAcceptConnection
+is called and the connection has been
+validated, the client is ready to receive a
+.PN ProtocolSetup
+(provided
+that
+.PN IceRegisterForProtocolReply
+was called) or send a
+.PN ProtocolSetup
+(provided that
+.PN IceRegisterForProtocolSetup
+was called).
+.NH 2
+Closing ICE Connections
+.XS
+\*(SN Closing ICE Connections
+.XE
+.LP
+To close an ICE connection created with
+.PN IceOpenConnection
+or
+.PN IceAcceptConnection ,
+use
+.PN IceCloseConnection .
+.sM
+.FD 0
+IceCloseStatus IceCloseConnection\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection to close.
+.LP
+.eM
+To actually close an ICE connection, the following conditions
+must be met:
+.IP \(bu 5
+The \fIopen reference count\fP must have reached zero on this ICE connection.
+When
+.PN IceOpenConnection
+is called, it tries to use a previously opened
+ICE connection. If it is able to use an existing connection, it increments
+the open reference count on the connection by one.
+So, to close an ICE connection, each call to
+.PN IceOpenConnection
+must be matched with a call to
+.PN IceCloseConnection .
+The connection can be closed only
+on the last call to
+.PN IceCloseConnection .
+.IP \(bu 5
+The \fIactive protocol count\fP\^ must have reached zero. Each time a
+.PN ProtocolSetup
+succeeds on the connection, the active protocol count
+is incremented by one. When the client no longer expects to use the
+protocol on the connection, the
+.PN IceProtocolShutdown
+function should be called, which decrements the active protocol count
+by one (see section 8, ``Protocol Setup and Shutdown'').
+.IP \(bu 5
+If shutdown negotiation is enabled on the connection, the client on the other
+side of the ICE connection must agree to have the connection closed.
+.LP
+.PN IceCloseConnection
+returns one of the following values:
+.IP \(bu 5
+.PN IceClosedNow
+\- the ICE connection was closed at this time. The watch procedures were
+invoked and the connection was freed.
+.IP \(bu 5
+.PN IceClosedASAP
+\- an IO error had occurred on the connection, but
+.PN IceCloseConnection
+is being called within a nested
+.PN IceProcessMessages .
+The watch procedures have been invoked at this time, but the connection
+will be freed as soon as possible (when the nesting level reaches zero and
+.PN IceProcessMessages
+returns a status of
+.PN IceProcessMessagesConnectionClosed ).
+.IP \(bu 5
+.PN IceConnectionInUse
+\- the connection was not closed at this time, because it is being used by
+other active protocols.
+.IP \(bu 5
+.PN IceStartedShutdownNegotiation
+\- the connection was not closed at this time and shutdown negotiation started
+with the client on the other side of the ICE connection. When the connection
+is actually closed,
+.PN IceProcessMessages
+will return a status of
+.PN IceProcessMessagesConnectionClosed .
+.sp
+.LP
+When it is known that the client on the other side of the ICE connection
+has terminated the connection without initiating shutdown negotiation, the
+.PN IceSetShutdownNegotiation
+function should be called to turn off shutdown negotiation. This will prevent
+.PN IceCloseConnection
+from writing to a broken connection.
+.sM
+.FD 0
+void IceSetShutdownNegotiation\^(\^\fIice_conn\fP, \fInegotiate\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ Bool \fInegotiate\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fInegotiate\fP 1i
+If
+.PN False ,
+shutdown negotiating will be turned off.
+.LP
+.eM
+.LP
+To check the shutdown negotiation status of an ICE connection, use
+.PN IceCheckShutdownNegotiation .
+.sM
+.FD 0
+Bool IceCheckShutdownNegotiation\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.LP
+.eM
+.PN IceCheckShutdownNegotiation
+returns
+.PN True
+if shutdown negotiation will take place on the connection;
+otherwise, it returns
+.PN False .
+Negotiation is on by default for a connection. It
+can only be changed with the
+.PN IceSetShutdownNegotiation
+function.
+.NH 2
+Connection Watch Procedures
+.XS
+\*(SN Connection Watch Procedures
+.XE
+.LP
+To add a watch procedure that will be called
+each time ICElib opens a new connection via
+.PN IceOpenConnection
+or
+.PN IceAcceptConnection
+or closes a connection via
+.PN IceCloseConnection ,
+use
+.PN IceAddConnectionWatch .
+.sM
+.FD 0
+Status IceAddConnectionWatch\^(\^\fIwatch_proc\fP, \fIclient_data\fP\^)
+.br
+ IceWatchProc \fIwatch_proc\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.FN
+.IP \fIwatch_proc\fP 1i
+The watch procedure to invoke when ICElib opens or
+closes a connection.
+.IP \fIclient_data\fP 1i
+This pointer will be passed to the watch procedure.
+.LP
+.eM
+The return value of
+.PN IceAddConnectionWatch
+is zero for failure, and a positive value for success.
+.LP
+Note that several calls to
+.PN IceOpenConnection
+might share the same ICE connection. In such a case, the watch procedure
+is only invoked when the connection is first created (after authentication
+succeeds). Similarly, because
+connections might be shared, the watch procedure is called only if
+.PN IceCloseConnection
+actually closes the connection (right before the IceConn is freed).
+.LP
+The watch procedures are very useful for applications that
+need to add a file descriptor to a select mask when a new connection
+is created and remove the file descriptor when the connection is destroyed.
+Because connections are shared, knowing when to add and remove the file
+descriptor from the select mask would be difficult without the watch
+procedures.
+.LP
+Multiple watch procedures may be registered with the ICE library.
+No assumptions should be made about their order of invocation.
+.LP
+If one or more ICE connections were already created by the ICE library at the
+time the watch procedure is registered, the watch procedure will instantly
+be invoked for each of these ICE connections (with the opening argument
+set to
+.PN True ).
+.LP
+The watch procedure is of type
+.PN IceWatchProc .
+.sM
+.FD 0
+typedef void (*IceWatchProc)();
+
+void WatchProc\^(\^\fIice_conn\fP, \fIclient_data\fP\^, \fIopening\fP\^, \fIwatch_data\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.br
+ Bool \fIopening\fP\^;
+.br
+ IcePointer *\fIwatch_data\fP\^;
+.FN
+.IP \fIice_conn\fP\^ 1i
+The opened or closed ICE connection. Call
+.PN IceConnectionNumber
+to get the file descriptor associated with this connection.
+.IP \fIclient_data\fP\^ 1i
+Client data specified in the call to
+.PN IceAddConnectionWatch .
+.IP \fIopening\fP\^ 1i
+If
+.PN True ,
+the connection is being opened. If
+.PN False ,
+the connection is being closed.
+.IP \fIwatch_data\fP\^ 1i
+Can be used to save a pointer to client data.
+.LP
+.eM
+If opening is
+.PN True ,
+the client should set the *watch_data
+pointer to any data it may need to save until the connection is closed
+and the watch procedure is
+invoked again with opening set to
+.PN False .
+.sp
+.LP
+To remove a watch procedure, use
+.PN IceRemoveConnectionWatch .
+.sM
+.FD 0
+void IceRemoveConnectionWatch\^(\^\fIwatch_proc\fP, \fIclient_data\fP\^)
+.br
+ IceWatchProc \fIwatch_proc\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.LP
+.FN
+.IP \fIwatch_proc\fP 1i
+The watch procedure that was passed to
+.PN IceAddConnectionWatch .
+.IP \fIclient_data\fP 1i
+The client_data pointer that was passed to
+.PN IceAddConnectionWatch .
+.LP
+.eM
+.NH 1
+Protocol Setup and Shutdown
+.XS
+\*(SN Protocol Setup and Shutdown
+.XE
+.LP
+To activate a protocol on a given ICE connection, use
+.PN IceProtocolSetup .
+.LP
+.sM
+.FD 0
+IceProtocolSetupStatus IceProtocolSetup\^(\^\fIice_conn\fP, \fImy_opcode\fP\^, \fIclient_data\fP\^, \fImust_authenticate\fP\^,
+.br
+ \fImajor_version_ret\fP\^, \fIminor_version_ret\fP\^, \fIvendor_ret\fP\^, \fIrelease_ret\fP\^, \fIerror_length\fP\^, \fIerror_string_ret\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fImy_opcode\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.br
+ Bool \fImust_authenticate\fP\^;
+.br
+ int *\fImajor_version_ret\fP\^;
+.br
+ int *\fIminor_version_ret\fP\^;
+.br
+ char **\fIvendor_ret\fP\^;
+.br
+ char **\fIrelease_ret\fP\^;
+.br
+ int \fIerror_length\fP\^;
+.br
+ char *\fIerror_string_ret\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fImy_opcode\fP 1i
+The major opcode of the protocol to be set up, as returned by
+.PN IceRegisterForProtocolSetup .
+.IP \fIclient_data\fP 1i
+The client data stored in this pointer will be passed to the
+.PN IcePoProcessMsgProc
+callback.
+.IP \fImust_authenticate\fP 1i
+If
+.PN True ,
+the other client may not bypass authentication.
+.IP \fImajor_version_ret\fP 1i
+The major version of the protocol to be used is returned.
+.IP \fIminor_version_ret\fP 1i
+The minor version of the protocol to be used is returned.
+.IP \fIvendor_ret\fP 1i
+The vendor string specified by the protocol acceptor.
+.IP \fIrelease_ret\fP 1i
+The release string specified by the protocol acceptor.
+.IP \fIerror_length\fP 1i
+Specifies the length of the error_string_ret argument passed in.
+.IP \fIerror_string_ret\fP 1i
+Returns a null-terminated error message, if any.
+The error_string_ret argument points to user supplied memory.
+No more than error_length bytes are used.
+.LP
+.eM
+The vendor_ret and release_ret strings should be freed with
+.PN free
+when no longer needed.
+.LP
+.PN IceProtocolSetup
+returns one of the following values:
+.IP \(bu 5
+.PN IceProtocolSetupSuccess
+\- the major_version_ret, minor_version_ret, vendor_ret, release_ret are set.
+.IP \(bu 5
+.PN IceProtocolSetupFailure
+or
+.PN IceProtocolSetupIOError
+\- check error_string_ret for failure reason.
+The major_version_ret, minor_version_ret, vendor_ret, release_ret are not set.
+.IP \(bu 5
+.PN IceProtocolAlreadyActive
+\- this protocol is already active on this connection.
+The major_version_ret, minor_version_ret, vendor_ret, release_ret are not set.
+.sp
+.LP
+To notify the ICE library when a given protocol
+will no longer be used on an ICE connection, use
+.PN IceProtocolShutdown .
+.LP
+.sM
+.FD 0
+Status IceProtocolShutdown\^(\^\fIice_conn\fP, \fImajor_opcode\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fImajor_opcode\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fImajor_opcode\fP 1i
+The major opcode of the protocol to shut down.
+.LP
+.eM
+The return value of
+.PN IceProtocolShutdown
+is zero for failure and a positive value for success.
+.LP
+Failure will occur if the major opcode was never registered OR the protocol
+of the major opcode was never activated on the connection. By activated,
+we mean that a
+.PN ProtocolSetup
+succeeded on the connection.
+Note that ICE does not define how each sub-protocol triggers a
+protocol shutdown.
+.NH 1
+Processing Messages
+.XS
+\*(SN Processing Messages
+.XE
+.LP
+To process incoming messages on an ICE connection, use
+.PN IceProcessMessages .
+.sM
+.FD 0
+IceProcessMessagesStatus IceProcessMessages\^(\^\fIice_conn\fP, \fIreply_wait\fP\^, \fIreply_ready_ret\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IceReplyWaitInfo *\fIreply_wait\fP\^;
+.br
+ Bool *\fIreply_ready_ret\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIreply_wait\fP 1i
+Indicates if a reply is being waited for.
+.IP \fIreply_ready_ret\fP 1i
+If set to
+.PN True
+on return, a reply is ready.
+.LP
+.eM
+.PN IceProcessMessages
+is used in two ways:
+.IP \(bu 5
+In the first, a client may
+generate a message and block by calling
+.PN IceProcessMessages
+repeatedly until it gets its reply.
+.IP \(bu 5
+In the second, a
+client calls
+.PN IceProcessMessages
+with reply_wait set to NULL in response to
+.PN select
+showing that there is data to read on the ICE connection.
+The ICE library may process zero or more complete messages.
+Note that messages that are not blocked for are always processed by
+invoking callbacks.
+.LP
+.PN IceReplyWaitInfo
+contains the major/minor opcodes and sequence number
+of the message for which a reply is being awaited. It also contains
+a pointer to the reply message to be filled in (the protocol library
+should cast this
+.PN IcePointer
+to the appropriate reply type). In most
+cases, the reply will have some fixed-size part, and the client waiting
+for the reply will have provided a pointer to a structure to hold
+this fixed-size data. If there is variable-length data, it would be
+expected that the
+.PN IcePoProcessMsgProc
+callback will have to allocate additional
+memory and store pointer(s) to that memory in the fixed-size
+structure. If the entire data is variable length (for example, a single
+variable-length string), then the client waiting for the reply would probably
+just pass a pointer to fixed-size space to hold a pointer, and the
+.PN IcePoProcessMsgProc
+callback would allocate the storage and store the pointer.
+It is the responsibility of the client receiving the reply to
+free up any memory allocated on its behalf.
+.LP
+.sM
+.Ds 0
+.TA .5i
+.ta .5i
+typedef struct {
+ unsigned long sequence_of_request;
+ int major_opcode_of_request;
+ int minor_opcode_of_request;
+ IcePointer reply;
+} IceReplyWaitInfo;
+.De
+.LP
+.eM
+If reply_wait is not NULL and
+.PN IceProcessMessages
+has a reply or error to return in response to this reply_wait
+(that is, no callback was generated), then the reply_ready_ret argument
+will be set to
+.PN True .
+.LP
+If reply_wait is NULL,
+then the caller may also pass NULL
+for reply_ready_ret and be guaranteed that no value will be stored
+in this pointer.
+.LP
+.PN IceProcessMessages
+returns one of the following values:
+.IP \(bu 5
+.PN IceProcessMessagesSuccess
+\- no error occurred.
+.IP \(bu 5
+.PN IceProcessMessagesIOError
+\- an IO error occurred,
+and the caller must explicitly close the connection by calling
+.PN IceCloseConnection .
+.IP \(bu 5
+.PN IceProcessMessagesConnectionClosed
+\- the ICE connection has been closed (closing of the connection was deferred
+because of shutdown negotiation, or because the
+.PN IceProcessMessages
+nesting level was not zero). Do not attempt
+to access the ICE connection at this point, since it has been freed.
+.NH 1
+Ping
+.XS
+\*(SN Ping
+.XE
+.LP
+To send a ``Ping'' message to the client on the other side of the
+ICE connection, use
+.PN IcePing .
+.sM
+.FD 0
+Status IcePing\^(\^\fIice_conn\fP, \fIping_reply_proc\fP\^, \fIclient_data\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IcePingReplyProc \fIping_reply_proc\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIping_reply_proc\fP 1i
+The callback to invoke when the Ping reply arrives.
+.IP \fIclient_data\fP 1i
+This pointer will be passed to the
+.PN IcePingReplyProc
+callback.
+.LP
+.eM
+.PN IcePing
+returns zero for failure and a positive value for success.
+.LP
+When
+.PN IceProcessMessages
+processes the Ping reply, it will invoke the
+.PN IcePingReplyProc
+callback.
+.sM
+.FD 0
+typedef void (*IcePingReplyProc)();
+
+void PingReplyProc\^(\^\fIice_conn\fP, \fIclient_data\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ IcePointer \fIclient_data\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.IP \fIclient_data\fP 1i
+The client data specified in the call to
+.PN IcePing .
+.LP
+.eM
+.NH 1
+Using ICElib Informational Functions
+.XS
+\*(SN Using ICElib Informational Functions
+.XE
+.LP
+.sM
+.FD 0
+IceConnectStatus IceConnectionStatus\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceConnectionStatus
+returns the status of an ICE connection. The possible return values are:
+.IP \(bu 5
+.PN IceConnectPending
+\- the connection is not valid yet (that is, authentication is taking place).
+This is only relevant to connections created by
+.PN IceAcceptConnection .
+.IP \(bu 5
+.PN IceConnectAccepted
+\- the connection has been accepted.
+This is only relevant to connections created by
+.PN IceAcceptConnection .
+.IP \(bu 5
+.PN IceConnectRejected
+\- the connection had been rejected (that is, authentication failed).
+This is only relevant to connections created by
+.PN IceAcceptConnection .
+.IP \(bu 5
+.PN IceConnectIOError
+\- an IO error has occurred on the connection.
+.LP
+.sM
+.FD 0
+char *IceVendor\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceVendor
+returns the ICE library vendor identification
+for the other side of the connection.
+The string should be freed with a call to
+.PN free
+when no longer needed.
+.LP
+.sM
+.FD 0
+char *IceRelease\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceRelease
+returns the release identification of the ICE library
+on the other side of the connection.
+The string should be freed with a call to
+.PN free
+when no longer needed.
+.LP
+.sM
+.FD 0
+int IceProtocolVersion\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceProtocolVersion
+returns the major version of the ICE protocol on this connection.
+.LP
+.sM
+.FD 0
+int IceProtocolRevision\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceProtocolRevision
+returns the minor version of the ICE protocol on this connection.
+.LP
+.sM
+.FD 0
+int IceConnectionNumber\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceConnectionNumber
+returns the file descriptor of this ICE connection.
+.LP
+.sM
+.FD 0
+char *IceConnectionString\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceConnectionString
+returns the network ID of the client that
+accepted this connection. The string should be freed with a call to
+.PN free
+when no longer needed.
+.LP
+.sM
+.FD 0
+unsigned long IceLastSentSequenceNumber\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceLastSentSequenceNumber
+returns the sequence number of the last message sent on this ICE connection.
+.LP
+.sM
+.FD 0
+unsigned long IceLastReceivedSequenceNumber\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceLastReceivedSequenceNumber
+returns the sequence number of the last message received on this
+ICE connection.
+.LP
+.sM
+.FD 0
+Bool IceSwapping\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceSwapping
+returns
+.PN True
+if byte swapping is necessary when reading messages on the ICE connection.
+.LP
+.sM
+.FD 0
+IcePointer IceGetContext\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.eM
+.PN IceGetContext
+returns the context associated with a connection created by
+.PN IceOpenConnection .
+.NH 1
+ICE Messages
+.XS
+\*(SN ICE Messages
+.XE
+.LP
+All ICE messages have a standard 8-byte header. The ICElib macros that
+read and write messages rely on the following naming convention for message
+headers:
+.LP
+.Ds 0
+.TA .5i 1i
+.ta .5i 1i
+ CARD8 major_opcode;
+ CARD8 minor_opcode;
+ CARD8 data[2];
+ CARD32 length B32;
+.De
+.LP
+The 3rd and 4th bytes of the message header can be used as needed.
+The length field is specified in units of 8 bytes.
+.NH 2
+Sending ICE Messages
+.XS
+\*(SN Sending ICE Messages
+.XE
+.LP
+The ICE library maintains an output buffer used for generating messages.
+Protocol libraries layered on top of ICE may choose to batch messages
+together and flush the output buffer at appropriate times.
+.LP
+If an IO error has occurred on an ICE connection, all write operations
+will be ignored.
+For further information, see section 13, ``Error Handling.''
+.sp
+.LP
+To get the size of the ICE output buffer, use
+.PN IceGetOutBufSize .
+.sM
+.FD 0
+int IceGetOutBufSize\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.LP
+.eM
+.LP
+To flush the ICE output buffer, use
+.PN IceFlush .
+.sM
+.FD 0
+IceFlush\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.LP
+.eM
+Note that the output buffer may be implicitly flushed if there is insufficient
+space to generate a message.
+.LP
+The following macros can be used to generate ICE messages:
+.LP
+.sM
+.FD 0
+IceGetHeader\^(\^\fIice_conn\fP, \fImajor_opcode\fP\^, \fIminor_opcode\fP\^, \fIheader_size\fP\^, \fI<C_data_type>\fP\^, \fIpmsg\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fImajor_opcode\fP\^;
+.br
+ int \fIminor_opcode\fP\^;
+.br
+ int \fIheader_size\fP\^;
+.br
+ <C_data_type> *\fIpmsg\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fImajor_opcode\fP 1i
+The major opcode of the message.
+.IP \fIminor_opcode\fP 1i
+The minor opcode of the message.
+.IP \fIheader_size\fP 1i
+The size of the message header (in bytes).
+.IP \fI<C_data_type>\fP 1i
+The actual C data type of the message header.
+.IP \fIpmsg\fP 1i
+The message header pointer. After this macro is called, the
+library can store data in the message header.
+.LP
+.eM
+.PN IceGetHeader
+is used to set up a message header on an ICE connection.
+It sets the major and minor opcodes of the message, and initializes
+the message's length to the length of the header. If additional
+variable length data follows, the message's length field should be
+updated.
+.sp
+.LP
+.sM
+.FD 0
+IceGetHeaderExtra\^(\^\fIice_conn\fP, \fImajor_opcode\fP\^, \fIminor_opcode\fP\^, \fIheader_size\fP\^, \fIextra\fP\^, \fI<C_data_type>\fP\^, \fIpmsg\fP\^, \fIpdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fImajor_opcode\fP\^;
+.br
+ int \fIminor_opcode\fP\^;
+.br
+ int \fIheader_size\fP\^;
+.br
+ int \fIextra\fP\^;
+.br
+ <C_data_type> *\fIpmsg\fP\^;
+.br
+ char *\fIpdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fImajor_opcode\fP 1i
+The major opcode of the message.
+.IP \fIminor_opcode\fP 1i
+The minor opcode of the message.
+.IP \fIheader_size\fP 1i
+The size of the message header (in bytes).
+.IP \fIextra\fP 1i
+The size of the extra data beyond the header (in 8-byte units).
+.IP \fI<C_data_type>\fP 1i
+The actual C data type of the message header.
+.IP \fIpmsg\fP 1i
+The message header pointer. After this macro is called, the
+library can store data in the message header.
+.IP \fIpdata\fP 1i
+Returns a pointer to the ICE output buffer that points
+immediately after the message header. The variable length
+data should be stored here. If there was not enough room
+in the ICE output buffer, pdata is set to NULL.
+.LP
+.eM
+.PN IceGetHeaderExtra
+is used to generate a message with a fixed (and relatively small) amount
+of variable length data. The complete message must fit in the ICE output
+buffer.
+.sp
+.LP
+.sM
+.FD 0
+IceSimpleMessage\^(\^\fIice_conn\fP, \fImajor_opcode\fP\^, \fIminor_opcode\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fImajor_opcode\fP\^;
+.br
+ int \fIminor_opcode\fP\^;
+.FN
+.br
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fImajor_opcode\fP 1i
+The major opcode of the message.
+.IP \fIminor_opcode\fP 1i
+The minor opcode of the message.
+.LP
+.eM
+.PN IceSimpleMessage
+is used to generate a message that is identical
+in size to the ICE header message, and has no additional data.
+.sp
+.LP
+.sM
+.FD 0
+IceErrorHeader\^(\^\fIice_conn\fP, \fIoffending_major_opcode\fP\^, \fIoffending_minor_opcode\fP\^, \fIoffending_sequence_num\fP\^,
+.br
+ \fIseverity\fP\^, \fIerror_class\fP\^, \fIdata_length\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIoffending_major_opcode\fP\^;
+.br
+ int \fIoffending_minor_opcode\fP\^;
+.br
+ int \fIoffending_sequence_num\fP\^;
+.br
+ int \fIseverity\fP\^;
+.br
+ int \fIerror_class\fP\^;
+.br
+ int \fIdata_length\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIoffending_major_opcode\fP 1i
+The major opcode of the protocol in which an error was detected.
+.IP \fIoffending_minor_opcode\fP 1i
+The minor opcode of the protocol in which an error was detected.
+.IP \fIoffending_sequence_num\fP 1i
+The sequence number of the message that caused the error.
+.IP \fIseverity\fP 1i
+.PN IceCanContinue ,
+.PN IceFatalToProtocol ,
+or
+.PN IceFatalToConnection .
+.IP \fIerror_class\fP 1i
+The error class.
+.IP \fIdata_length\fP 1i
+Length of data (in 8-byte units) to be written after the header.
+.LP
+.eM
+.PN IceErrorHeader
+sets up an error message header.
+.LP
+Note that the two clients connected by ICE may be using different
+major opcodes for a given protocol. The offending_major_opcode passed
+to this macro is the major opcode of the protocol for the client
+sending the error message.
+.LP
+Generic errors, which are common to all protocols, have classes
+in the range 0x8000..0xFFFF.
+See the \fIInter-Client Exchange Protocol\fP\^ standard for more details.
+.TS
+lw(1i) lw(1i).
+T{
+.PN IceBadMinor
+T} T{
+0x8000
+T}
+.sp 4p
+T{
+.PN IceBadState
+T} T{
+0x8001
+T}
+.sp 4p
+T{
+.PN IceBadLength
+T} T{
+0x8002
+T}
+.sp 4p
+T{
+.PN IceBadValue
+T} T{
+0x8003
+T}
+.TE
+.LP
+Per-protocol errors have classes in the range 0x0000-0x7fff.
+.sp
+.LP
+To write data to an ICE connection, use the
+.PN IceWriteData
+macro. If the data fits into the ICE output buffer, it is copied there.
+Otherwise, the ICE output buffer is flushed and the data is directly sent.
+.LP
+This macro is used in conjunction with
+.PN IceGetHeader
+and
+.PN IceErrorHeader .
+.sp
+.LP
+.sM
+.FD 0
+IceWriteData\^(\^\fIice_conn\fP, \fIbytes\fP\^, \fIdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIbytes\fP\^;
+.br
+ char *\fIdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIbytes\fP 1i
+The number of bytes to write.
+.IP \fIdata\fP 1i
+The data to write.
+.LP
+.eM
+.sp
+To write data as 16-bit quantities, use
+.PN IceWriteData16 .
+.sM
+.FD 0
+IceWriteData16\^(\^\fIice_conn\fP, \fIbytes\fP\^, \fIdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIbytes\fP\^;
+.br
+ short *\fIdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIbytes\fP 1i
+The number of bytes to write.
+.IP \fIdata\fP 1i
+The data to write.
+.LP
+.eM
+.sp
+To write data as 32-bit quantities, use
+.PN IceWriteData32 .
+.sM
+.FD 0
+IceWriteData32\^(\^\fIice_conn\fP, \fIbytes\fP\^, \fIdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIbytes\fP\^;
+.br
+ long *\fIdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIbytes\fP 1i
+The number of bytes to write.
+.IP \fIdata\fP 1i
+The data to write.
+.LP
+.eM
+.sp
+To bypass copying data to the ICE output buffer, use
+.PN IceSendData
+to directly send data over the network connection. If necessary, the
+ICE output buffer is first flushed.
+.sM
+.FD 0
+IceSendData\^(\^\fIice_conn\fP, \fIbytes\fP\^, \fI(char *) data\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIbytes\fP\^;
+.br
+ char *\fIdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIbytes\fP 1i
+The number of bytes to send.
+.IP \fIdata\fP 1i
+The data to send.
+.LP
+.eM
+.sp
+To force 32-bit or 64-bit alignment, use
+.PN IceWritePad .
+A maximum of 7 pad bytes can be specified.
+.sM
+.FD 0
+IceWritePad\^(\^\fIice_conn\fP, \fIbytes\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIbytes\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIbytes\fP 1i
+The number of pad bytes.
+.LP
+.eM
+.NH 2
+Reading ICE Messages
+.XS
+\*(SN Reading ICE Messages
+.XE
+.LP
+The ICE library maintains an input buffer used for reading messages.
+If the ICE library chooses to perform nonblocking reads (this is
+implementation-dependent), then for every read operation that it makes,
+zero or more complete messages may be read into the input buffer. As
+a result, for all of the macros described in this section that read
+messages, an actual read operation will occur on the connection only if
+the data is not already present in the input buffer.
+.sp
+.LP
+To get the size of the ICE input buffer, use
+.PN IceGetInBufSize .
+.sM
+.FD 0
+int IceGetInBufSize\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.LP
+.eM
+.LP
+When reading messages, care must be taken to check for IO errors. If
+any IO error occurs in reading any part of a message, the message should
+be thrown out. After using any of the macros described below for reading
+messages, the
+.PN IceValidIO
+macro can be used to check if an IO error occurred on the
+connection. After an IO error has occurred on an ICE connection, all
+read operations will be ignored.
+For further information, see section 13, ``Error Handling.''
+.sp
+.LP
+.sM
+.FD 0
+Bool IceValidIO\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.LP
+.eM
+.LP
+The following macros can be used to read ICE messages.
+.sM
+.FD 0
+IceReadSimpleMessage\^(\^\fIice_conn\fP, \fI<C_data_type>\fP\^, \fIpmsg\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ <C_data_type> *\fIpmsg\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fI<C_data_type>\fP 1i
+The actual C data type of the message header.
+.IP \fIpmsg\fP 1i
+This pointer is set to the message header.
+.LP
+.eM
+.PN IceReadSimpleMessage
+is used for messages that are identical in size to the 8-byte ICE header, but
+use the spare 2 bytes in the header to encode additional data. Note that the
+ICE library always reads in these first 8 bytes, so it can obtain the major
+opcode of the message.
+.PN IceReadSimpleMessage
+simply returns a pointer to these 8 bytes; it does not actually read any data
+into the input buffer.
+.LP
+For a message with variable length data, there are two ways of reading
+the message. One method involves reading the complete message in one
+pass using
+.PN IceReadCompleteMessage .
+The second method involves reading the message header (note that this may
+be larger than the 8-byte ICE header), then reading
+the variable length data in chunks (see
+.PN IceReadMessageHeader
+and
+.PN IceReadData ).
+.sp
+.LP
+.sM
+.FD 0
+IceReadCompleteMessage\^(\^\fIice_conn\fP, \fIheader_size\fP\^, \fI<C_data_type>\fP\^, \fIpmsg\fP\^, \fIpdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIheader_size\fP\^;
+.br
+ <C_data_type> *\fIpmsg\fP\^;
+.br
+ char *\fIpdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIheader_size\fP 1i
+The size of the message header (in bytes).
+.IP \fI<C_data_type>\fP 1i
+The actual C data type of the message header.
+.IP \fIpmsg\fP 1i
+This pointer is set to the message header.
+.IP \fIpdata\fP 1i
+This pointer is set to the variable length data of the message.
+.LP
+.eM
+If the ICE input buffer has sufficient space,
+.PN IceReadCompleteMessage
+will read the complete message into the
+ICE input buffer. Otherwise, a buffer will be allocated to hold the
+variable length data. After the call, the pdata argument should
+be checked against NULL to make sure that there was sufficient memory
+to allocate the buffer.
+.sp
+.LP
+After calling
+.PN IceReadCompleteMessage
+and processing the message,
+.PN IceDisposeCompleteMessage
+should be called.
+.LP
+.sM
+.FD 0
+IceDisposeCompleteMessage\^(\^\fIice_conn\fP, \fIpdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ char *\fIpdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIpdata\fP 1i
+The pointer to the variable length data returned in
+.PN IceReadCompleteMessage .
+.LP
+.eM
+If a buffer had to be allocated to hold the variable length data (because
+it did not fit in the ICE input buffer), it is freed here by ICElib.
+.sp
+.LP
+.sM
+.FD 0
+IceReadMessageHeader\^(\^\fIice_conn\fP, \fIheader_size\fP\^, \fI<C_data_type>\fP\^, \fIpmsg\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIheader_size\fP\^;
+.br
+ <C_data_type> *\fIpmsg\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIheader_size\fP 1i
+The size of the message header (in bytes).
+.IP \fI<C_data_type>\fP 1i
+The actual C data type of the message header.
+.IP \fIpmsg\fP 1i
+This pointer is set to the message header.
+.LP
+.eM
+.PN IceReadMessageHeader
+reads just the message header. The rest
+of the data should be read with the
+.PN IceReadData
+family of macros. This method of reading a message should be used when the
+variable length data must be read in chunks.
+.sp
+.LP
+To read data directly into a user supplied buffer, use
+.PN IceReadData .
+.sM
+.FD 0
+IceReadData\^(\^\fIice_conn\fP, \fIbytes\fP\^, \fIpdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIbytes\fP\^;
+.br
+ char *\fIpdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIbytes\fP 1i
+The number of bytes to read.
+.IP \fIpdata\fP 1i
+The data is read into this user supplied buffer.
+.LP
+.eM
+.sp
+To read data as 16-bit quantities, use
+.PN IceReadData16 .
+.sM
+.FD 0
+IceReadData16\^(\^\fIice_conn\fP, \fIswap\fP\^, \fIbytes\fP\^, \fIpdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ Bool \fIswap\fP\^;
+.br
+ int \fIbytes\fP\^;
+.br
+ short *\fIpdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIswap\fP 1i
+If
+.PN True,
+the values will be byte swapped.
+.IP \fIbytes\fP 1i
+The number of bytes to read.
+.IP \fIpdata\fP 1i
+The data is read into this user supplied buffer.
+.LP
+.eM
+.sp
+To read data as 32-bit quantities, use
+.PN IceReadData32 .
+.sM
+.FD 0
+IceReadData32\^(\^\fIice_conn\fP, \fIswap\fP\^, \fIbytes\fP\^, \fIpdata\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ Bool \fIswap\fP\^;
+.br
+ int \fIbytes\fP\^;
+.br
+ long *\fIpdata\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIswap\fP 1i
+If
+.PN True,
+the values will be byte swapped.
+.IP \fIbytes\fP 1i
+The number of bytes to read.
+.IP \fIpdata\fP 1i
+The data is read into this user supplied buffer.
+.LP
+.eM
+.sp
+To force 32-bit or 64-bit alignment, use
+.PN IceReadPad .
+A maximum of 7 pad bytes can be specified.
+.sM
+.FD 0
+IceReadPad\^(\^\fIice_conn\fP, \fIbytes\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ int \fIbytes\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIbytes\fP 1i
+The number of pad bytes.
+.LP
+.eM
+.NH 1
+Error Handling
+.XS
+\*(SN Error Handling
+.XE
+.LP
+There are two default error handlers in ICElib:
+.IP \(bu 5
+One to handle typically fatal conditions (for example,
+a connection dying because a machine crashed)
+.IP \(bu 5
+One to handle ICE-specific protocol errors
+.LP
+These error handlers can be changed to user-supplied routines if you
+prefer your own error handling and can be changed as often as you like.
+.sp
+.LP
+To set the ICE error handler, use
+.PN IceSetErrorHandler .
+.sM
+.FD 0
+IceErrorHandler IceSetErrorHandler\^(\^\fIhandler\fP\^)
+.br
+ IceErrorHandler \fIhandler\fP\^;
+.FN
+.IP \fIhandler\fP 1i
+The ICE error handler.
+You should pass NULL to restore the default handler.
+.LP
+.eM
+.PN IceSetErrorHandler
+returns the previous error handler.
+.LP
+The ICE error handler is invoked when an unexpected ICE protocol
+error (major opcode 0) is encountered. The action of the default
+handler is to print an explanatory message to
+.PN stderr
+and if the severity is fatal, call
+.PN exit
+with a nonzero value. If exiting
+is undesirable, the application should register its own error handler.
+.LP
+Note that errors in other protocol
+domains should be handled by their respective libraries (these libraries
+should have their own error handlers).
+.LP
+An ICE error handler has the type of
+.PN IceErrorHandler .
+.sM
+.FD 0
+typedef void (*IceErrorHandler)();
+
+void ErrorHandler\^(\^\fIice_conn\fP, \fIswap\fP\^, \fIoffending_minor_opcode\fP\^, \fIoffending_sequence_num\fP\^, \fIerror_class\fP\^,
+.br
+ \fIseverity\fP\^, \fIvalues\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ Bool \fIswap\fP\^;
+.br
+ int \fIoffending_minor_opcode\fP\^;
+.br
+ unsigned long \fIoffending_sequence_num\fP\^;
+.br
+ int \fIerror_class\fP\^;
+.br
+ int \fIseverity\fP\^;
+.br
+ IcePointer \fIvalues\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.IP \fIswap\fP 1i
+A flag that indicates if the values need byte swapping.
+.IP \fIoffending_minor_opcode\fP 1i
+The ICE minor opcode of the offending message.
+.IP \fIoffending_sequence_num\fP 1i
+The sequence number of the offending message.
+.IP \fIerror_class\fP 1i
+The error class of the offending message.
+.IP \fIseverity\fP 1i
+.PN IceCanContinue ,
+.PN IceFatalToProtocol ,
+or
+.PN IceFatalToConnection .
+.IP \fIvalues\fP 1i
+Any additional error values specific to the minor opcode and class.
+.LP
+.eM
+The following error classes are defined at the ICE level:
+.LP
+.Ds 0
+.PN IceBadMinor
+.PN IceBadState
+.PN IceBadLength
+.PN IceBadValue
+.PN IceBadMajor
+.PN IceNoAuth
+.PN IceNoVersion
+.PN IceSetupFailed
+.PN IceAuthRejected
+.PN IceAuthFailed
+.PN IceProtocolDuplicate
+.PN IceMajorOpcodeDuplicate
+.PN IceUnknownProtocol
+.De
+.LP
+For further information, see
+the \fIInter-Client Exchange Protocol\fP\^ standard.
+.sp
+.LP
+To handle fatal I/O errors, use
+.PN IceSetIOErrorHandler .
+.LP
+.sM
+.FD 0
+IceIOErrorHandler IceSetIOErrorHandler\^(\^\fIhandler\fP\^)
+.br
+ IceIOErrorHandler \fIhandler\fP\^;
+.FN
+.IP \fIhandler\fP 1i
+The I/O error handler.
+You should pass NULL to restore the default handler.
+.LP
+.eM
+.PN IceSetIOErrorHandler
+returns the previous IO error handler.
+.LP
+An ICE I/O error handler has the type of
+.PN IceIOErrorHandler .
+.LP
+.sM
+.FD 0
+typedef void (*IceIOErrorHandler)();
+
+void IOErrorHandler\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.LP
+.eM
+There are two ways of handling IO errors in ICElib:
+.IP \(bu 5
+In the first, the IO error handler does whatever is necessary
+to respond to the IO error and then returns, but it does not call
+.PN IceCloseConnection .
+The ICE connection is given a ``bad IO'' status, and all future reads
+and writes to the connection are ignored. The next time
+.PN IceProcessMessages
+is called it will return a status of
+.PN IceProcessMessagesIOError .
+At that time, the application should call
+.PN IceCloseConnection .
+.IP \(bu 5
+In the second, the IO error handler does call
+.PN IceCloseConnection ,
+and then uses the
+.PN longjmp
+call to get back to the application's main event loop.
+The
+.PN setjmp
+and
+.PN longjmp
+calls may not work properly on all platforms,
+and special care must be taken to avoid memory leaks.
+Therefore, this second model is less desirable.
+.LP
+Before the application I/O error handler is invoked, protocol libraries
+that were interested in being notified of I/O errors will have their
+.PN IceIOErrorProc
+handlers invoked. This handler is set up in the protocol registration
+functions (see
+.PN IceRegisterForProtocolSetup
+and
+.PN IceRegisterForProtocolReply )
+and could be used to clean up
+state specific to the protocol.
+.sp
+.LP
+.sM
+typedef void (*IceIOErrorProc)();
+.LP
+.FD 0
+void IOErrorProc\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection object.
+.LP
+.eM
+Note that every
+.PN IceIOErrorProc
+callback must return. This is required
+because each active protocol must be notified of the broken connection,
+and the application IO error handler must be invoked afterwards.
+.NH 1
+Multi-Threading Support
+.XS
+\*(SN Multi-Threading Support
+.XE
+.LP
+To declare that multiple threads in an application will be using the ICE
+library, use
+.PN IceInitThreads .
+.LP
+.sM
+.FD 0
+Status IceInitThreads\^()
+.FN
+.LP
+.eM
+The
+.PN IceInitThreads
+function must be the first ICElib function a
+multi-threaded program calls. It must complete before any other ICElib
+call is made.
+.PN IceInitThreads
+returns a nonzero status if and only if it was able
+to initialize the threads package successfully.
+It is safe to call
+.PN IceInitThreads
+more than once, although the threads package will only be initialized once.
+.LP
+Protocol libraries layered on top of ICElib will have to lock critical
+sections of code that access an ICE connection (for example, when
+generating messages). Two calls, which are generally implemented as
+macros, are provided:
+.sM
+.FD 0
+IceLockConn\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+.sp
+IceUnlockConn\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection.
+.LP
+.eM
+.sp
+To keep an ICE connection locked across several ICElib calls, applications use
+.PN IceAppLockConn
+and
+.PN IceAppUnlockConn .
+.sM
+.FD 0
+void IceAppLockConn\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection to lock.
+.LP
+.eM
+The
+.PN IceAppLockConn
+function completely locks out other threads using the connection
+until
+.PN IceAppUnlockConn
+is called. Other threads attempting to use ICElib
+calls on the connection will block.
+If the program has not previously called
+.PN IceInitThreads ,
+.PN IceAppLockConn
+has no effect.
+.LP
+.sM
+.FD 0
+void IceAppUnlockConn\^(\^\fIice_conn\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+The ICE connection to unlock.
+.LP
+.eM
+The
+.PN IceAppUnlockConn
+function allows other threads to complete ICElib
+calls on the connection that were blocked by a previous call to
+.PN IceAppLockConn
+from this thread. If the program has not previously called
+.PN IceInitThreads ,
+.PN IceAppUnlockConn
+has no effect.
+.NH 1
+Miscellaneous Functions
+.XS
+\*(SN Miscellaneous Functions
+.XE
+.LP
+To allocate scratch space (for example, when generating
+messages with variable data), use
+.PN IceAllocScratch .
+Each ICE connection has one scratch space associated with it.
+The scratch space starts off as empty and grows as needed.
+The contents of the scratch space is not guaranteed to be preserved
+after any ICElib function is called.
+.LP
+.sM
+.FD 0
+char *IceAllocScratch\^(\^\fIice_conn\fP, \fIsize\fP\^)
+.br
+ IceConn \fIice_conn\fP\^;
+.br
+ unsigned long \fIsize\fP\^;
+.FN
+.IP \fIice_conn\fP 1i
+A valid ICE connection object.
+.IP \fIsize\fP 1i
+The number of bytes required.
+.LP
+.eM
+Note that the memory returned by
+.PN IceAllocScratch
+should not be freed by the caller.
+The ICE library will free the memory when the ICE connection is closed.
+.NH 1
+Acknowledgements
+.XS
+\*(SN Acknowledgements
+.XE
+.LP
+Thanks to Bob Scheifler for his thoughtful input on the design
+of the ICE library. Thanks also to Jordan Brown, Larry Cable, Donna Converse,
+Clive Feather, Stephen Gildea, Vania Joloboff, Kaleb Keithley,
+Stuart Marks, Hiro Miyamoto, Ralph Swick, Jim VanGilder, and Mike Wexler.
+.bp
+.XS
+Appendix A \- Authentication Utility Functions
+.XE
+.ce 10
+.sp 5
+\s+2\fBAppendix A\fP\s-2
+.sp
+\s+1\fBAuthentication Utility Functions\fP\s-1
+.ce 0
+.sp
+.LP
+As discussed in this document, the means by which authentication data
+is obtained by the ICE library (for
+.PN ConnectionSetup
+messages or
+.PN ProtocolSetup
+messages) is implementation-dependent.\(dg
+.FS \(dg
+The X Consortium's ICElib implementation assumes the presence of an
+ICE authority file.
+.FE
+.LP
+This appendix describes some utility functions that manipulate an
+ICE authority file. The authority file can be used to pass authentication
+data between clients.
+.LP
+The basic operations on the \&.ICEauthority file are:
+.IP \(bu 5
+Get file name
+.IP \(bu 5
+Lock
+.IP \(bu 5
+Unlock
+.IP \(bu 5
+Read entry
+.IP \(bu 5
+Write entry
+.IP \(bu 5
+Search for entry
+.LP
+These are fairly low-level operations, and it is expected that a program,
+like "iceauth", would
+exist to add, remove, and display entries in the file.
+.LP
+In order to use these utility functions, the
+.Pn < X11/ICE/ICEutil.h >
+header file must be included.
+.LP
+An entry in the \&.ICEauthority file is defined by the following data structure:
+.LP
+.sM
+.Ds 0
+.TA .5i
+.ta .5i
+typedef struct {
+ char *protocol_name;
+ unsigned short protocol_data_length;
+ char *protocol_data;
+ char *network_id;
+ char *auth_name;
+ unsigned short auth_data_length;
+ char *auth_data;
+} IceAuthFileEntry;
+.De
+.LP
+.eM
+The protocol_name member is either ``ICE'' for connection setup authentication
+or the subprotocol name, such as ``XSMP''. For each entry, protocol specific
+data can be specified in the protocol_data member. This can be used
+to search for old entries that need to be removed from the file.
+.LP
+The network_id member is the network ID of the client accepting authentication
+(for example, the network ID of a session manager).
+A network ID has the following form:
+.TS
+lw(0.25i) lw(2.5i) lw(1i).
+ tcp/<hostname>:<portnumber> or
+ decnet/<hostname>::<objname> or
+ local/<hostname>:<path>
+.TE
+.LP
+The auth_name member is the name of the authentication method.
+The auth_data member is the actual authentication data,
+and the auth_data_length member is the number of bytes in the data.
+.sp
+.LP
+To obtain the default authorization file name, use
+.PN IceAuthFileName .
+.sM
+.FD 0
+char *IceAuthFileName\^()
+.FN
+.LP
+.eM
+If the ICEAUTHORITY environment variable if set, this value is returned.
+Otherwise, the default authorization file name is $HOME/\&.ICEauthority.
+This name is statically allocated and should not be freed.
+.LP
+To synchronously update the authorization file, the file must
+be locked with a call to
+.PN IceLockAuthFile .
+This function takes advantage of the fact that the
+.PN link
+system call will fail if the name of the new link already exists.
+.sM
+.FD 0
+int IceLockAuthFile\^(\^\fIfile_name\fP, \fIretries\fP\^, \fItimeout\fP\^, \fIdead\fP\^)
+.br
+ char *\fIfile_name\fP\^;
+.br
+ int \fIretries\fP\^;
+.br
+ int \fItimeout\fP\^;
+.br
+ long \fIdead\fP\^;
+.FN
+.IP \fIfile_name\fP 1i
+The authorization file to lock.
+.IP \fIretries\fP 1i
+The number of retries.
+.IP \fItimeout\fP 1i
+The number of seconds before each retry.
+.IP \fIdead\fP 1i
+If a lock already exists that is the specified dead seconds old,
+it is broken.
+A value of zero is used to unconditionally break an old lock.
+.LP
+.eM
+One of three values is returned:
+.IP \(bu 5
+.PN IceAuthLockSuccess
+\- the lock succeeded.
+.IP \(bu 5
+.PN IceAuthLockError
+\- a system error occurred, and
+.PN errno
+may prove useful.
+.IP \(bu 5
+.PN IceAuthLockTimeout
+\- the specified number of retries failed.
+.LP
+.sp
+To unlock an authorization file, use
+.PN IceUnlockAuthFile .
+.sM
+.FD 0
+void IceUnlockAuthFile\^(\^\fIfile_name\fP\^)
+.br
+ char *\fIfile_name\fP\^;
+.FN
+.IP \fIfile_name\fP 1i
+The authorization file to unlock.
+.LP
+.eM
+.LP
+To read the next entry in an authorization file, use
+.PN IceReadAuthFileEntry .
+.sM
+.FD 0
+IceAuthFileEntry *IceReadAuthFileEntry\^(\^\fIauth_file\fP\^)
+.br
+ FILE *\fIauth_file\fP\^;
+.FN
+.IP \fIauth_file\fP 1i
+The authorization file.
+.LP
+.eM
+Note that it is the responsibility of the application to open the file
+for reading before calling this function. If an error is encountered,
+or there are no more entries to read, NULL is returned.
+.LP
+Entries should be free with a call to
+.PN IceFreeAuthFileEntry .
+.LP
+.sp
+To write an entry in an authorization file, use
+.PN IceWriteAuthFileEntry .
+.sM
+.FD 0
+Status IceWriteAuthFileEntry\^(\^\fIauth_file\fP, \fIentry\fP\^)
+.br
+ FILE *\fIauth_file\fP\^;
+.br
+ IceAuthFileEntry *\fIentry\fP\^;
+.FN
+.IP \fIauth_file\fP 1i
+The authorization file.
+.IP \fIentry\fP 1i
+The entry to write.
+.LP
+.eM
+Note that it is the responsibility of the application to open the file
+for writing before calling this function. The function returns a nonzero
+status if the operation was successful.
+.LP
+.sp
+To search the default authorization file for an entry that matches a given
+protocol_name/network_id/auth_name tuple, use
+.PN IceGetAuthFileEntry .
+.sM
+.FD 0
+IceAuthFileEntry *IceGetAuthFileEntry\^(\^\fIprotocol_name\fP, \fInetwork_id\fP\^, \fIauth_name\fP\^)
+.br
+ char *\fIprotocol_name\fP\^;
+.br
+ char *\fInetwork_id\fP\^;
+.br
+ char *\fIauth_name\fP\^;
+.FN
+.IP \fIprotocol_name\fP 1i
+The name of the protocol to search on.
+.IP \fInetwork_id\fP 1i
+The network ID to search on.
+.IP \fIauth_name\fP 1i
+The authentication method to search on.
+.LP
+.eM
+If
+.PN IceGetAuthFileEntry
+fails to find such an entry, NULL is returned.
+.LP
+.sp
+To free an entry returned by
+.PN IceReadAuthFileEntry
+or
+.PN IceGetAuthFileEntry ,
+use
+.PN IceFreeAuthFileEntry .
+.sM
+.FD 0
+void IceFreeAuthFileEntry\^(\^\fIentry\fP\^)
+.br
+ IceAuthFileEntry *\fIentry\fP\^;
+.FN
+.IP \fIentry\fP 1i
+The entry to free.
+.LP
+.eM
+.bp
+.XS
+Appendix B \- MIT-MAGIC-COOKIE-1 Authentication
+.XE
+.ce 10
+.sp 5
+\s+2\fBAppendix B\fP\s-2
+.sp
+\s+1\fBMIT-MAGIC-COOKIE-1 Authentication\fP\s-1
+.ce 0
+.sp
+.LP
+The X Consortium's ICElib implementation supports a simple
+MIT-MAGIC-COOKIE-1 authentication scheme using the authority file utilities
+described in Appendix A.
+.LP
+In this model, an application, such as a session manager, obtains a
+magic cookie by calling
+.PN IceGenerateMagicCookie ,
+and then stores it in the user's local \&.ICEauthority file
+so that local clients can connect. In order to allow remote clients to
+connect, some remote execution mechanism should be used to store the
+magic cookie in the user's \&.ICEauthority file on a remote machine.
+.LP
+In addition to storing the magic cookie in the \&.ICEauthority file, the
+application needs to call the
+.PN IceSetPaAuthData
+function in order to store the magic cookie in memory. When it comes time
+for the MIT-MAGIC-COOKIE-1 authentication procedure to accept or reject the
+connection, it will compare the magic cookie presented by the requestor to
+the magic cookie in memory.
+.LP
+.sM
+.FD 0
+char *IceGenerateMagicCookie\^(\^\fIlength\fP\^)
+.br
+ int \fIlength\fP\^;
+.FN
+.IP \fIlength\fP 1i
+The desired length of the magic cookie.
+.LP
+.eM
+.LP
+The magic cookie returned will be null-terminated. If memory can not be
+allocated for the magic cookie, the function will return NULL.
+Otherwise, the magic cookie should be freed with a call to
+.PN free .
+.LP
+.sp
+To store the authentication data in memory, use
+.PN IceSetPaAuthData .
+Currently, this function is only used for MIT-MAGIC-COOKIE-1
+authentication, but it may be used for additional authentication
+methods in the future.
+.sM
+.FD 0
+void IceSetPaAuthData\^(\^\fInum_entries\fP, \fIentries\fP\^)
+.br
+ int \fInum_entries\fP\^;
+.br
+ IceAuthDataEntry *\fIentries\fP\^;
+.FN
+.IP \fInum_entries\fP 1i
+The number of authentication data entries.
+.IP \fIentries\fP 1i
+The list of authentication data entries.
+.LP
+.eM
+Each entry has associated with it a protocol name
+(for example, ``ICE'' for ICE connection setup authentication,
+``XSMP'' for session management authentication), a network ID for the
+``accepting'' client, an authentication name (for example, MIT-MAGIC-COOKIE-1),
+and authentication data. The ICE library
+will merge these entries with previously set entries, based on the
+(protocol_name, network_id, auth_name) tuple.
+.LP
+.sM
+.Ds 0
+.TA .5i
+.ta .5i
+typedef struct {
+ char *protocol_name;
+ char *network_id;
+ char *auth_name;
+ unsigned short auth_data_length;
+ char *auth_data;
+} IceAuthDataEntry;
+.De
+.LP
+.eM
+.EH ''''
+.OH ''''
+.YZ 3