








               IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy

                        VVeerrssiioonn 11..00

                   XX CCoonnssoorrttiiuumm SSttaannddaarrdd

                 XX VVeerrssiioonn 1111,, RReelleeaassee 66..44

                         _R_a_l_p_h _M_o_r
                        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.



































































































































11..  OOvveerrvviieeww ooff IICCEE

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.

22..  TThhee IICCEE LLiibbrraarryy -- CC LLaanngguuaaggee IInntteerrffaaccee ttoo IICCEE

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.

33..  IInntteennddeedd AAuuddiieennccee

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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


44..  HHeeaaddeerr FFiilleess aanndd LLiibbrraarryy NNaammee

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.

55..  NNoottee oonn PPrreeffiixxeess

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

66..  PPrroottooccooll RReeggiissttrraattiioonn

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(_p_r_o_t_o_c_o_l___n_a_m_e,    _v_e_n_d_o_r,
_r_e_l_e_a_s_e, _v_e_r_s_i_o_n___c_o_u_n_t, _v_e_r_s_i_o_n___r_e_c_s,
                 _a_u_t_h___c_o_u_n_t,     _a_u_t_h___n_a_m_e_s,     _a_u_t_h___p_r_o_c_s,
_i_o___e_r_r_o_r___p_r_o_c)
     char *_p_r_o_t_o_c_o_l___n_a_m_e;
     char *_v_e_n_d_o_r;
     char *_r_e_l_e_a_s_e;
     int _v_e_r_s_i_o_n___c_o_u_n_t;



                            - 2 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


     IcePoVersionRec *_v_e_r_s_i_o_n___r_e_c_s;
     int _a_u_t_h___c_o_u_n_t;
     char **_a_u_t_h___n_a_m_e_s;
     IcePoAuthProc *_a_u_t_h___p_r_o_c_s;
     IceIOErrorProc _i_o___e_r_r_o_r___p_r_o_c;

_p_r_o_t_o_c_o_l___n_a_m_e
          A  string  specifying  the name of the protocol to
          register.

_v_e_n_d_o_r    A vendor string with semantics  specified  by  the
          protocol.

_r_e_l_e_a_s_e   A  release  string with semantics specified by the
          protocol.

_v_e_r_s_i_o_n___c_o_u_n_t
          The number of different versions of  the  protocol
          supported.

_v_e_r_s_i_o_n___r_e_c_s
          List of versions and associated callbacks.

_a_u_t_h___c_o_u_n_t
          The number of authentication methods supported.

_a_u_t_h___n_a_m_e_s
          The list of authentication methods supported.

_a_u_t_h___p_r_o_c_s
          The list of authentication callbacks, one for each
          authentication method.

_i_o___e_r_r_o_r___p_r_o_c
          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.

__
||  typedef    struct   {        int   major_version;        int
minor_version;      IcePoProcessMsgProc process_msg_proc;  }
IcePoVersionRec;



                            - 3 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


||__

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(_p_r_o_t_o_c_o_l___n_a_m_e,    _v_e_n_d_o_r,
_r_e_l_e_a_s_e, _v_e_r_s_i_o_n___c_o_u_n_t, _v_e_r_s_i_o_n___r_e_c_s,
                    _a_u_t_h___c_o_u_n_t,    _a_u_t_h___n_a_m_e_s,   _a_u_t_h___p_r_o_c_s,
_h_o_s_t___b_a_s_e_d___a_u_t_h___p_r_o_c, _p_r_o_t_o_c_o_l___s_e_t_u_p___p_r_o_c,
                     _p_r_o_t_o_c_o_l___a_c_t_i_v_a_t_e___p_r_o_c, _i_o___e_r_r_o_r___p_r_o_c)
     char *_p_r_o_t_o_c_o_l___n_a_m_e;
     char *_v_e_n_d_o_r;
     char *_r_e_l_e_a_s_e;
     int _v_e_r_s_i_o_n___c_o_u_n_t;
     IcePaVersionRec *_v_e_r_s_i_o_n___r_e_c_s;
     int _a_u_t_h___c_o_u_n_t;
     char **_a_u_t_h___n_a_m_e_s;
     IcePaAuthProc *_a_u_t_h___p_r_o_c_s;
     IceHostBasedAuthProc _h_o_s_t___b_a_s_e_d___a_u_t_h___p_r_o_c;
     IceProtocolSetupProc _p_r_o_t_o_c_o_l___s_e_t_u_p___p_r_o_c;
     IceProtocolActivateProc _p_r_o_t_o_c_o_l___a_c_t_i_v_a_t_e___p_r_o_c;
     IceIOErrorProc _i_o___e_r_r_o_r___p_r_o_c;

_p_r_o_t_o_c_o_l___n_a_m_e
          A string specifying the name of  the  protocol  to
          register.

_v_e_n_d_o_r    A  vendor  string  with semantics specified by the
          protocol.

_r_e_l_e_a_s_e   A release string with semantics specified  by  the
          protocol.

_v_e_r_s_i_o_n___c_o_u_n_t
          The  number  of different versions of the protocol



                            - 4 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


          supported.

_v_e_r_s_i_o_n___r_e_c_s
          List of versions and associated callbacks.

_a_u_t_h___c_o_u_n_t
          The number of authentication methods supported.

_a_u_t_h___n_a_m_e_s
          The list of authentication methods supported.

_a_u_t_h___p_r_o_c_s
          The list of authentication callbacks, one for each
          authentication method.

_h_o_s_t___b_a_s_e_d___a_u_t_h___p_r_o_c
          Host based authentication callback.

_p_r_o_t_o_c_o_l___s_e_t_u_p___p_r_o_c
          A  callback  to be invoked when authentication has
          succeeded for a but before the is sent.

_p_r_o_t_o_c_o_l___a_c_t_i_v_a_t_e___p_r_o_c
          A callback to be invoked after the is sent.

_i_o___e_r_r_o_r___p_r_o_c
          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;
