








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

                        [1mVersion 1.0[0m

                   [1mX Consortium Standard[0m

                 [1mX Version 11, Release 6.8[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 The Open Group.



































































































































[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
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 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
accept  ICE  connections  (for  example,  a  session manager
accepting connections from clients).  But in general, proto-
col  libraries  should be designed to hide the inner details
of ICE from applications.






                            - 1 -





[1mInter-Client Exchange Library               X11, Release 6.8[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
defines 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
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.


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



                            - 2 -





[1mInter-Client Exchange Library               X11, Release 6.8[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
occurred.   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.

__
||





                            - 3 -





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


typedef struct {
     int major_version;
     int minor_version;
     IcePoProcessMsgProc process_msg_proc;
} IcePoVersionRec;

||__

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
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
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
interested 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,
[4mrelease[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.



                            - 4 -





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


[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.

[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
occurred.  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_version;
     IcePaProcessMsgProc process_msg_proc;
} IcePaVersionRec;





                            - 5 -





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


||__

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
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
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
invoked with the host name of the  originating  client.   If
the callback returns the will succeed, even though the orig-
inal authentication failed.  Note  that  authentication  can
effectively  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
response 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) ();




                            - 6 -





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


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;

[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.




                            - 7 -





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


[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
interested in being notified.  For further information,  see
section 13, ``Error Handling.''

[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.



                            - 8 -





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


||__

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)
    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
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 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






                            - 9 -





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


sent.  The reply_wait is of type
__
||
typedef struct {
     unsigned long sequence_of_request;
     int major_opcode_of_request;
     int minor_opcode_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
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
Request'' 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).




                           - 10 -





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


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

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:

+o    One to handle the side that initiates a

+o    One to handle the side that  accepts  or  rejects  this
     request

is  the  callback  invoked for the client that initiated the
This callback  must  be  able  to  respond  to  the  initial
``Authentication  Required'' message or subsequent ``Authen-
tication 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,
[4merror_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
          (depending 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.




                           - 11 -





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


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

[4merror_string_ret[0m
          If  the  authentication  procedure  encounters  an
          error 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
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,
[4merror_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;



                           - 12 -





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


[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.

[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.




                           - 13 -





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


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

[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.





                           - 14 -





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


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
     local/<hostname>:<path>


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
-----------
   The X Consortium's ICElib  implementation  uses
an .ICEauthority file (see Appendix A).



                           - 15 -





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


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.

[4mlisten_objs_ret[0m
          Returns  a  list  of  pointers  to  opaque  listen
          objects.

[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
          address(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
          objects.

[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.



                           - 16 -





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


          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
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 returns  fail-
ure.

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
object, use
__
||  char *IceGetListenConnectionString([4mlisten_obj[24m)
    IceListenObj [4mlisten_obj[24m;

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




                           - 17 -





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


||__


A network ID has the following format:

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


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

__
||  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.







                           - 18 -





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

__
||  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

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
     returns 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



                           - 19 -





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


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.

The following pseudo-code demonstrates how  connections  are
accepted:
















































                           - 20 -





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


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);
}


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).





                           - 21 -





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


[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
     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
     actually closed, will return a status of





                           - 22 -





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


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.
||__

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



                           - 23 -





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


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
library.  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

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








                           - 24 -





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


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)
    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.



                           - 25 -





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


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

[4mrelease_ret[0m
          The  release  string  specified  by  the  protocol
          acceptor.

[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.

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,
     release_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.





                           - 26 -





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


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,
[4mreply_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.
||__

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
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 up any  memory  allocated
on its behalf.



                           - 27 -





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

__
||
typedef struct {
     unsigned long sequence_of_request;
     int major_opcode_of_request;
     int minor_opcode_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

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

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

returns zero for failure and a positive value for success.





                           - 28 -





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


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
return values are:

+o    - the connection is not valid yet (that is, authentica-
     tion is taking place).  This is only relevant  to  con-
     nections 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.





                           - 29 -





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

__
||  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.

__
||  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




                           - 30 -





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


[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
buffer 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;

[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;



                           - 31 -





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


     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.


__
||  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).





                           - 32 -





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


[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
          buffer, 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.

[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;





                           - 33 -





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


[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
          after 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.

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







                           - 34 -





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

__
||  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;

[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
directly send data over the network connection.   If  neces-
sary, 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.




                           - 35 -





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


[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;

[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;




                           - 36 -





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


||__


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
opcode 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
involves  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;
     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.




                           - 37 -





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


||__

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.

[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.







                           - 38 -





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


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;
     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





                           - 39 -





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


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
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,



                           - 40 -





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


                     [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

__
||  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






                           - 41 -





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

__
||  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
because  each active protocol must be notified of the broken
connection, and the application IO  error  handler  must  be
invoked afterwards.

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

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







                           - 42 -





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

__
||  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;

[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.







                           - 43 -





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


[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
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.



























                           - 44 -





[1mInter-Client Exchange Library               X11, Release 6.8[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;
} IceAuthFileEntry;



-----------
   The  X   Consortium's   ICElib   implementation
assumes the presence of an ICE authority file.



                           - 45 -





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


||__

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 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:

lw(0.25i)  lw(2.5i)  lw(1i).        tcp/<hostname>:<portnum-
ber>   or                   decnet/<hostname>::<objname>  or
     local/<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.



                           - 46 -





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


||__

One of three values is returned:

+o    - the lock succeeded.

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

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



                           - 47 -





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


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;

[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.
||__





























                           - 48 -





[1mInter-Client Exchange Library               X11, Release 6.8[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,



                           - 49 -





[1mInter-Client Exchange Library               X11, Release 6.8[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
entries, based on the (protocol_name, network_id, auth_name)
tuple.

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

||__







































                           - 50 -


