








               [1mInter-Client Exchange Library[0m

                        [1mVersion 1.0[0m

                   [1mX Consortium Standard[0m

                 [1mX Version 11, Release 6.4[0m


                         [4mRalph[24m [4mMor[0m
                        X Consortium



        Copyright (C) 1993, 1994, 1996 X Consortium







Permission  is hereby granted, free of charge, to any person
obtaining a copy of this software and associated  documenta-
tion files (the ``Software''), to deal in the Software with-
out 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 fol-
lowing conditions:

The above copyright notice and this permission notice  shall
be  included  in  all  copies or substantial portions of the
Software.

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 PUR-
POSE  AND  NONINFRINGEMENT.  IN NO EVENT SHALL THE X CONSOR-
TIUM 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.

Except  as  contained in this notice, the name of the X Con-
sortium 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.















X Window System is a trademark of X Consortium, Inc.



































































































































[1m1.  Overview of ICE[0m

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.

[1m2.  The ICE Library - C Language Interface to ICE[0m

A client that wishes to utilize ICE must first register  the
protocols  it understands with the ICE library.  Each proto-
col 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 connec-
tions made by other  clients.   Authentication  may  be  re-
quired.   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 connec-
tion is established between the  two  clients,  one  of  the
clients  needs  to initiate a in order to "activate" a given
protocol.  Once the other client accepts  the  (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 con-
nection, although ICE does not define how  each  subprotocol
triggers a protocol shutdown.

The  ICE library utilizes callbacks to process incoming mes-
sages.  Using callbacks allows 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.

[1m3.  Intended Audience[0m

This document is intended primarily for implementors of pro-
tocol libraries layered on top of ICE.  Typically,  applica-
tions that wish to utilize ICE will make calls into individ-
ual 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 ac-
cept ICE connections (for example, a session manager accept-
ing connections from clients).  But in general, protocol li-
braries  should be designed to hide the inner details of ICE
from applications.






                            - 1 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[1m4.  Header Files and Library Name[0m

The header file defines all of the  ICElib  data  structures
and function prototypes.  includes the header file which de-
fines all of the ICElib constants.  Protocol libraries  that
need  to  read  and write messages should include the header
file

Applications should link against ICElib using -lICE.

[1m5.  Note on Prefixes[0m

The following name prefixes are used in the library to  dis-
tinguish between a client that initiates a and a client that
responds with a

+o    - Ice Protocol Originator

+o    - Ice Protocol Acceptor

[1m6.  Protocol Registration[0m

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 call-
backs for processing messages and  handling  authentication.
There are two separate registration functions:

+o    One to handle the side that does a

+o    One to handle the side that responds with a

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  is  re-
ceived,  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.


The function should be called for the client that  initiates
a
__
||  int  IceRegisterForProtocolSetup([4mprotocol_name[24m,  [4mvendor[24m, [4mre-[0m
[4mlease[24m, [4mversion_count[24m, [4mversion_recs[24m,
                 [4mauth_count[24m, [4mauth_names[24m, [4mauth_procs[24m,  [4mio_er-[0m
[4mror_proc[24m)
     char *[4mprotocol_name[24m;
     char *[4mvendor[24m;
     char *[4mrelease[24m;
     int [4mversion_count[24m;



                            - 2 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


     IcePoVersionRec *[4mversion_recs[24m;
     int [4mauth_count[24m;
     char **[4mauth_names[24m;
     IcePoAuthProc *[4mauth_procs[24m;
     IceIOErrorProc [4mio_error_proc[24m;

[4mprotocol_name[0m
          A  string  specifying  the name of the protocol to
          register.

[4mvendor[24m    A vendor string with semantics  specified  by  the
          protocol.

[4mrelease[24m   A  release  string with semantics specified by the
          protocol.

[4mversion_count[0m
          The number of different versions of  the  protocol
          supported.

[4mversion_recs[0m
          List of versions and associated callbacks.

[4mauth_count[0m
          The number of authentication methods supported.

[4mauth_names[0m
          The list of authentication methods supported.

[4mauth_procs[0m
          The list of authentication callbacks, one for each
          authentication method.

[4mio_error_proc[0m
          IO error handler, or NULL.
||__

returns the major opcode reserved or  -1  if  an  error  oc-
curred.   In  order  to  actually activate the protocol, the
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.

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 con-
sists of a major and minor version of the protocol  as  well
as a callback to be used for processing incoming messages.

__
||  typedef struct {      int major_version;      int minor_ver-
sion;      IcePoProcessMsgProc process_msg_proc; } IcePoVer-
sionRec;



                            - 3 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


||__

The  callback  is responsible for processing the set of mes-
sages that can be received by the client that initiated  the
For  further  information,  see section 6.1, ``Callbacks for
Processing Messages.''

Authentication may be required before the protocol  can  be-
come active.  The protocol library must register the authen-
tication methods that it supports with the ICE library.  The
auth_names  and auth_procs arguments are a list of authenti-
cation names and callbacks that are  prioritized in decreas-
ing  order  of preference.  For information on the callback,
see section 6.2, ``Authentication Methods.''

The callback is invoked if the ICE  connection  unexpectedly
breaks.   You  should pass NULL for io_error_proc if not in-
terested in being notified.  For  further  information,  see
section 13, ``Error Handling.''


The  function  should be called for the client that responds
to a with a
__
||  int IceRegisterForProtocolReply([4mprotocol_name[24m,  [4mvendor[24m,  [4mre-[0m
[4mlease[24m, [4mversion_count[24m, [4mversion_recs[24m,
                    [4mauth_count[24m,    [4mauth_names[24m,   [4mauth_procs[24m,
[4mhost_based_auth_proc[24m, [4mprotocol_setup_proc[24m,
                     [4mprotocol_activate_proc[24m, [4mio_error_proc[24m)
     char *[4mprotocol_name[24m;
     char *[4mvendor[24m;
     char *[4mrelease[24m;
     int [4mversion_count[24m;
     IcePaVersionRec *[4mversion_recs[24m;
     int [4mauth_count[24m;
     char **[4mauth_names[24m;
     IcePaAuthProc *[4mauth_procs[24m;
     IceHostBasedAuthProc [4mhost_based_auth_proc[24m;
     IceProtocolSetupProc [4mprotocol_setup_proc[24m;
     IceProtocolActivateProc [4mprotocol_activate_proc[24m;
     IceIOErrorProc [4mio_error_proc[24m;

[4mprotocol_name[0m
          A string specifying the name of  the  protocol  to
          register.

[4mvendor[24m    A  vendor  string  with semantics specified by the
          protocol.

[4mrelease[24m   A release string with semantics specified  by  the
          protocol.

[4mversion_count[0m
          The  number  of different versions of the protocol



                            - 4 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


          supported.

[4mversion_recs[0m
          List of versions and associated callbacks.

[4mauth_count[0m
          The number of authentication methods supported.

[4mauth_names[0m
          The list of authentication methods supported.

[4mauth_procs[0m
          The list of authentication callbacks, one for each
          authentication method.

[4mhost_based_auth_proc[0m
          Host based authentication callback.

[4mprotocol_setup_proc[0m
          A  callback  to be invoked when authentication has
          succeeded for a but before the is sent.

[4mprotocol_activate_proc[0m
          A callback to be invoked after the is sent.

[4mio_error_proc[0m
          IO error handler, or NULL.
||__

returns the major opcode reserved or  -1  if  an  error  oc-
curred.   The  major opcode should be used in all subsequent
messages sent for this protocol.

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 con-
sists of a major and minor version of the protocol  as  well
as a callback to be used for processing incoming messages.

__
||  typedef struct {      int major_version;      int minor_ver-
sion;      IcePaProcessMsgProc process_msg_proc; } IcePaVer-
sionRec;
||__

The  callback  is responsible for processing the set of mes-
sages that can be received by the client that  accepted  the
For  further  information,  see section 6.1, ``Callbacks for
Processing Messages.''

Authentication may be required before the protocol  can  be-
come active.  The protocol library must register the authen-
tication methods that it supports with the ICE library.  The



                            - 5 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


auth_names  and auth_procs arguments are a list of authenti-
cation names and callbacks that are prioritized in  decreas-
ing  order  of preference.  For information on the callback,
see section 6.2, ``Authentication Methods.''

If authentication fails and the client attempting to  initi-
ate the has not required authentication, the callback is in-
voked with the host name of the originating client.  If  the
callback  returns the will succeed, even though the original
authentication failed.  Note that authentication can  effec-
tively be disabled by registering an which always returns If
no host based authentication is  allowed,  you  should  pass
NULL for host_based_auth_proc.

__
||  typedef Bool (*IceHostBasedAuthProc) ();

Bool HostBasedAuthProc([4mhost_name[24m)
    char *[4mhost_name[24m;

[4mhost_name[24m The host name of the client that sent the
||__

The  host_name  argument  is  a  string  of  the form [4mproto-[0m
[4mcol[24m/[4mhostname[24m, where [4mprotocol[24m is one of {tcp, decnet, local}.

Because messages and authentication happen behind the scenes
via  callbacks, the protocol library needs some way of being
notified when the has completed.  This occurs in two phases.
In  the first phase, the callback is invoked after authenti-
cation has successfully completed but before the ICE library
sends  a  Any resources required for this protocol should be
allocated at this time.  If the returns a successful status,
the  ICE library will send the and then invoke the callback.
Otherwise, an error will be sent to the other client in  re-
sponse to the

The is an optional callback and should be registered only if
the protocol library intends to generate a  message  immedi-
ately  following the You should pass NULL for protocol_acti-
vate_proc if not interested in this callback.
__
||  typedef Status (*IceProtocolSetupProc) ();

Status ProtocolSetupProc([4mice_conn[24m, [4mmajor_version[24m, [4mminor_ver-[0m
[4msion[24m, [4mvendor[24m, [4mrelease[24m,
                    [4mclient_data_ret[24m, [4mfailure_reason_ret[24m)
     IceConn [4mice_conn[24m;
     int [4mmajor_version[24m;
     int [4mminor_version[24m;
     char *[4mvendor[24m;
     char *[4mrelease[24m;
     IcePointer *[4mclient_data_ret[24m;
     char **[4mfailure_reason_ret[24m;



                            - 6 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mice_conn[24m  The ICE connection object.

[4mmajor_version[0m
          The major version of the protocol.

[4mminor_version[0m
          The minor version of the protocol.

[4mvendor[24m    The vendor string registered by the protocol orig-
          inator.

[4mrelease[24m   The release  string  registered  by  the  protocol
          originator.

[4mclient_data_ret[0m
          Client data to be set by callback.

[4mfailure_reason_ret[0m
          Failure reason returned.
||__

The  pointer  stored in the client_data_ret argument will be
passed to the callback whenever a message  has  arrived  for
this protocol on the ICE connection.

The  vendor  and  release  strings should be freed with when
they are no longer needed.

If a failure occurs, the should return a zero status as well
as  allocate  and  return  a  failure reason string in fail-
ure_reason_ret.  The ICE library  will  be  responsible  for
freeing this memory.

The callback is defined as follows:
__
||  typedef void (*IceProtocolActivateProc)();

void ProtocolActivateProc([4mice_conn[24m, [4mclient_data[24m)
    IceConn [4mice_conn[24m;
    IcePointer [4mclient_data[24m;

[4mice_conn[24m  The ICE connection object.

[4mclient_data[0m
          The client data set in the callback.
||__

The  callback  is invoked if the ICE connection unexpectedly
breaks.  You should pass NULL for io_error_proc if  not  in-
terested  in  being  notified.  For further information, see
section 13, ``Error Handling.''






                            - 7 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[1m6.1.  Callbacks for Processing Messages[0m

When an application detects that there is new data  to  read
on an ICE connection (via it calls the function (see section
9, ``Processing Messages'').   When  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 accord-
ingly.

If the message arrives at the client that initiated the  the
callback is invoked.
__
||  typedef void (*IcePoProcessMsgProc)();

void PoProcessMsgProc([4mice_conn[24m, [4mclient_data[24m, [4mopcode[24m, [4mlength[24m,
[4mswap[24m, [4mreply_wait[24m, [4mreply_ready_ret[24m)
    IceConn [4mice_conn[24m;
    IcePointer [4mclient_data[24m;
    int [4mopcode[24m;
    unsigned long [4mlength[24m;
    Bool [4mswap[24m;
    IceReplyWaitInfo *[4mreply_wait[24m;
    Bool *[4mreply_ready_ret[24m;

[4mice_conn[24m  The ICE connection object.

[4mclient_data[0m
          Client data associated with this protocol  on  the
          ICE connection.

[4mopcode[24m    The minor opcode of the message.

[4mlength[24m    The length (in 8-byte units) of the message beyond
          the ICE header.

[4mswap[24m      A flag that indicates if byte swapping  is  neces-
          sary.

[4mreply_wait[0m
          Indicates  if the invoking client is waiting for a
          reply.

[4mreply_ready_ret[0m
          If set to a reply is ready.
||__

If the message arrives at the client that accepted  the  the
callback is invoked.
__
||  typedef void (*IcePaProcessMsgProc)();

void PaProcessMsgProc([4mice_conn[24m, [4mclient_data[24m, [4mopcode[24m, [4mlength[24m,
[4mswap[24m)



                            - 8 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


    IceConn [4mice_conn[24m;
    IcePointer [4mclient_data[24m;
    int [4mopcode[24m;
    unsigned long [4mlength[24m;
    Bool [4mswap[24m;

[4mice_conn[24m  The ICE connection object.

[4mclient_data[0m
          Client data associated with this protocol  on  the
          ICE connection.

[4mopcode[24m    The minor opcode of the message.

[4mlength[24m    The length (in 8-byte units) of the message beyond
          the ICE header.

[4mswap[24m      A flag that indicates if byte swapping  is  neces-
          sary.
||__

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.

In  both  of  these callbacks, the client_data argument is a
pointer to client data that was registered at time.  In  the
case  of  the client data was set in the call to In the case
of the client data was set in the callback.

The callback needs to check the reply_wait argument.  If re-
ply_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  Your-
self''  via  a callback.  The details of how such a callback
would be defined are implementation-dependent.

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
__
||  typedef struct  {       unsigned  long  sequence_of_request;
     int    major_opcode_of_request;         int   minor_op-
code_of_request;      IcePointer reply; } IceReplyWaitInfo;
||__

contains the major/minor opcodes and sequence number of  the
message  for  which  a reply is being awaited.  It also con-
tains a pointer to the reply message to be  filled  in  (the
protocol  library  should cast this to the appropriate reply
type).  In most cases, the reply will have  some  fixed-size



                            - 9 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


part,  and  the  client waiting for the reply will have pro-
vided a pointer to a structure to hold this fixed-size data.
If  there is variable-length data, it would be expected that
the 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  sin-
gle 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 callback would allocate the stor-
age and store the pointer.  It is the responsibility of  the
client  receiving  the reply to free any memory allocated on
its behalf.

If reply_wait is not NULL and 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  Note  that an error should only be returned if it corre-
sponds to the reply being waited for.  Otherwise, the should
either  handle  the error internally or invoke an error han-
dler for its library.

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.

The callback, on the other hand, should always pass the mes-
sage  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 Re-
quest'' via a callback.

The reason the callback does not  have  a  reply_wait,  like
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).

[1m6.2.  Authentication Methods[0m

As already stated, a protocol library must register the  au-
thentication  methods that it supports with the ICE library.
For each authentication method, there are two callbacks that
may be registered:

+o    One to handle the side that initiates a

+o    One to handle the side that accepts or rejects this re-
     quest

is the callback invoked for the client  that  initiated  the
This  callback  must be able to respond to the initial ``Au-
thentication Required'' message or subsequent  ``Authentica-





                           - 10 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


tion Next Phase'' messages sent by the other client.
__
||  typedef IcePoAuthStatus (*IcePoAuthProc)();

IcePoAuthStatus     PoAuthProc([4mice_conn[24m,     [4mauth_state_ptr[24m,
[4mclean_up[24m, [4mswap[24m, [4mauth_datalen[24m, [4mauth_data[24m,
                    [4mreply_datalen_ret[24m,  [4mreply_data_ret[24m,  [4mer-[0m
[4mror_string_ret[24m)
    IceConn [4mice_conn[24m;
    IcePointer *[4mauth_state_ptr[24m;
    Bool [4mclean_up[24m;
    Bool [4mswap[24m;
    int [4mauth_datalen[24m;
    IcePointer [4mauth_data[24m;
    int *[4mreply_datalen_ret[24m;
    IcePointer *[4mreply_data_ret[24m;
    char **[4merror_string_ret[24m;

[4mice_conn[24m  The ICE connection object.

[4mauth_state_ptr[0m
          A  pointer  to state for use by the authentication
          callback procedure.

[4mclean_up[24m  If authentication is over, and the function should
          clean up any state it was maintaining.  The last 6
          arguments should be ignored.

[4mswap[24m      If the auth_data may have to be byte swapped  (de-
          pending on its contents).

[4mauth_datalen[0m
          The length (in bytes) of the authenticator data.

[4mauth_data[24m The data from the authenticator.

[4mreply_datalen_ret[0m
          The length (in bytes) of the reply data returned.

[4mreply_data_ret[0m
          The reply data returned.

[4merror_string_ret[0m
          If  the authentication procedure encounters an er-
          ror during authentication, it should allocate  and
          return an error string.
||__

Authentication  may require several phases, depending on the
authentication method.  As a result, the 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  *auth_state_ptr  is  NULL, and the function should
initialize its state and set this  pointer.   In  subsequent



                           - 11 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


invocations  of  the callback, the pointer should be used to
get at any state previously stored by the callback.

If needed, the network ID of the client accepting the can be
obtained by calling the function.

ICElib  will  be  responsible for freeing the reply_data_ret
and error_string_ret pointers with

The auth_data pointer may point to a volatile block of  mem-
ory.  If the data must be kept beyond this invocation of the
callback, be sure to make a copy of it.

The should return one of four values:

+o    - a reply is available.

+o    - authentication rejected.

+o    - authentication failed.

+o    - done cleaning up.

is the callback invoked for the client that received the
__
||  typedef IcePaAuthStatus (*IcePaAuthProc) ();

IcePaAuthStatus PaAuthProc([4mice_conn[24m,  [4mauth_state_ptr[24m,  [4mswap[24m,
[4mauth_datalen[24m, [4mauth_data[24m,
                    [4mreply_datalen_ret[24m,  [4mreply_data_ret[24m,  [4mer-[0m
[4mror_string_ret[24m)
    IceConn [4mice_conn[24m;
    IcePointer *[4mauth_state_ptr[24m;
    Bool [4mswap[24m;
    int [4mauth_datalen[24m;
    IcePointer [4mauth_data[24m;
    int *[4mreply_datalen_ret[24m;
    IcePointer *[4mreply_data_ret[24m;
    char **[4merror_string_ret[24m;

[4mice_conn[24m  The ICE connection object.

[4mauth_state_ptr[0m
          A pointer to state for use by  the  authentication
          callback procedure.

[4mswap[24m      If  auth_data may have to be byte swapped (depend-
          ing on its contents).

[4mauth_datalen[0m
          The length (in bytes) of the  protocol  originator
          authentication data.





                           - 12 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mauth_data[24m The authentication data from the protocol origina-
          tor.

[4mreply_datalen_ret[0m
          The length of the authentication data returned.

[4mreply_data_ret[0m
          The authentication data returned.

[4merror_string_ret[0m
          If authentication is rejected or fails,  an  error
          string is returned.
||__


Authentication  may require several phases, depending on the
authentication method.  As a result, the 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  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.

If needed, the network ID of the client accepting the can be
obtained by calling the function.

The auth_data pointer may point to a volatile block of  mem-
ory.  If the data must be kept beyond this invocation of the
callback, be sure to make a copy of it.

ICElib will be responsible for transmitting and freeing  the
reply_data_ret and error_string_ret pointers with

The should return one of four values:

+o    - continue (or start) authentication.

+o    - authentication accepted.

+o    - authentication rejected.

+o    - authentication failed.

[1m7.  ICE Connections[0m

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.






                           - 13 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[1m7.1.  Opening an ICE Connection[0m

To open an ICE connection  with  another  client  (that  is,
waiting for connections), use
__
||  IceConn     IceOpenConnection([4mnetwork_ids_list[24m,     [4mcontext[24m,
[4mmust_authenticate[24m, [4mmajor_opcode_check[24m,
                    [4merror_length[24m, [4merror_string_ret[24m)
     char *[4mnetwork_ids_list[24m;
     IcePointer [4mcontext[24m;
     Bool [4mmust_authenticate[24m;
     int [4mmajor_opcode_check[24m;
     int  [4merror_length[24m;
     char *[4merror_string_ret[24m;

[4mnetwork_ids_list[0m
          Specifies the network ID(s) of the other client.

[4mcontext[24m   A pointer to an opaque object or  NULL.   Used  to
          determine  if an ICE connection can be shared (see
          below).

[4mmust_authenticate[0m
          If the other client may not bypass authentication.

[4mmajor_opcode_check[0m
          Used to force a new ICE connection to  be  created
          (see below).

[4merror_length[0m
          Length of the error_string_ret argument passed in.

[4merror_string_ret[0m
          Returns  a  null-terminated error message, if any.
          The error_string_ret argument points to user  sup-
          plied memory.  No more than error_length bytes are
          used.
||__

returns an opaque ICE connection object if it succeeds; oth-
erwise, it returns NULL.

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:

lw(0.25i)  lw(2.5i)  lw(1i).        tcp/<hostname>:<portnum-
ber>   or        decnet/<hostname>::<objname>  or        lo-
cal/<hostname>:<path>






                           - 14 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


Most protocol libraries will have some sort of open function
that should internally make a call into When 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.

The  context argument is used to determine if an ICE connec-
tion 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.

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  connec-
tion.   This  can  be used to force multiple ICE connections
between two clients for the same protocol.

Any authentication requirements are  handled  internally  by
the  ICE  library.   The  method by which the authentication
data is obtained is implementation-dependent.

After  is  called,  the  client is ready to send a (provided
that was called) or receive a (provided that was called).

[1m7.2.  Listening for ICE Connections[0m

Clients wishing to accept ICE connections must first call or
so  that  they can listen for connections.  A list of opaque
"listen" objects are returned, one for each type  of  trans-
port  method  that  is  available (for example, Unix Domain,
TCP, DECnet, and so on).

Normally clients will let ICElib allocate an available  name
in  each transport and return listen objects.  Such a client
will then use 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 to specify the names for the listen objects.
__
||  Status  IceListenForConnections([4mcount_ret[24m,  [4mlisten_objs_ret[24m,
[4merror_length[24m, [4merror_string_ret[24m)
     int  *[4mcount_ret[24m;
     IceListenObj **[4mlisten_objs_ret[24m;
     int  [4merror_length[24m;
     char *[4merror_string_ret[24m;

[4mcount_ret[24m Returns the number of listen objects created.

-----------
   The X Consortium's ICElib  implementation  uses
an .ICEauthority file (see Appendix A).



                           - 15 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mlisten_objs_ret[0m
          Returns  a  list  of pointers to opaque listen ob-
          jects.

[4merror_length[0m
          The length of the error_string_ret argument passed
          in.

[4merror_string_ret[0m
          Returns  a  null-terminated error message, if any.
          The error_string_ret points to user supplied  mem-
          ory.  No more than error_length bytes are used.
||__

The return value of is zero for failure and a positive value
for success.

__
||  Status IceListenForWellKnownConnections([4mport_id[24m,  [4mcount_ret[24m,
[4mlisten_objs_ret[24m, [4merror_length[24m, [4merror_string_ret[24m)
     char *[4mport_id[24m;
     int  *[4mcount_ret[24m;
     IceListenObj **[4mlisten_objs_ret[24m;
     int  [4merror_length[24m;
     char *[4merror_string_ret[24m;

[4mport_id[24m   Specifies  the  port  identification  for  the ad-
          dress(es) to be opened.  The value must  not  con-
          tain the slash (``/'') or comma (``,'') character;
          these are reserved for future use.

[4mcount_ret[24m Returns the number of listen objects created.

[4mlisten_objs_ret[0m
          Returns a list of pointers to  opaque  listen  ob-
          jects.

[4merror_length[0m
          The length of the error_string_ret argument passed
          in.

[4merror_string_ret[0m
          Returns a null-terminated error message,  if  any.
          The  error_string_ret points to user supplied mem-
          ory.  No more than error_length bytes are used.
||__

constructs a list of network IDs by  prepending  each  known
transport  to port_id and then attempts to create listen ob-
jects 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 returns fail-
ure.



                           - 16 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


The return value of is zero for failure and a positive value
for success.


To close and free the listen objects, use

__
||  void IceFreeListenObjs([4mcount[24m, [4mlisten_objs[24m)
    int [4mcount[24m;
    IceListenObj *[4mlisten_objs[24m;

[4mcount[24m     The number of listen objects.

[4mlisten_objs[0m
          The listen objects.
||__


To  detect  a  new connection on a listen object, use on the
descriptor associated with the listen object.


To obtain the descriptor, use

__
||  int IceGetListenConnectionNumber([4mlisten_obj[24m)
    IceListenObj [4mlisten_obj[24m;

[4mlisten_obj[0m
          The listen object.
||__


To obtain the network ID string associated with a listen ob-
ject, use
__
||  char *IceGetListenConnectionString([4mlisten_obj[24m)
    IceListenObj [4mlisten_obj[24m;

[4mlisten_obj[0m
          The listen object.
||__


A network ID has the following format:

lw(0.25i)  lw(2.5i)  lw(1i).        tcp/<hostname>:<portnum-
ber>   or        decnet/<hostname>::<objname>  or        lo-
cal/<hostname>:<path>


To  compose  a string containing a list of network IDs sepa-
rated by commas (the format recognized by use




                           - 17 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m

__
||  char *IceComposeNetworkIdList([4mcount[24m, [4mlisten_objs[24m)
    int [4mcount[24m;
    IceListenObj *[4mlisten_objs[24m;

[4mcount[24m     The number of listen objects.

[4mlisten_objs[0m
          The listen objects.
||__


[1m7.3.  Host Based Authentication for ICE Connections[0m

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 function.
__
||  void                     IceSetHostBasedAuthProc([4mlisten_obj[24m,
[4mhost_based_auth_proc[24m)
    IceListenObj [4mlisten_obj[24m;
    IceHostBasedAuthProc [4mhost_based_auth_proc[24m;

[4mlisten_obj[0m
          The listen object.

[4mhost_based_auth_proc[0m
          The host based authentication procedure.
||__

By default, each listen object has no host based authentica-
tion  procedure  associated  with  it.   Passing  NULL   for
host_based_auth_proc  turns off host based authentication if
it was previously set.

__
||  typedef Bool (*IceHostBasedAuthProc) ();

Bool HostBasedAuthProc([4mhost_name[24m)
    char *[4mhost_name[24m;

[4mhost_name[24m The host name of the client that tried to open  an
          ICE connection.
||__

The  host_name  argument  is  a  string  in  the form [4mproto-[0m
[4mcol[24m/[4mhostname[24m, where [4mprotocol[24m is one of {tcp, decnet, local}.

If returns access will be granted, even though the  original
authentication  failed.  Note that authentication can effec-
tively be disabled by registering an which always returns




                           - 18 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


Host based authentication is  also  allowed  at  time.   The
callback is specified in the function (see section 6, ``Pro-
tocol Registration'').

[1m7.4.  Accepting ICE Connections[0m

After a connection attempt is detected on  a  listen  object
returned  by  you  should call This returns a new opaque ICE
connection object.
__
||  IceConn IceAcceptConnection([4mlisten_obj[24m, [4mstatus_ret[24m)
    IceListenObj [4mlisten_obj[24m;
    IceAcceptStatus *[4mstatus_ret[24m;

[4mlisten_obj[0m
          The listen object on which a  new  connection  was
          detected.

[4mstatus_ret[0m
          Return status information.
||__

The  status_ret argument is set to one of the following val-
ues:

+o    - the accept operation succeeded, and the function  re-
     turns a new connection object.

+o    - the accept operation failed, and the function returns
     NULL.

+o    - a memory allocation failed, and the function  returns
     NULL.

In  general,  to  detect new connections, you should call on
the file descriptors associated  with  the  listen  objects.
When  a  new  connection is detected, the function should be
called.  may return a new ICE connection that is in a  pend-
ing state.  This is because before the connection can become
valid, authentication may be necessary.  Because the ICE li-
brary  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.

The following pseudo-code demonstrates how  connections  are
accepted:

new_ice_conn = IceAcceptConnection (listen_obj, &accept_sta-
tus); if (accept_status !=  IceAcceptSuccess)  {       close
the file descriptor and return }

status  =  IceConnectionStatus  (new_ice_conn); time_start =
time_now;



                           - 19 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


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 ==  IceProcessMessagesIOEr-
ror)                        IceCloseConnection   (ice_conn);
          }

     if (data ready  on  new_ice_conn)       {            /*
            * IceProcessMessages is called until the connec-
tion            * is non-pending.  Doing so handles the con-
nection              *  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 {      IceCloseConnec-
tion (new_ice_conn); }

After is called and the connection has been  validated,  the
client  is  ready to receive a (provided that was called) or
send a (provided that was called).

[1m7.5.  Closing ICE Connections[0m

To close an ICE connection created with or use
__
||  IceCloseStatus IceCloseConnection([4mice_conn[24m)
    IceConn [4mice_conn[24m;

[4mice_conn[24m  The ICE connection to close.
||__

To actually close an ICE connection,  the  following  condi-
tions must be met:

+o    The [4mopen[24m [4mreference[24m [4mcount[24m must have reached zero on this
     ICE connection.  When is called, it tries to use a pre-
     viously 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 must be matched with a call to
     The connection can be closed only on the last call to

+o    The [4mactive[24m [4mprotocol[24m [4mcount[24m must have reached zero.  Each
     time a succeeds on the connection, the active  protocol
     count is incremented by one.  When the client no longer



                           - 20 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


     expects to use the  protocol  on  the  connection,  the
     function  should be called, which decrements the active
     protocol count by one (see section 8, ``Protocol  Setup
     and Shutdown'').

+o    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.

returns one of the following values:

+o    -  the  ICE  connection  was  closed at this time.  The
     watch procedures were invoked and  the  connection  was
     freed.

+o    -  an  IO  error had occurred on the connection, but is
     being called within a nested 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 returns a status of

+o    -  the  connection was not closed at this time, because
     it is being used by other active protocols.

+o    - the connection was not closed at this time and  shut-
     down  negotiation  started with the client on the other
     side of the ICE connection.  When the connection is ac-
     tually closed, will return a status of


When  it  is  known that the client on the other side of the
ICE connection has terminated the connection without  initi-
ating shutdown negotiation, the function should be called to
turn off shutdown negotiation.  This will prevent from writ-
ing to a broken connection.
__
||  void IceSetShutdownNegotiation([4mice_conn[24m, [4mnegotiate[24m)
    IceConn [4mice_conn[24m;
    Bool [4mnegotiate[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mnegotiate[24m If shutdown negotiating will be turned off.
||__


To  check  the shutdown negotiation status of an ICE connec-
tion, use
__
||  Bool IceCheckShutdownNegotiation([4mice_conn[24m)
    IceConn [4mice_conn[24m;

[4mice_conn[24m  A valid ICE connection object.




                           - 21 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


||__

returns if shutdown negotiation will take place on the  con-
nection;  otherwise, it returns Negotiation is on by default
for a connection.  It can only be changed with the function.

[1m7.6.  Connection Watch Procedures[0m

To add a watch procedure  that  will  be  called  each  time
ICElib  opens a new connection via or or closes a connection
via use
__
||  Status IceAddConnectionWatch([4mwatch_proc[24m, [4mclient_data[24m)
    IceWatchProc [4mwatch_proc[24m;
    IcePointer [4mclient_data[24m;

[4mwatch_proc[0m
          The watch procedure to invoke when ICElib opens or
          closes a connection.

[4mclient_data[0m
          This  pointer  will  be passed to the watch proce-
          dure.
||__

The return value of is zero  for  failure,  and  a  positive
value for success.

Note  that several calls to might share the same ICE connec-
tion.  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 actually closes the
connection (right before the IceConn is freed).

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.

Multiple watch procedures may be registered with the ICE li-
brary.   No  assumptions should be made about their order of
invocation.

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






                           - 22 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


The watch procedure is of type
__
||  typedef void (*IceWatchProc)();

void WatchProc([4mice_conn[24m, [4mclient_data[24m, [4mopening[24m, [4mwatch_data[24m)
    IceConn [4mice_conn[24m;
    IcePointer [4mclient_data[24m;
    Bool [4mopening[24m;
    IcePointer *[4mwatch_data[24m;

[4mice_conn[24m  The  opened or closed ICE connection.  Call to get
          the file descriptor associated with  this  connec-
          tion.

[4mclient_data[0m
          Client data specified in the call to

[4mopening[24m   If the connection is being opened.  If the connec-
          tion is being closed.

[4mwatch_data[0m
          Can be used to save a pointer to client data.
||__

If opening is 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


To remove a watch procedure, use
__
||  void IceRemoveConnectionWatch([4mwatch_proc[24m, [4mclient_data[24m)
    IceWatchProc [4mwatch_proc[24m;
    IcePointer [4mclient_data[24m;


[4mwatch_proc[0m
          The watch procedure that was passed to

[4mclient_data[0m
          The client_data pointer that was passed to
||__


[1m8.  Protocol Setup and Shutdown[0m

To activate a protocol on a given ICE connection, use

__
||  IceProtocolSetupStatus IceProtocolSetup([4mice_conn[24m, [4mmy_opcode[24m,
[4mclient_data[24m, [4mmust_authenticate[24m,
                    [4mmajor_version_ret[24m,    [4mminor_version_ret[24m,
[4mvendor_ret[24m, [4mrelease_ret[24m, [4merror_length[24m, [4merror_string_ret[24m)



                           - 23 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


    IceConn [4mice_conn[24m;
    int [4mmy_opcode[24m;
    IcePointer [4mclient_data[24m;
    Bool [4mmust_authenticate[24m;
    int *[4mmajor_version_ret[24m;
    int *[4mminor_version_ret[24m;
    char **[4mvendor_ret[24m;
    char **[4mrelease_ret[24m;
    int [4merror_length[24m;
    char *[4merror_string_ret[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mmy_opcode[24m The  major opcode of the protocol to be set up, as
          returned by

[4mclient_data[0m
          The client data stored in  this  pointer  will  be
          passed to the callback.

[4mmust_authenticate[0m
          If the other client may not bypass authentication.

[4mmajor_version_ret[0m
          The  major  version  of the protocol to be used is
          returned.

[4mminor_version_ret[0m
          The minor version of the protocol to  be  used  is
          returned.

[4mvendor_ret[0m
          The vendor string specified by the protocol accep-
          tor.

[4mrelease_ret[0m
          The release string specified by the  protocol  ac-
          ceptor.

[4merror_length[0m
          Specifies the length of the error_string_ret argu-
          ment passed in.

[4merror_string_ret[0m
          Returns a null-terminated error message,  if  any.
          The  error_string_ret argument points to user sup-
          plied memory.  No more than error_length bytes are
          used.
||__

The  vendor_ret and release_ret strings should be freed with
when no longer needed.





                           - 24 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


returns one of the following values:

+o    - the major_version_ret, minor_version_ret, vendor_ret,
     release_ret are set.

+o    or  -  check  error_string_ret for failure reason.  The
     major_version_ret, minor_version_ret,  vendor_ret,  re-
     lease_ret are not set.

+o    -  this  protocol is already active on this connection.
     The major_version_ret,  minor_version_ret,  vendor_ret,
     release_ret are not set.


To  notify  the  ICE  library  when a given protocol will no
longer be used on an ICE connection, use

__
||  Status IceProtocolShutdown([4mice_conn[24m, [4mmajor_opcode[24m)
    IceConn [4mice_conn[24m;
    int [4mmajor_opcode[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mmajor_opcode[0m
          The major opcode of the protocol to shut down.
||__

The return value of is zero for failure and a positive value
for success.

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 succeeded on
the connection.  Note that ICE does not define how each sub-
protocol triggers a protocol shutdown.

[1m9.  Processing Messages[0m

To process incoming messages on an ICE connection, use
__
||  IceProcessMessagesStatus   IceProcessMessages([4mice_conn[24m,  [4mre-[0m
[4mply_wait[24m, [4mreply_ready_ret[24m)
    IceConn [4mice_conn[24m;
    IceReplyWaitInfo *[4mreply_wait[24m;
    Bool *[4mreply_ready_ret[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mreply_wait[0m
          Indicates if a reply is being waited for.

[4mreply_ready_ret[0m
          If set to on return, a reply is ready.



                           - 25 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


||__

is used in two ways:

+o    In the first, a client may generate a message and block
     by calling repeatedly until it gets its reply.

+o    In  the  second,  a client calls with reply_wait set to
     NULL in response to 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 invok-
     ing callbacks.

contains the major/minor opcodes and sequence number of  the
message  for  which  a reply is being awaited.  It also con-
tains a pointer to the reply message to be  filled  in  (the
protocol  library  should cast this 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 pro-
vided a pointer to a structure to hold this fixed-size data.
If  there is variable-length data, it would be expected that
the 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 re-
ply would probably just pass a pointer to  fixed-size  space
to hold a pointer, and the callback would allocate the stor-
age and store the pointer.  It is the responsibility of  the
client  receiving  the reply to free up any memory allocated
on its behalf.

__
||  typedef struct  {       unsigned  long  sequence_of_request;
     int    major_opcode_of_request;         int   minor_op-
code_of_request;      IcePointer reply; } IceReplyWaitInfo;
||__

If reply_wait is not NULL and 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

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.

returns one of the following values:

+o    - no error occurred.

+o    - an IO error occurred, and the caller must  explicitly
     close the connection by calling





                           - 26 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


+o    -  the  ICE  connection has been closed (closing of the
     connection was deferred because  of  shutdown  negotia-
     tion,  or  because the nesting level was not zero).  Do
     not attempt to access the ICE connection at this point,
     since it has been freed.

[1m10.  Ping[0m

To  send  a ``Ping'' message to the client on the other side
of the ICE connection, use
__
||  Status IcePing([4mice_conn[24m, [4mping_reply_proc[24m, [4mclient_data[24m)
    IceConn [4mice_conn[24m;
    IcePingReplyProc [4mping_reply_proc[24m;
    IcePointer [4mclient_data[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mping_reply_proc[0m
          The callback to invoke when  the  Ping  reply  ar-
          rives.

[4mclient_data[0m
          This pointer will be passed to the callback.
||__

returns zero for failure and a positive value for success.

When processes the Ping reply, it will invoke the callback.
__
||  typedef void (*IcePingReplyProc)();

void PingReplyProc([4mice_conn[24m, [4mclient_data[24m)
    IceConn [4mice_conn[24m;
    IcePointer [4mclient_data[24m;

[4mice_conn[24m  The ICE connection object.

[4mclient_data[0m
          The client data specified in the call to
||__


[1m11.  Using ICElib Informational Functions[0m

__
||  IceConnectStatus IceConnectionStatus([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns  the  status of an ICE connection.  The possible re-
turn values are:

+o    - the connection is not valid yet (that is, authentica-
     tion  is  taking  place).   This  is  only  relevant to



                           - 27 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


     connections created by

+o    - the connection has been accepted.  This is only rele-
     vant to connections created by

+o    - the connection had been rejected  (that is, authenti-
     cation failed).  This is only relevant  to  connections
     created by

+o    - an IO error has occurred on the connection.

__
||  char *IceVendor([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns  the ICE library vendor identification for the other
side of the connection.  The string should be freed  with  a
call to when no longer needed.

__
||  char *IceRelease([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns the release identification of the ICE library on the
other side of the connection.  The string  should  be  freed
with a call to when no longer needed.

__
||  int IceProtocolVersion([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns  the  major version of the ICE protocol on this con-
nection.

__
||  int IceProtocolRevision([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns the minor version of the ICE protocol on  this  con-
nection.

__
||  int IceConnectionNumber([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns the file descriptor of this ICE connection.

__
||  char *IceConnectionString([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns the network ID of the client that accepted this con-
nection.  The string should be freed with a call to when  no
longer needed.



                           - 28 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m

__
||  unsigned long IceLastSentSequenceNumber([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns the sequence number of the last message sent on this
ICE connection.

__
||  unsigned long IceLastReceivedSequenceNumber([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns the sequence number of the last message received  on
this ICE connection.

__
||  Bool IceSwapping([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns  if byte swapping is necessary when reading messages
on the ICE connection.

__
||  IcePointer IceGetContext([4mice_conn[24m)
||__    IceConn [4mice_conn[24m;

returns the context associated with a connection created by

[1m12.  ICE Messages[0m

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:

     CARD8major_opcode;                   CARD8minor_opcode;
     CARD8data[2];      CARD32length B32;

The  3rd  and 4th bytes of the message header can be used as
needed.  The length field is specified in units of 8 bytes.

[1m12.1.  Sending ICE Messages[0m

The ICE library maintains an output buffer used for generat-
ing  messages.  Protocol libraries layered on top of ICE may
choose to batch messages together and flush the output  buf-
fer at appropriate times.

If  an IO error has occurred on an ICE connection, all write
operations will be ignored.  For  further  information,  see
section 13, ``Error Handling.''


To get the size of the ICE output buffer, use
__
||  int IceGetOutBufSize([4mice_conn[24m)
     IceConn [4mice_conn[24m;



                           - 29 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mice_conn[24m  A valid ICE connection object.
||__


To flush the ICE output buffer, use
__
||  IceFlush([4mice_conn[24m)
     IceConn [4mice_conn[24m;

[4mice_conn[24m  A valid ICE connection object.
||__

Note  that  the  output  buffer may be implicitly flushed if
there is insufficient space to generate a message.

The following macros can be used to generate ICE messages:

__
||  IceGetHeader([4mice_conn[24m,      [4mmajor_opcode[24m,      [4mminor_opcode[24m,
[4mheader_size[24m, [4m<C_data_type>[24m, [4mpmsg[24m)
     IceConn [4mice_conn[24m;
     int [4mmajor_opcode[24m;
     int [4mminor_opcode[24m;
     int [4mheader_size[24m;
     <C_data_type> *[4mpmsg[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mmajor_opcode[0m
          The major opcode of the message.

[4mminor_opcode[0m
          The minor opcode of the message.

[4mheader_size[0m
          The size of the message header (in bytes).

[4m<C_data_type>[0m
          The actual C data type of the message header.

[4mpmsg[24m      The  message  header pointer.  After this macro is
          called, the library can store data in the  message
          header.
||__

is used to set up a message header on an ICE connection.  It
sets the major and minor opcodes of the  message,  and  ini-
tializes  the  message's length to the length of the header.
If additional variable length data  follows,  the  message's
length field should be updated.







                           - 30 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m

__
||  IceGetHeaderExtra([4mice_conn[24m,    [4mmajor_opcode[24m,   [4mminor_opcode[24m,
[4mheader_size[24m, [4mextra[24m, [4m<C_data_type>[24m, [4mpmsg[24m, [4mpdata[24m)
     IceConn [4mice_conn[24m;
     int [4mmajor_opcode[24m;
     int [4mminor_opcode[24m;
     int [4mheader_size[24m;
     int [4mextra[24m;
     <C_data_type> *[4mpmsg[24m;
     char *[4mpdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mmajor_opcode[0m
          The major opcode of the message.

[4mminor_opcode[0m
          The minor opcode of the message.

[4mheader_size[0m
          The size of the message header (in bytes).

[4mextra[24m     The size of the extra data beyond the  header  (in
          8-byte units).

[4m<C_data_type>[0m
          The actual C data type of the message header.

[4mpmsg[24m      The  message  header pointer.  After this macro is
          called, the library can store data in the  message
          header.

[4mpdata[24m     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  buf-
          fer, pdata is set to NULL.
||__

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.


__
||  IceSimpleMessage([4mice_conn[24m, [4mmajor_opcode[24m, [4mminor_opcode[24m)
     IceConn [4mice_conn[24m;
     int [4mmajor_opcode[24m;
     int [4mminor_opcode[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mmajor_opcode[0m
          The major opcode of the message.




                           - 31 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mminor_opcode[0m
          The minor opcode of the message.
||__

is  used  to generate a message that is identical in size to
the ICE header message, and has no additional data.


__
||  IceErrorHeader([4mice_conn[24m,   [4moffending_major_opcode[24m,   [4moffend-[0m
[4ming_minor_opcode[24m, [4moffending_sequence_num[24m,
                    [4mseverity[24m, [4merror_class[24m, [4mdata_length[24m)
     IceConn [4mice_conn[24m;
     int [4moffending_major_opcode[24m;
     int [4moffending_minor_opcode[24m;
     int [4moffending_sequence_num[24m;
     int [4mseverity[24m;
     int [4merror_class[24m;
     int [4mdata_length[24m;

[4mice_conn[24m  A valid ICE connection object.

[4moffending_major_opcode[0m
          The major opcode of the protocol in which an error
          was detected.

[4moffending_minor_opcode[0m
          The minor opcode of the protocol in which an error
          was detected.

[4moffending_sequence_num[0m
          The sequence number of the message that caused the
          error.

[4mseverity[24m  or

[4merror_class[0m
          The error class.

[4mdata_length[0m
          Length of data (in 8-byte units) to be written af-
          ter the header.
||__

sets up an error message header.

Note that the two clients connected by ICE may be using dif-
ferent major opcodes for  a  given  protocol.   The  offend-
ing_major_opcode passed to this macro is the major opcode of
the protocol for the client sending the error message.

Generic errors, which are  common  to  all  protocols,  have
classes  in  the range 0x8000..0xFFFF.  See the [4mInter-Client[0m
[4mExchange[24m [4mProtocol[24m standard for more details.



                           - 32 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


lw(1i) lw(1i).  T{ T}   T{ 0x8000 T}
T{ T}   T{ 0x8001 T}
T{ T}   T{ 0x8002 T}
T{ T}   T{ 0x8003 T}


Per-protocol errors have classes in the range 0x0000-0x7fff.


To write data to an ICE connection, use the 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.

This macro is used in conjunction with and


__
||  IceWriteData([4mice_conn[24m, [4mbytes[24m, [4mdata[24m)
     IceConn [4mice_conn[24m;
     int [4mbytes[24m;
     char *[4mdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mbytes[24m     The number of bytes to write.

[4mdata[24m      The data to write.
||__


To write data as 16-bit quantities, use
__
||  IceWriteData16([4mice_conn[24m, [4mbytes[24m, [4mdata[24m)
     IceConn [4mice_conn[24m;
     int [4mbytes[24m;
     short *[4mdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mbytes[24m     The number of bytes to write.

[4mdata[24m      The data to write.
||__


To write data as 32-bit quantities, use
__
||  IceWriteData32([4mice_conn[24m, [4mbytes[24m, [4mdata[24m)
     IceConn [4mice_conn[24m;
     int [4mbytes[24m;
     long *[4mdata[24m;





                           - 33 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mice_conn[24m  A valid ICE connection object.

[4mbytes[24m     The number of bytes to write.

[4mdata[24m      The data to write.
||__


To  bypass copying data to the ICE output buffer, use to di-
rectly send data over the network connection.  If necessary,
the ICE output buffer is first flushed.
__
||  IceSendData([4mice_conn[24m, [4mbytes[24m, [4m(char[24m [4m*)[24m [4mdata[24m)
     IceConn [4mice_conn[24m;
     int [4mbytes[24m;
     char *[4mdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mbytes[24m     The number of bytes to send.

[4mdata[24m      The data to send.
||__


To  force 32-bit or 64-bit alignment, use A maximum of 7 pad
bytes can be specified.
__
||  IceWritePad([4mice_conn[24m, [4mbytes[24m)
     IceConn [4mice_conn[24m;
     int [4mbytes[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mbytes[24m     The number of pad bytes.
||__


[1m12.2.  Reading ICE Messages[0m

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.


To get the size of the ICE input buffer, use
__
||  int IceGetInBufSize([4mice_conn[24m)
     IceConn [4mice_conn[24m;



                           - 34 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mice_conn[24m  A valid ICE connection object.
||__


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
macro  can  be  used to check if an IO error occurred on the
connection.  After an IO error has occurred on an  ICE  con-
nection,  all  read operations will be ignored.  For further
information, see section 13, ``Error Handling.''


__
||  Bool IceValidIO([4mice_conn[24m)
    IceConn [4mice_conn[24m;
||__


The following macros can be used to read ICE messages.
__
||  IceReadSimpleMessage([4mice_conn[24m, [4m<C_data_type>[24m, [4mpmsg[24m)
     IceConn [4mice_conn[24m;
     <C_data_type> *[4mpmsg[24m;

[4mice_conn[24m  A valid ICE connection object.

[4m<C_data_type>[0m
          The actual C data type of the message header.

[4mpmsg[24m      This pointer is set to the message header.
||__

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 op-
code of the message.  simply returns a pointer  to  these  8
bytes;  it  does  not  actually read any data into the input
buffer.

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  The  second  method  in-
volves  reading  the  message  header (note that this may be
larger than the 8-byte ICE header), then reading  the  vari-
able length data in chunks (see and


__
||  IceReadCompleteMessage([4mice_conn[24m, [4mheader_size[24m, [4m<C_data_type>[24m,
[4mpmsg[24m, [4mpdata[24m)
     IceConn [4mice_conn[24m;



                           - 35 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


     int [4mheader_size[24m;
     <C_data_type> *[4mpmsg[24m;
     char *[4mpdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mheader_size[0m
          The size of the message header (in bytes).

[4m<C_data_type>[0m
          The actual C data type of the message header.

[4mpmsg[24m      This pointer is set to the message header.

[4mpdata[24m     This pointer is set to the variable length data of
          the message.
||__

If  the ICE input buffer has sufficient space, 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 allo-
cate the buffer.


After calling and processing the message, should be called.

__
||  IceDisposeCompleteMessage([4mice_conn[24m, [4mpdata[24m)
     IceConn [4mice_conn[24m;
     char *[4mpdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mpdata[24m     The pointer to the variable length  data  returned
          in
||__

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.


__
||  IceReadMessageHeader([4mice_conn[24m,  [4mheader_size[24m,  [4m<C_data_type>[24m,
[4mpmsg[24m)
     IceConn [4mice_conn[24m;
     int [4mheader_size[24m;
     <C_data_type> *[4mpmsg[24m;

[4mice_conn[24m  A valid ICE connection object.





                           - 36 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mheader_size[0m
          The size of the message header (in bytes).

[4m<C_data_type>[0m
          The actual C data type of the message header.

[4mpmsg[24m      This pointer is set to the message header.
||__

reads just the message header.  The rest of the data  should
be read with the family of macros.  This method of reading a
message should be used when the variable length data must be
read in chunks.


To read data directly into a user supplied buffer, use
__
||  IceReadData([4mice_conn[24m, [4mbytes[24m, [4mpdata[24m)
     IceConn [4mice_conn[24m;
     int [4mbytes[24m;
     char *[4mpdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mbytes[24m     The number of bytes to read.

[4mpdata[24m     The data is read into this user supplied buffer.
||__


To read data as 16-bit quantities, use
__
||  IceReadData16([4mice_conn[24m, [4mswap[24m, [4mbytes[24m, [4mpdata[24m)
     IceConn [4mice_conn[24m;
     Bool [4mswap[24m;
     int [4mbytes[24m;
     short *[4mpdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mswap[24m      If the values will be byte swapped.

[4mbytes[24m     The number of bytes to read.

[4mpdata[24m     The data is read into this user supplied buffer.
||__


To read data as 32-bit quantities, use
__
||  IceReadData32([4mice_conn[24m, [4mswap[24m, [4mbytes[24m, [4mpdata[24m)
     IceConn [4mice_conn[24m;
     Bool [4mswap[24m;
     int [4mbytes[24m;



                           - 37 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


     long *[4mpdata[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mswap[24m      If the values will be byte swapped.

[4mbytes[24m     The number of bytes to read.

[4mpdata[24m     The data is read into this user supplied buffer.
||__


To  force 32-bit or 64-bit alignment, use A maximum of 7 pad
bytes can be specified.
__
||  IceReadPad([4mice_conn[24m, [4mbytes[24m)
     IceConn [4mice_conn[24m;
     int [4mbytes[24m;

[4mice_conn[24m  A valid ICE connection object.

[4mbytes[24m     The number of pad bytes.
||__


[1m13.  Error Handling[0m

There are two default error handlers in ICElib:

+o    One to handle typically fatal conditions (for  example,
     a connection dying because a machine crashed)

+o    One to handle ICE-specific protocol errors

These  error  handlers  can be changed to user-supplied rou-
tines if you prefer your  own  error  handling  and  can  be
changed as often as you like.


To set the ICE error handler, use
__
||  IceErrorHandler IceSetErrorHandler([4mhandler[24m)
    IceErrorHandler [4mhandler[24m;

[4mhandler[24m   The  ICE  error  handler.  You should pass NULL to
          restore the default handler.
||__

returns the previous error handler.

The ICE error handler is invoked when an unexpected ICE pro-
tocol  error (major opcode 0) is encountered.  The action of
the default handler is to print an  explanatory  message  to
and if the severity is fatal, call with a nonzero value.  If



                           - 38 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


exiting is undesirable, the application should register  its
own error handler.

Note that errors in other protocol domains should be handled
by their respective libraries (these libraries  should  have
their own error handlers).

An ICE error handler has the type of
__
||  typedef void (*IceErrorHandler)();

void  ErrorHandler([4mice_conn[24m,  [4mswap[24m,  [4moffending_minor_opcode[24m,
[4moffending_sequence_num[24m, [4merror_class[24m,
                     [4mseverity[24m, [4mvalues[24m)
    IceConn [4mice_conn[24m;
    Bool [4mswap[24m;
    int [4moffending_minor_opcode[24m;
    unsigned long [4moffending_sequence_num[24m;
    int [4merror_class[24m;
    int [4mseverity[24m;
    IcePointer [4mvalues[24m;

[4mice_conn[24m  The ICE connection object.

[4mswap[24m      A flag that indicates  if  the  values  need  byte
          swapping.

[4moffending_minor_opcode[0m
          The ICE minor opcode of the offending message.

[4moffending_sequence_num[0m
          The sequence number of the offending message.

[4merror_class[0m
          The error class of the offending message.

[4mseverity[24m  or

[4mvalues[24m    Any  additional error values specific to the minor
          opcode and class.
||__

The following error classes are defined at the ICE level:


For further information, see the [4mInter-Client[24m [4mExchange[24m  [4mPro-[0m
[4mtocol[24m standard.


To handle fatal I/O errors, use







                           - 39 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m

__
||  IceIOErrorHandler IceSetIOErrorHandler([4mhandler[24m)
    IceIOErrorHandler [4mhandler[24m;

[4mhandler[24m   The  I/O  error  handler.  You should pass NULL to
          restore the default handler.
||__

returns the previous IO error handler.

An ICE I/O error handler has the type of

__
||  typedef void (*IceIOErrorHandler)();

void IOErrorHandler([4mice_conn[24m)
    IceConn [4mice_conn[24m;

[4mice_conn[24m  The ICE connection object.
||__

There are two ways of handling IO errors in ICElib:

+o    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 The  ICE  connection  is  given  a
     ``bad  IO''  status, and all future reads and writes to
     the connection are ignored.  The next time is called it
     will  return  a status of At that time, the application
     should call

+o    In the second, the IO error handler does call and  then
     uses  the  call  to  get back to the application's main
     event loop.  The and calls may not work properly on all
     platforms, and special care must be taken to avoid mem-
     ory leaks.  Therefore, this second model is less desir-
     able.

Before  the application I/O error handler is invoked, proto-
col libraries that were interested in being notified of  I/O
errors  will  have  their handlers invoked.  This handler is
set up in the protocol registration functions (see  and  and
could be used to clean up state specific to the protocol.


__
||  typedef void (*IceIOErrorProc)();

void IOErrorProc([4mice_conn[24m)
    IceConn [4mice_conn[24m;

[4mice_conn[24m  The ICE connection object.
||__

Note  that  every  callback  must  return.  This is required



                           - 40 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


because each active protocol must be notified of the  broken
connection, and the application IO error handler must be in-
voked afterwards.

[1m14.  Multi-Threading Support[0m

To declare that multiple threads in an application  will  be
using the ICE library, use

__
||  Status IceInitThreads()
||__

The  function  must  be  the  first ICElib function a multi-
threaded program calls.  It must complete before  any  other
ICElib  call  is made.  returns a nonzero status if and only
if it was able to initialize the  threads  package  success-
fully.   It  is  safe  to  call more than once, although the
threads package will only be initialized once.

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:
__
||  IceLockConn([4mice_conn[24m)
    IceConn [4mice_conn[24m;

IceUnlockConn([4mice_conn[24m)
    IceConn [4mice_conn[24m;

[4mice_conn[24m  The ICE connection.
||__


To  keep  an  ICE  connection  locked  across several ICElib
calls, applications use and
__
||  void IceAppLockConn([4mice_conn[24m)
    IceConn [4mice_conn[24m;

[4mice_conn[24m  The ICE connection to lock.
||__

The function completely locks out other  threads  using  the
connection until is called.  Other threads attempting to use
ICElib calls on the connection will block.  If  the  program
has not previously called has no effect.

__
||  void IceAppUnlockConn([4mice_conn[24m)
    IceConn [4mice_conn[24m;





                           - 41 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mice_conn[24m  The ICE connection to unlock.
||__

The  function  allows other threads to complete ICElib calls
on the connection that were blocked by a  previous  call  to
from  this thread.  If the program has not previously called
has no effect.

[1m15.  Miscellaneous Functions[0m

To allocate scratch space (for example, when generating mes-
sages  with  variable data), use 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.

__
||  char *IceAllocScratch([4mice_conn[24m, [4msize[24m)
    IceConn [4mice_conn[24m;
    unsigned long [4msize[24m;

[4mice_conn[24m  A valid ICE connection object.

[4msize[24m      The number of bytes required.
||__

Note  that the memory returned by should not be freed by the
caller.  The ICE library will free the memory when  the  ICE
connection is closed.

[1m16.  Acknowledgements[0m

Thanks  to Bob Scheifler for his thoughtful input on the de-
sign 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.



















                           - 42 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


                         [1mAppendix A[0m

              [1mAuthentication Utility Functions[0m


As  discussed in this document, the means by which authenti-
cation data is obtained by the ICE library (for messages  or
messages) is implementation-dependent.

This appendix describes some utility functions that  manipu-
late  an ICE authority file.  The authority file can be used
to pass authentication data between clients.

The basic operations on the .ICEauthority file are:

+o    Get file name

+o    Lock

+o    Unlock

+o    Read entry

+o    Write entry

+o    Search for entry

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.

In order to use these utility  functions,  the  header  file
must be included.

An entry in the .ICEauthority file is defined by the follow-
ing data structure:

__
||  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;  } IceAuth-
FileEntry;
||__

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.
-----------
   The  X  Consortium's  ICElib implementation as-
sumes the presence of an ICE authority file.



                           - 43 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


The  network_id  member  is the network ID of the client ac-
cepting authentication (for example, the  network  ID  of  a
session manager).  A network ID has the following form:

lw(0.25i)  lw(2.5i)  lw(1i).        tcp/<hostname>:<portnum-
ber>   or        decnet/<hostname>::<objname>  or        lo-
cal/<hostname>:<path>


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.


To obtain the default authorization file name, use
__
||  char *IceAuthFileName()
||__

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.

To  synchronously  update  the  authorization file, the file
must be locked with a call to This function takes  advantage
of  the  fact  that the system call will fail if the name of
the new link already exists.
__
||  int IceLockAuthFile([4mfile_name[24m, [4mretries[24m, [4mtimeout[24m, [4mdead[24m)
    char *[4mfile_name[24m;
    int [4mretries[24m;
    int [4mtimeout[24m;
    long [4mdead[24m;

[4mfile_name[24m The authorization file to lock.

[4mretries[24m   The number of retries.

[4mtimeout[24m   The number of seconds before each retry.

[4mdead[24m      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.
||__

One of three values is returned:

+o    - the lock succeeded.

+o    - a system error occurred, and may prove useful.





                           - 44 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


+o    - the specified number of retries failed.


To unlock an authorization file, use
__
||  void IceUnlockAuthFile([4mfile_name[24m)
    char *[4mfile_name[24m;

[4mfile_name[24m The authorization file to unlock.
||__


To read the next entry in an authorization file, use
__
||  IceAuthFileEntry *IceReadAuthFileEntry([4mauth_file[24m)
    FILE *[4mauth_file[24m;

[4mauth_file[24m The authorization file.
||__

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.

Entries should be free with a call to


To write an entry in an authorization file, use
__
||  Status IceWriteAuthFileEntry([4mauth_file[24m, [4mentry[24m)
    FILE *[4mauth_file[24m;
    IceAuthFileEntry *[4mentry[24m;

[4mauth_file[24m The authorization file.

[4mentry[24m     The entry to write.
||__

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 suc-
cessful.


To search the default authorization file for an  entry  that
matches  a  given  protocol_name/network_id/auth_name tuple,
use
__
||  IceAuthFileEntry  *IceGetAuthFileEntry([4mprotocol_name[24m,   [4mnet-[0m
[4mwork_id[24m, [4mauth_name[24m)
    char *[4mprotocol_name[24m;
    char *[4mnetwork_id[24m;
    char *[4mauth_name[24m;



                           - 45 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


[4mprotocol_name[0m
          The name of the protocol to search on.

[4mnetwork_id[0m
          The network ID to search on.

[4mauth_name[24m The authentication method to search on.
||__

If fails to find such an entry, NULL is returned.


To free an entry returned by or use
__
||  void IceFreeAuthFileEntry([4mentry[24m)
    IceAuthFileEntry *[4mentry[24m;

[4mentry[24m     The entry to free.
||__






































                           - 46 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


                         [1mAppendix B[0m

             [1mMIT-MAGIC-COOKIE-1 Authentication[0m


The  X  Consortium's ICElib implementation supports a simple
MIT-MAGIC-COOKIE-1 authentication scheme using the authority
file utilities described in Appendix A.

In  this  model,  an application, such as a session manager,
obtains a magic cookie by calling 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.

In addition to storing the magic cookie in the .ICEauthority
file, the application needs to call the 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 pre-
sented by the requestor to the magic cookie in memory.

__
||  char *IceGenerateMagicCookie([4mlength[24m)
    int [4mlength[24m;

[4mlength[24m    The desired length of the magic cookie.
||__


The  magic cookie returned will be null-terminated.  If mem-
ory can not be allocated for the magic cookie, the  function
will  return  NULL.   Otherwise,  the magic cookie should be
freed with a call to


To store the authentication data in memory,  use  Currently,
this  function is only used for MIT-MAGIC-COOKIE-1 authenti-
cation, but it may be  used  for  additional  authentication
methods in the future.
__
||  void IceSetPaAuthData([4mnum_entries[24m, [4mentries[24m)
    int [4mnum_entries[24m;
    IceAuthDataEntry *[4mentries[24m;

[4mnum_entries[0m
          The number of authentication data entries.

[4mentries[24m   The list of authentication data entries.
||__

Each entry has associated with it a protocol name (for exam-
ple,  ``ICE''  for  ICE  connection  setup   authentication,



                           - 47 -





[1mInter-Client Exchange Library               X11, Release 6.4[0m


``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 en-
tries,  based  on the (protocol_name, network_id, auth_name)
tuple.

__
||  typedef struct {      char *protocol_name;       char  *net-
work_id;         char    *auth_name;        unsigned   short
auth_data_length;      char *auth_data; } IceAuthDataEntry;
||__













































                           - 48 -