||__

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



                            - 5 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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(_h_o_s_t___n_a_m_e)
    char *_h_o_s_t___n_a_m_e;

_h_o_s_t___n_a_m_e The host name of the client that sent the
||__

The   host_name   argument   is   a   string   of  the  form
_p_r_o_t_o_c_o_l/_h_o_s_t_n_a_m_e, where _p_r_o_t_o_c_o_l 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   proto-
col_activate_proc if not interested in this callback.
__
||  typedef Status (*IceProtocolSetupProc) ();

Status       ProtocolSetupProc(_i_c_e___c_o_n_n,      _m_a_j_o_r___v_e_r_s_i_o_n,
_m_i_n_o_r___v_e_r_s_i_o_n, _v_e_n_d_o_r, _r_e_l_e_a_s_e,
                    _c_l_i_e_n_t___d_a_t_a___r_e_t, _f_a_i_l_u_r_e___r_e_a_s_o_n___r_e_t)
     IceConn _i_c_e___c_o_n_n;
     int _m_a_j_o_r___v_e_r_s_i_o_n;
     int _m_i_n_o_r___v_e_r_s_i_o_n;
     char *_v_e_n_d_o_r;
     char *_r_e_l_e_a_s_e;
     IcePointer *_c_l_i_e_n_t___d_a_t_a___r_e_t;



                            - 6 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


     char **_f_a_i_l_u_r_e___r_e_a_s_o_n___r_e_t;

_i_c_e___c_o_n_n  The ICE connection object.

_m_a_j_o_r___v_e_r_s_i_o_n
          The major version of the protocol.

_m_i_n_o_r___v_e_r_s_i_o_n
          The minor version of the protocol.

_v_e_n_d_o_r    The vendor string registered by the protocol orig-
          inator.

_r_e_l_e_a_s_e   The  release  string  registered  by  the protocol
          originator.

_c_l_i_e_n_t___d_a_t_a___r_e_t
          Client data to be set by callback.

_f_a_i_l_u_r_e___r_e_a_s_o_n___r_e_t
          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(_i_c_e___c_o_n_n, _c_l_i_e_n_t___d_a_t_a)
    IceConn _i_c_e___c_o_n_n;
    IcePointer _c_l_i_e_n_t___d_a_t_a;

_i_c_e___c_o_n_n  The ICE connection object.

_c_l_i_e_n_t___d_a_t_a
          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.''




                            - 7 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


66..11..  CCaallllbbaacckkss ffoorr PPrroocceessssiinngg MMeessssaaggeess

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(_i_c_e___c_o_n_n, _c_l_i_e_n_t___d_a_t_a, _o_p_c_o_d_e, _l_e_n_g_t_h,
_s_w_a_p, _r_e_p_l_y___w_a_i_t, _r_e_p_l_y___r_e_a_d_y___r_e_t)
    IceConn _i_c_e___c_o_n_n;
    IcePointer _c_l_i_e_n_t___d_a_t_a;
    int _o_p_c_o_d_e;
    unsigned long _l_e_n_g_t_h;
    Bool _s_w_a_p;
    IceReplyWaitInfo *_r_e_p_l_y___w_a_i_t;
    Bool *_r_e_p_l_y___r_e_a_d_y___r_e_t;

_i_c_e___c_o_n_n  The ICE connection object.

_c_l_i_e_n_t___d_a_t_a
          Client  data  associated with this protocol on the
          ICE connection.

_o_p_c_o_d_e    The minor opcode of the message.

_l_e_n_g_t_h    The length (in 8-byte units) of the message beyond
          the ICE header.

_s_w_a_p      A  flag  that indicates if byte swapping is neces-
          sary.

_r_e_p_l_y___w_a_i_t
          Indicates if the invoking client is waiting for  a
          reply.

_r_e_p_l_y___r_e_a_d_y___r_e_t
          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(_i_c_e___c_o_n_n, _c_l_i_e_n_t___d_a_t_a, _o_p_c_o_d_e, _l_e_n_g_t_h,
_s_w_a_p)



                            - 8 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


    IceConn _i_c_e___c_o_n_n;
    IcePointer _c_l_i_e_n_t___d_a_t_a;
    int _o_p_c_o_d_e;
    unsigned long _l_e_n_g_t_h;
    Bool _s_w_a_p;

_i_c_e___c_o_n_n  The ICE connection object.

_c_l_i_e_n_t___d_a_t_a
          Client  data  associated with this protocol on the
          ICE connection.

_o_p_c_o_d_e    The minor opcode of the message.

_l_e_n_g_t_h    The length (in 8-byte units) of the message beyond
          the ICE header.

_s_w_a_p      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
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; } IceReply-
WaitInfo;
||__

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



                            - 9 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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

66..22..  AAuutthheennttiiccaattiioonn MMeetthhooddss

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-




                           - 10 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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

IcePoAuthStatus     PoAuthProc(_i_c_e___c_o_n_n,     _a_u_t_h___s_t_a_t_e___p_t_r,
_c_l_e_a_n___u_p, _s_w_a_p, _a_u_t_h___d_a_t_a_l_e_n, _a_u_t_h___d_a_t_a,
                    _r_e_p_l_y___d_a_t_a_l_e_n___r_e_t,       _r_e_p_l_y___d_a_t_a___r_e_t,
_e_r_r_o_r___s_t_r_i_n_g___r_e_t)
    IceConn _i_c_e___c_o_n_n;
    IcePointer *_a_u_t_h___s_t_a_t_e___p_t_r;
    Bool _c_l_e_a_n___u_p;
    Bool _s_w_a_p;
    int _a_u_t_h___d_a_t_a_l_e_n;
    IcePointer _a_u_t_h___d_a_t_a;
    int *_r_e_p_l_y___d_a_t_a_l_e_n___r_e_t;
    IcePointer *_r_e_p_l_y___d_a_t_a___r_e_t;
    char **_e_r_r_o_r___s_t_r_i_n_g___r_e_t;

_i_c_e___c_o_n_n  The ICE connection object.

_a_u_t_h___s_t_a_t_e___p_t_r
          A  pointer  to state for use by the authentication
          callback procedure.

_c_l_e_a_n___u_p  If authentication is over, and the function should
          clean up any state it was maintaining.  The last 6
          arguments should be ignored.

_s_w_a_p      If the auth_data  may  have  to  be  byte  swapped
          (depending on its contents).

_a_u_t_h___d_a_t_a_l_e_n
          The length (in bytes) of the authenticator data.

_a_u_t_h___d_a_t_a The data from the authenticator.

_r_e_p_l_y___d_a_t_a_l_e_n___r_e_t
          The  length (in bytes) of the reply data returned.

_r_e_p_l_y___d_a_t_a___r_e_t
          The reply data returned.

_e_r_r_o_r___s_t_r_i_n_g___r_e_t
          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



                           - 11 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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(_i_c_e___c_o_n_n,  _a_u_t_h___s_t_a_t_e___p_t_r, _s_w_a_p,
_a_u_t_h___d_a_t_a_l_e_n, _a_u_t_h___d_a_t_a,
                    _r_e_p_l_y___d_a_t_a_l_e_n___r_e_t,       _r_e_p_l_y___d_a_t_a___r_e_t,
_e_r_r_o_r___s_t_r_i_n_g___r_e_t)
    IceConn _i_c_e___c_o_n_n;
    IcePointer *_a_u_t_h___s_t_a_t_e___p_t_r;
    Bool _s_w_a_p;
    int _a_u_t_h___d_a_t_a_l_e_n;
    IcePointer _a_u_t_h___d_a_t_a;
    int *_r_e_p_l_y___d_a_t_a_l_e_n___r_e_t;
    IcePointer *_r_e_p_l_y___d_a_t_a___r_e_t;
    char **_e_r_r_o_r___s_t_r_i_n_g___r_e_t;

_i_c_e___c_o_n_n  The ICE connection object.

_a_u_t_h___s_t_a_t_e___p_t_r
          A  pointer  to state for use by the authentication
          callback procedure.

_s_w_a_p      If auth_data may have to be byte swapped  (depend-
          ing on its contents).

_a_u_t_h___d_a_t_a_l_e_n
          The  length  (in bytes) of the protocol originator
          authentication data.





                           - 12 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_a_u_t_h___d_a_t_a The authentication data from the protocol origina-
          tor.

_r_e_p_l_y___d_a_t_a_l_e_n___r_e_t
          The length of the authentication data returned.

_r_e_p_l_y___d_a_t_a___r_e_t
          The authentication data returned.

_e_r_r_o_r___s_t_r_i_n_g___r_e_t
          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.

77..  IICCEE CCoonnnneeccttiioonnss

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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


77..11..  OOppeenniinngg aann IICCEE CCoonnnneeccttiioonn

To  open  an  ICE  connection  with another client (that is,
waiting for connections), use
__
||  IceConn     IceOpenConnection(_n_e_t_w_o_r_k___i_d_s___l_i_s_t,     _c_o_n_t_e_x_t,
_m_u_s_t___a_u_t_h_e_n_t_i_c_a_t_e, _m_a_j_o_r___o_p_c_o_d_e___c_h_e_c_k,
                    _e_r_r_o_r___l_e_n_g_t_h, _e_r_r_o_r___s_t_r_i_n_g___r_e_t)
     char *_n_e_t_w_o_r_k___i_d_s___l_i_s_t;
     IcePointer _c_o_n_t_e_x_t;
     Bool _m_u_s_t___a_u_t_h_e_n_t_i_c_a_t_e;
     int _m_a_j_o_r___o_p_c_o_d_e___c_h_e_c_k;
     int  _e_r_r_o_r___l_e_n_g_t_h;
     char *_e_r_r_o_r___s_t_r_i_n_g___r_e_t;

_n_e_t_w_o_r_k___i_d_s___l_i_s_t
          Specifies the network ID(s) of the other client.

_c_o_n_t_e_x_t   A  pointer  to  an opaque object or NULL.  Used to
          determine if an ICE connection can be shared  (see
          below).

_m_u_s_t___a_u_t_h_e_n_t_i_c_a_t_e
          If the other client may not bypass authentication.

_m_a_j_o_r___o_p_c_o_d_e___c_h_e_c_k
          Used to force a new ICE connection to  be  created
          (see below).

_e_r_r_o_r___l_e_n_g_t_h
          Length of the error_string_ret argument passed in.

_e_r_r_o_r___s_t_r_i_n_g___r_e_t
          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>:<portnumber>   or
     decnet/<hostname>::<objname>  or
     local/<hostname>:<path>





                           - 14 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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

77..22..  LLiisstteenniinngg ffoorr IICCEE CCoonnnneeccttiioonnss

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(_c_o_u_n_t___r_e_t,  _l_i_s_t_e_n___o_b_j_s___r_e_t,
_e_r_r_o_r___l_e_n_g_t_h, _e_r_r_o_r___s_t_r_i_n_g___r_e_t)
     int  *_c_o_u_n_t___r_e_t;
     IceListenObj **_l_i_s_t_e_n___o_b_j_s___r_e_t;
     int  _e_r_r_o_r___l_e_n_g_t_h;
     char *_e_r_r_o_r___s_t_r_i_n_g___r_e_t;

_c_o_u_n_t___r_e_t Returns the number of listen objects created.

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



                           - 15 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_l_i_s_t_e_n___o_b_j_s___r_e_t
          Returns  a  list  of  pointers  to  opaque  listen
          objects.

_e_r_r_o_r___l_e_n_g_t_h
          The length of the error_string_ret argument passed
          in.

_e_r_r_o_r___s_t_r_i_n_g___r_e_t
          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(_p_o_r_t___i_d, _c_o_u_n_t___r_e_t,
_l_i_s_t_e_n___o_b_j_s___r_e_t, _e_r_r_o_r___l_e_n_g_t_h, _e_r_r_o_r___s_t_r_i_n_g___r_e_t)
     char *_p_o_r_t___i_d;
     int  *_c_o_u_n_t___r_e_t;
     IceListenObj **_l_i_s_t_e_n___o_b_j_s___r_e_t;
     int  _e_r_r_o_r___l_e_n_g_t_h;
     char *_e_r_r_o_r___s_t_r_i_n_g___r_e_t;

_p_o_r_t___i_d   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.

_c_o_u_n_t___r_e_t Returns the number of listen objects created.

_l_i_s_t_e_n___o_b_j_s___r_e_t
          Returns  a  list  of  pointers  to  opaque  listen
          objects.

_e_r_r_o_r___l_e_n_g_t_h
          The length of the error_string_ret argument passed
          in.

_e_r_r_o_r___s_t_r_i_n_g___r_e_t
          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
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.



                           - 16 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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


To close and free the listen objects, use

__
||  void IceFreeListenObjs(_c_o_u_n_t, _l_i_s_t_e_n___o_b_j_s)
    int _c_o_u_n_t;
    IceListenObj *_l_i_s_t_e_n___o_b_j_s;

_c_o_u_n_t     The number of listen objects.

_l_i_s_t_e_n___o_b_j_s
          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(_l_i_s_t_e_n___o_b_j)
    IceListenObj _l_i_s_t_e_n___o_b_j;

_l_i_s_t_e_n___o_b_j
          The listen object.
||__


To  obtain  the  network  ID string associated with a listen
object, use
__
||  char *IceGetListenConnectionString(_l_i_s_t_e_n___o_b_j)
    IceListenObj _l_i_s_t_e_n___o_b_j;

_l_i_s_t_e_n___o_b_j
          The listen object.
||__


A network ID has the following format:

lw(0.25i)                  lw(2.5i)                  lw(1i).
     tcp/<hostname>:<portnumber>   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



                           - 17 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44

__
||  char *IceComposeNetworkIdList(_c_o_u_n_t, _l_i_s_t_e_n___o_b_j_s)
    int _c_o_u_n_t;
    IceListenObj *_l_i_s_t_e_n___o_b_j_s;

_c_o_u_n_t     The number of listen objects.

_l_i_s_t_e_n___o_b_j_s
          The listen objects.
||__


77..33..  HHoosstt BBaasseedd AAuutthheennttiiccaattiioonn ffoorr IICCEE CCoonnnneeccttiioonnss

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(_l_i_s_t_e_n___o_b_j,
_h_o_s_t___b_a_s_e_d___a_u_t_h___p_r_o_c)
    IceListenObj _l_i_s_t_e_n___o_b_j;
    IceHostBasedAuthProc _h_o_s_t___b_a_s_e_d___a_u_t_h___p_r_o_c;

_l_i_s_t_e_n___o_b_j
          The listen object.

_h_o_s_t___b_a_s_e_d___a_u_t_h___p_r_o_c
          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(_h_o_s_t___n_a_m_e)
    char *_h_o_s_t___n_a_m_e;

_h_o_s_t___n_a_m_e The host name of the client that tried to open  an
          ICE connection.
||__

The   host_name   argument   is   a   string   in  the  form
_p_r_o_t_o_c_o_l/_h_o_s_t_n_a_m_e, where _p_r_o_t_o_c_o_l 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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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

77..44..  AAcccceeppttiinngg IICCEE CCoonnnneeccttiioonnss

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(_l_i_s_t_e_n___o_b_j, _s_t_a_t_u_s___r_e_t)
    IceListenObj _l_i_s_t_e_n___o_b_j;
    IceAcceptStatus *_s_t_a_t_u_s___r_e_t;

_l_i_s_t_e_n___o_b_j
          The  listen  object  on which a new connection was
          detected.

_s_t_a_t_u_s___r_e_t
          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 pend-
ing 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:

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;



                           - 19 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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

77..55..  CClloossiinngg IICCEE CCoonnnneeccttiioonnss

To close an ICE connection created with or use
__
||  IceCloseStatus IceCloseConnection(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;

_i_c_e___c_o_n_n  The ICE connection to close.
||__

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

+o    The _o_p_e_n _r_e_f_e_r_e_n_c_e _c_o_u_n_t 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 _a_c_t_i_v_e _p_r_o_t_o_c_o_l _c_o_u_n_t 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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


     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


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(_i_c_e___c_o_n_n, _n_e_g_o_t_i_a_t_e)
    IceConn _i_c_e___c_o_n_n;
    Bool _n_e_g_o_t_i_a_t_e;

_i_c_e___c_o_n_n  A valid ICE connection object.

_n_e_g_o_t_i_a_t_e If shutdown negotiating will be turned off.
||__


To check the shutdown negotiation status of an  ICE  connec-
tion, use
__
||  Bool IceCheckShutdownNegotiation(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;

_i_c_e___c_o_n_n  A valid ICE connection object.




                           - 21 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


||__

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.

77..66..  CCoonnnneeccttiioonn WWaattcchh PPrroocceedduurreess

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(_w_a_t_c_h___p_r_o_c, _c_l_i_e_n_t___d_a_t_a)
    IceWatchProc _w_a_t_c_h___p_r_o_c;
    IcePointer _c_l_i_e_n_t___d_a_t_a;

_w_a_t_c_h___p_r_o_c
          The watch procedure to invoke when ICElib opens or
          closes a connection.

_c_l_i_e_n_t___d_a_t_a
          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
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






                           - 22 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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

void WatchProc(_i_c_e___c_o_n_n, _c_l_i_e_n_t___d_a_t_a, _o_p_e_n_i_n_g, _w_a_t_c_h___d_a_t_a)
    IceConn _i_c_e___c_o_n_n;
    IcePointer _c_l_i_e_n_t___d_a_t_a;
    Bool _o_p_e_n_i_n_g;
    IcePointer *_w_a_t_c_h___d_a_t_a;

_i_c_e___c_o_n_n  The  opened or closed ICE connection.  Call to get
          the file descriptor associated with  this  connec-
          tion.

_c_l_i_e_n_t___d_a_t_a
          Client data specified in the call to

_o_p_e_n_i_n_g   If the connection is being opened.  If the connec-
          tion is being closed.

_w_a_t_c_h___d_a_t_a
          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(_w_a_t_c_h___p_r_o_c, _c_l_i_e_n_t___d_a_t_a)
    IceWatchProc _w_a_t_c_h___p_r_o_c;
    IcePointer _c_l_i_e_n_t___d_a_t_a;


_w_a_t_c_h___p_r_o_c
          The watch procedure that was passed to

_c_l_i_e_n_t___d_a_t_a
          The client_data pointer that was passed to
||__


88..  PPrroottooccooll SSeettuupp aanndd SShhuuttddoowwnn

To activate a protocol on a given ICE connection, use

__
||  IceProtocolSetupStatus IceProtocolSetup(_i_c_e___c_o_n_n, _m_y___o_p_c_o_d_e,
_c_l_i_e_n_t___d_a_t_a, _m_u_s_t___a_u_t_h_e_n_t_i_c_a_t_e,
                    _m_a_j_o_r___v_e_r_s_i_o_n___r_e_t,    _m_i_n_o_r___v_e_r_s_i_o_n___r_e_t,
_v_e_n_d_o_r___r_e_t, _r_e_l_e_a_s_e___r_e_t, _e_r_r_o_r___l_e_n_g_t_h, _e_r_r_o_r___s_t_r_i_n_g___r_e_t)



                           - 23 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


    IceConn _i_c_e___c_o_n_n;
    int _m_y___o_p_c_o_d_e;
    IcePointer _c_l_i_e_n_t___d_a_t_a;
    Bool _m_u_s_t___a_u_t_h_e_n_t_i_c_a_t_e;
    int *_m_a_j_o_r___v_e_r_s_i_o_n___r_e_t;
    int *_m_i_n_o_r___v_e_r_s_i_o_n___r_e_t;
    char **_v_e_n_d_o_r___r_e_t;
    char **_r_e_l_e_a_s_e___r_e_t;
    int _e_r_r_o_r___l_e_n_g_t_h;
    char *_e_r_r_o_r___s_t_r_i_n_g___r_e_t;

_i_c_e___c_o_n_n  A valid ICE connection object.

_m_y___o_p_c_o_d_e The  major opcode of the protocol to be set up, as
          returned by

_c_l_i_e_n_t___d_a_t_a
          The client data stored in  this  pointer  will  be
          passed to the callback.

_m_u_s_t___a_u_t_h_e_n_t_i_c_a_t_e
          If the other client may not bypass authentication.

_m_a_j_o_r___v_e_r_s_i_o_n___r_e_t
          The major version of the protocol to  be  used  is
          returned.

_m_i_n_o_r___v_e_r_s_i_o_n___r_e_t
          The  minor  version  of the protocol to be used is
          returned.

_v_e_n_d_o_r___r_e_t
          The vendor string specified by the protocol accep-
          tor.

_r_e_l_e_a_s_e___r_e_t
          The  release  string  specified  by  the  protocol
          acceptor.

_e_r_r_o_r___l_e_n_g_t_h
          Specifies the length of the error_string_ret argu-
          ment passed in.

_e_r_r_o_r___s_t_r_i_n_g___r_e_t
          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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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(_i_c_e___c_o_n_n, _m_a_j_o_r___o_p_c_o_d_e)
    IceConn _i_c_e___c_o_n_n;
    int _m_a_j_o_r___o_p_c_o_d_e;

_i_c_e___c_o_n_n  A valid ICE connection object.

_m_a_j_o_r___o_p_c_o_d_e
          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.

99..  PPrroocceessssiinngg MMeessssaaggeess

To process incoming messages on an ICE connection, use
__
||  IceProcessMessagesStatus        IceProcessMessages(_i_c_e___c_o_n_n,
_r_e_p_l_y___w_a_i_t, _r_e_p_l_y___r_e_a_d_y___r_e_t)
    IceConn _i_c_e___c_o_n_n;
    IceReplyWaitInfo *_r_e_p_l_y___w_a_i_t;
    Bool *_r_e_p_l_y___r_e_a_d_y___r_e_t;

_i_c_e___c_o_n_n  A valid ICE connection object.

_r_e_p_l_y___w_a_i_t
          Indicates if a reply is being waited for.

_r_e_p_l_y___r_e_a_d_y___r_e_t
          If set to on return, a reply is ready.



                           - 25 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


||__

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.

__
||  typedef  struct  {       unsigned  long sequence_of_request;
     int          major_opcode_of_request;               int
minor_opcode_of_request;       IcePointer reply; } IceReply-
WaitInfo;
||__

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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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

1100..  PPiinngg

To send a ``Ping'' message to the client on the  other  side
of the ICE connection, use
__
||  Status IcePing(_i_c_e___c_o_n_n, _p_i_n_g___r_e_p_l_y___p_r_o_c, _c_l_i_e_n_t___d_a_t_a)
    IceConn _i_c_e___c_o_n_n;
    IcePingReplyProc _p_i_n_g___r_e_p_l_y___p_r_o_c;
    IcePointer _c_l_i_e_n_t___d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_p_i_n_g___r_e_p_l_y___p_r_o_c
          The   callback  to  invoke  when  the  Ping  reply
          arrives.

_c_l_i_e_n_t___d_a_t_a
          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(_i_c_e___c_o_n_n, _c_l_i_e_n_t___d_a_t_a)
    IceConn _i_c_e___c_o_n_n;
    IcePointer _c_l_i_e_n_t___d_a_t_a;

_i_c_e___c_o_n_n  The ICE connection object.

_c_l_i_e_n_t___d_a_t_a
          The client data specified in the call to
||__


1111..  UUssiinngg IICCEElliibb IInnffoorrmmaattiioonnaall FFuunnccttiioonnss

__
||  IceConnectStatus IceConnectionStatus(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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



                           - 27 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


     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(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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

__
||  int IceProtocolRevision(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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

__
||  int IceConnectionNumber(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

returns the file descriptor of this ICE connection.

__
||  char *IceConnectionString(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44

__
||  unsigned long IceLastSentSequenceNumber(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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

__
||  unsigned long IceLastReceivedSequenceNumber(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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

__
||  Bool IceSwapping(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

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

__
||  IcePointer IceGetContext(_i_c_e___c_o_n_n)
||__    IceConn _i_c_e___c_o_n_n;

returns the context associated with a connection created by

1122..  IICCEE MMeessssaaggeess

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.

1122..11..  SSeennddiinngg IICCEE MMeessssaaggeess

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(_i_c_e___c_o_n_n)
     IceConn _i_c_e___c_o_n_n;



                           - 29 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_i_c_e___c_o_n_n  A valid ICE connection object.
||__


To flush the ICE output buffer, use
__
||  IceFlush(_i_c_e___c_o_n_n)
     IceConn _i_c_e___c_o_n_n;

_i_c_e___c_o_n_n  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(_i_c_e___c_o_n_n,      _m_a_j_o_r___o_p_c_o_d_e,      _m_i_n_o_r___o_p_c_o_d_e,
_h_e_a_d_e_r___s_i_z_e, _<_C___d_a_t_a___t_y_p_e_>, _p_m_s_g)
     IceConn _i_c_e___c_o_n_n;
     int _m_a_j_o_r___o_p_c_o_d_e;
     int _m_i_n_o_r___o_p_c_o_d_e;
     int _h_e_a_d_e_r___s_i_z_e;
     <C_data_type> *_p_m_s_g;

_i_c_e___c_o_n_n  A valid ICE connection object.

_m_a_j_o_r___o_p_c_o_d_e
          The major opcode of the message.

_m_i_n_o_r___o_p_c_o_d_e
          The minor opcode of the message.

_h_e_a_d_e_r___s_i_z_e
          The size of the message header (in bytes).

_<_C___d_a_t_a___t_y_p_e_>
          The actual C data type of the message header.

_p_m_s_g      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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44

__
||  IceGetHeaderExtra(_i_c_e___c_o_n_n,   _m_a_j_o_r___o_p_c_o_d_e,    _m_i_n_o_r___o_p_c_o_d_e,
_h_e_a_d_e_r___s_i_z_e, _e_x_t_r_a, _<_C___d_a_t_a___t_y_p_e_>, _p_m_s_g, _p_d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     int _m_a_j_o_r___o_p_c_o_d_e;
     int _m_i_n_o_r___o_p_c_o_d_e;
     int _h_e_a_d_e_r___s_i_z_e;
     int _e_x_t_r_a;
     <C_data_type> *_p_m_s_g;
     char *_p_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_m_a_j_o_r___o_p_c_o_d_e
          The major opcode of the message.

_m_i_n_o_r___o_p_c_o_d_e
          The minor opcode of the message.

_h_e_a_d_e_r___s_i_z_e
          The size of the message header (in bytes).

_e_x_t_r_a     The  size  of the extra data beyond the header (in
          8-byte units).

_<_C___d_a_t_a___t_y_p_e_>
          The actual C data type of the message header.

_p_m_s_g      The message header pointer.  After this  macro  is
          called,  the library can store data in the message
          header.

_p_d_a_t_a     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(_i_c_e___c_o_n_n, _m_a_j_o_r___o_p_c_o_d_e, _m_i_n_o_r___o_p_c_o_d_e)
     IceConn _i_c_e___c_o_n_n;
     int _m_a_j_o_r___o_p_c_o_d_e;
     int _m_i_n_o_r___o_p_c_o_d_e;

_i_c_e___c_o_n_n  A valid ICE connection object.

_m_a_j_o_r___o_p_c_o_d_e
          The major opcode of the message.




                           - 31 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_m_i_n_o_r___o_p_c_o_d_e
          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(_i_c_e___c_o_n_n,             _o_f_f_e_n_d_i_n_g___m_a_j_o_r___o_p_c_o_d_e,
_o_f_f_e_n_d_i_n_g___m_i_n_o_r___o_p_c_o_d_e, _o_f_f_e_n_d_i_n_g___s_e_q_u_e_n_c_e___n_u_m,
                    _s_e_v_e_r_i_t_y, _e_r_r_o_r___c_l_a_s_s, _d_a_t_a___l_e_n_g_t_h)
     IceConn _i_c_e___c_o_n_n;
     int _o_f_f_e_n_d_i_n_g___m_a_j_o_r___o_p_c_o_d_e;
     int _o_f_f_e_n_d_i_n_g___m_i_n_o_r___o_p_c_o_d_e;
     int _o_f_f_e_n_d_i_n_g___s_e_q_u_e_n_c_e___n_u_m;
     int _s_e_v_e_r_i_t_y;
     int _e_r_r_o_r___c_l_a_s_s;
     int _d_a_t_a___l_e_n_g_t_h;

_i_c_e___c_o_n_n  A valid ICE connection object.

_o_f_f_e_n_d_i_n_g___m_a_j_o_r___o_p_c_o_d_e
          The major opcode of the protocol in which an error
          was detected.

_o_f_f_e_n_d_i_n_g___m_i_n_o_r___o_p_c_o_d_e
          The minor opcode of the protocol in which an error
          was detected.

_o_f_f_e_n_d_i_n_g___s_e_q_u_e_n_c_e___n_u_m
          The sequence number of the message that caused the
          error.

_s_e_v_e_r_i_t_y  or

_e_r_r_o_r___c_l_a_s_s
          The error class.

_d_a_t_a___l_e_n_g_t_h
          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  _I_n_t_e_r_-_C_l_i_e_n_t
_E_x_c_h_a_n_g_e _P_r_o_t_o_c_o_l standard for more details.



                           - 32 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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(_i_c_e___c_o_n_n, _b_y_t_e_s, _d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     int _b_y_t_e_s;
     char *_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_b_y_t_e_s     The number of bytes to write.

_d_a_t_a      The data to write.
||__


To write data as 16-bit quantities, use
__
||  IceWriteData16(_i_c_e___c_o_n_n, _b_y_t_e_s, _d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     int _b_y_t_e_s;
     short *_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_b_y_t_e_s     The number of bytes to write.

_d_a_t_a      The data to write.
||__


To write data as 32-bit quantities, use
__
||  IceWriteData32(_i_c_e___c_o_n_n, _b_y_t_e_s, _d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     int _b_y_t_e_s;
     long *_d_a_t_a;





                           - 33 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_i_c_e___c_o_n_n  A valid ICE connection object.

_b_y_t_e_s     The number of bytes to write.

_d_a_t_a      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(_i_c_e___c_o_n_n, _b_y_t_e_s, _(_c_h_a_r _*_) _d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     int _b_y_t_e_s;
     char *_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_b_y_t_e_s     The number of bytes to send.

_d_a_t_a      The data to send.
||__


To  force 32-bit or 64-bit alignment, use A maximum of 7 pad
bytes can be specified.
__
||  IceWritePad(_i_c_e___c_o_n_n, _b_y_t_e_s)
     IceConn _i_c_e___c_o_n_n;
     int _b_y_t_e_s;

_i_c_e___c_o_n_n  A valid ICE connection object.

_b_y_t_e_s     The number of pad bytes.
||__


1122..22..  RReeaaddiinngg IICCEE MMeessssaaggeess

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(_i_c_e___c_o_n_n)
     IceConn _i_c_e___c_o_n_n;



                           - 34 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_i_c_e___c_o_n_n  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(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;
||__


The following macros can be used to read ICE messages.
__
||  IceReadSimpleMessage(_i_c_e___c_o_n_n, _<_C___d_a_t_a___t_y_p_e_>, _p_m_s_g)
     IceConn _i_c_e___c_o_n_n;
     <C_data_type> *_p_m_s_g;

_i_c_e___c_o_n_n  A valid ICE connection object.

_<_C___d_a_t_a___t_y_p_e_>
          The actual C data type of the message header.

_p_m_s_g      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(_i_c_e___c_o_n_n, _h_e_a_d_e_r___s_i_z_e, _<_C___d_a_t_a___t_y_p_e_>,
_p_m_s_g, _p_d_a_t_a)
     IceConn _i_c_e___c_o_n_n;



                           - 35 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


     int _h_e_a_d_e_r___s_i_z_e;
     <C_data_type> *_p_m_s_g;
     char *_p_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_h_e_a_d_e_r___s_i_z_e
          The size of the message header (in bytes).

_<_C___d_a_t_a___t_y_p_e_>
          The actual C data type of the message header.

_p_m_s_g      This pointer is set to the message header.

_p_d_a_t_a     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(_i_c_e___c_o_n_n, _p_d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     char *_p_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_p_d_a_t_a     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(_i_c_e___c_o_n_n,  _h_e_a_d_e_r___s_i_z_e,  _<_C___d_a_t_a___t_y_p_e_>,
_p_m_s_g)
     IceConn _i_c_e___c_o_n_n;
     int _h_e_a_d_e_r___s_i_z_e;
     <C_data_type> *_p_m_s_g;

_i_c_e___c_o_n_n  A valid ICE connection object.





                           - 36 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_h_e_a_d_e_r___s_i_z_e
          The size of the message header (in bytes).

_<_C___d_a_t_a___t_y_p_e_>
          The actual C data type of the message header.

_p_m_s_g      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(_i_c_e___c_o_n_n, _b_y_t_e_s, _p_d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     int _b_y_t_e_s;
     char *_p_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_b_y_t_e_s     The number of bytes to read.

_p_d_a_t_a     The data is read into this user supplied buffer.
||__


To read data as 16-bit quantities, use
__
||  IceReadData16(_i_c_e___c_o_n_n, _s_w_a_p, _b_y_t_e_s, _p_d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     Bool _s_w_a_p;
     int _b_y_t_e_s;
     short *_p_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_s_w_a_p      If the values will be byte swapped.

_b_y_t_e_s     The number of bytes to read.

_p_d_a_t_a     The data is read into this user supplied buffer.
||__


To read data as 32-bit quantities, use
__
||  IceReadData32(_i_c_e___c_o_n_n, _s_w_a_p, _b_y_t_e_s, _p_d_a_t_a)
     IceConn _i_c_e___c_o_n_n;
     Bool _s_w_a_p;
     int _b_y_t_e_s;



                           - 37 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


     long *_p_d_a_t_a;

_i_c_e___c_o_n_n  A valid ICE connection object.

_s_w_a_p      If the values will be byte swapped.

_b_y_t_e_s     The number of bytes to read.

_p_d_a_t_a     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(_i_c_e___c_o_n_n, _b_y_t_e_s)
     IceConn _i_c_e___c_o_n_n;
     int _b_y_t_e_s;

_i_c_e___c_o_n_n  A valid ICE connection object.

_b_y_t_e_s     The number of pad bytes.
||__


1133..  EErrrroorr HHaannddlliinngg

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(_h_a_n_d_l_e_r)
    IceErrorHandler _h_a_n_d_l_e_r;

_h_a_n_d_l_e_r   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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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(_i_c_e___c_o_n_n,  _s_w_a_p,  _o_f_f_e_n_d_i_n_g___m_i_n_o_r___o_p_c_o_d_e,
_o_f_f_e_n_d_i_n_g___s_e_q_u_e_n_c_e___n_u_m, _e_r_r_o_r___c_l_a_s_s,
                     _s_e_v_e_r_i_t_y, _v_a_l_u_e_s)
    IceConn _i_c_e___c_o_n_n;
    Bool _s_w_a_p;
    int _o_f_f_e_n_d_i_n_g___m_i_n_o_r___o_p_c_o_d_e;
    unsigned long _o_f_f_e_n_d_i_n_g___s_e_q_u_e_n_c_e___n_u_m;
    int _e_r_r_o_r___c_l_a_s_s;
    int _s_e_v_e_r_i_t_y;
    IcePointer _v_a_l_u_e_s;

_i_c_e___c_o_n_n  The ICE connection object.

_s_w_a_p      A  flag  that  indicates  if  the values need byte
          swapping.

_o_f_f_e_n_d_i_n_g___m_i_n_o_r___o_p_c_o_d_e
          The ICE minor opcode of the offending message.

_o_f_f_e_n_d_i_n_g___s_e_q_u_e_n_c_e___n_u_m
          The sequence number of the offending message.

_e_r_r_o_r___c_l_a_s_s
          The error class of the offending message.

_s_e_v_e_r_i_t_y  or

_v_a_l_u_e_s    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 _I_n_t_e_r_-_C_l_i_e_n_t _E_x_c_h_a_n_g_e _P_r_o_-
_t_o_c_o_l standard.


To handle fatal I/O errors, use







                           - 39 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44

__
||  IceIOErrorHandler IceSetIOErrorHandler(_h_a_n_d_l_e_r)
    IceIOErrorHandler _h_a_n_d_l_e_r;

_h_a_n_d_l_e_r   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(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;

_i_c_e___c_o_n_n  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(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;

_i_c_e___c_o_n_n  The ICE connection object.
||__

Note that every callback  must  return.   This  is  required



                           - 40 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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

1144..  MMuullttii--TThhrreeaaddiinngg SSuuppppoorrtt

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(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;

IceUnlockConn(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;

_i_c_e___c_o_n_n  The ICE connection.
||__


To keep an  ICE  connection  locked  across  several  ICElib
calls, applications use and
__
||  void IceAppLockConn(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;

_i_c_e___c_o_n_n  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(_i_c_e___c_o_n_n)
    IceConn _i_c_e___c_o_n_n;





                           - 41 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_i_c_e___c_o_n_n  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.

1155..  MMiisscceellllaanneeoouuss FFuunnccttiioonnss

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(_i_c_e___c_o_n_n, _s_i_z_e)
    IceConn _i_c_e___c_o_n_n;
    unsigned long _s_i_z_e;

_i_c_e___c_o_n_n  A valid ICE connection object.

_s_i_z_e      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.

1166..  AAcckknnoowwlleeddggeemmeennttss

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.



















                           - 42 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


                         AAppppeennddiixx AA

              AAuutthheennttiiccaattiioonn UUttiilliittyy FFuunnccttiioonnss


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
assumes the presence of an ICE authority file.



                           - 43 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


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>:<portnumber>   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(_f_i_l_e___n_a_m_e, _r_e_t_r_i_e_s, _t_i_m_e_o_u_t, _d_e_a_d)
    char *_f_i_l_e___n_a_m_e;
    int _r_e_t_r_i_e_s;
    int _t_i_m_e_o_u_t;
    long _d_e_a_d;

_f_i_l_e___n_a_m_e The authorization file to lock.

_r_e_t_r_i_e_s   The number of retries.

_t_i_m_e_o_u_t   The number of seconds before each retry.

_d_e_a_d      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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


+o    - the specified number of retries failed.


To unlock an authorization file, use
__
||  void IceUnlockAuthFile(_f_i_l_e___n_a_m_e)
    char *_f_i_l_e___n_a_m_e;

_f_i_l_e___n_a_m_e The authorization file to unlock.
||__


To read the next entry in an authorization file, use
__
||  IceAuthFileEntry *IceReadAuthFileEntry(_a_u_t_h___f_i_l_e)
    FILE *_a_u_t_h___f_i_l_e;

_a_u_t_h___f_i_l_e 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(_a_u_t_h___f_i_l_e, _e_n_t_r_y)
    FILE *_a_u_t_h___f_i_l_e;
    IceAuthFileEntry *_e_n_t_r_y;

_a_u_t_h___f_i_l_e The authorization file.

_e_n_t_r_y     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(_p_r_o_t_o_c_o_l___n_a_m_e,
_n_e_t_w_o_r_k___i_d, _a_u_t_h___n_a_m_e)
    char *_p_r_o_t_o_c_o_l___n_a_m_e;
    char *_n_e_t_w_o_r_k___i_d;
    char *_a_u_t_h___n_a_m_e;



                           - 45 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


_p_r_o_t_o_c_o_l___n_a_m_e
          The name of the protocol to search on.

_n_e_t_w_o_r_k___i_d
          The network ID to search on.

_a_u_t_h___n_a_m_e 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(_e_n_t_r_y)
    IceAuthFileEntry *_e_n_t_r_y;

_e_n_t_r_y     The entry to free.
||__






































                           - 46 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


                         AAppppeennddiixx BB

             MMIITT--MMAAGGIICC--CCOOOOKKIIEE--11 AAuutthheennttiiccaattiioonn


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(_l_e_n_g_t_h)
    int _l_e_n_g_t_h;

_l_e_n_g_t_h    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(_n_u_m___e_n_t_r_i_e_s, _e_n_t_r_i_e_s)
    int _n_u_m___e_n_t_r_i_e_s;
    IceAuthDataEntry *_e_n_t_r_i_e_s;

_n_u_m___e_n_t_r_i_e_s
          The number of authentication data entries.

_e_n_t_r_i_e_s   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 -





IInntteerr--CClliieenntt EExxcchhaannggee LLiibbrraarryy               XX1111,, RReelleeaassee 66..44


``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 *net-
work_id;        char   *auth_name;         unsigned    short
auth_data_length;      char *auth_data; } IceAuthDataEntry;
||__













































                           - 48 -


