summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:36 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:36 +0000
commitee452992357329f7af846eba8f5bbe61c5d27bfa (patch)
tree6566d7217c47e446e454f5ab461d9b15f8e4c480 /src
R6.6 is the Xorg base-lineXORG-MAINXORG-STABLE
Diffstat (limited to 'src')
-rw-r--r--src/ICElibint.h588
-rw-r--r--src/accept.c185
-rw-r--r--src/authutil.c536
-rw-r--r--src/connect.c544
-rw-r--r--src/error.c641
-rw-r--r--src/getauth.c270
-rw-r--r--src/globals.h57
-rw-r--r--src/iceauth.c278
-rw-r--r--src/listen.c280
-rw-r--r--src/listenwk.c157
-rw-r--r--src/locking.c64
-rw-r--r--src/misc.c621
-rw-r--r--src/ping.c63
-rw-r--r--src/process.c2490
-rw-r--r--src/protosetup.c289
-rw-r--r--src/register.c253
-rw-r--r--src/replywait.c158
-rw-r--r--src/setauth.c113
-rw-r--r--src/shutdown.c325
-rw-r--r--src/watch.c203
20 files changed, 8115 insertions, 0 deletions
diff --git a/src/ICElibint.h b/src/ICElibint.h
new file mode 100644
index 0000000..0a1ffcb
--- /dev/null
+++ b/src/ICElibint.h
@@ -0,0 +1,588 @@
+/* $Xorg: ICElibint.h,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#ifndef _ICELIBINT_H_
+#define _ICELIBINT_H_
+
+#include <X11/Xos.h>
+#include <X11/Xfuncs.h>
+#include <X11/Xmd.h>
+#include <X11/ICE/ICEproto.h>
+#include <X11/ICE/ICEconn.h>
+#include <X11/ICE/ICEmsg.h>
+
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#else
+char *malloc();
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+/*
+ * Vendor & Release
+ */
+
+#define IceVendorString "MIT"
+#define IceReleaseString "1.0"
+
+
+/*
+ * Pad to a 64 bit boundary
+ */
+
+#define PAD64(_bytes) ((8 - ((unsigned int) (_bytes) % 8)) % 8)
+
+#define PADDED_BYTES64(_bytes) (_bytes + PAD64 (_bytes))
+
+
+/*
+ * Pad to 32 bit boundary
+ */
+
+#define PAD32(_bytes) ((4 - ((unsigned int) (_bytes) % 4)) % 4)
+
+#define PADDED_BYTES32(_bytes) (_bytes + PAD32 (_bytes))
+
+
+/*
+ * Number of 8 byte units in _bytes.
+ */
+
+#define WORD64COUNT(_bytes) (((unsigned int) ((_bytes) + 7)) >> 3)
+
+
+/*
+ * Number of 4 byte units in _bytes.
+ */
+
+#define WORD32COUNT(_bytes) (((unsigned int) ((_bytes) + 3)) >> 2)
+
+
+/*
+ * Given a string, compute the number of bytes for the STRING representation
+ */
+
+#define STRING_BYTES(_string) \
+ (2 + strlen (_string) + PAD32 (2 + strlen (_string)))
+
+
+/*
+ * Size of ICE input/output buffers
+ */
+
+#define ICE_INBUFSIZE 1024
+
+#define ICE_OUTBUFSIZE 1024
+
+
+/*
+ * Maxium number of ICE authentication methods allowed, and maxiumum
+ * number of authentication data entries allowed to be set in the
+ * IceSetPaAuthData function.
+ *
+ * We should use linked lists, but this is easier and should suffice.
+ */
+
+#define MAX_ICE_AUTH_NAMES 32
+#define ICE_MAX_AUTH_DATA_ENTRIES 100
+
+
+/*
+ * ICE listen object
+ */
+
+struct _IceListenObj {
+ struct _XtransConnInfo *trans_conn; /* transport connection object */
+ char *network_id;
+ IceHostBasedAuthProc host_based_auth_proc;
+};
+
+
+/*
+ * Some internal data structures for processing ICE messages.
+ */
+
+typedef void (*_IceProcessCoreMsgProc) (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* opcode */,
+ unsigned long /* length */,
+ Bool /* swap */,
+ IceReplyWaitInfo * /* replyWait */,
+ Bool * /* replyReadyRet */,
+ Bool * /* connectionClosedRet */
+#endif
+);
+
+typedef struct {
+ int major_version;
+ int minor_version;
+ _IceProcessCoreMsgProc process_core_msg_proc;
+} _IceVersion;
+
+
+/*
+ * STORE FOO
+ */
+
+#define STORE_CARD8(_pBuf, _val) \
+{ \
+ *((CARD8 *) _pBuf) = _val; \
+ _pBuf += 1; \
+}
+
+#ifndef WORD64
+
+#define STORE_CARD16(_pBuf, _val) \
+{ \
+ *((CARD16 *) _pBuf) = _val; \
+ _pBuf += 2; \
+}
+
+#define STORE_CARD32(_pBuf, _val) \
+{ \
+ *((CARD32 *) _pBuf) = _val; \
+ _pBuf += 4; \
+}
+
+#else /* WORD64 */
+
+#define STORE_CARD16(_pBuf, _val) \
+{ \
+ struct { \
+ int value :16; \
+ int pad :16; \
+ } _d; \
+ _d.value = _val; \
+ memcpy (_pBuf, &_d, 2); \
+ _pBuf += 2; \
+}
+
+#define STORE_CARD32(_pBuf, _val) \
+{ \
+ struct { \
+ int value :32; \
+ } _d; \
+ _d.value = _val; \
+ memcpy (_pBuf, &_d, 4); \
+ _pBuf += 4; \
+}
+
+#endif /* WORD64 */
+
+#define STORE_STRING(_pBuf, _string) \
+{ \
+ CARD16 _len = strlen (_string); \
+ STORE_CARD16 (_pBuf, _len); \
+ memcpy (_pBuf, _string, _len); \
+ _pBuf += _len; \
+ if (PAD32 (2 + _len)) \
+ _pBuf += PAD32 (2 + _len); \
+}
+
+
+/*
+ * EXTRACT FOO
+ */
+
+#define EXTRACT_CARD8(_pBuf, _val) \
+{ \
+ _val = *((CARD8 *) _pBuf); \
+ _pBuf += 1; \
+}
+
+#ifndef WORD64
+
+#define EXTRACT_CARD16(_pBuf, _swap, _val) \
+{ \
+ _val = *((CARD16 *) _pBuf); \
+ _pBuf += 2; \
+ if (_swap) \
+ _val = lswaps (_val); \
+}
+
+#define EXTRACT_CARD32(_pBuf, _swap, _val) \
+{ \
+ _val = *((CARD32 *) _pBuf); \
+ _pBuf += 4; \
+ if (_swap) \
+ _val = lswapl (_val); \
+}
+
+#else /* WORD64 */
+
+#define EXTRACT_CARD16(_pBuf, _swap, _val) \
+{ \
+ _val = *(_pBuf + 0) & 0xff; /* 0xff incase _pBuf is signed */ \
+ _val <<= 8; \
+ _val |= *(_pBuf + 1) & 0xff;\
+ _pBuf += 2; \
+ if (_swap) \
+ _val = lswaps (_val); \
+}
+
+#define EXTRACT_CARD32(_pBuf, _swap, _val) \
+{ \
+ _val = *(_pBuf + 0) & 0xff; /* 0xff incase _pBuf is signed */ \
+ _val <<= 8; \
+ _val |= *(_pBuf + 1) & 0xff;\
+ _val <<= 8; \
+ _val |= *(_pBuf + 2) & 0xff;\
+ _val <<= 8; \
+ _val |= *(_pBuf + 3) & 0xff;\
+ _pBuf += 4; \
+ if (_swap) \
+ _val = lswapl (_val); \
+}
+
+#endif /* WORD64 */
+
+#define EXTRACT_STRING(_pBuf, _swap, _string) \
+{ \
+ CARD16 _len; \
+ EXTRACT_CARD16 (_pBuf, _swap, _len); \
+ _string = (char *) malloc (_len + 1); \
+ memcpy (_string, _pBuf, _len); \
+ _pBuf += _len; \
+ _string[_len] = '\0'; \
+ if (PAD32 (2 + _len)) \
+ _pBuf += PAD32 (2 + _len); \
+}
+
+#define EXTRACT_LISTOF_STRING(_pBuf, _swap, _count, _strings) \
+{ \
+ int _i; \
+ for (_i = 0; _i < _count; _i++) \
+ EXTRACT_STRING (_pBuf, _swap, _strings[_i]); \
+}
+
+
+#define SKIP_STRING(_pBuf, _swap) \
+{ \
+ CARD16 _len; \
+ EXTRACT_CARD16 (_pBuf, _swap, _len); \
+ _pBuf += _len; \
+ if (PAD32 (2 + _len)) \
+ _pBuf += PAD32 (2 + _len); \
+}
+
+#define SKIP_LISTOF_STRING(_pBuf, _swap, _count) \
+{ \
+ int _i; \
+ for (_i = 0; _i < _count; _i++) \
+ SKIP_STRING (_pBuf, _swap); \
+}
+
+
+
+/*
+ * Byte swapping
+ */
+
+/* byte swap a long literal */
+#define lswapl(_val) ((((_val) & 0xff) << 24) |\
+ (((_val) & 0xff00) << 8) |\
+ (((_val) & 0xff0000) >> 8) |\
+ (((_val) >> 24) & 0xff))
+
+/* byte swap a short literal */
+#define lswaps(_val) ((((_val) & 0xff) << 8) | (((_val) >> 8) & 0xff))
+
+
+
+/*
+ * ICE replies (not processed via callbacks because we block)
+ */
+
+#define ICE_CONNECTION_REPLY 1
+#define ICE_CONNECTION_ERROR 2
+#define ICE_PROTOCOL_REPLY 3
+#define ICE_PROTOCOL_ERROR 4
+
+typedef struct {
+ int type;
+ int version_index;
+ char *vendor;
+ char *release;
+} _IceConnectionReply;
+
+typedef struct {
+ int type;
+ char *error_message;
+} _IceConnectionError;
+
+typedef struct {
+ int type;
+ int major_opcode;
+ int version_index;
+ char *vendor;
+ char *release;
+} _IceProtocolReply;
+
+typedef struct {
+ int type;
+ char *error_message;
+} _IceProtocolError;
+
+
+typedef union {
+ int type;
+ _IceConnectionReply connection_reply;
+ _IceConnectionError connection_error;
+ _IceProtocolReply protocol_reply;
+ _IceProtocolError protocol_error;
+} _IceReply;
+
+
+/*
+ * Watch for ICE connection create/destroy.
+ */
+
+typedef struct _IceWatchedConnection {
+ IceConn iceConn;
+ IcePointer watch_data;
+ struct _IceWatchedConnection *next;
+} _IceWatchedConnection;
+
+typedef struct _IceWatchProc {
+ IceWatchProc watch_proc;
+ IcePointer client_data;
+ _IceWatchedConnection *watched_connections;
+ struct _IceWatchProc *next;
+} _IceWatchProc;
+
+
+/*
+ * Locking
+ */
+
+#define IceLockConn(_iceConn)
+#define IceUnlockConn(_iceConn)
+
+
+/*
+ * Extern declarations
+ */
+
+extern IceConn _IceConnectionObjs[];
+extern char *_IceConnectionStrings[];
+extern int _IceConnectionCount;
+
+extern _IceProtocol _IceProtocols[];
+extern int _IceLastMajorOpcode;
+
+extern int _IceAuthCount;
+extern char *_IceAuthNames[];
+extern IcePoAuthProc _IcePoAuthProcs[];
+extern IcePaAuthProc _IcePaAuthProcs[];
+
+extern int _IceVersionCount;
+extern _IceVersion _IceVersions[];
+
+extern _IceWatchProc *_IceWatchProcs;
+
+extern IceErrorHandler _IceErrorHandler;
+extern IceIOErrorHandler _IceIOErrorHandler;
+
+
+extern void _IceErrorBadMajor (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMajor */,
+ int /* offendingMinor */,
+ int /* severity */
+#endif
+);
+
+extern void _IceErrorNoAuthentication (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */
+#endif
+);
+
+extern void _IceErrorNoVersion (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */
+#endif
+);
+
+extern void _IceErrorSetupFailed (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */,
+ char * /* reason */
+#endif
+);
+
+extern void _IceErrorAuthenticationRejected (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */,
+ char * /* reason */
+#endif
+);
+
+extern void _IceErrorAuthenticationFailed (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* offendingMinor */,
+ char * /* reason */
+#endif
+);
+
+extern void _IceErrorProtocolDuplicate (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ char * /* protocolName */
+#endif
+);
+
+extern void _IceErrorMajorOpcodeDuplicate (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */
+#endif
+);
+
+extern void _IceErrorUnknownProtocol (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ char * /* protocolName */
+#endif
+);
+
+extern void _IceAddOpcodeMapping (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* hisOpcode */,
+ int /* myOpcode */
+#endif
+);
+
+extern char *_IceGetPeerName (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+extern void _IceFreeConnection (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+extern void _IceAddReplyWait (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IceReplyWaitInfo * /* replyWait */
+#endif
+);
+
+extern IceReplyWaitInfo *_IceSearchReplyWaits (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ int /* majorOpcode */
+#endif
+);
+
+extern void _IceSetReplyReady (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IceReplyWaitInfo * /* replyWait */
+#endif
+);
+
+extern Bool _IceCheckReplyReady (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */,
+ IceReplyWaitInfo * /* replyWait */
+#endif
+);
+
+extern void _IceConnectionOpened (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+extern void _IceConnectionClosed (
+#if NeedFunctionPrototypes
+ IceConn /* iceConn */
+#endif
+);
+
+extern void _IceGetPoAuthData (
+#if NeedFunctionPrototypes
+ char * /* protocol_name */,
+ char * /* address */,
+ char * /* auth_name */,
+ unsigned short * /* auth_data_length_ret */,
+ char ** /* auth_data_ret */
+#endif
+);
+
+extern void _IceGetPaAuthData (
+#if NeedFunctionPrototypes
+ char * /* protocol_name */,
+ char * /* address */,
+ char * /* auth_name */,
+ unsigned short * /* auth_data_length_ret */,
+ char ** /* auth_data_ret */
+#endif
+);
+
+extern void _IceGetPoValidAuthIndices (
+#if NeedFunctionPrototypes
+ char * /* protocol_name */,
+ char * /* address */,
+ int /* num_auth_names */,
+ char ** /* auth_names */,
+ int * /* num_indices_ret */,
+ int * /* indices_ret */
+#endif
+);
+
+extern void _IceGetPaValidAuthIndices (
+#if NeedFunctionPrototypes
+ char * /* protocol_name */,
+ char * /* address */,
+ int /* num_auth_names */,
+ char ** /* auth_names */,
+ int * /* num_indices_ret */,
+ int * /* indices_ret */
+#endif
+);
+
+#endif /* _ICELIBINT_H_ */
diff --git a/src/accept.c b/src/accept.c
new file mode 100644
index 0000000..eea5389
--- /dev/null
+++ b/src/accept.c
@@ -0,0 +1,185 @@
+/* $Xorg: accept.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/Xtrans.h>
+
+
+IceConn
+IceAcceptConnection (listenObj, statusRet)
+
+IceListenObj listenObj;
+IceAcceptStatus *statusRet;
+
+{
+ IceConn iceConn;
+ XtransConnInfo newconn;
+ iceByteOrderMsg *pMsg;
+ int endian, status;
+
+ /*
+ * Accept the connection.
+ */
+
+ if ((newconn = _IceTransAccept (listenObj->trans_conn, &status)) == 0)
+ {
+ if (status == TRANS_ACCEPT_BAD_MALLOC)
+ *statusRet = IceAcceptBadMalloc;
+ else
+ *statusRet = IceAcceptFailure;
+ return (NULL);
+ }
+
+
+ /*
+ * Set close-on-exec so that programs that fork() don't get confused.
+ */
+
+ _IceTransSetOption (newconn, TRANS_CLOSEONEXEC, 1);
+
+
+ /*
+ * Create an ICE object for this connection.
+ */
+
+ if ((iceConn = (IceConn) malloc (sizeof (struct _IceConn))) == NULL)
+ {
+ _IceTransClose (newconn);
+ *statusRet = IceAcceptBadMalloc;
+ return (NULL);
+ }
+
+ iceConn->listen_obj = listenObj;
+
+ iceConn->waiting_for_byteorder = True;
+ iceConn->connection_status = IceConnectPending;
+ iceConn->io_ok = True;
+ iceConn->dispatch_level = 0;
+ iceConn->context = NULL;
+ iceConn->my_ice_version_index = 0;
+
+ iceConn->trans_conn = newconn;
+ iceConn->send_sequence = 0;
+ iceConn->receive_sequence = 0;
+
+ iceConn->connection_string = (char *) malloc (
+ strlen (listenObj->network_id) + 1);
+
+ if (iceConn->connection_string == NULL)
+ {
+ _IceTransClose (newconn);
+ free ((char *) iceConn);
+ *statusRet = IceAcceptBadMalloc;
+ return (NULL);
+ }
+ else
+ strcpy (iceConn->connection_string, listenObj->network_id);
+
+ iceConn->vendor = NULL;
+ iceConn->release = NULL;
+
+ if ((iceConn->inbuf = iceConn->inbufptr =
+ (char *) malloc (ICE_INBUFSIZE)) != NULL)
+ {
+ iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE;
+ }
+ else
+ {
+ _IceTransClose (newconn);
+ free ((char *) iceConn);
+ *statusRet = IceAcceptBadMalloc;
+ return (NULL);
+ }
+
+ if ((iceConn->outbuf = iceConn->outbufptr =
+ (char *) malloc (ICE_OUTBUFSIZE)) != NULL)
+ {
+ iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE;
+ }
+ else
+ {
+ _IceTransClose (newconn);
+ free (iceConn->inbuf);
+ free ((char *) iceConn);
+ *statusRet = IceAcceptBadMalloc;
+ return (NULL);
+ }
+
+ iceConn->scratch = NULL;
+ iceConn->scratch_size = 0;
+
+ iceConn->open_ref_count = 1;
+ iceConn->proto_ref_count = 0;
+
+ iceConn->skip_want_to_close = False;
+ iceConn->want_to_close = False;
+ iceConn->free_asap = False;
+
+ iceConn->saved_reply_waits = NULL;
+ iceConn->ping_waits = NULL;
+
+ iceConn->process_msg_info = NULL;
+
+ iceConn->connect_to_you = NULL;
+ iceConn->protosetup_to_you = NULL;
+
+ iceConn->connect_to_me = NULL;
+ iceConn->protosetup_to_me = NULL;
+
+
+ /*
+ * Send our byte order.
+ */
+
+ IceGetHeader (iceConn, 0, ICE_ByteOrder,
+ SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pMsg);
+
+ endian = 1;
+ if (*(char *) &endian)
+ pMsg->byteOrder = IceLSBfirst;
+ else
+ pMsg->byteOrder = IceMSBfirst;
+
+ IceFlush (iceConn);
+
+
+ if (_IceWatchProcs)
+ {
+ /*
+ * Notify the watch procedures that an iceConn was opened.
+ */
+
+ _IceConnectionOpened (iceConn);
+ }
+
+ *statusRet = IceAcceptSuccess;
+
+ return (iceConn);
+}
diff --git a/src/authutil.c b/src/authutil.c
new file mode 100644
index 0000000..64ad848
--- /dev/null
+++ b/src/authutil.c
@@ -0,0 +1,536 @@
+/* $Xorg: authutil.c,v 1.5 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/ICE/ICEutil.h>
+#include <X11/Xos.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+extern long time ();
+extern char *getenv();
+#define Time_t long
+#else
+#include <time.h>
+#define Time_t time_t
+#endif
+#ifndef X_NOT_POSIX
+#include <unistd.h>
+#else
+#ifndef WIN32
+extern unsigned sleep ();
+#else
+#define link rename
+#endif
+#endif
+
+static Status read_short ();
+static Status read_string ();
+static Status read_counted_string ();
+static Status write_short ();
+static Status write_string ();
+static Status write_counted_string ();
+
+
+
+/*
+ * The following routines are for manipulating the .ICEauthority file
+ * These are utility functions - they are not part of the standard
+ * ICE library specification.
+ */
+
+char *
+IceAuthFileName ()
+
+{
+ static char slashDotICEauthority[] = "/.ICEauthority";
+ char *name;
+ static char *buf;
+ static int bsize;
+ int size;
+#ifdef WIN32
+#ifndef PATH_MAX
+#define PATH_MAX 512
+#endif
+ char dir[PATH_MAX];
+#endif
+
+ if ((name = getenv ("ICEAUTHORITY")))
+ return (name);
+
+ name = getenv ("HOME");
+
+ if (!name)
+ {
+#ifdef WIN32
+ register char *ptr1;
+ register char *ptr2;
+ int len1 = 0, len2 = 0;
+
+ if ((ptr1 = getenv("HOMEDRIVE")) && (ptr2 = getenv("HOMEDIR"))) {
+ len1 = strlen (ptr1);
+ len2 = strlen (ptr2);
+ } else if (ptr2 = getenv("USERNAME")) {
+ len1 = strlen (ptr1 = "/users/");
+ len2 = strlen (ptr2);
+ }
+ if ((len1 + len2 + 1) < PATH_MAX) {
+ sprintf (dir, "%s%s", ptr1, (ptr2) ? ptr2 : "");
+ name = dir;
+ }
+ if (!name)
+#endif
+ return (NULL);
+ }
+
+ size = strlen (name) + strlen (&slashDotICEauthority[1]) + 2;
+
+ if (size > bsize)
+ {
+ if (buf)
+ free (buf);
+ buf = malloc ((unsigned) size);
+ if (!buf)
+ return (NULL);
+ bsize = size;
+ }
+
+ strcpy (buf, name);
+ strcat (buf, slashDotICEauthority + (name[1] == '\0' ? 1 : 0));
+
+ return (buf);
+}
+
+
+
+int
+IceLockAuthFile (file_name, retries, timeout, dead)
+
+char *file_name;
+int retries;
+int timeout;
+long dead;
+
+{
+ char creat_name[1025], link_name[1025];
+ struct stat statb;
+ Time_t now;
+ int creat_fd = -1;
+
+ if ((int) strlen (file_name) > 1022)
+ return (IceAuthLockError);
+
+ strcpy (creat_name, file_name);
+ strcat (creat_name, "-c");
+ strcpy (link_name, file_name);
+ strcat (link_name, "-l");
+
+ if (stat (creat_name, &statb) != -1)
+ {
+ now = time ((Time_t *) 0);
+
+ /*
+ * NFS may cause ctime to be before now, special
+ * case a 0 deadtime to force lock removal
+ */
+
+ if (dead == 0 || now - statb.st_ctime > dead)
+ {
+ unlink (creat_name);
+ unlink (link_name);
+ }
+ }
+
+ while (retries > 0)
+ {
+ if (creat_fd == -1)
+ {
+ creat_fd = creat (creat_name, 0666);
+
+ if (creat_fd == -1)
+ {
+ if (errno != EACCES)
+ return (IceAuthLockError);
+ }
+ else
+ close (creat_fd);
+ }
+
+ if (creat_fd != -1)
+ {
+ if (link (creat_name, link_name) != -1)
+ return (IceAuthLockSuccess);
+
+ if (errno == ENOENT)
+ {
+ creat_fd = -1; /* force re-creat next time around */
+ continue;
+ }
+
+ if (errno != EEXIST)
+ return (IceAuthLockError);
+ }
+
+ sleep ((unsigned) timeout);
+ --retries;
+ }
+
+ return (IceAuthLockTimeout);
+}
+
+
+
+void
+IceUnlockAuthFile (file_name)
+
+char *file_name;
+
+{
+#ifndef WIN32
+ char creat_name[1025];
+#endif
+ char link_name[1025];
+
+ if ((int) strlen (file_name) > 1022)
+ return;
+
+#ifndef WIN32
+ strcpy (creat_name, file_name);
+ strcat (creat_name, "-c");
+#endif
+ strcpy (link_name, file_name);
+ strcat (link_name, "-l");
+
+#ifndef WIN32
+ unlink (creat_name);
+#endif
+ unlink (link_name);
+}
+
+
+
+IceAuthFileEntry *
+IceReadAuthFileEntry (auth_file)
+
+FILE *auth_file;
+
+{
+ IceAuthFileEntry local;
+ IceAuthFileEntry *ret;
+
+ local.protocol_name = NULL;
+ local.protocol_data = NULL;
+ local.network_id = NULL;
+ local.auth_name = NULL;
+ local.auth_data = NULL;
+
+ if (!read_string (auth_file, &local.protocol_name))
+ return (NULL);
+
+ if (!read_counted_string (auth_file,
+ &local.protocol_data_length, &local.protocol_data))
+ goto bad;
+
+ if (!read_string (auth_file, &local.network_id))
+ goto bad;
+
+ if (!read_string (auth_file, &local.auth_name))
+ goto bad;
+
+ if (!read_counted_string (auth_file,
+ &local.auth_data_length, &local.auth_data))
+ goto bad;
+
+ if (!(ret = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry))))
+ goto bad;
+
+ *ret = local;
+
+ return (ret);
+
+ bad:
+
+ if (local.protocol_name) free (local.protocol_name);
+ if (local.protocol_data) free (local.protocol_data);
+ if (local.network_id) free (local.network_id);
+ if (local.auth_name) free (local.auth_name);
+ if (local.auth_data) free (local.auth_data);
+
+ return (NULL);
+}
+
+
+
+void
+IceFreeAuthFileEntry (auth)
+
+IceAuthFileEntry *auth;
+
+{
+ if (auth)
+ {
+ if (auth->protocol_name) free (auth->protocol_name);
+ if (auth->protocol_data) free (auth->protocol_data);
+ if (auth->network_id) free (auth->network_id);
+ if (auth->auth_name) free (auth->auth_name);
+ if (auth->auth_data) free (auth->auth_data);
+ free ((char *) auth);
+ }
+}
+
+
+
+Status
+IceWriteAuthFileEntry (auth_file, auth)
+
+FILE *auth_file;
+IceAuthFileEntry *auth;
+
+{
+ if (!write_string (auth_file, auth->protocol_name))
+ return (0);
+
+ if (!write_counted_string (auth_file,
+ auth->protocol_data_length, auth->protocol_data))
+ return (0);
+
+ if (!write_string (auth_file, auth->network_id))
+ return (0);
+
+ if (!write_string (auth_file, auth->auth_name))
+ return (0);
+
+ if (!write_counted_string (auth_file,
+ auth->auth_data_length, auth->auth_data))
+ return (0);
+
+ return (1);
+}
+
+
+
+IceAuthFileEntry *
+IceGetAuthFileEntry (protocol_name, network_id, auth_name)
+
+char *protocol_name;
+char *network_id;
+char *auth_name;
+
+{
+ FILE *auth_file;
+ char *filename;
+ IceAuthFileEntry *entry;
+
+ if (!(filename = IceAuthFileName ()))
+ return (NULL);
+
+ if (access (filename, R_OK) != 0) /* checks REAL id */
+ return (NULL);
+
+ if (!(auth_file = fopen (filename, "rb")))
+ return (NULL);
+
+ for (;;)
+ {
+ if (!(entry = IceReadAuthFileEntry (auth_file)))
+ break;
+
+ if (strcmp (protocol_name, entry->protocol_name) == 0 &&
+ strcmp (network_id, entry->network_id) == 0 &&
+ strcmp (auth_name, entry->auth_name) == 0)
+ {
+ break;
+ }
+
+ IceFreeAuthFileEntry (entry);
+ }
+
+ fclose (auth_file);
+
+ return (entry);
+}
+
+
+
+/*
+ * local routines
+ */
+
+static Status
+read_short (file, shortp)
+
+FILE *file;
+unsigned short *shortp;
+
+{
+ unsigned char file_short[2];
+
+ if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
+ return (0);
+
+ *shortp = file_short[0] * 256 + file_short[1];
+ return (1);
+}
+
+
+static Status
+read_string (file, stringp)
+
+FILE *file;
+char **stringp;
+
+{
+ unsigned short len;
+ char *data;
+
+ if (!read_short (file, &len))
+ return (0);
+
+ if (len == 0)
+ {
+ data = 0;
+ }
+ else
+ {
+ data = malloc ((unsigned) len + 1);
+
+ if (!data)
+ return (0);
+
+ if (fread (data, (int) sizeof (char), (int) len, file) != len)
+ {
+ free (data);
+ return (0);
+ }
+
+ data[len] = '\0';
+ }
+
+ *stringp = data;
+
+ return (1);
+}
+
+
+static Status
+read_counted_string (file, countp, stringp)
+
+FILE *file;
+unsigned short *countp;
+char **stringp;
+
+{
+ unsigned short len;
+ char *data;
+
+ if (!read_short (file, &len))
+ return (0);
+
+ if (len == 0)
+ {
+ data = 0;
+ }
+ else
+ {
+ data = malloc ((unsigned) len);
+
+ if (!data)
+ return (0);
+
+ if (fread (data, (int) sizeof (char), (int) len, file) != len)
+ {
+ free (data);
+ return (0);
+ }
+ }
+
+ *stringp = data;
+ *countp = len;
+
+ return (1);
+}
+
+
+static Status
+write_short (file, s)
+
+FILE *file;
+unsigned short s;
+
+{
+ unsigned char file_short[2];
+
+ file_short[0] = (s & (unsigned) 0xff00) >> 8;
+ file_short[1] = s & 0xff;
+
+ if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
+ return (0);
+
+ return (1);
+}
+
+
+static Status
+write_string (file, string)
+
+FILE *file;
+char *string;
+
+{
+ unsigned short count = strlen (string);
+
+ if (!write_short (file, count))
+ return (0);
+
+ if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
+ return (0);
+
+ return (1);
+}
+
+
+static Status
+write_counted_string (file, count, string)
+
+FILE *file;
+unsigned short count;
+char *string;
+
+{
+ if (!write_short (file, count))
+ return (0);
+
+ if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
+ return (0);
+
+ return (1);
+}
diff --git a/src/connect.c b/src/connect.c
new file mode 100644
index 0000000..57ee86a
--- /dev/null
+++ b/src/connect.c
@@ -0,0 +1,544 @@
+/* $Xorg: connect.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/Xtrans.h>
+#include "globals.h"
+
+static XtransConnInfo ConnectToPeer();
+
+#ifndef X_NOT_STDC_ENV
+#define Strstr strstr
+#else
+static char *Strstr(s1, s2)
+ char *s1, *s2;
+{
+ int n1, n2;
+
+ n1 = strlen(s1);
+ n2 = strlen(s2);
+ for ( ; n1 >= n2; s1++, n1--) {
+ if (!strncmp(s1, s2, n2))
+ return s1;
+ }
+ return NULL;
+}
+#endif
+
+IceConn
+IceOpenConnection (networkIdsList, context, mustAuthenticate, majorOpcodeCheck,
+ errorLength, errorStringRet)
+
+char *networkIdsList;
+IcePointer context;
+Bool mustAuthenticate;
+int majorOpcodeCheck;
+int errorLength;
+char *errorStringRet;
+
+{
+ IceConn iceConn;
+ int extra, i, j;
+ int endian;
+ Bool gotReply, ioErrorOccured;
+ unsigned long setup_sequence;
+ iceByteOrderMsg *pByteOrderMsg;
+ iceConnectionSetupMsg *pSetupMsg;
+ char *pData;
+ IceReplyWaitInfo replyWait;
+ _IceReply reply;
+ int authUsableCount;
+ int authUsableFlags[MAX_ICE_AUTH_NAMES];
+ int authIndices[MAX_ICE_AUTH_NAMES];
+
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ if (networkIdsList == NULL || *networkIdsList == '\0')
+ {
+ strncpy (errorStringRet,
+ "networkIdsList argument is NULL", errorLength);
+ return (NULL);
+ }
+
+ /*
+ * Check to see if we can use a previously created ICE connection.
+ *
+ * If iceConn->want_to_close is True, or iceConn->free_asap is True,
+ * we can not use the iceConn.
+ *
+ * If 'context' is non-NULL, we will only use a previously opened ICE
+ * connection if the specified 'context' is equal to the context
+ * associated with the ICE connection, or if the context associated
+ * with the ICE connection is NULL.
+ *
+ * If 'majorOpcodeCheck' is non-zero, it will contain a protocol major
+ * opcode that we should make sure is not already active on the ICE
+ * connection. Some clients will want two seperate connections for the
+ * same protocol to the same destination client.
+ */
+
+ for (i = 0; i < _IceConnectionCount; i++)
+ {
+ char *strptr;
+ if ((strptr = (char *) Strstr (
+ networkIdsList, _IceConnectionStrings[i])) != NULL)
+ {
+ char ch = *(strptr + strlen (_IceConnectionStrings[i]));
+ if (ch == ',' || ch == '\0')
+ {
+ /*
+ * OK, we found a connection. Make sure we can reuse it.
+ */
+
+ IceConn iceConn = _IceConnectionObjs[i];
+
+ if (iceConn->want_to_close || iceConn->free_asap ||
+ (context && iceConn->context &&
+ iceConn->context != context))
+ {
+ /* force a new connection to be created */
+ break;
+ }
+
+ if (majorOpcodeCheck)
+ {
+ for (j = iceConn->his_min_opcode;
+ j <= iceConn->his_max_opcode; j++)
+ {
+ if (iceConn->process_msg_info[
+ j - iceConn->his_min_opcode].in_use &&
+ iceConn->process_msg_info[
+ j - iceConn->his_min_opcode].my_opcode ==
+ majorOpcodeCheck)
+ break;
+ }
+
+ if (j <= iceConn->his_max_opcode ||
+ (iceConn->protosetup_to_you &&
+ iceConn->protosetup_to_you->my_opcode ==
+ majorOpcodeCheck))
+ {
+ /* force a new connection to be created */
+ break;
+ }
+ }
+
+ iceConn->open_ref_count++;
+ if (context && !iceConn->context)
+ iceConn->context = context;
+ return (iceConn);
+ }
+ }
+ }
+
+ if ((iceConn = (IceConn) malloc (sizeof (struct _IceConn))) == NULL)
+ {
+ strncpy (errorStringRet, "Can't malloc", errorLength);
+ return (NULL);
+ }
+
+
+ /*
+ * Open a network connection with the peer client.
+ */
+
+ if ((iceConn->trans_conn = ConnectToPeer (networkIdsList,
+ &iceConn->connection_string)) == NULL)
+ {
+ free ((char *) iceConn);
+ strncpy (errorStringRet, "Could not open network socket", errorLength);
+ return (NULL);
+ }
+
+ /*
+ * Set close-on-exec so that programs that fork() don't get confused.
+ */
+
+ _IceTransSetOption (iceConn->trans_conn, TRANS_CLOSEONEXEC, 1);
+
+ iceConn->listen_obj = NULL;
+
+ iceConn->connection_status = IceConnectPending;
+ iceConn->io_ok = True;
+ iceConn->dispatch_level = 0;
+ iceConn->context = context;
+ iceConn->my_ice_version_index = 0;
+ iceConn->send_sequence = 0;
+ iceConn->receive_sequence = 0;
+
+ iceConn->vendor = NULL;
+ iceConn->release = NULL;
+ iceConn->outbuf = NULL;
+
+ iceConn->scratch = NULL;
+ iceConn->scratch_size = 0;
+
+ iceConn->process_msg_info = NULL;
+
+ iceConn->connect_to_you = NULL;
+ iceConn->protosetup_to_you = NULL;
+
+ iceConn->connect_to_me = NULL;
+ iceConn->protosetup_to_me = NULL;
+
+ if ((iceConn->inbuf = iceConn->inbufptr =
+ (char *) malloc (ICE_INBUFSIZE)) == NULL)
+ {
+ _IceFreeConnection (iceConn);
+ strncpy (errorStringRet, "Can't malloc", errorLength);
+ return (NULL);
+ }
+
+ iceConn->inbufmax = iceConn->inbuf + ICE_INBUFSIZE;
+
+ if ((iceConn->outbuf = iceConn->outbufptr =
+ (char *) malloc (ICE_OUTBUFSIZE)) == NULL)
+ {
+ _IceFreeConnection (iceConn);
+ strncpy (errorStringRet, "Can't malloc", errorLength);
+ return (NULL);
+ }
+
+ iceConn->outbufmax = iceConn->outbuf + ICE_OUTBUFSIZE;
+
+ iceConn->open_ref_count = 1;
+ iceConn->proto_ref_count = 0;
+
+ iceConn->skip_want_to_close = False;
+ iceConn->want_to_close = False;
+ iceConn->free_asap = False;
+
+ iceConn->saved_reply_waits = NULL;
+ iceConn->ping_waits = NULL;
+
+ iceConn->connect_to_you = (_IceConnectToYouInfo *) malloc (
+ sizeof (_IceConnectToYouInfo));
+ iceConn->connect_to_you->auth_active = 0;
+
+ /*
+ * Send our byte order.
+ */
+
+ IceGetHeader (iceConn, 0, ICE_ByteOrder,
+ SIZEOF (iceByteOrderMsg), iceByteOrderMsg, pByteOrderMsg);
+
+ endian = 1;
+ if (*(char *) &endian)
+ pByteOrderMsg->byteOrder = IceLSBfirst;
+ else
+ pByteOrderMsg->byteOrder = IceMSBfirst;
+
+ IceFlush (iceConn);
+
+
+ /*
+ * Now read the ByteOrder message from the other client.
+ * iceConn->swap should be set to the appropriate boolean
+ * value after the call to IceProcessMessages.
+ */
+
+ iceConn->waiting_for_byteorder = True;
+
+ ioErrorOccured = False;
+ while (iceConn->waiting_for_byteorder == True && !ioErrorOccured)
+ {
+ ioErrorOccured = (IceProcessMessages (
+ iceConn, NULL, NULL) == IceProcessMessagesIOError);
+ }
+
+ if (ioErrorOccured)
+ {
+ _IceFreeConnection (iceConn);
+ strncpy (errorStringRet, "IO error occured opening connection",
+ errorLength);
+ return (NULL);
+ }
+
+ if (iceConn->connection_status == IceConnectRejected)
+ {
+ /*
+ * We failed to get the required ByteOrder message.
+ */
+
+ _IceFreeConnection (iceConn);
+ strncpy (errorStringRet,
+ "Internal error - did not receive the expected ByteOrder message",
+ errorLength);
+ return (NULL);
+ }
+
+
+ /*
+ * Determine which authentication methods are available for
+ * the Connection Setup authentication.
+ */
+
+ _IceGetPoValidAuthIndices (
+ "ICE", iceConn->connection_string,
+ _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
+
+ for (i = 0; i < _IceAuthCount; i++)
+ {
+ authUsableFlags[i] = 0;
+ for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
+ authUsableFlags[i] = (authIndices[j] == i);
+ }
+
+
+ /*
+ * Now send a Connection Setup message.
+ */
+
+ extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
+
+ for (i = 0; i < _IceAuthCount; i++)
+ if (authUsableFlags[i])
+ {
+ extra += STRING_BYTES (_IceAuthNames[i]);
+ }
+
+ extra += (_IceVersionCount * 4);
+
+ IceGetHeaderExtra (iceConn, 0, ICE_ConnectionSetup,
+ SIZEOF (iceConnectionSetupMsg), WORD64COUNT (extra),
+ iceConnectionSetupMsg, pSetupMsg, pData);
+
+ setup_sequence = iceConn->send_sequence;
+
+ pSetupMsg->versionCount = _IceVersionCount;
+ pSetupMsg->authCount = authUsableCount;
+ pSetupMsg->mustAuthenticate = mustAuthenticate;
+
+ STORE_STRING (pData, IceVendorString);
+ STORE_STRING (pData, IceReleaseString);
+
+ for (i = 0; i < _IceAuthCount; i++)
+ if (authUsableFlags[i])
+ {
+ STORE_STRING (pData, _IceAuthNames[i]);
+ }
+
+ for (i = 0; i < _IceVersionCount; i++)
+ {
+ STORE_CARD16 (pData, _IceVersions[i].major_version);
+ STORE_CARD16 (pData, _IceVersions[i].minor_version);
+ }
+
+ IceFlush (iceConn);
+
+
+ /*
+ * Process messages until we get a Connection Reply or an Error Message.
+ * Authentication will take place behind the scenes.
+ */
+
+ replyWait.sequence_of_request = setup_sequence;
+ replyWait.major_opcode_of_request = 0;
+ replyWait.minor_opcode_of_request = ICE_ConnectionSetup;
+ replyWait.reply = (IcePointer) &reply;
+
+ gotReply = False;
+ ioErrorOccured = False;
+
+ while (!gotReply && !ioErrorOccured)
+ {
+ ioErrorOccured = (IceProcessMessages (
+ iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
+
+ if (ioErrorOccured)
+ {
+ strncpy (errorStringRet, "IO error occured opening connection",
+ errorLength);
+ _IceFreeConnection (iceConn);
+ iceConn = NULL;
+ }
+ else if (gotReply)
+ {
+ if (reply.type == ICE_CONNECTION_REPLY)
+ {
+ if (reply.connection_reply.version_index >= _IceVersionCount)
+ {
+ strncpy (errorStringRet,
+ "Got a bad version index in the Connection Reply",
+ errorLength);
+
+ free (reply.connection_reply.vendor);
+ free (reply.connection_reply.release);
+ _IceFreeConnection (iceConn);
+ iceConn = NULL;
+ }
+ else
+ {
+ iceConn->my_ice_version_index =
+ reply.connection_reply.version_index;
+ iceConn->vendor = reply.connection_reply.vendor;
+ iceConn->release = reply.connection_reply.release;
+
+ _IceConnectionObjs[_IceConnectionCount] = iceConn;
+ _IceConnectionStrings[_IceConnectionCount] =
+ iceConn->connection_string;
+ _IceConnectionCount++;
+
+ free ((char *) iceConn->connect_to_you);
+ iceConn->connect_to_you = NULL;
+
+ iceConn->connection_status = IceConnectAccepted;
+ }
+ }
+ else /* reply.type == ICE_CONNECTION_ERROR */
+ {
+ /* Connection failed */
+
+ strncpy (errorStringRet, reply.connection_error.error_message,
+ errorLength);
+
+ free (reply.connection_error.error_message);
+
+ _IceFreeConnection (iceConn);
+ iceConn = NULL;
+ }
+ }
+ }
+
+ if (iceConn && _IceWatchProcs)
+ {
+ /*
+ * Notify the watch procedures that an iceConn was opened.
+ */
+
+ _IceConnectionOpened (iceConn);
+ }
+
+ return (iceConn);
+}
+
+
+
+IcePointer
+IceGetConnectionContext (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->context);
+}
+
+
+
+/* ------------------------------------------------------------------------- *
+ * local routines *
+ * ------------------------------------------------------------------------- */
+
+#define ICE_CONNECTION_RETRIES 5
+
+
+static XtransConnInfo
+ConnectToPeer (networkIdsList, actualConnectionRet)
+
+char *networkIdsList;
+char **actualConnectionRet;
+
+{
+ char addrbuf[256];
+ char* address;
+ char *ptr, *endptr, *delim;
+ int madeConnection = 0;
+ int len, retry;
+ int connect_stat;
+ XtransConnInfo trans_conn = NULL;
+
+ *actualConnectionRet = NULL;
+
+ ptr = networkIdsList;
+ len = strlen (networkIdsList);
+ endptr = networkIdsList + len;
+
+ if (len < sizeof addrbuf) address = addrbuf;
+ else address = malloc (len + 1);
+
+ while (ptr < endptr && !madeConnection)
+ {
+ if ((delim = (char *) strchr (ptr, ',')) == NULL)
+ delim = endptr;
+
+ len = delim - ptr;
+ strncpy (address, ptr, len);
+ address[len] = '\0';
+
+ ptr = delim + 1;
+
+ for (retry = ICE_CONNECTION_RETRIES; retry >= 0; retry--)
+ {
+ if ((trans_conn = _IceTransOpenCOTSClient (address)) == NULL)
+ {
+ break;
+ }
+
+ if ((connect_stat = _IceTransConnect (trans_conn, address)) < 0)
+ {
+ _IceTransClose (trans_conn);
+
+ if (connect_stat == TRANS_TRY_CONNECT_AGAIN)
+ {
+ sleep(1);
+ continue;
+ }
+ else
+ break;
+ }
+ else
+ {
+ madeConnection = 1;
+ break;
+ }
+ }
+ }
+
+ if (madeConnection)
+ {
+ /*
+ * We need to return the actual network connection string
+ */
+
+ *actualConnectionRet = (char *) malloc (strlen (address) + 1);
+ strcpy (*actualConnectionRet, address);
+
+
+ /*
+ * Return the file descriptor
+ */
+ }
+ else trans_conn = NULL;
+
+ if (address != addrbuf) free (address);
+
+ return trans_conn;
+}
diff --git a/src/error.c b/src/error.c
new file mode 100644
index 0000000..6caf66f
--- /dev/null
+++ b/src/error.c
@@ -0,0 +1,641 @@
+/* $Xorg: error.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <stdio.h>
+
+#include <errno.h>
+
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+
+
+void
+_IceErrorBadMinor (iceConn, majorOpcode, offendingMinor, severity)
+
+IceConn iceConn;
+int majorOpcode;
+int offendingMinor;
+int severity;
+
+{
+ IceErrorHeader (iceConn,
+ majorOpcode, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceBadMinor,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorBadState (iceConn, majorOpcode, offendingMinor, severity)
+
+IceConn iceConn;
+int majorOpcode;
+int offendingMinor;
+int severity;
+
+{
+ IceErrorHeader (iceConn,
+ majorOpcode, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceBadState,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorBadLength (iceConn, majorOpcode, offendingMinor, severity)
+
+IceConn iceConn;
+int majorOpcode;
+int offendingMinor;
+int severity;
+
+{
+ IceErrorHeader (iceConn,
+ majorOpcode, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceBadLength,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorBadValue (iceConn, majorOpcode, offendingMinor, offset, length, value)
+
+IceConn iceConn;
+int majorOpcode;
+int offendingMinor;
+int offset;
+int length; /* in bytes */
+IcePointer value;
+
+{
+ IceErrorHeader (iceConn,
+ majorOpcode, offendingMinor,
+ iceConn->receive_sequence,
+ IceCanContinue,
+ IceBadValue,
+ WORD64COUNT (8 + length));
+
+ IceWriteData32 (iceConn, 4, &offset);
+ IceWriteData32 (iceConn, 4, &length);
+ IceWriteData (iceConn, length, (char *) value);
+
+ if (PAD64 (length))
+ IceWritePad (iceConn, PAD64 (length));
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorNoAuthentication (iceConn, offendingMinor)
+
+IceConn iceConn;
+int offendingMinor;
+
+{
+ int severity = (offendingMinor == ICE_ConnectionSetup) ?
+ IceFatalToConnection : IceFatalToProtocol;
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceNoAuth,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorNoVersion (iceConn, offendingMinor)
+
+IceConn iceConn;
+int offendingMinor;
+
+{
+ int severity = (offendingMinor == ICE_ConnectionSetup) ?
+ IceFatalToConnection : IceFatalToProtocol;
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceNoVersion,
+ 0);
+
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorSetupFailed (iceConn, offendingMinor, reason)
+
+IceConn iceConn;
+int offendingMinor;
+char *reason;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+ int severity = (offendingMinor == ICE_ConnectionSetup) ?
+ IceFatalToConnection : IceFatalToProtocol;
+
+ if (!reason)
+ reason = "";
+ bytes = STRING_BYTES (reason);
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceSetupFailed,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, reason);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorAuthenticationRejected (iceConn, offendingMinor, reason)
+
+IceConn iceConn;
+int offendingMinor;
+char *reason;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+
+ if (!reason)
+ reason = "";
+ bytes = STRING_BYTES (reason);
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceAuthRejected,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, reason);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorAuthenticationFailed (iceConn, offendingMinor, reason)
+
+IceConn iceConn;
+int offendingMinor;
+char *reason;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+
+ if (!reason)
+ reason = "";
+ bytes = STRING_BYTES (reason);
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceAuthFailed,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, reason);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorProtocolDuplicate (iceConn, protocolName)
+
+IceConn iceConn;
+char *protocolName;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+
+ if (!protocolName)
+ protocolName = "";
+ bytes = STRING_BYTES (protocolName);
+
+ IceErrorHeader (iceConn,
+ 0, ICE_ProtocolSetup,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceProtocolDuplicate,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, protocolName);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorMajorOpcodeDuplicate (iceConn, majorOpcode)
+
+IceConn iceConn;
+int majorOpcode;
+
+{
+ char mOp = (char) majorOpcode;
+
+ IceErrorHeader (iceConn,
+ 0, ICE_ProtocolSetup,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceMajorOpcodeDuplicate,
+ 1 /* length */);
+
+ IceWriteData (iceConn, 8, &mOp);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorUnknownProtocol (iceConn, protocolName)
+
+IceConn iceConn;
+char *protocolName;
+
+{
+ char *pBuf, *pStart;
+ int bytes;
+
+ if (!protocolName)
+ protocolName = "";
+ bytes = STRING_BYTES (protocolName);
+
+ IceErrorHeader (iceConn,
+ 0, ICE_ProtocolSetup,
+ iceConn->receive_sequence,
+ IceFatalToProtocol,
+ IceUnknownProtocol,
+ WORD64COUNT (bytes));
+
+ pBuf = pStart = IceAllocScratch (iceConn, PADDED_BYTES64 (bytes));
+ STORE_STRING (pBuf, protocolName);
+
+ IceWriteData (iceConn, PADDED_BYTES64 (bytes), pStart);
+ IceFlush (iceConn);
+}
+
+
+void
+_IceErrorBadMajor (iceConn, offendingMajor, offendingMinor, severity)
+
+IceConn iceConn;
+int offendingMajor;
+int offendingMinor;
+int severity;
+
+{
+ char maj = (char) offendingMajor;
+
+ IceErrorHeader (iceConn,
+ 0, offendingMinor,
+ iceConn->receive_sequence,
+ severity,
+ IceBadMajor,
+ 1 /* length */);
+
+ IceWriteData (iceConn, 8, &maj);
+ IceFlush (iceConn);
+}
+
+
+
+/*
+ * Default error handler.
+ */
+
+void
+_IceDefaultErrorHandler (iceConn, swap,
+ offendingMinorOpcode, offendingSequence, errorClass, severity, values)
+
+IceConn iceConn;
+Bool swap;
+int offendingMinorOpcode;
+unsigned long offendingSequence;
+int errorClass;
+int severity;
+IcePointer values;
+
+{
+ char *str;
+ char *pData = (char *) values;
+
+ switch (offendingMinorOpcode)
+ {
+ case ICE_ConnectionSetup:
+ str = "ConnectionSetup";
+ break;
+ case ICE_AuthRequired:
+ str = "AuthRequired";
+ break;
+ case ICE_AuthReply:
+ str = "AuthReply";
+ break;
+ case ICE_AuthNextPhase:
+ str = "AuthNextPhase";
+ break;
+ case ICE_ConnectionReply:
+ str = "ConnectionReply";
+ break;
+ case ICE_ProtocolSetup:
+ str = "ProtocolSetup";
+ break;
+ case ICE_ProtocolReply:
+ str = "ProtocolReply";
+ break;
+ case ICE_Ping:
+ str = "Ping";
+ break;
+ case ICE_PingReply:
+ str = "PingReply";
+ break;
+ case ICE_WantToClose:
+ str = "WantToClose";
+ break;
+ case ICE_NoClose:
+ str = "NoClose";
+ break;
+ default:
+ str = "";
+ }
+
+ fprintf (stderr, "\n");
+
+ fprintf (stderr, "ICE error: Offending minor opcode = %d (%s)\n",
+ offendingMinorOpcode, str);
+
+ fprintf (stderr, " Offending sequence number = %d\n",
+ offendingSequence);
+
+ switch (errorClass)
+ {
+ case IceBadMinor:
+ str = "BadMinor";
+ break;
+ case IceBadState:
+ str = "BadState";
+ break;
+ case IceBadLength:
+ str = "BadLength";
+ break;
+ case IceBadValue:
+ str = "BadValue";
+ break;
+ case IceBadMajor:
+ str = "BadMajor";
+ break;
+ case IceNoAuth:
+ str = "NoAuthentication";
+ break;
+ case IceNoVersion:
+ str = "NoVersion";
+ break;
+ case IceSetupFailed:
+ str = "SetupFailed";
+ break;
+ case IceAuthRejected:
+ str = "AuthenticationRejected";
+ break;
+ case IceAuthFailed:
+ str = "AuthenticationFailed";
+ break;
+ case IceProtocolDuplicate:
+ str = "ProtocolDuplicate";
+ break;
+ case IceMajorOpcodeDuplicate:
+ str = "MajorOpcodeDuplicate";
+ break;
+ case IceUnknownProtocol:
+ str = "UnknownProtocol";
+ break;
+ default:
+ str = "???";
+ }
+
+ fprintf (stderr, " Error class = %s\n", str);
+
+ if (severity == IceCanContinue)
+ str = "CanContinue";
+ else if (severity == IceFatalToProtocol)
+ str = "FatalToProtocol";
+ else if (severity == IceFatalToConnection)
+ str = "FatalToConnection";
+ else
+ str = "???";
+
+ fprintf (stderr, " Severity = %s\n", str);
+
+ switch (errorClass)
+ {
+ case IceBadValue:
+ {
+ int offset, length, val;
+
+ EXTRACT_CARD32 (pData, swap, offset);
+ EXTRACT_CARD32 (pData, swap, length);
+
+ fprintf (stderr,
+ " BadValue Offset = %d\n", offset);
+ fprintf (stderr,
+ " BadValue Length = %d\n", length);
+
+ if (length <= 4)
+ {
+ if (length == 1)
+ val = (int) *pData;
+ else if (length == 2)
+ {
+ EXTRACT_CARD16 (pData, swap, val);
+ }
+ else
+ {
+ EXTRACT_CARD32 (pData, swap, val);
+ }
+
+ fprintf (stderr,
+ " BadValue = %d\n", val);
+ }
+ break;
+ }
+
+ case IceBadMajor:
+
+ fprintf (stderr, "Major opcode : %d\n", (int) *pData);
+ break;
+
+ case IceSetupFailed:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Reason : %s\n", str);
+ break;
+
+ case IceAuthRejected:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Reason : %s\n", str);
+ break;
+
+ case IceAuthFailed:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Reason : %s\n", str);
+ break;
+
+ case IceProtocolDuplicate:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Protocol name : %s\n", str);
+ break;
+
+ case IceMajorOpcodeDuplicate:
+
+ fprintf (stderr, "Major opcode : %d\n", (int) *pData);
+ break;
+
+ case IceUnknownProtocol:
+
+ EXTRACT_STRING (pData, swap, str);
+ fprintf (stderr, "Protocol name : %s\n", str);
+ break;
+
+ default:
+ break;
+ }
+
+ fprintf (stderr, "\n");
+
+ if (severity != IceCanContinue)
+ exit (1);
+}
+
+
+
+/*
+ * This procedure sets the ICE error handler to be the specified
+ * routine. If NULL is passed in the default error handler is restored.
+ * The function's return value is the previous error handler.
+ */
+
+IceErrorHandler
+IceSetErrorHandler (handler)
+
+IceErrorHandler handler;
+
+{
+ IceErrorHandler oldHandler = _IceErrorHandler;
+
+ if (handler != NULL)
+ _IceErrorHandler = handler;
+ else
+ _IceErrorHandler = _IceDefaultErrorHandler;
+
+ return (oldHandler);
+}
+
+
+
+/*
+ * Default IO error handler.
+ */
+
+void
+_IceDefaultIOErrorHandler (iceConn)
+
+IceConn iceConn;
+
+{
+ fprintf (stderr,
+ "ICE default IO error handler doing an exit(), pid = %d, errno = %d\n",
+ getpid(), errno);
+
+ exit (1);
+}
+
+
+
+/*
+ * This procedure sets the ICE fatal I/O error handler to be the
+ * specified routine. If NULL is passed in the default error
+ * handler is restored. The function's return value is the
+ * previous error handler.
+ */
+
+IceIOErrorHandler
+IceSetIOErrorHandler (handler)
+
+IceIOErrorHandler handler;
+
+{
+ IceIOErrorHandler oldHandler = _IceIOErrorHandler;
+
+ if (handler != NULL)
+ _IceIOErrorHandler = handler;
+ else
+ _IceIOErrorHandler = _IceDefaultIOErrorHandler;
+
+ return (oldHandler);
+}
diff --git a/src/getauth.c b/src/getauth.c
new file mode 100644
index 0000000..50024bd
--- /dev/null
+++ b/src/getauth.c
@@ -0,0 +1,270 @@
+/* $Xorg: getauth.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/ICE/ICEutil.h>
+
+static Bool auth_valid ();
+
+extern int _IcePaAuthDataEntryCount;
+extern IceAuthDataEntry _IcePaAuthDataEntries[];
+
+
+/*
+ * The functions in this file are not a standard part of ICElib.
+ *
+ * The sample implementation uses an .ICEauthority to manipulate
+ * authentication data.
+ *
+ * For the client that initiates a Protocol Setup, we look in the
+ * .ICEauthority file to get the data.
+ *
+ * For the client accepting the Protocol Setup, we get the data
+ * from an in-memory database of authentication data (set by the
+ * application calling IceSetPaAuthData). We have to get the data
+ * from memory because getting it directly from the .ICEauthority
+ * file is not secure - someone can just modify the contents of the
+ * .ICEauthority file behind our back.
+ */
+
+void
+_IceGetPoAuthData (protocolName, networkId, authName,
+ authDataLenRet, authDataRet)
+
+char *protocolName;
+char *networkId;
+char *authName;
+unsigned short *authDataLenRet;
+char **authDataRet;
+
+{
+ IceAuthFileEntry *entry;
+
+ entry = IceGetAuthFileEntry (protocolName, networkId, authName);
+
+ if (entry)
+ {
+ *authDataLenRet = entry->auth_data_length;
+
+ if ((*authDataRet = (char *) malloc (entry->auth_data_length)) != NULL)
+ memcpy (*authDataRet, entry->auth_data, entry->auth_data_length);
+ }
+ else
+ {
+ *authDataLenRet = 0;
+ *authDataRet = NULL;
+ }
+
+ IceFreeAuthFileEntry (entry);
+}
+
+
+
+void
+_IceGetPaAuthData (protocolName, networkId, authName,
+ authDataLenRet, authDataRet)
+
+char *protocolName;
+char *networkId;
+char *authName;
+unsigned short *authDataLenRet;
+char **authDataRet;
+
+{
+ IceAuthDataEntry *entry;
+ int found = 0;
+ int i;
+
+ for (i = 0; i < _IcePaAuthDataEntryCount && !found; i++)
+ {
+ entry = &_IcePaAuthDataEntries[i];
+
+ found =
+ strcmp (protocolName, entry->protocol_name) == 0 &&
+ strcmp (networkId, entry->network_id) == 0 &&
+ strcmp (authName, entry->auth_name) == 0;
+ }
+
+ if (found)
+ {
+ *authDataLenRet = entry->auth_data_length;
+
+ if ((*authDataRet = (char *) malloc (entry->auth_data_length)) != NULL)
+ memcpy (*authDataRet, entry->auth_data, entry->auth_data_length);
+ }
+ else
+ {
+ *authDataLenRet = 0;
+ *authDataRet = NULL;
+ }
+}
+
+
+
+void
+_IceGetPoValidAuthIndices (protocol_name, network_id,
+ num_auth_names, auth_names, num_indices_ret, indices_ret)
+
+char *protocol_name;
+char *network_id;
+int num_auth_names;
+char **auth_names;
+int *num_indices_ret;
+int *indices_ret; /* in/out arg */
+
+{
+ FILE *auth_file;
+ char *filename;
+ IceAuthFileEntry *entry;
+ int index_ret, i;
+
+ *num_indices_ret = 0;
+
+ if (!(filename = IceAuthFileName ()))
+ return;
+
+ if (access (filename, R_OK) != 0) /* checks REAL id */
+ return;
+
+ if (!(auth_file = fopen (filename, "rb")))
+ return;
+
+ for (;;)
+ {
+ if (!(entry = IceReadAuthFileEntry (auth_file)))
+ break;
+
+ if (strcmp (protocol_name, entry->protocol_name) == 0 &&
+ strcmp (network_id, entry->network_id) == 0 &&
+ auth_valid (entry->auth_name, num_auth_names,
+ auth_names, &index_ret))
+ {
+ /*
+ * Make sure we didn't store this index already.
+ */
+
+ for (i = 0; i < *num_indices_ret; i++)
+ if (index_ret == indices_ret[i])
+ break;
+
+ if (i >= *num_indices_ret)
+ {
+ indices_ret[*num_indices_ret] = index_ret;
+ *num_indices_ret += 1;
+ }
+ }
+
+ IceFreeAuthFileEntry (entry);
+ }
+
+ fclose (auth_file);
+}
+
+
+
+void
+_IceGetPaValidAuthIndices (protocol_name, network_id,
+ num_auth_names, auth_names, num_indices_ret, indices_ret)
+
+char *protocol_name;
+char *network_id;
+int num_auth_names;
+char **auth_names;
+int *num_indices_ret;
+int *indices_ret; /* in/out arg */
+
+{
+ int index_ret;
+ int i, j;
+ IceAuthDataEntry *entry;
+
+ *num_indices_ret = 0;
+
+ for (i = 0; i < _IcePaAuthDataEntryCount; i++)
+ {
+ entry = &_IcePaAuthDataEntries[i];
+
+ if (strcmp (protocol_name, entry->protocol_name) == 0 &&
+ strcmp (network_id, entry->network_id) == 0 &&
+ auth_valid (entry->auth_name, num_auth_names,
+ auth_names, &index_ret))
+ {
+ /*
+ * Make sure we didn't store this index already.
+ */
+
+ for (j = 0; j < *num_indices_ret; j++)
+ if (index_ret == indices_ret[j])
+ break;
+
+ if (j >= *num_indices_ret)
+ {
+ indices_ret[*num_indices_ret] = index_ret;
+ *num_indices_ret += 1;
+ }
+ }
+ }
+}
+
+
+
+/*
+ * local routines
+ */
+
+static Bool
+auth_valid (auth_name, num_auth_names, auth_names, index_ret)
+
+char *auth_name;
+int num_auth_names;
+char **auth_names;
+int *index_ret;
+
+{
+ /*
+ * Check if auth_name is in auth_names. Return index.
+ */
+
+ int i;
+
+ for (i = 0; i < num_auth_names; i++)
+ if (strcmp (auth_name, auth_names[i]) == 0)
+ {
+ break;
+ }
+
+ if (i < num_auth_names)
+ {
+ *index_ret = i;
+ return (1);
+ }
+ else
+ return (0);
+}
diff --git a/src/globals.h b/src/globals.h
new file mode 100644
index 0000000..6bffe7c
--- /dev/null
+++ b/src/globals.h
@@ -0,0 +1,57 @@
+/* $Xorg: globals.h,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+extern void _IceDefaultErrorHandler ();
+extern void _IceDefaultIOErrorHandler ();
+
+extern IcePoAuthStatus _IcePoMagicCookie1Proc ();
+extern IcePaAuthStatus _IcePaMagicCookie1Proc ();
+
+extern void _IceProcessCoreMessage ();
+
+IceConn _IceConnectionObjs[256];
+char *_IceConnectionStrings[256];
+int _IceConnectionCount = 0;
+
+_IceProtocol _IceProtocols[255];
+int _IceLastMajorOpcode = 0;
+
+int _IceAuthCount = 1;
+char *_IceAuthNames[] = {"MIT-MAGIC-COOKIE-1"};
+IcePoAuthProc _IcePoAuthProcs[] = {_IcePoMagicCookie1Proc};
+IcePaAuthProc _IcePaAuthProcs[] = {_IcePaMagicCookie1Proc};
+
+int _IceVersionCount = 1;
+_IceVersion _IceVersions[] = {
+ {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}};
+
+_IceWatchProc *_IceWatchProcs = NULL;
+
+IceErrorHandler _IceErrorHandler = _IceDefaultErrorHandler;
+IceIOErrorHandler _IceIOErrorHandler = _IceDefaultIOErrorHandler;
diff --git a/src/iceauth.c b/src/iceauth.c
new file mode 100644
index 0000000..4556b9a
--- /dev/null
+++ b/src/iceauth.c
@@ -0,0 +1,278 @@
+/* $Xorg: iceauth.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/ICE/ICEutil.h>
+
+#ifdef X_NOT_STDC_ENV
+#define Time_t long
+extern Time_t time ();
+#else
+#include <time.h>
+#define Time_t time_t
+#endif
+
+static int binaryEqual ();
+
+static int was_called_state;
+
+/*
+ * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by
+ * the SI. It is not part of standard ICElib.
+ */
+
+
+char *
+IceGenerateMagicCookie (len)
+
+int len;
+
+{
+ char *auth;
+ long ldata[2];
+ int seed;
+ int value;
+ int i;
+
+ if ((auth = (char *) malloc (len + 1)) == NULL)
+ return (NULL);
+
+#ifdef ITIMER_REAL
+ {
+ struct timeval now;
+ X_GETTIMEOFDAY (&now);
+ ldata[0] = now.tv_sec;
+ ldata[1] = now.tv_usec;
+ }
+#else
+ {
+ long time ();
+
+ ldata[0] = time ((long *) 0);
+ ldata[1] = getpid ();
+ }
+#endif
+ seed = (ldata[0]) + (ldata[1] << 16);
+ srand (seed);
+ for (i = 0; i < len; i++)
+ {
+ value = rand ();
+ auth[i] = value & 0xff;
+ }
+ auth[len] = '\0';
+
+ return (auth);
+}
+
+
+
+IcePoAuthStatus
+_IcePoMagicCookie1Proc (iceConn, authStatePtr, cleanUp, swap,
+ authDataLen, authData, replyDataLenRet, replyDataRet, errorStringRet)
+
+IceConn iceConn;
+IcePointer *authStatePtr;
+Bool cleanUp;
+Bool swap;
+int authDataLen;
+IcePointer authData;
+int *replyDataLenRet;
+IcePointer *replyDataRet;
+char **errorStringRet;
+
+{
+ if (cleanUp)
+ {
+ /*
+ * We didn't allocate any state. We're done.
+ */
+
+ return (IcePoAuthDoneCleanup);
+ }
+
+ *errorStringRet = NULL;
+
+ if (*authStatePtr == NULL)
+ {
+ /*
+ * This is the first time we're being called. Search the
+ * authentication data for the first occurence of
+ * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string.
+ */
+
+ unsigned short length;
+ char *data;
+
+ _IceGetPoAuthData ("ICE", iceConn->connection_string,
+ "MIT-MAGIC-COOKIE-1", &length, &data);
+
+ if (!data)
+ {
+ char *tempstr =
+ "Could not find correct MIT-MAGIC-COOKIE-1 authentication";
+
+ *errorStringRet = (char *) malloc (strlen (tempstr) + 1);
+ if (*errorStringRet)
+ strcpy (*errorStringRet, tempstr);
+
+ return (IcePoAuthFailed);
+ }
+ else
+ {
+ *authStatePtr = (IcePointer) &was_called_state;
+
+ *replyDataLenRet = length;
+ *replyDataRet = data;
+
+ return (IcePoAuthHaveReply);
+ }
+ }
+ else
+ {
+ /*
+ * We should never get here for MIT-MAGIC-COOKIE-1 since it is
+ * a single pass authentication method.
+ */
+
+ char *tempstr = "MIT-MAGIC-COOKIE-1 authentication internal error";
+
+ *errorStringRet = (char *) malloc (strlen (tempstr) + 1);
+ if (*errorStringRet)
+ strcpy (*errorStringRet, tempstr);
+
+ return (IcePoAuthFailed);
+ }
+}
+
+
+
+IcePaAuthStatus
+_IcePaMagicCookie1Proc (iceConn, authStatePtr, swap,
+ authDataLen, authData, replyDataLenRet, replyDataRet, errorStringRet)
+
+IceConn iceConn;
+IcePointer *authStatePtr;
+Bool swap;
+int authDataLen;
+IcePointer authData;
+int *replyDataLenRet;
+IcePointer *replyDataRet;
+char **errorStringRet;
+
+{
+ *errorStringRet = NULL;
+ *replyDataLenRet = 0;
+ *replyDataRet = NULL;
+
+ if (*authStatePtr == NULL)
+ {
+ /*
+ * This is the first time we're being called. We don't have
+ * any data to pass to the other client.
+ */
+
+ *authStatePtr = (IcePointer) &was_called_state;
+
+ return (IcePaAuthContinue);
+ }
+ else
+ {
+ /*
+ * Search the authentication data for the first occurence of
+ * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string.
+ */
+
+ unsigned short length;
+ char *data;
+
+ _IceGetPaAuthData ("ICE", iceConn->connection_string,
+ "MIT-MAGIC-COOKIE-1", &length, &data);
+
+ if (data)
+ {
+ IcePaAuthStatus stat;
+
+ if (authDataLen == length &&
+ binaryEqual ((char *) authData, data, authDataLen))
+ {
+ stat = IcePaAuthAccepted;
+ }
+ else
+ {
+ char *tempstr = "MIT-MAGIC-COOKIE-1 authentication rejected";
+
+ *errorStringRet = (char *) malloc (strlen (tempstr) + 1);
+ if (*errorStringRet)
+ strcpy (*errorStringRet, tempstr);
+
+ stat = IcePaAuthRejected;
+ }
+
+ free (data);
+ return (stat);
+ }
+ else
+ {
+ /*
+ * We should never get here because in the ConnectionReply
+ * we should have passed all the valid methods. So we should
+ * always find a valid entry.
+ */
+
+ char *tempstr =
+ "MIT-MAGIC-COOKIE-1 authentication internal error";
+
+ *errorStringRet = (char *) malloc (strlen (tempstr) + 1);
+ if (*errorStringRet)
+ strcpy (*errorStringRet, tempstr);
+
+ return (IcePaAuthFailed);
+ }
+ }
+}
+
+
+
+/*
+ * local routines
+ */
+
+static int
+binaryEqual (a, b, len)
+
+register char *a, *b;
+register unsigned len;
+
+{
+ while (len--)
+ if (*a++ != *b++)
+ return 0;
+ return 1;
+}
diff --git a/src/listen.c b/src/listen.c
new file mode 100644
index 0000000..cee141f
--- /dev/null
+++ b/src/listen.c
@@ -0,0 +1,280 @@
+/* $Xorg: listen.c,v 1.5 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/Xtrans.h>
+#include <stdio.h>
+
+
+Status
+IceListenForConnections (countRet, listenObjsRet, errorLength, errorStringRet)
+
+int *countRet;
+IceListenObj **listenObjsRet;
+int errorLength;
+char *errorStringRet;
+
+{
+ struct _IceListenObj *listenObjs;
+ char *networkId;
+ int transCount, partial, i, j;
+ Status status = 1;
+ XtransConnInfo *transConns = NULL;
+
+
+ if ((_IceTransMakeAllCOTSServerListeners (NULL, &partial,
+ &transCount, &transConns) < 0) || (transCount < 1))
+ {
+ *listenObjsRet = NULL;
+ *countRet = 0;
+
+ strncpy (errorStringRet,
+ "Cannot establish any listening sockets", errorLength);
+
+ return (0);
+ }
+
+ if ((listenObjs = (struct _IceListenObj *) malloc (
+ transCount * sizeof (struct _IceListenObj))) == NULL)
+ {
+ for (i = 0; i < transCount; i++)
+ _IceTransClose (transConns[i]);
+ free ((char *) transConns);
+ return (0);
+ }
+
+ *countRet = 0;
+
+ for (i = 0; i < transCount; i++)
+ {
+ networkId = _IceTransGetMyNetworkId (transConns[i]);
+
+ if (networkId)
+ {
+ listenObjs[*countRet].trans_conn = transConns[i];
+ listenObjs[*countRet].network_id = networkId;
+
+ (*countRet)++;
+ }
+ }
+
+ if (*countRet == 0)
+ {
+ *listenObjsRet = NULL;
+
+ strncpy (errorStringRet,
+ "Cannot establish any listening sockets", errorLength);
+
+ status = 0;
+ }
+ else
+ {
+ *listenObjsRet = (IceListenObj *) malloc (
+ *countRet * sizeof (IceListenObj));
+
+ if (*listenObjsRet == NULL)
+ {
+ strncpy (errorStringRet, "Malloc failed", errorLength);
+
+ status = 0;
+ }
+ else
+ {
+ for (i = 0; i < *countRet; i++)
+ {
+ (*listenObjsRet)[i] = (IceListenObj) malloc (
+ sizeof (struct _IceListenObj));
+
+ if ((*listenObjsRet)[i] == NULL)
+ {
+ strncpy (errorStringRet, "Malloc failed", errorLength);
+
+ for (j = 0; j < i; j++)
+ free ((char *) (*listenObjsRet)[j]);
+
+ free ((char *) *listenObjsRet);
+
+ status = 0;
+ }
+ else
+ {
+ *((*listenObjsRet)[i]) = listenObjs[i];
+ }
+ }
+ }
+ }
+
+ if (status == 1)
+ {
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ for (i = 0; i < *countRet; i++)
+ {
+ (*listenObjsRet)[i]->host_based_auth_proc = NULL;
+ }
+ }
+ else
+ {
+ for (i = 0; i < transCount; i++)
+ _IceTransClose (transConns[i]);
+ }
+
+ free ((char *) listenObjs);
+ free ((char *) transConns);
+
+ return (status);
+}
+
+
+
+int
+IceGetListenConnectionNumber (listenObj)
+
+IceListenObj listenObj;
+
+{
+ return (_IceTransGetConnectionNumber (listenObj->trans_conn));
+}
+
+
+
+char *
+IceGetListenConnectionString (listenObj)
+
+IceListenObj listenObj;
+
+{
+ char *networkId;
+
+ networkId = (char *) malloc (strlen (listenObj->network_id) + 1);
+
+ if (networkId)
+ strcpy (networkId, listenObj->network_id);
+
+ return (networkId);
+}
+
+
+
+char *
+IceComposeNetworkIdList (count, listenObjs)
+
+int count;
+IceListenObj *listenObjs;
+
+{
+ char *list;
+ int len = 0;
+ int i;
+
+ if (count < 1 || listenObjs == NULL)
+ return (NULL);
+
+ for (i = 0; i < count; i++)
+ len += (strlen (listenObjs[i]->network_id) + 1);
+
+ list = (char *) malloc (len);
+
+ if (list == NULL)
+ return (NULL);
+ else
+ {
+ int doneCount = 0;
+
+ list[0] = '\0';
+
+ for (i = 0; i < count; i++)
+ {
+ if (_IceTransIsLocal (listenObjs[i]->trans_conn))
+ {
+ strcat (list, listenObjs[i]->network_id);
+ doneCount++;
+ if (doneCount < count)
+ strcat (list, ",");
+ }
+ }
+
+ if (doneCount < count)
+ {
+ for (i = 0; i < count; i++)
+ {
+ if (!_IceTransIsLocal (listenObjs[i]->trans_conn))
+ {
+ strcat (list, listenObjs[i]->network_id);
+ doneCount++;
+ if (doneCount < count)
+ strcat (list, ",");
+ }
+ }
+ }
+
+ return (list);
+ }
+}
+
+
+
+void
+IceFreeListenObjs (count, listenObjs)
+
+int count;
+IceListenObj *listenObjs;
+
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ free (listenObjs[i]->network_id);
+ _IceTransClose (listenObjs[i]->trans_conn);
+ free ((char *) listenObjs[i]);
+ }
+
+ free ((char *) listenObjs);
+}
+
+
+
+/*
+ * Allow host based authentication for the ICE Connection Setup.
+ * Do not confuse with the host based authentication callbacks that
+ * can be set up in IceRegisterForProtocolReply.
+ */
+
+void
+IceSetHostBasedAuthProc (listenObj, hostBasedAuthProc)
+
+IceListenObj listenObj;
+IceHostBasedAuthProc hostBasedAuthProc;
+
+{
+ listenObj->host_based_auth_proc = hostBasedAuthProc;
+}
diff --git a/src/listenwk.c b/src/listenwk.c
new file mode 100644
index 0000000..156fc61
--- /dev/null
+++ b/src/listenwk.c
@@ -0,0 +1,157 @@
+/* $Xorg: listenwk.c,v 1.5 2001/02/09 02:03:26 xorgcvs Exp $ */
+
+/*
+
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+*/
+
+
+/* Author: Ralph Mor, X Consortium */
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/Xtrans.h>
+#include <stdio.h>
+
+
+Status
+IceListenForWellKnownConnections (port, countRet, listenObjsRet, errorLength, errorStringRet)
+
+char *port;
+int *countRet;
+IceListenObj **listenObjsRet;
+int errorLength;
+char *errorStringRet;
+
+{
+ struct _IceListenObj *listenObjs;
+ char *networkId;
+ int transCount, partial, i, j;
+ Status status = 1;
+ XtransConnInfo *transConns = NULL;
+
+
+ if ((_IceTransMakeAllCOTSServerListeners (port, &partial,
+ &transCount, &transConns) < 0) || (transCount < 1))
+ {
+ *listenObjsRet = NULL;
+ *countRet = 0;
+
+ strncpy (errorStringRet,
+ "Cannot establish any listening sockets", errorLength);
+
+ return (0);
+ }
+
+ if ((listenObjs = (struct _IceListenObj *) malloc (
+ transCount * sizeof (struct _IceListenObj))) == NULL)
+ {
+ for (i = 0; i < transCount; i++)
+ _IceTransClose (transConns[i]);
+ free ((char *) transConns);
+ return (0);
+ }
+
+ *countRet = 0;
+
+ for (i = 0; i < transCount; i++)
+ {
+ networkId = (char *)_IceTransGetMyNetworkId (transConns[i]);
+
+ if (networkId)
+ {
+ listenObjs[*countRet].trans_conn = transConns[i];
+ listenObjs[*countRet].network_id = networkId;
+
+ (*countRet)++;
+ }
+ }
+
+ if (*countRet == 0)
+ {
+ *listenObjsRet = NULL;
+
+ strncpy (errorStringRet,
+ "Cannot establish any listening sockets", errorLength);
+
+ status = 0;
+ }
+ else
+ {
+ *listenObjsRet = (IceListenObj *) malloc (
+ *countRet * sizeof (IceListenObj));
+
+ if (*listenObjsRet == NULL)
+ {
+ strncpy (errorStringRet, "Malloc failed", errorLength);
+
+ status = 0;
+ }
+ else
+ {
+ for (i = 0; i < *countRet; i++)
+ {
+ (*listenObjsRet)[i] = (IceListenObj) malloc (
+ sizeof (struct _IceListenObj));
+
+ if ((*listenObjsRet)[i] == NULL)
+ {
+ strncpy (errorStringRet, "Malloc failed", errorLength);
+
+ for (j = 0; j < i; j++)
+ free ((char *) (*listenObjsRet)[j]);
+
+ free ((char *) *listenObjsRet);
+
+ status = 0;
+ }
+ else
+ {
+ *((*listenObjsRet)[i]) = listenObjs[i];
+ }
+ }
+ }
+ }
+
+ if (status == 1)
+ {
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ for (i = 0; i < *countRet; i++)
+ {
+ (*listenObjsRet)[i]->host_based_auth_proc = NULL;
+ }
+ }
+ else
+ {
+ for (i = 0; i < transCount; i++)
+ _IceTransClose (transConns[i]);
+ }
+
+ free ((char *) listenObjs);
+ free ((char *) transConns);
+
+ return (status);
+}
diff --git a/src/locking.c b/src/locking.c
new file mode 100644
index 0000000..c16c3a1
--- /dev/null
+++ b/src/locking.c
@@ -0,0 +1,64 @@
+/* $Xorg: locking.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+
+
+/*
+ * NOT IMPLEMENTED YET
+ */
+
+
+Status
+IceInitThreads ()
+
+{
+ return (0);
+}
+
+
+void
+IceAppLockConn (iceConn)
+
+IceConn iceConn;
+
+{
+ IceLockConn (iceConn);
+}
+
+
+void
+IceAppUnlockConn (iceConn)
+
+IceConn iceConn;
+
+{
+ IceUnlockConn (iceConn);
+}
diff --git a/src/misc.c b/src/misc.c
new file mode 100644
index 0000000..0ed98b0
--- /dev/null
+++ b/src/misc.c
@@ -0,0 +1,621 @@
+/* $Xorg: misc.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#ifdef WIN32
+#define _WILLWINSOCK_
+#endif
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/Xtrans.h>
+#include <stdio.h>
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#include <X11/Xw32defs.h>
+#endif
+
+
+/*
+ * scratch buffer
+ */
+
+char *
+IceAllocScratch (iceConn, size)
+
+IceConn iceConn;
+unsigned long size;
+
+{
+ if (!iceConn->scratch || size > iceConn->scratch_size)
+ {
+ if (iceConn->scratch)
+ free (iceConn->scratch);
+
+ iceConn->scratch = (char *) malloc ((unsigned) size);
+ iceConn->scratch_size = size;
+ }
+
+ return (iceConn->scratch);
+}
+
+
+
+/*
+ * Output/Input buffer functions
+ */
+
+IceFlush (iceConn)
+
+IceConn iceConn;
+
+{
+ _IceWrite (iceConn,
+ (unsigned long) (iceConn->outbufptr - iceConn->outbuf),
+ iceConn->outbuf);
+
+ iceConn->outbufptr = iceConn->outbuf;
+ return 1;
+}
+
+
+int
+IceGetOutBufSize (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->outbufmax - iceConn->outbuf);
+}
+
+
+int
+IceGetInBufSize (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->inbufmax - iceConn->inbuf);
+}
+
+
+
+/*
+ * informational functions
+ */
+
+IceConnectStatus
+IceConnectionStatus (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->connection_status);
+}
+
+
+char *
+IceVendor (iceConn)
+
+IceConn iceConn;
+
+{
+ char *string = (char *) malloc (strlen (iceConn->vendor) + 1);
+
+ if (string)
+ strcpy (string, iceConn->vendor);
+
+ return (string);
+}
+
+
+char *
+IceRelease (iceConn)
+
+IceConn iceConn;
+
+{
+ char *string = (char *) malloc (strlen (iceConn->release) + 1);
+
+ if (string)
+ strcpy (string, iceConn->release);
+
+ return (string);
+}
+
+
+int
+IceProtocolVersion (iceConn)
+
+IceConn iceConn;
+
+{
+ return (_IceVersions[iceConn->my_ice_version_index].major_version);
+}
+
+
+int
+IceProtocolRevision (iceConn)
+
+IceConn iceConn;
+
+{
+ return (_IceVersions[iceConn->my_ice_version_index].minor_version);
+}
+
+
+int
+IceConnectionNumber (iceConn)
+
+IceConn iceConn;
+
+{
+ return (_IceTransGetConnectionNumber (iceConn->trans_conn));
+}
+
+
+char *
+IceConnectionString (iceConn)
+
+IceConn iceConn;
+
+{
+ if (iceConn->connection_string)
+ {
+ char *string = (char *) malloc (
+ strlen (iceConn->connection_string) + 1);
+
+ if (string)
+ strcpy (string, iceConn->connection_string);
+
+ return (string);
+ }
+ else
+ return (NULL);
+}
+
+
+unsigned long
+IceLastSentSequenceNumber (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->send_sequence);
+}
+
+
+unsigned long
+IceLastReceivedSequenceNumber (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->receive_sequence);
+}
+
+
+Bool
+IceSwapping (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->swap);
+}
+
+
+
+/*
+ * Read "n" bytes from a connection.
+ *
+ * Return Status 0 if we detected an EXPECTED closed connection.
+ *
+ */
+
+Status
+_IceRead (iceConn, nbytes, ptr)
+
+register IceConn iceConn;
+unsigned long nbytes;
+register char *ptr;
+
+{
+ register unsigned long nleft;
+
+ nleft = nbytes;
+ while (nleft > 0)
+ {
+ int nread;
+
+ if (iceConn->io_ok)
+ nread = _IceTransRead (iceConn->trans_conn, ptr, (int) nleft);
+ else
+ return (1);
+
+ if (nread <= 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ if (iceConn->want_to_close)
+ {
+ /*
+ * We sent a WantToClose message and now we detected that
+ * the other side closed the connection.
+ */
+
+ _IceConnectionClosed (iceConn); /* invoke watch procs */
+ _IceFreeConnection (iceConn);
+
+ return (0);
+ }
+ else
+ {
+ /*
+ * Fatal IO error. First notify each protocol's IceIOErrorProc
+ * callback, then invoke the application IO error handler.
+ */
+
+ iceConn->io_ok = False;
+
+ if (iceConn->connection_status == IceConnectPending)
+ {
+ /*
+ * Don't invoke IO error handler if we are in the
+ * middle of a connection setup.
+ */
+
+ return (1);
+ }
+
+ if (iceConn->process_msg_info)
+ {
+ int i;
+
+ for (i = iceConn->his_min_opcode;
+ i <= iceConn->his_max_opcode; i++)
+ {
+ _IceProcessMsgInfo *process;
+
+ process = &iceConn->process_msg_info[
+ i - iceConn->his_min_opcode];
+
+ if (process->in_use)
+ {
+ IceIOErrorProc IOErrProc = process->accept_flag ?
+ process->protocol->accept_client->io_error_proc :
+ process->protocol->orig_client->io_error_proc;
+
+ if (IOErrProc)
+ (*IOErrProc) (iceConn);
+ }
+ }
+ }
+
+ (*_IceIOErrorHandler) (iceConn);
+ return (1);
+ }
+ }
+
+ nleft -= nread;
+ ptr += nread;
+ }
+
+ return (1);
+}
+
+
+
+/*
+ * If we read a message header with a bad major or minor opcode,
+ * we need to advance to the end of the message. This way, the next
+ * message can be processed correctly.
+ */
+
+void
+_IceReadSkip (iceConn, nbytes)
+
+register IceConn iceConn;
+register unsigned long nbytes;
+
+{
+ char temp[512];
+
+ while (nbytes > 0)
+ {
+ unsigned long rbytes = nbytes > 512 ? 512 : nbytes;
+
+ _IceRead (iceConn, rbytes, temp);
+ nbytes -= rbytes;
+ }
+}
+
+
+
+/*
+ * Write "n" bytes to a connection.
+ */
+
+void
+_IceWrite (iceConn, nbytes, ptr)
+
+register IceConn iceConn;
+unsigned long nbytes;
+register char *ptr;
+
+{
+ register unsigned long nleft;
+
+ nleft = nbytes;
+ while (nleft > 0)
+ {
+ int nwritten;
+
+ if (iceConn->io_ok)
+ nwritten = _IceTransWrite (iceConn->trans_conn, ptr, (int) nleft);
+ else
+ return;
+
+ if (nwritten <= 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ /*
+ * Fatal IO error. First notify each protocol's IceIOErrorProc
+ * callback, then invoke the application IO error handler.
+ */
+
+ iceConn->io_ok = False;
+
+ if (iceConn->connection_status == IceConnectPending)
+ {
+ /*
+ * Don't invoke IO error handler if we are in the
+ * middle of a connection setup.
+ */
+
+ return;
+ }
+
+ if (iceConn->process_msg_info)
+ {
+ int i;
+
+ for (i = iceConn->his_min_opcode;
+ i <= iceConn->his_max_opcode; i++)
+ {
+ _IceProcessMsgInfo *process;
+
+ process = &iceConn->process_msg_info[
+ i - iceConn->his_min_opcode];
+
+ if (process->in_use)
+ {
+ IceIOErrorProc IOErrProc = process->accept_flag ?
+ process->protocol->accept_client->io_error_proc :
+ process->protocol->orig_client->io_error_proc;
+
+ if (IOErrProc)
+ (*IOErrProc) (iceConn);
+ }
+ }
+ }
+
+ (*_IceIOErrorHandler) (iceConn);
+ return;
+ }
+
+ nleft -= nwritten;
+ ptr += nwritten;
+ }
+}
+
+#ifdef WORD64
+
+IceWriteData16 (iceConn, nbytes, data)
+
+IceConn iceConn;
+unsigned long nbytes;
+short *data;
+
+{
+ int numShorts = nbytes / 2;
+ int index = 0;
+
+ while (index < numShorts)
+ {
+ int spaceLeft, count, i;
+ int shortsLeft = numShorts - index;
+
+ spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
+
+ if (spaceLeft < 2)
+ {
+ IceFlush (iceConn);
+ spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
+ }
+
+ count = (shortsLeft < spaceLeft / 2) ? shortsLeft : spaceLeft / 2;
+
+ for (i = 0; i < count; i++)
+ STORE_CARD16 (iceConn->outbufptr, data[index++]);
+ }
+}
+
+
+IceWriteData32 (iceConn, nbytes, data)
+
+IceConn iceConn;
+unsigned long nbytes;
+int *data;
+
+{
+ int numLongs = nbytes / 4;
+ int index = 0;
+
+ while (index < numLongs)
+ {
+ int spaceLeft, count, i;
+ int longsLeft = numLongs - index;
+
+ spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
+
+ if (spaceLeft < 4)
+ {
+ IceFlush (iceConn);
+ spaceLeft = iceConn->outbufmax - iceConn->outbufptr - 1;
+ }
+
+ count = (longsLeft < spaceLeft / 4) ? longsLeft : spaceLeft / 4;
+
+ for (i = 0; i < count; i++)
+ STORE_CARD32 (iceConn->outbufptr, data[index++]);
+ }
+}
+
+
+IceReadData16 (iceConn, swap, nbytes, data)
+
+IceConn iceConn;
+Bool swap;
+unsigned long nbytes;
+short *data;
+
+{
+ /* NOT IMPLEMENTED YET */
+}
+
+
+IceReadData32 (iceConn, swap, nbytes, data)
+
+IceConn iceConn;
+Bool swap;
+unsigned long nbytes;
+int *data;
+
+{
+ /* NOT IMPLEMENTED YET */
+}
+
+#endif /* WORD64 */
+
+
+
+void
+_IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode)
+
+IceConn iceConn;
+int hisOpcode;
+int myOpcode;
+
+{
+ if (hisOpcode <= 0 || hisOpcode > 255)
+ {
+ return;
+ }
+ else if (iceConn->process_msg_info == NULL)
+ {
+ iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc (
+ sizeof (_IceProcessMsgInfo));
+ iceConn->his_min_opcode = iceConn->his_max_opcode = hisOpcode;
+ }
+ else if (hisOpcode < iceConn->his_min_opcode)
+ {
+ _IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
+ int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
+ int newsize = iceConn->his_max_opcode - hisOpcode + 1;
+ int i;
+
+ iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc (
+ newsize * sizeof (_IceProcessMsgInfo));
+
+ memcpy (&iceConn->process_msg_info[
+ iceConn->his_min_opcode - hisOpcode], oldVec,
+ oldsize * sizeof (_IceProcessMsgInfo));
+
+ free ((char *) oldVec);
+
+ for (i = hisOpcode + 1; i < iceConn->his_min_opcode; i++)
+ {
+ iceConn->process_msg_info[i -
+ iceConn->his_min_opcode].in_use = False;
+
+ iceConn->process_msg_info[i -
+ iceConn->his_min_opcode].protocol = NULL;
+ }
+
+ iceConn->his_min_opcode = hisOpcode;
+ }
+ else if (hisOpcode > iceConn->his_max_opcode)
+ {
+ _IceProcessMsgInfo *oldVec = iceConn->process_msg_info;
+ int oldsize = iceConn->his_max_opcode - iceConn->his_min_opcode + 1;
+ int newsize = hisOpcode - iceConn->his_min_opcode + 1;
+ int i;
+
+ iceConn->process_msg_info = (_IceProcessMsgInfo *) malloc (
+ newsize * sizeof (_IceProcessMsgInfo));
+
+ memcpy (iceConn->process_msg_info, oldVec,
+ oldsize * sizeof (_IceProcessMsgInfo));
+
+ free ((char *) oldVec);
+
+ for (i = iceConn->his_max_opcode + 1; i < hisOpcode; i++)
+ {
+ iceConn->process_msg_info[i -
+ iceConn->his_min_opcode].in_use = False;
+
+ iceConn->process_msg_info[i -
+ iceConn->his_min_opcode].protocol = NULL;
+ }
+
+ iceConn->his_max_opcode = hisOpcode;
+ }
+
+ iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode].in_use = True;
+
+ iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode].my_opcode = myOpcode;
+
+ iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode].protocol = &_IceProtocols[myOpcode - 1];
+}
+
+
+
+char *
+_IceGetPeerName (iceConn)
+
+IceConn iceConn;
+
+{
+ return (_IceTransGetPeerNetworkId (iceConn->trans_conn));
+}
diff --git a/src/ping.c b/src/ping.c
new file mode 100644
index 0000000..bee042a
--- /dev/null
+++ b/src/ping.c
@@ -0,0 +1,63 @@
+/* $Xorg: ping.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+
+Status
+IcePing (iceConn, pingReplyProc, clientData)
+
+IceConn iceConn;
+IcePingReplyProc pingReplyProc;
+IcePointer clientData;
+
+{
+ _IcePingWait *newping = (_IcePingWait *) malloc (sizeof (_IcePingWait));
+ _IcePingWait *ptr = iceConn->ping_waits;
+
+ if (newping == NULL)
+ return (0);
+
+ newping->ping_reply_proc = pingReplyProc;
+ newping->client_data = clientData;
+ newping->next = NULL;
+
+ while (ptr && ptr->next)
+ ptr = ptr->next;
+
+ if (ptr == NULL)
+ iceConn->ping_waits = newping;
+ else
+ ptr->next = newping;
+
+ IceSimpleMessage (iceConn, 0, ICE_Ping);
+ IceFlush (iceConn);
+
+ return (1);
+}
diff --git a/src/process.c b/src/process.c
new file mode 100644
index 0000000..159348d
--- /dev/null
+++ b/src/process.c
@@ -0,0 +1,2490 @@
+/* $Xorg: process.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+
+
+/*
+ * Check for bad length
+ */
+
+#define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity) \
+ if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
+ return (0); \
+ }
+
+#define CHECK_AT_LEAST_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _severity) \
+ if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) > _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
+ return (0); \
+ }
+
+#define CHECK_COMPLETE_SIZE(_iceConn, _opcode, _expected_len, _actual_len, _pStart, _severity) \
+ if (((PADDED_BYTES64((_actual_len)) - SIZEOF (iceMsg)) >> 3) \
+ != _expected_len) \
+ { \
+ _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \
+ IceDisposeCompleteMessage (iceConn, _pStart); \
+ return (0); \
+ }
+
+
+
+/*
+ * IceProcessMessages:
+ *
+ * If replyWait == NULL, the client is not waiting for a reply.
+ *
+ * If replyWait != NULL, the client is waiting for a reply...
+ *
+ * - replyWait->sequence_of_request is the sequence number of the
+ * message for which the client is waiting a reply. This is needed
+ * to determine if an error matches a replyWait.
+ *
+ * - replyWait->major_opcode_of_request is the major opcode of the
+ * message for which we are waiting a reply.
+ *
+ * - replyWait->minor_opcode_of_request is the minor opcode of the
+ * message for which we are waiting a reply.
+ *
+ * - replyWait->reply is a pointer to the reply message which will be
+ * filled in when the reply is ready (the protocol library should
+ * cast this IcePointer to the appropriate reply type). In most cases,
+ * the reply will have some fixed-size part, and the sender function
+ * will have provided a pointer to a structure (e.g.) to hold this
+ * fixed-size data. If there is variable-length data, it would be
+ * expected that the reply function 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 (e.g., a single
+ * variable-length string), then the sender function would probably
+ * just pass a pointer to fixed-size space to hold a pointer, and the
+ * reply function would allocate the storage and store the pointer.
+ * It is the responsibility of the client receiving the reply to
+ * free up any memory allocated on it's behalf.
+ *
+ * We might be waiting for several different replies (a function can wait
+ * for a reply, and while calling IceProcessMessages, a callback can be
+ * invoked which will wait for another reply). We take advantage of the
+ * fact that for a given protocol, we are guaranteed that messages are
+ * processed in the order we sent them. So, everytime we have a new
+ * replyWait, we add it to the END of the 'saved_reply_waits' list. When
+ * we read a message and want to see if it matches a replyWait, we use the
+ * FIRST replyWait in the list with the major opcode of the message. If the
+ * reply is ready, we remove that replyWait from the list.
+ *
+ * If the reply/error is ready for the replyWait passed in to
+ * IceProcessMessages, *replyReadyRet is set to True.
+ *
+ * The return value of IceProcessMessages is one of the following:
+ *
+ * IceProcessMessagesSuccess - the message was processed successfully.
+ * IceProcessMessagesIOError - an IO error occured. The caller should
+ * invoked IceCloseConnection.
+ * IceProcessMessagesConnectionClosed - the connection was closed as a
+ * result of shutdown negotiation.
+ */
+
+IceProcessMessagesStatus
+IceProcessMessages (iceConn, replyWait, replyReadyRet)
+
+IceConn iceConn;
+IceReplyWaitInfo *replyWait;
+Bool *replyReadyRet;
+
+{
+ iceMsg *header;
+ Bool replyReady = False;
+ IceReplyWaitInfo *useThisReplyWait = NULL;
+ IceProcessMessagesStatus retStatus = IceProcessMessagesSuccess;
+
+ if (replyWait)
+ *replyReadyRet = False;
+
+ /*
+ * Each time IceProcessMessages is entered, we increment the dispatch
+ * level. Each time we leave it, we decrement the dispatch level.
+ */
+
+ iceConn->dispatch_level++;
+
+
+ /*
+ * Read the ICE message header.
+ */
+
+ if (!_IceRead (iceConn, (unsigned long) SIZEOF (iceMsg), iceConn->inbuf))
+ {
+ /*
+ * If we previously sent a WantToClose and now we detected
+ * that the connection was closed, _IceRead returns status 0.
+ * Since the connection was closed, we just want to return here.
+ */
+
+ return (IceProcessMessagesConnectionClosed);
+ }
+
+ if (!iceConn->io_ok)
+ {
+ /*
+ * An unexpected IO error occured. The caller of IceProcessMessages
+ * should call IceCloseConnection which will cause the watch procedures
+ * to be invoked and the ICE connection to be freed.
+ */
+
+ iceConn->dispatch_level--;
+ iceConn->connection_status = IceConnectIOError;
+ return (IceProcessMessagesIOError);
+ }
+
+ header = (iceMsg *) iceConn->inbuf;
+ iceConn->inbufptr = iceConn->inbuf + SIZEOF (iceMsg);
+
+ iceConn->receive_sequence++;
+
+ if (iceConn->waiting_for_byteorder)
+ {
+ if (header->majorOpcode == 0 &&
+ header->minorOpcode == ICE_ByteOrder)
+ {
+ char byteOrder = ((iceByteOrderMsg *) header)->byteOrder;
+ int endian = 1;
+
+ CHECK_SIZE_MATCH (iceConn, ICE_ByteOrder,
+ header->length, SIZEOF (iceByteOrderMsg),
+ IceFatalToConnection);
+
+ if (byteOrder != IceMSBfirst && byteOrder != IceLSBfirst)
+ {
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ByteOrder, 2, 1, &byteOrder);
+
+ iceConn->connection_status = IceConnectRejected;
+ }
+ else
+ {
+ iceConn->swap =
+ (((*(char *) &endian) && byteOrder == IceMSBfirst) ||
+ !(*(char *) &endian) && byteOrder == IceLSBfirst);
+
+ iceConn->waiting_for_byteorder = 0;
+ }
+ }
+ else
+ {
+ if (header->majorOpcode != 0)
+ {
+ _IceErrorBadMajor (iceConn, header->majorOpcode,
+ header->minorOpcode, IceFatalToConnection);
+ }
+ else
+ {
+ _IceErrorBadState (iceConn, 0,
+ header->minorOpcode, IceFatalToConnection);
+ }
+
+ iceConn->connection_status = IceConnectRejected;
+ }
+
+ iceConn->dispatch_level--;
+ if (!iceConn->io_ok)
+ {
+ iceConn->connection_status = IceConnectIOError;
+ retStatus = IceProcessMessagesIOError;
+ }
+
+ return (retStatus);
+ }
+
+ if (iceConn->swap)
+ {
+ /* swap the length field */
+
+ header->length = lswapl (header->length);
+ }
+
+ if (replyWait)
+ {
+ /*
+ * Add to the list of replyWaits (only if it doesn't exist
+ * in the list already.
+ */
+
+ _IceAddReplyWait (iceConn, replyWait);
+
+
+ /*
+ * Note that there are two different replyWaits. The first is
+ * the one passed into IceProcessMessages, and is the replyWait
+ * for the message the client is blocking on. The second is
+ * the replyWait for the message currently being processed
+ * by IceProcessMessages. We call it "useThisReplyWait".
+ */
+
+ useThisReplyWait = _IceSearchReplyWaits (iceConn, header->majorOpcode);
+ }
+
+ if (header->majorOpcode == 0)
+ {
+ /*
+ * ICE protocol
+ */
+
+ Bool connectionClosed;
+
+ _IceProcessCoreMsgProc processIce =
+ _IceVersions[iceConn->my_ice_version_index].process_core_msg_proc;
+
+ (*processIce) (iceConn, header->minorOpcode,
+ header->length, iceConn->swap,
+ useThisReplyWait, &replyReady, &connectionClosed);
+
+ if (connectionClosed)
+ {
+ /*
+ * As a result of shutdown negotiation, the connection was closed.
+ */
+
+ return (IceProcessMessagesConnectionClosed);
+ }
+ }
+ else
+ {
+ /*
+ * Sub protocol
+ */
+
+ if ((int) header->majorOpcode < iceConn->his_min_opcode ||
+ (int) header->majorOpcode > iceConn->his_max_opcode ||
+ !(iceConn->process_msg_info[header->majorOpcode -
+ iceConn->his_min_opcode].in_use))
+ {
+ /*
+ * The protocol of the message we just read is not supported.
+ */
+
+ _IceErrorBadMajor (iceConn, header->majorOpcode,
+ header->minorOpcode, IceCanContinue);
+
+ _IceReadSkip (iceConn, header->length << 3);
+ }
+ else
+ {
+ _IceProcessMsgInfo *processMsgInfo = &iceConn->process_msg_info[
+ header->majorOpcode - iceConn->his_min_opcode];
+
+ if (processMsgInfo->accept_flag)
+ {
+ IcePaProcessMsgProc processProc =
+ processMsgInfo->process_msg_proc.accept_client;
+
+ (*processProc) (iceConn, processMsgInfo->client_data,
+ header->minorOpcode, header->length, iceConn->swap);
+ }
+ else
+ {
+ IcePoProcessMsgProc processProc =
+ processMsgInfo->process_msg_proc.orig_client;
+
+ (*processProc) (iceConn,
+ processMsgInfo->client_data, header->minorOpcode,
+ header->length, iceConn->swap,
+ useThisReplyWait, &replyReady);
+ }
+ }
+ }
+
+ if (replyReady)
+ {
+ _IceSetReplyReady (iceConn, useThisReplyWait);
+ }
+
+
+ /*
+ * Now we check if the reply is ready for the replyWait passed
+ * into IceProcessMessages. The replyWait is removed from the
+ * replyWait list if it is ready.
+ */
+
+ if (replyWait)
+ *replyReadyRet = _IceCheckReplyReady (iceConn, replyWait);
+
+
+ /*
+ * Decrement the dispatch level. If we reach level 0, and the
+ * free_asap bit is set, free the connection now. Also check for
+ * possible bad IO status.
+ */
+
+ iceConn->dispatch_level--;
+
+ if (iceConn->dispatch_level == 0 && iceConn->free_asap)
+ {
+ _IceFreeConnection (iceConn);
+ retStatus = IceProcessMessagesConnectionClosed;
+ }
+ else if (!iceConn->io_ok)
+ {
+ iceConn->connection_status = IceConnectIOError;
+ retStatus = IceProcessMessagesIOError;
+ }
+
+ return (retStatus);
+}
+
+
+
+static void
+AuthRequired (iceConn, authIndex, authDataLen, authData)
+
+IceConn iceConn;
+int authIndex;
+int authDataLen;
+IcePointer authData;
+
+{
+ iceAuthRequiredMsg *pMsg;
+
+ IceGetHeader (iceConn, 0, ICE_AuthRequired,
+ SIZEOF (iceAuthRequiredMsg), iceAuthRequiredMsg, pMsg);
+
+ pMsg->authIndex = authIndex;
+ pMsg->authDataLength = authDataLen;
+ pMsg->length += WORD64COUNT (authDataLen);
+
+ IceWriteData (iceConn, authDataLen, (char *) authData);
+
+ if (PAD64 (authDataLen))
+ IceWritePad (iceConn, PAD64 (authDataLen));
+
+ IceFlush (iceConn);
+}
+
+
+
+static void
+AuthReply (iceConn, authDataLen, authData)
+
+IceConn iceConn;
+int authDataLen;
+IcePointer authData;
+
+{
+ iceAuthReplyMsg *pMsg;
+
+ IceGetHeader (iceConn, 0, ICE_AuthReply,
+ SIZEOF (iceAuthReplyMsg), iceAuthReplyMsg, pMsg);
+
+ pMsg->authDataLength = authDataLen;
+ pMsg->length += WORD64COUNT (authDataLen);
+
+ IceWriteData (iceConn, authDataLen, (char *) authData);
+
+ if (PAD64 (authDataLen))
+ IceWritePad (iceConn, PAD64 (authDataLen));
+
+ IceFlush (iceConn);
+}
+
+
+
+static void
+AuthNextPhase (iceConn, authDataLen, authData)
+
+IceConn iceConn;
+int authDataLen;
+IcePointer authData;
+
+{
+ iceAuthNextPhaseMsg *pMsg;
+
+ IceGetHeader (iceConn, 0, ICE_AuthNextPhase,
+ SIZEOF (iceAuthNextPhaseMsg), iceAuthNextPhaseMsg, pMsg);
+
+ pMsg->authDataLength = authDataLen;
+ pMsg->length += WORD64COUNT (authDataLen);
+
+ IceWriteData (iceConn, authDataLen, (char *) authData);
+
+ if (PAD64 (authDataLen))
+ IceWritePad (iceConn, PAD64 (authDataLen));
+
+ IceFlush (iceConn);
+}
+
+
+
+static void
+AcceptConnection (iceConn, versionIndex)
+
+IceConn iceConn;
+int versionIndex;
+
+{
+ iceConnectionReplyMsg *pMsg;
+ char *pData;
+ int extra;
+
+ extra = STRING_BYTES (IceVendorString) + STRING_BYTES (IceReleaseString);
+
+ IceGetHeaderExtra (iceConn, 0, ICE_ConnectionReply,
+ SIZEOF (iceConnectionReplyMsg), WORD64COUNT (extra),
+ iceConnectionReplyMsg, pMsg, pData);
+
+ pMsg->versionIndex = versionIndex;
+
+ STORE_STRING (pData, IceVendorString);
+ STORE_STRING (pData, IceReleaseString);
+
+ IceFlush (iceConn);
+
+ iceConn->connection_status = IceConnectAccepted;
+}
+
+
+
+static void
+AcceptProtocol (iceConn, hisOpcode, myOpcode, versionIndex, vendor, release)
+
+IceConn iceConn;
+int hisOpcode;
+int myOpcode;
+int versionIndex;
+char *vendor;
+char *release;
+
+{
+ iceProtocolReplyMsg *pMsg;
+ char *pData;
+ int extra;
+
+ extra = STRING_BYTES (vendor) + STRING_BYTES (release);
+
+ IceGetHeaderExtra (iceConn, 0, ICE_ProtocolReply,
+ SIZEOF (iceProtocolReplyMsg), WORD64COUNT (extra),
+ iceProtocolReplyMsg, pMsg, pData);
+
+ pMsg->protocolOpcode = myOpcode;
+ pMsg->versionIndex = versionIndex;
+
+ STORE_STRING (pData, vendor);
+ STORE_STRING (pData, release);
+
+ IceFlush (iceConn);
+
+
+ /*
+ * We may be using a different major opcode for this protocol
+ * than the other client. Whenever we get a message, we must
+ * map to our own major opcode.
+ */
+
+ _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
+}
+
+
+
+static void
+PingReply (iceConn)
+
+IceConn iceConn;
+
+{
+ IceSimpleMessage (iceConn, 0, ICE_PingReply);
+ IceFlush (iceConn);
+}
+
+
+
+static Bool
+ProcessError (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ int invokeHandler;
+ Bool errorReturned = False;
+ iceErrorMsg *message;
+ char *pData, *pStart;
+ char severity;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_Error,
+ length, SIZEOF (iceErrorMsg),
+ (iceConn->connect_to_you || iceConn->connect_to_me) ?
+ IceFatalToConnection : IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceErrorMsg),
+ iceErrorMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ severity = message->severity;
+
+ if (severity != IceCanContinue && severity != IceFatalToProtocol &&
+ severity != IceFatalToConnection)
+ {
+ _IceErrorBadValue (iceConn, 0,
+ ICE_Error, 9, 1, &severity);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ if (swap)
+ {
+ message->errorClass = lswaps (message->errorClass);
+ message->offendingSequenceNum = lswapl (message->offendingSequenceNum);
+ }
+
+ if (!replyWait ||
+ message->offendingSequenceNum != replyWait->sequence_of_request)
+ {
+ invokeHandler = 1;
+ }
+ else
+ {
+ if (iceConn->connect_to_you &&
+ ((!iceConn->connect_to_you->auth_active &&
+ message->offendingMinorOpcode == ICE_ConnectionSetup) ||
+ (iceConn->connect_to_you->auth_active &&
+ message->offendingMinorOpcode == ICE_AuthReply)))
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+ char *errorStr = NULL;
+ char *tempstr;
+ char *prefix, *temp;
+
+ invokeHandler = 0;
+ errorReturned = True;
+
+ switch (message->errorClass)
+ {
+ case IceNoVersion:
+
+ tempstr =
+ "None of the ICE versions specified are supported";
+ errorStr = (char *) malloc (strlen (tempstr) + 1);
+ strcpy (errorStr, tempstr);
+ break;
+
+ case IceNoAuth:
+
+ tempstr =
+ "None of the authentication protocols specified are supported";
+ errorStr = (char *) malloc (strlen (tempstr) + 1);
+ strcpy (errorStr, tempstr);
+ break;
+
+ case IceSetupFailed:
+
+ prefix = "Connection Setup Failed, reason : ";
+
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceAuthRejected:
+
+ prefix = "Authentication Rejected, reason : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceAuthFailed:
+
+ prefix = "Authentication Failed, reason : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ default:
+ invokeHandler = 1;
+ }
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message = errorStr;
+ }
+ else if (iceConn->protosetup_to_you &&
+ ((!iceConn->protosetup_to_you->auth_active &&
+ message->offendingMinorOpcode == ICE_ProtocolSetup) ||
+ (iceConn->protosetup_to_you->auth_active &&
+ message->offendingMinorOpcode == ICE_AuthReply)))
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+ char *errorStr = "";
+ char *prefix, *temp;
+
+ invokeHandler = 0;
+ errorReturned = True;
+
+ switch (message->errorClass)
+ {
+ case IceNoVersion:
+
+ temp =
+ "None of the protocol versions specified are supported";
+ errorStr = (char *) malloc (strlen (temp) + 1);
+ strcpy (errorStr, temp);
+ break;
+
+ case IceNoAuth:
+
+ temp =
+ "None of the authentication protocols specified are supported";
+ errorStr = (char *) malloc (strlen (temp) + 1);
+ strcpy (errorStr, temp);
+ break;
+
+ case IceSetupFailed:
+
+ prefix = "Protocol Setup Failed, reason : ";
+
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceAuthRejected:
+
+ prefix = "Authentication Rejected, reason : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceAuthFailed:
+
+ prefix = "Authentication Failed, reason : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceProtocolDuplicate:
+
+ prefix = "Protocol was already registered : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ case IceMajorOpcodeDuplicate:
+
+ prefix = "The major opcode was already used : ";
+ errorStr = (char *) malloc (strlen (prefix) + 2);
+ sprintf (errorStr, "%s%d", prefix, (int) *pData);
+ break;
+
+ case IceUnknownProtocol:
+
+ prefix = "Unknown Protocol : ";
+ EXTRACT_STRING (pData, swap, temp);
+ errorStr = (char *) malloc (
+ strlen (prefix) + strlen (temp) + 1);
+ sprintf (errorStr, "%s%s", prefix, temp);
+ free (temp);
+ break;
+
+ default:
+ invokeHandler = 1;
+ }
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message = errorStr;
+ }
+
+ if (errorReturned == True)
+ {
+ /*
+ * If we tried to authenticate, tell the authentication
+ * procedure to clean up.
+ */
+
+ IcePoAuthProc authProc;
+
+ if (iceConn->connect_to_you &&
+ iceConn->connect_to_you->auth_active)
+ {
+ authProc = _IcePoAuthProcs[
+ iceConn->connect_to_you->my_auth_index];
+
+ (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
+ True /* clean up */, False /* swap */,
+ 0, NULL, NULL, NULL, NULL);
+ }
+ else if (iceConn->protosetup_to_you &&
+ iceConn->protosetup_to_you->auth_active)
+ {
+ _IcePoProtocol *protocol = _IceProtocols[
+ iceConn->protosetup_to_you->my_opcode - 1].orig_client;
+
+ authProc = protocol->auth_procs[iceConn->
+ protosetup_to_you->my_auth_index];
+
+ (*authProc) (iceConn,
+ &iceConn->protosetup_to_you->my_auth_state,
+ True /* clean up */, False /* swap */,
+ 0, NULL, NULL, NULL, NULL);
+ }
+ }
+ }
+
+ if (invokeHandler)
+ {
+ (*_IceErrorHandler) (iceConn, swap, message->offendingMinorOpcode,
+ message->offendingSequenceNum, message->errorClass,
+ message->severity, (IcePointer) pData);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ return (errorReturned);
+}
+
+
+
+static
+ProcessConnectionSetup (iceConn, length, swap)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+
+{
+ iceConnectionSetupMsg *message;
+ int myVersionCount, hisVersionCount;
+ int myVersionIndex, hisVersionIndex;
+ int hisMajorVersion, hisMinorVersion;
+ int myAuthCount, hisAuthCount;
+ int found, i, j;
+ char *myAuthName, **hisAuthNames;
+ char *pData, *pStart;
+ char *vendor = NULL;
+ char *release = NULL;
+ int myAuthIndex = 0;
+ int hisAuthIndex = 0;
+ int accept_setup_now = 0;
+ char mustAuthenticate;
+ int authUsableCount;
+ int authUsableFlags[MAX_ICE_AUTH_NAMES];
+ int authIndices[MAX_ICE_AUTH_NAMES];
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionSetup,
+ length, SIZEOF (iceConnectionSetupMsg), IceFatalToConnection);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionSetupMsg),
+ iceConnectionSetupMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ SKIP_STRING (pData, swap); /* vendor */
+ SKIP_STRING (pData, swap); /* release */
+ SKIP_LISTOF_STRING (pData, swap, (int) message->authCount);/* auth names */
+ pData += (message->versionCount * 4); /* versions */
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionSetup,
+ length, pData - pStart + SIZEOF (iceConnectionSetupMsg),
+ pStart, IceFatalToConnection);
+
+ mustAuthenticate = message->mustAuthenticate;
+ if (mustAuthenticate != 0 && mustAuthenticate != 1)
+ {
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ConnectionSetup, 8, 1, &mustAuthenticate);
+ iceConn->connection_status = IceConnectRejected;
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ EXTRACT_STRING (pData, swap, vendor);
+ EXTRACT_STRING (pData, swap, release);
+
+ if ((hisAuthCount = message->authCount) > 0)
+ {
+ hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
+ EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
+ }
+
+ hisVersionCount = message->versionCount;
+ myVersionCount = _IceVersionCount;
+
+ hisVersionIndex = myVersionIndex = found = 0;
+
+ for (i = 0; i < hisVersionCount && !found; i++)
+ {
+ EXTRACT_CARD16 (pData, swap, hisMajorVersion);
+ EXTRACT_CARD16 (pData, swap, hisMinorVersion);
+
+ for (j = 0; j < myVersionCount && !found; j++)
+ {
+ if (_IceVersions[j].major_version == hisMajorVersion &&
+ _IceVersions[j].minor_version == hisMinorVersion)
+ {
+ hisVersionIndex = i;
+ myVersionIndex = j;
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ _IceErrorNoVersion (iceConn, ICE_ConnectionSetup);
+ iceConn->connection_status = IceConnectRejected;
+
+ free (vendor);
+ free (release);
+
+ if (hisAuthCount > 0)
+ {
+ for (i = 0; i < hisAuthCount; i++)
+ free (hisAuthNames[i]);
+
+ free ((char *) hisAuthNames);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ _IceGetPaValidAuthIndices ("ICE", iceConn->connection_string,
+ _IceAuthCount, _IceAuthNames, &authUsableCount, authIndices);
+
+ for (i = 0; i < _IceAuthCount; i++)
+ {
+ authUsableFlags[i] = 0;
+ for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
+ authUsableFlags[i] = (authIndices[j] == i);
+ }
+
+ myAuthCount = _IceAuthCount;
+
+ for (i = found = 0; i < myAuthCount && !found; i++)
+ {
+ if (authUsableFlags[i])
+ {
+ myAuthName = _IceAuthNames[i];
+
+ for (j = 0; j < hisAuthCount && !found; j++)
+ if (strcmp (myAuthName, hisAuthNames[j]) == 0)
+ {
+ myAuthIndex = i;
+ hisAuthIndex = j;
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ /*
+ * None of the authentication methods specified by the
+ * other client is supported. If the other client requires
+ * authentication, we must reject the connection now.
+ * Otherwise, we can invoke the host-based authentication callback
+ * to see if we can accept this connection.
+ */
+
+ if (mustAuthenticate || !iceConn->listen_obj->host_based_auth_proc)
+ {
+ _IceErrorNoAuthentication (iceConn, ICE_ConnectionSetup);
+ iceConn->connection_status = IceConnectRejected;
+ }
+ else
+ {
+ char *hostname = _IceGetPeerName (iceConn);
+
+ if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
+ {
+ accept_setup_now = 1;
+ }
+ else
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_ConnectionSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
+
+ iceConn->connection_status = IceConnectRejected;
+ }
+
+ if (hostname)
+ free (hostname);
+ }
+
+ if (iceConn->connection_status == IceConnectRejected)
+ {
+ free (vendor);
+ free (release);
+ }
+ }
+ else
+ {
+ IcePaAuthStatus status;
+ int authDataLen;
+ IcePointer authData = NULL;
+ IcePointer authState;
+ char *errorString = NULL;
+ IcePaAuthProc authProc = _IcePaAuthProcs[myAuthIndex];
+
+ authState = NULL;
+
+ status = (*authProc) (iceConn, &authState,
+ swap, 0, NULL, &authDataLen, &authData, &errorString);
+
+ if (status == IcePaAuthContinue)
+ {
+ _IceConnectToMeInfo *setupInfo;
+
+ AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
+
+ iceConn->connect_to_me = setupInfo = (_IceConnectToMeInfo *)
+ malloc (sizeof (_IceConnectToMeInfo));
+
+ setupInfo->my_version_index = myVersionIndex;
+ setupInfo->his_version_index = hisVersionIndex;
+ setupInfo->his_vendor = vendor;
+ setupInfo->his_release = release;
+ setupInfo->my_auth_index = myAuthIndex;
+ setupInfo->my_auth_state = authState;
+ setupInfo->must_authenticate = mustAuthenticate;
+ }
+ else if (status == IcePaAuthAccepted)
+ {
+ accept_setup_now = 1;
+ }
+
+ if (authData && authDataLen > 0)
+ free ((char *) authData);
+
+ if (errorString)
+ free (errorString);
+ }
+
+ if (accept_setup_now)
+ {
+ AcceptConnection (iceConn, hisVersionIndex);
+
+ iceConn->vendor = vendor;
+ iceConn->release = release;
+ iceConn->my_ice_version_index = myVersionIndex;
+ }
+
+ if (hisAuthCount > 0)
+ {
+ for (i = 0; i < hisAuthCount; i++)
+ free (hisAuthNames[i]);
+
+ free ((char *) hisAuthNames);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+}
+
+
+
+static Bool
+ProcessAuthRequired (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ iceAuthRequiredMsg *message;
+ int authDataLen;
+ IcePointer authData;
+ int replyDataLen;
+ IcePointer replyData = NULL;
+ char *errorString = NULL;
+ IcePoAuthProc authProc;
+ IcePoAuthStatus status;
+ IcePointer authState;
+ int realAuthIndex;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthRequired,
+ length, SIZEOF (iceAuthRequiredMsg),
+ iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceAuthRequiredMsg),
+ iceAuthRequiredMsg, message, authData);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (0);
+ }
+
+ if (swap)
+ {
+ message->authDataLength = lswaps (message->authDataLength);
+ }
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_AuthRequired, length,
+ message->authDataLength + SIZEOF (iceAuthRequiredMsg), authData,
+ iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
+
+ if (iceConn->connect_to_you)
+ {
+ if ((int) message->authIndex >= _IceAuthCount)
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+
+ char *tempstr = "Received bad authIndex in the AuthRequired message";
+ char errIndex = (int) message->authIndex;
+
+ errorString = (char *) malloc (strlen (tempstr) + 1);
+ strcpy (errorString, tempstr);
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message = errorString;
+
+ _IceErrorBadValue (iceConn, 0,
+ ICE_AuthRequired, 2, 1, &errIndex);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (1);
+ }
+ else
+ {
+ authProc = _IcePoAuthProcs[message->authIndex];
+
+ iceConn->connect_to_you->auth_active = 1;
+ }
+ }
+ else if (iceConn->protosetup_to_you)
+ {
+ if ((int) message->authIndex >=
+ iceConn->protosetup_to_you->my_auth_count)
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+
+ char *tempstr = "Received bad authIndex in the AuthRequired message";
+ char errIndex = (int) message->authIndex;
+
+ errorString = (char *) malloc (strlen (tempstr) + 1);
+ strcpy (errorString, tempstr);
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message = errorString;
+
+ _IceErrorBadValue (iceConn, 0,
+ ICE_AuthRequired, 2, 1, &errIndex);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (1);
+ }
+ else
+ {
+ _IcePoProtocol *myProtocol = _IceProtocols[
+ iceConn->protosetup_to_you->my_opcode - 1].orig_client;
+
+ realAuthIndex = iceConn->protosetup_to_you->
+ my_auth_indices[message->authIndex];
+
+ authProc = myProtocol->auth_procs[realAuthIndex];
+
+ iceConn->protosetup_to_you->auth_active = 1;
+ }
+ }
+ else
+ {
+ /*
+ * Unexpected message
+ */
+
+ _IceErrorBadState (iceConn, 0, ICE_AuthRequired, IceCanContinue);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (0);
+ }
+
+ authState = NULL;
+ authDataLen = message->authDataLength;
+
+ status = (*authProc) (iceConn, &authState, False /* don't clean up */,
+ swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
+
+ if (status == IcePoAuthHaveReply)
+ {
+ AuthReply (iceConn, replyDataLen, replyData);
+
+ replyWait->sequence_of_request = iceConn->send_sequence;
+ replyWait->minor_opcode_of_request = ICE_AuthReply;
+
+ if (iceConn->connect_to_you)
+ {
+ iceConn->connect_to_you->my_auth_state = authState;
+ iceConn->connect_to_you->my_auth_index = message->authIndex;
+ }
+ else if (iceConn->protosetup_to_you)
+ {
+ iceConn->protosetup_to_you->my_auth_state = authState;
+ iceConn->protosetup_to_you->my_auth_index = realAuthIndex;
+ }
+ }
+ else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
+ {
+ char *prefix, *returnErrorString;
+
+ if (status == IcePoAuthRejected)
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_AuthRequired, errorString);
+
+ prefix = "Authentication Rejected, reason : ";
+ }
+ else
+ {
+ _IceErrorAuthenticationFailed (iceConn,
+ ICE_AuthRequired, errorString);
+
+ prefix = "Authentication Failed, reason : ";
+ }
+
+ returnErrorString = (char *) malloc (strlen (prefix) +
+ strlen (errorString) + 1);
+ sprintf (returnErrorString, "%s%s", prefix, errorString);
+ free (errorString);
+
+ if (iceConn->connect_to_you)
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message = returnErrorString;
+ }
+ else
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message = returnErrorString;
+ }
+ }
+
+ if (replyData && replyDataLen > 0)
+ free ((char *) replyData);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+
+ return (status != IcePoAuthHaveReply);
+}
+
+
+
+static
+ProcessAuthReply (iceConn, length, swap)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+
+{
+ iceAuthReplyMsg *message;
+ int replyDataLen;
+ IcePointer replyData;
+ int authDataLen;
+ IcePointer authData = NULL;
+ char *errorString = NULL;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthReply,
+ length, SIZEOF (iceAuthReplyMsg),
+ iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceAuthReplyMsg),
+ iceAuthReplyMsg, message, replyData);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, replyData);
+ return (0);
+ }
+
+ if (swap)
+ {
+ message->authDataLength = lswaps (message->authDataLength);
+ }
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_AuthReply, length,
+ message->authDataLength + SIZEOF (iceAuthReplyMsg), replyData,
+ iceConn->connect_to_me ? IceFatalToConnection : IceFatalToProtocol);
+
+ replyDataLen = message->authDataLength;
+
+ if (iceConn->connect_to_me)
+ {
+ IcePaAuthProc authProc = _IcePaAuthProcs[
+ iceConn->connect_to_me->my_auth_index];
+ IcePaAuthStatus status =
+ (*authProc) (iceConn, &iceConn->connect_to_me->my_auth_state, swap,
+ replyDataLen, replyData, &authDataLen, &authData, &errorString);
+
+ if (status == IcePaAuthContinue)
+ {
+ AuthNextPhase (iceConn, authDataLen, authData);
+ }
+ else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
+ {
+ /*
+ * Before we reject, invoke host-based authentication callback
+ * and give it a chance to accept the connection (only if the
+ * other client doesn't require authentication).
+ */
+
+ if (!iceConn->connect_to_me->must_authenticate &&
+ iceConn->listen_obj->host_based_auth_proc)
+ {
+ char *hostname = _IceGetPeerName (iceConn);
+
+ if ((*iceConn->listen_obj->host_based_auth_proc) (hostname))
+ {
+ status = IcePaAuthAccepted;
+ }
+
+ if (hostname)
+ free (hostname);
+ }
+
+ if (status != IcePaAuthAccepted)
+ {
+ free (iceConn->connect_to_me->his_vendor);
+ free (iceConn->connect_to_me->his_release);
+ free ((char *) iceConn->connect_to_me);
+ iceConn->connect_to_me = NULL;
+
+ iceConn->connection_status = IceConnectRejected;
+
+ if (status == IcePaAuthRejected)
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_AuthReply, errorString);
+ }
+ else
+ {
+ _IceErrorAuthenticationFailed (iceConn,
+ ICE_AuthReply, errorString);
+ }
+ }
+ }
+
+ if (status == IcePaAuthAccepted)
+ {
+ AcceptConnection (iceConn,
+ iceConn->connect_to_me->his_version_index);
+
+ iceConn->vendor = iceConn->connect_to_me->his_vendor;
+ iceConn->release = iceConn->connect_to_me->his_release;
+ iceConn->my_ice_version_index =
+ iceConn->connect_to_me->my_version_index;
+
+ free ((char *) iceConn->connect_to_me);
+ iceConn->connect_to_me = NULL;
+ }
+ }
+ else if (iceConn->protosetup_to_me)
+ {
+ _IcePaProtocol *myProtocol = _IceProtocols[iceConn->protosetup_to_me->
+ my_opcode - 1].accept_client;
+ IcePaAuthProc authProc = myProtocol->auth_procs[
+ iceConn->protosetup_to_me->my_auth_index];
+ IcePaAuthStatus status =
+ (*authProc) (iceConn, &iceConn->protosetup_to_me->my_auth_state,
+ swap, replyDataLen, replyData,
+ &authDataLen, &authData, &errorString);
+ int free_setup_info = 1;
+
+ if (status == IcePaAuthContinue)
+ {
+ AuthNextPhase (iceConn, authDataLen, authData);
+ free_setup_info = 0;
+ }
+ else if (status == IcePaAuthRejected || status == IcePaAuthFailed)
+ {
+ /*
+ * Before we reject, invoke host-based authentication callback
+ * and give it a chance to accept the Protocol Setup (only if the
+ * other client doesn't require authentication).
+ */
+
+ if (!iceConn->protosetup_to_me->must_authenticate &&
+ myProtocol->host_based_auth_proc)
+ {
+ char *hostname = _IceGetPeerName (iceConn);
+
+ if ((*myProtocol->host_based_auth_proc) (hostname))
+ {
+ status = IcePaAuthAccepted;
+ }
+
+ if (hostname)
+ free (hostname);
+ }
+
+ if (status == IcePaAuthRejected)
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_AuthReply, errorString);
+ }
+ else
+ {
+ _IceErrorAuthenticationFailed (iceConn,
+ ICE_AuthReply, errorString);
+ }
+ }
+
+ if (status == IcePaAuthAccepted)
+ {
+ IcePaProcessMsgProc processMsgProc;
+ IceProtocolSetupProc protocolSetupProc;
+ IceProtocolActivateProc protocolActivateProc;
+ _IceProcessMsgInfo *process_msg_info;
+ IcePointer clientData = NULL;
+ char *failureReason = NULL;
+ Status status = 1;
+
+ protocolSetupProc = myProtocol->protocol_setup_proc;
+ protocolActivateProc = myProtocol->protocol_activate_proc;
+
+ if (protocolSetupProc)
+ {
+ /*
+ * Notify the client of the Protocol Setup.
+ */
+
+ status = (*protocolSetupProc) (iceConn,
+ myProtocol->version_recs[iceConn->protosetup_to_me->
+ my_version_index].major_version,
+ myProtocol->version_recs[iceConn->protosetup_to_me->
+ my_version_index].minor_version,
+ iceConn->protosetup_to_me->his_vendor,
+ iceConn->protosetup_to_me->his_release,
+ &clientData, &failureReason);
+
+ /*
+ * Set vendor and release pointers to NULL, so it won't
+ * get freed below. The ProtocolSetupProc should
+ * free it.
+ */
+
+ iceConn->protosetup_to_me->his_vendor = NULL;
+ iceConn->protosetup_to_me->his_release = NULL;
+ }
+
+ if (status != 0)
+ {
+ /*
+ * Send the Protocol Reply
+ */
+
+ AcceptProtocol (iceConn,
+ iceConn->protosetup_to_me->his_opcode,
+ iceConn->protosetup_to_me->my_opcode,
+ iceConn->protosetup_to_me->his_version_index,
+ myProtocol->vendor, myProtocol->release);
+
+
+ /*
+ * Set info for this protocol.
+ */
+
+ processMsgProc = myProtocol->version_recs[
+ iceConn->protosetup_to_me->
+ my_version_index].process_msg_proc;
+
+ process_msg_info = &iceConn->process_msg_info[
+ iceConn->protosetup_to_me->
+ his_opcode -iceConn->his_min_opcode];
+
+ process_msg_info->client_data = clientData;
+ process_msg_info->accept_flag = 1;
+ process_msg_info->process_msg_proc.
+ accept_client = processMsgProc;
+
+
+ /*
+ * Increase the reference count for the number
+ * of active protocols.
+ */
+
+ iceConn->proto_ref_count++;
+
+
+ /*
+ * Notify the client that the protocol is active. The reason
+ * we have this 2nd callback invoked is because the client
+ * may wish to immediately generate a message for this
+ * protocol, but it must wait until we send the Protocol Reply.
+ */
+
+ if (protocolActivateProc)
+ {
+ (*protocolActivateProc) (iceConn,
+ process_msg_info->client_data);
+ }
+ }
+ else
+ {
+ /*
+ * An error was encountered.
+ */
+
+ _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup,
+ failureReason);
+
+ if (failureReason)
+ free (failureReason);
+ }
+ }
+
+
+ if (free_setup_info)
+ {
+ if (iceConn->protosetup_to_me->his_vendor)
+ free (iceConn->protosetup_to_me->his_vendor);
+ if (iceConn->protosetup_to_me->his_release)
+ free (iceConn->protosetup_to_me->his_release);
+ free ((char *) iceConn->protosetup_to_me);
+ iceConn->protosetup_to_me = NULL;
+ }
+ }
+ else
+ {
+ /*
+ * Unexpected message
+ */
+
+ _IceErrorBadState (iceConn, 0, ICE_AuthReply, IceCanContinue);
+ }
+
+ if (authData && authDataLen > 0)
+ free ((char *) authData);
+
+ if (errorString)
+ free (errorString);
+
+ IceDisposeCompleteMessage (iceConn, replyData);
+ return (0);
+}
+
+
+
+static Bool
+ProcessAuthNextPhase (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ iceAuthNextPhaseMsg *message;
+ int authDataLen;
+ IcePointer authData;
+ int replyDataLen;
+ IcePointer replyData = NULL;
+ char *errorString = NULL;
+ IcePoAuthProc authProc;
+ IcePoAuthStatus status;
+ IcePointer *authState;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_AuthNextPhase,
+ length, SIZEOF (iceAuthNextPhaseMsg),
+ iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceAuthNextPhaseMsg),
+ iceAuthNextPhaseMsg, message, authData);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (0);
+ }
+
+ if (swap)
+ {
+ message->authDataLength = lswaps (message->authDataLength);
+ }
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_AuthNextPhase, length,
+ message->authDataLength + SIZEOF (iceAuthNextPhaseMsg), authData,
+ iceConn->connect_to_you ? IceFatalToConnection : IceFatalToProtocol);
+
+ if (iceConn->connect_to_you)
+ {
+ authProc = _IcePoAuthProcs[
+ iceConn->connect_to_you->my_auth_index];
+
+ authState = &iceConn->connect_to_you->my_auth_state;
+ }
+ else if (iceConn->protosetup_to_you)
+ {
+ _IcePoProtocol *myProtocol =
+ _IceProtocols[iceConn->protosetup_to_you->my_opcode - 1].orig_client;
+
+ authProc = myProtocol->auth_procs[
+ iceConn->protosetup_to_you->my_auth_index];
+
+ authState = &iceConn->protosetup_to_you->my_auth_state;
+ }
+ else
+ {
+ /*
+ * Unexpected message
+ */
+
+ _IceErrorBadState (iceConn, 0, ICE_AuthNextPhase, IceCanContinue);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+ return (0);
+ }
+
+ authDataLen = message->authDataLength;
+
+ status = (*authProc) (iceConn, authState, False /* don't clean up */,
+ swap, authDataLen, authData, &replyDataLen, &replyData, &errorString);
+
+ if (status == IcePoAuthHaveReply)
+ {
+ AuthReply (iceConn, replyDataLen, replyData);
+
+ replyWait->sequence_of_request = iceConn->send_sequence;
+ }
+ else if (status == IcePoAuthRejected || status == IcePoAuthFailed)
+ {
+ char *prefix, *returnErrorString;
+
+ if (status == IcePoAuthRejected)
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_AuthNextPhase, errorString);
+
+ prefix = "Authentication Rejected, reason : ";
+ }
+ else if (status == IcePoAuthFailed)
+ {
+ _IceErrorAuthenticationFailed (iceConn,
+ ICE_AuthNextPhase, errorString);
+
+ prefix = "Authentication Failed, reason : ";
+ }
+
+ returnErrorString = (char *) malloc (strlen (prefix) +
+ strlen (errorString) + 1);
+ sprintf (returnErrorString, "%s%s", prefix, errorString);
+ free (errorString);
+
+ if (iceConn->connect_to_you)
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message = returnErrorString;
+ }
+ else
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message = returnErrorString;
+ }
+ }
+
+ if (replyData && replyDataLen > 0)
+ free ((char *) replyData);
+
+ IceDisposeCompleteMessage (iceConn, authData);
+
+ return (status != IcePoAuthHaveReply);
+}
+
+
+
+static Bool
+ProcessConnectionReply (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ iceConnectionReplyMsg *message;
+ char *pData, *pStart;
+ Bool replyReady;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply,
+ length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg),
+ iceConnectionReplyMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ SKIP_STRING (pData, swap); /* vendor */
+ SKIP_STRING (pData, swap); /* release */
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_ConnectionReply,
+ length, pData - pStart + SIZEOF (iceConnectionReplyMsg),
+ pStart, IceFatalToConnection);
+
+ pData = pStart;
+
+ if (iceConn->connect_to_you)
+ {
+ if (iceConn->connect_to_you->auth_active)
+ {
+ /*
+ * Tell the authentication procedure to clean up.
+ */
+
+ IcePoAuthProc authProc = _IcePoAuthProcs[
+ iceConn->connect_to_you->my_auth_index];
+
+ (*authProc) (iceConn, &iceConn->connect_to_you->my_auth_state,
+ True /* clean up */, False /* swap */,
+ 0, NULL, NULL, NULL, NULL);
+ }
+
+ if ((int) message->versionIndex >= _IceVersionCount)
+ {
+ _IceConnectionError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->connection_error);
+ char errIndex = message->versionIndex;
+
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ConnectionReply, 2, 1, &errIndex);
+
+ errorReply->type = ICE_CONNECTION_ERROR;
+ errorReply->error_message =
+ "Received bad version index in Connection Reply";
+ }
+ else
+ {
+ _IceReply *reply = (_IceReply *) (replyWait->reply);
+
+ reply->type = ICE_CONNECTION_REPLY;
+ reply->connection_reply.version_index = message->versionIndex;
+
+ EXTRACT_STRING (pData, swap, reply->connection_reply.vendor);
+ EXTRACT_STRING (pData, swap, reply->connection_reply.release);
+ }
+
+ replyReady = True;
+ }
+ else
+ {
+ /*
+ * Unexpected message
+ */
+
+ _IceErrorBadState (iceConn, 0, ICE_ConnectionReply, IceCanContinue);
+
+ replyReady = False;
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ return (replyReady);
+}
+
+
+
+static
+ProcessProtocolSetup (iceConn, length, swap)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+
+{
+ iceProtocolSetupMsg *message;
+ _IcePaProtocol *myProtocol;
+ int myVersionCount, hisVersionCount;
+ int myVersionIndex, hisVersionIndex;
+ int hisMajorVersion, hisMinorVersion;
+ int myAuthCount, hisAuthCount;
+ int myOpcode, hisOpcode;
+ int found, i, j;
+ char *myAuthName, **hisAuthNames;
+ char *protocolName;
+ char *pData, *pStart;
+ char *vendor = NULL;
+ char *release = NULL;
+ int accept_setup_now = 0;
+ int myAuthIndex = 0;
+ int hisAuthIndex = 0;
+ char mustAuthenticate;
+ int authUsableCount;
+ int authUsableFlags[MAX_ICE_AUTH_NAMES];
+ int authIndices[MAX_ICE_AUTH_NAMES];
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolSetup,
+ length, SIZEOF (iceProtocolSetupMsg), IceFatalToProtocol);
+
+ if (iceConn->want_to_close)
+ {
+ /*
+ * If we sent a WantToClose message, but just got a ProtocolSetup,
+ * we must cancel our WantToClose. It is the responsiblity of the
+ * other client to send a WantToClose later on.
+ */
+
+ iceConn->want_to_close = 0;
+ }
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolSetupMsg),
+ iceProtocolSetupMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ SKIP_STRING (pData, swap); /* proto name */
+ SKIP_STRING (pData, swap); /* vendor */
+ SKIP_STRING (pData, swap); /* release */
+ SKIP_LISTOF_STRING (pData, swap, (int) message->authCount);/* auth names */
+ pData += (message->versionCount * 4); /* versions */
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolSetup,
+ length, pData - pStart + SIZEOF (iceProtocolSetupMsg),
+ pStart, IceFatalToProtocol);
+
+ mustAuthenticate = message->mustAuthenticate;
+
+ if (mustAuthenticate != 0 && mustAuthenticate != 1)
+ {
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ProtocolSetup, 4, 1, &mustAuthenticate);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ if (iceConn->process_msg_info &&
+ (int) message->protocolOpcode >= iceConn->his_min_opcode &&
+ (int) message->protocolOpcode <= iceConn->his_max_opcode &&
+ iceConn->process_msg_info[
+ message->protocolOpcode - iceConn->his_min_opcode].in_use)
+ {
+ _IceErrorMajorOpcodeDuplicate (iceConn, message->protocolOpcode);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ EXTRACT_STRING (pData, swap, protocolName);
+
+ if (iceConn->process_msg_info)
+ {
+ for (i = 0;
+ i <= (iceConn->his_max_opcode - iceConn->his_min_opcode); i++)
+ {
+ if (iceConn->process_msg_info[i].in_use && strcmp (protocolName,
+ iceConn->process_msg_info[i].protocol->protocol_name) == 0)
+ {
+ _IceErrorProtocolDuplicate (iceConn, protocolName);
+ free (protocolName);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+ }
+ }
+
+ for (i = 0; i < _IceLastMajorOpcode; i++)
+ if (strcmp (protocolName, _IceProtocols[i].protocol_name) == 0)
+ break;
+
+ if (i < _IceLastMajorOpcode &&
+ (myProtocol = _IceProtocols[i].accept_client) != NULL)
+ {
+ hisOpcode = message->protocolOpcode;
+ myOpcode = i + 1;
+ free (protocolName);
+ }
+ else
+ {
+ _IceErrorUnknownProtocol (iceConn, protocolName);
+ free (protocolName);
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ EXTRACT_STRING (pData, swap, vendor);
+ EXTRACT_STRING (pData, swap, release);
+
+ if ((hisAuthCount = message->authCount) > 0)
+ {
+ hisAuthNames = (char **) malloc (hisAuthCount * sizeof (char *));
+ EXTRACT_LISTOF_STRING (pData, swap, hisAuthCount, hisAuthNames);
+ }
+
+ hisVersionCount = message->versionCount;
+ myVersionCount = myProtocol->version_count;
+
+ hisVersionIndex = myVersionIndex = found = 0;
+
+ for (i = 0; i < hisVersionCount && !found; i++)
+ {
+ EXTRACT_CARD16 (pData, swap, hisMajorVersion);
+ EXTRACT_CARD16 (pData, swap, hisMinorVersion);
+
+ for (j = 0; j < myVersionCount && !found; j++)
+ {
+ if (myProtocol->version_recs[j].major_version == hisMajorVersion &&
+ myProtocol->version_recs[j].minor_version == hisMinorVersion)
+ {
+ hisVersionIndex = i;
+ myVersionIndex = j;
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ _IceErrorNoVersion (iceConn, ICE_ProtocolSetup);
+
+ free (vendor);
+ free (release);
+
+ if (hisAuthCount > 0)
+ {
+ for (i = 0; i < hisAuthCount; i++)
+ free (hisAuthNames[i]);
+
+ free ((char *) hisAuthNames);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ myAuthCount = myProtocol->auth_count;
+
+ _IceGetPaValidAuthIndices (
+ _IceProtocols[myOpcode - 1].protocol_name,
+ iceConn->connection_string, myAuthCount, myProtocol->auth_names,
+ &authUsableCount, authIndices);
+
+ for (i = 0; i < myAuthCount; i++)
+ {
+ authUsableFlags[i] = 0;
+ for (j = 0; j < authUsableCount && !authUsableFlags[i]; j++)
+ authUsableFlags[i] = (authIndices[j] == i);
+ }
+
+ for (i = found = 0; i < myAuthCount && !found; i++)
+ {
+ if (authUsableFlags[i])
+ {
+ myAuthName = myProtocol->auth_names[i];
+
+ for (j = 0; j < hisAuthCount && !found; j++)
+ if (strcmp (myAuthName, hisAuthNames[j]) == 0)
+ {
+ myAuthIndex = i;
+ hisAuthIndex = j;
+ found = 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ /*
+ * None of the authentication methods specified by the
+ * other client is supported. If the other client requires
+ * authentication, we must reject the Protocol Setup now.
+ * Otherwise, we can invoke the host-based authentication callback
+ * to see if we can accept this Protocol Setup.
+ */
+
+ if (mustAuthenticate || !myProtocol->host_based_auth_proc)
+ {
+ _IceErrorNoAuthentication (iceConn, ICE_ProtocolSetup);
+ }
+ else
+ {
+ char *hostname = _IceGetPeerName (iceConn);
+
+ if ((*myProtocol->host_based_auth_proc) (hostname))
+ {
+ accept_setup_now = 1;
+ }
+ else
+ {
+ _IceErrorAuthenticationRejected (iceConn,
+ ICE_ProtocolSetup, "None of the authentication protocols specified are supported and host-based authentication failed");
+ }
+
+ if (hostname)
+ free (hostname);
+ }
+ }
+ else
+ {
+ IcePaAuthStatus status;
+ int authDataLen;
+ IcePointer authData = NULL;
+ IcePointer authState;
+ char *errorString = NULL;
+ IcePaAuthProc authProc =
+ myProtocol->auth_procs[myAuthIndex];
+
+ authState = NULL;
+
+ status = (*authProc) (iceConn, &authState, swap, 0, NULL,
+ &authDataLen, &authData, &errorString);
+
+ if (status == IcePaAuthContinue)
+ {
+ _IceProtoSetupToMeInfo *setupInfo;
+
+ AuthRequired (iceConn, hisAuthIndex, authDataLen, authData);
+
+ iceConn->protosetup_to_me = setupInfo =
+ (_IceProtoSetupToMeInfo *) malloc (
+ sizeof (_IceProtoSetupToMeInfo));
+
+ setupInfo->his_opcode = hisOpcode;
+ setupInfo->my_opcode = myOpcode;
+ setupInfo->my_version_index = myVersionIndex;
+ setupInfo->his_version_index = hisVersionIndex;
+ setupInfo->his_vendor = vendor;
+ setupInfo->his_release = release;
+ vendor = release = NULL; /* so we don't free it */
+ setupInfo->my_auth_index = myAuthIndex;
+ setupInfo->my_auth_state = authState;
+ setupInfo->must_authenticate = mustAuthenticate;
+ }
+ else if (status == IcePaAuthAccepted)
+ {
+ accept_setup_now = 1;
+ }
+
+ if (authData && authDataLen > 0)
+ free ((char *) authData);
+
+ if (errorString)
+ free (errorString);
+ }
+
+ if (accept_setup_now)
+ {
+ IcePaProcessMsgProc processMsgProc;
+ IceProtocolSetupProc protocolSetupProc;
+ IceProtocolActivateProc protocolActivateProc;
+ _IceProcessMsgInfo *process_msg_info;
+ IcePointer clientData = NULL;
+ char *failureReason = NULL;
+ Status status = 1;
+
+ protocolSetupProc = myProtocol->protocol_setup_proc;
+ protocolActivateProc = myProtocol->protocol_activate_proc;
+
+ if (protocolSetupProc)
+ {
+ /*
+ * Notify the client of the Protocol Setup.
+ */
+
+ status = (*protocolSetupProc) (iceConn,
+ myProtocol->version_recs[myVersionIndex].major_version,
+ myProtocol->version_recs[myVersionIndex].minor_version,
+ vendor, release, &clientData, &failureReason);
+
+ vendor = release = NULL; /* so we don't free it */
+ }
+
+ if (status != 0)
+ {
+ /*
+ * Send the Protocol Reply
+ */
+
+ AcceptProtocol (iceConn, hisOpcode, myOpcode, hisVersionIndex,
+ myProtocol->vendor, myProtocol->release);
+
+
+ /*
+ * Set info for this protocol.
+ */
+
+ processMsgProc = myProtocol->version_recs[
+ myVersionIndex].process_msg_proc;
+
+ process_msg_info = &iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode];
+
+ process_msg_info->client_data = clientData;
+ process_msg_info->accept_flag = 1;
+ process_msg_info->process_msg_proc.accept_client = processMsgProc;
+
+
+ /*
+ * Increase the reference count for the number of active protocols.
+ */
+
+ iceConn->proto_ref_count++;
+
+
+ /*
+ * Notify the client that the protocol is active. The reason
+ * we have this 2nd callback invoked is because the client
+ * may wish to immediately generate a message for this
+ * protocol, but it must wait until we send the Protocol Reply.
+ */
+
+ if (protocolActivateProc)
+ {
+ (*protocolActivateProc) (iceConn,
+ process_msg_info->client_data);
+ }
+ }
+ else
+ {
+ /*
+ * An error was encountered.
+ */
+
+ _IceErrorSetupFailed (iceConn, ICE_ProtocolSetup, failureReason);
+
+ if (failureReason)
+ free (failureReason);
+ }
+ }
+
+ if (vendor)
+ free (vendor);
+
+ if (release)
+ free (release);
+
+ if (hisAuthCount > 0)
+ {
+ for (i = 0; i < hisAuthCount; i++)
+ free (hisAuthNames[i]);
+
+ free ((char *) hisAuthNames);
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+}
+
+
+
+static Bool
+ProcessProtocolReply (iceConn, length, swap, replyWait)
+
+IceConn iceConn;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+
+{
+ iceProtocolReplyMsg *message;
+ char *pData, *pStart;
+ Bool replyReady;
+
+ CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply,
+ length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol);
+
+ IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg),
+ iceProtocolReplyMsg, message, pStart);
+
+ if (!IceValidIO (iceConn))
+ {
+ IceDisposeCompleteMessage (iceConn, pStart);
+ return (0);
+ }
+
+ pData = pStart;
+
+ SKIP_STRING (pData, swap); /* vendor */
+ SKIP_STRING (pData, swap); /* release */
+
+ CHECK_COMPLETE_SIZE (iceConn, ICE_ProtocolReply,
+ length, pData - pStart + SIZEOF (iceProtocolReplyMsg),
+ pStart, IceFatalToProtocol);
+
+ pData = pStart;
+
+ if (iceConn->protosetup_to_you)
+ {
+ if (iceConn->protosetup_to_you->auth_active)
+ {
+ /*
+ * Tell the authentication procedure to clean up.
+ */
+
+ _IcePoProtocol *myProtocol = _IceProtocols[
+ iceConn->protosetup_to_you->my_opcode - 1].orig_client;
+
+ IcePoAuthProc authProc = myProtocol->auth_procs[
+ iceConn->protosetup_to_you->my_auth_index];
+
+#ifdef SVR4
+
+/*
+ * authProc is never NULL, but the cc compiler on UNIX System V/386
+ * Release 4.2 Version 1 screws up an optimization. Unless there is
+ * some sort of reference to authProc before the function call, the
+ * function call will seg fault.
+ */
+ if (authProc)
+#endif
+ (*authProc) (iceConn,
+ &iceConn->protosetup_to_you->my_auth_state,
+ True /* clean up */, False /* swap */,
+ 0, NULL, NULL, NULL, NULL);
+ }
+
+ if ((int) message->versionIndex >= _IceVersionCount)
+ {
+ _IceProtocolError *errorReply =
+ &(((_IceReply *) (replyWait->reply))->protocol_error);
+ char errIndex = message->versionIndex;
+
+ _IceErrorBadValue (iceConn, 0,
+ ICE_ProtocolReply, 2, 1, &errIndex);
+
+ errorReply->type = ICE_PROTOCOL_ERROR;
+ errorReply->error_message =
+ "Received bad version index in Protocol Reply";
+ }
+ else
+ {
+ _IceProtocolReply *reply =
+ &(((_IceReply *) (replyWait->reply))->protocol_reply);
+
+ reply->type = ICE_PROTOCOL_REPLY;
+ reply->major_opcode = message->protocolOpcode;
+ reply->version_index = message->versionIndex;
+
+ EXTRACT_STRING (pData, swap, reply->vendor);
+ EXTRACT_STRING (pData, swap, reply->release);
+ }
+
+ replyReady = True;
+ }
+ else
+ {
+ _IceErrorBadState (iceConn, 0, ICE_ProtocolReply, IceCanContinue);
+
+ replyReady = False;
+ }
+
+ IceDisposeCompleteMessage (iceConn, pStart);
+
+ return (replyReady);
+}
+
+
+
+static
+ProcessPing (iceConn, length)
+
+IceConn iceConn;
+unsigned long length;
+
+{
+ CHECK_SIZE_MATCH (iceConn, ICE_Ping,
+ length, SIZEOF (icePingMsg), IceFatalToConnection);
+
+ PingReply (iceConn);
+
+ return (0);
+}
+
+
+
+static
+ProcessPingReply (iceConn, length)
+
+IceConn iceConn;
+unsigned long length;
+
+{
+ CHECK_SIZE_MATCH (iceConn, ICE_PingReply,
+ length, SIZEOF (icePingReplyMsg), IceFatalToConnection);
+
+ if (iceConn->ping_waits)
+ {
+ _IcePingWait *next = iceConn->ping_waits->next;
+
+ (*iceConn->ping_waits->ping_reply_proc) (iceConn,
+ iceConn->ping_waits->client_data);
+
+ free ((char *) iceConn->ping_waits);
+ iceConn->ping_waits = next;
+ }
+ else
+ {
+ _IceErrorBadState (iceConn, 0, ICE_PingReply, IceCanContinue);
+ }
+
+ return (0);
+}
+
+
+
+static
+ProcessWantToClose (iceConn, length, connectionClosedRet)
+
+IceConn iceConn;
+unsigned long length;
+Bool *connectionClosedRet;
+
+{
+ *connectionClosedRet = False;
+
+ CHECK_SIZE_MATCH (iceConn, ICE_WantToClose,
+ length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection);
+
+ if (iceConn->want_to_close || iceConn->open_ref_count == 0)
+ {
+ /*
+ * We just received a WantToClose. Either we also sent a
+ * WantToClose, so we close the connection, or the iceConn
+ * is not being used, so we close the connection. This
+ * second case is possible if we sent a WantToClose because
+ * the iceConn->open_ref_count reached zero, but then we
+ * received a NoClose.
+ */
+
+ _IceConnectionClosed (iceConn); /* invoke watch procs */
+ _IceFreeConnection (iceConn);
+ *connectionClosedRet = True;
+ }
+ else if (iceConn->proto_ref_count > 0)
+ {
+ /*
+ * We haven't shut down all of our protocols yet. We send a NoClose,
+ * and it's up to us to generate a WantToClose later on.
+ */
+
+ IceSimpleMessage (iceConn, 0, ICE_NoClose);
+ IceFlush (iceConn);
+ }
+ else
+ {
+ /*
+ * The reference count on this iceConn is zero. This means that
+ * there are no active protocols, but the client didn't explicitly
+ * close the connection yet. If we didn't just send a Protocol Setup,
+ * we send a NoClose, and it's up to us to generate a WantToClose
+ * later on.
+ */
+
+ if (!iceConn->protosetup_to_you)
+ {
+ IceSimpleMessage (iceConn, 0, ICE_NoClose);
+ IceFlush (iceConn);
+ }
+ }
+
+ return (0);
+}
+
+
+
+static
+ProcessNoClose (iceConn, length)
+
+IceConn iceConn;
+unsigned long length;
+
+{
+ CHECK_SIZE_MATCH (iceConn, ICE_NoClose,
+ length, SIZEOF (iceNoCloseMsg), IceFatalToConnection);
+
+ if (iceConn->want_to_close)
+ {
+ /*
+ * The other side can't close now. We cancel our WantToClose,
+ * and we can expect a WantToClose from the other side.
+ */
+
+ iceConn->want_to_close = 0;
+ }
+ else
+ {
+ _IceErrorBadState (iceConn, 0, ICE_NoClose, IceCanContinue);
+ }
+
+ return (0);
+}
+
+
+
+void
+_IceProcessCoreMessage (iceConn, opcode, length, swap,
+ replyWait, replyReadyRet, connectionClosedRet)
+
+IceConn iceConn;
+int opcode;
+unsigned long length;
+Bool swap;
+IceReplyWaitInfo *replyWait;
+Bool *replyReadyRet;
+Bool *connectionClosedRet;
+
+{
+ Bool replyReady = False;
+
+ *connectionClosedRet = False;
+
+ switch (opcode)
+ {
+ case ICE_Error:
+
+ replyReady = ProcessError (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_ConnectionSetup:
+
+ ProcessConnectionSetup (iceConn, length, swap);
+ break;
+
+ case ICE_AuthRequired:
+
+ replyReady = ProcessAuthRequired (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_AuthReply:
+
+ ProcessAuthReply (iceConn, length, swap);
+ break;
+
+ case ICE_AuthNextPhase:
+
+ replyReady = ProcessAuthNextPhase (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_ConnectionReply:
+
+ replyReady = ProcessConnectionReply (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_ProtocolSetup:
+
+ ProcessProtocolSetup (iceConn, length, swap);
+ break;
+
+ case ICE_ProtocolReply:
+
+ replyReady = ProcessProtocolReply (iceConn, length, swap, replyWait);
+ break;
+
+ case ICE_Ping:
+
+ ProcessPing (iceConn, length);
+ break;
+
+ case ICE_PingReply:
+
+ ProcessPingReply (iceConn, length);
+ break;
+
+ case ICE_WantToClose:
+
+ ProcessWantToClose (iceConn, length, connectionClosedRet);
+ break;
+
+ case ICE_NoClose:
+
+ ProcessNoClose (iceConn, length);
+ break;
+
+ default:
+
+ _IceErrorBadMinor (iceConn, 0, opcode, IceCanContinue);
+ _IceReadSkip (iceConn, length << 3);
+ break;
+ }
+
+ if (replyWait)
+ *replyReadyRet = replyReady;
+}
diff --git a/src/protosetup.c b/src/protosetup.c
new file mode 100644
index 0000000..78be316
--- /dev/null
+++ b/src/protosetup.c
@@ -0,0 +1,289 @@
+/* $Xorg: protosetup.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+
+
+IceProtocolSetupStatus
+IceProtocolSetup (iceConn, myOpcode, clientData, mustAuthenticate,
+ majorVersionRet, minorVersionRet, vendorRet, releaseRet,
+ errorLength, errorStringRet)
+
+IceConn iceConn;
+int myOpcode;
+IcePointer clientData;
+Bool mustAuthenticate;
+int *majorVersionRet;
+int *minorVersionRet;
+char **vendorRet;
+char **releaseRet;
+int errorLength;
+char *errorStringRet;
+
+{
+ iceProtocolSetupMsg *pMsg;
+ char *pData;
+ _IceProtocol *myProtocol;
+ int extra;
+ Bool gotReply, ioErrorOccured;
+ int accepted, i;
+ int hisOpcode;
+ unsigned long setup_sequence;
+ IceReplyWaitInfo replyWait;
+ _IceReply reply;
+ IcePoVersionRec *versionRec;
+ int authCount;
+ int *authIndices;
+
+ if (errorStringRet && errorLength > 0)
+ *errorStringRet = '\0';
+
+ *majorVersionRet = 0;
+ *minorVersionRet = 0;
+ *vendorRet = NULL;
+ *releaseRet = NULL;
+
+ if (myOpcode < 1 || myOpcode > _IceLastMajorOpcode)
+ {
+ strncpy (errorStringRet, "myOpcode out of range", errorLength);
+ return (IceProtocolSetupFailure);
+ }
+
+ myProtocol = &_IceProtocols[myOpcode - 1];
+
+ if (myProtocol->orig_client == NULL)
+ {
+ strncpy (errorStringRet,
+ "IceRegisterForProtocolSetup was not called", errorLength);
+ return (IceProtocolSetupFailure);
+ }
+
+
+ /*
+ * Make sure this protocol hasn't been activated already.
+ */
+
+ if (iceConn->process_msg_info)
+ {
+ for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
+ {
+ if (iceConn->process_msg_info[
+ i - iceConn->his_min_opcode].in_use &&
+ iceConn->process_msg_info[
+ i - iceConn->his_min_opcode ].my_opcode == myOpcode)
+ break;
+ }
+
+ if (i <= iceConn->his_max_opcode)
+ {
+ return (IceProtocolAlreadyActive);
+ }
+ }
+
+ /*
+ * Generate the message.
+ */
+
+ if (myProtocol->orig_client->auth_count > 0)
+ {
+ authIndices = (int *) malloc (
+ myProtocol->orig_client->auth_count * sizeof (int));
+
+ _IceGetPoValidAuthIndices (myProtocol->protocol_name,
+ iceConn->connection_string,
+ myProtocol->orig_client->auth_count,
+ myProtocol->orig_client->auth_names,
+ &authCount, authIndices);
+
+ }
+ else
+ {
+ authCount = 0;
+ authIndices = NULL;
+ }
+
+ extra = STRING_BYTES (myProtocol->protocol_name) +
+ STRING_BYTES (myProtocol->orig_client->vendor) +
+ STRING_BYTES (myProtocol->orig_client->release);
+
+ for (i = 0; i < authCount; i++)
+ {
+ extra += STRING_BYTES (myProtocol->orig_client->auth_names[
+ authIndices[i]]);
+ }
+
+ extra += (myProtocol->orig_client->version_count * 4);
+
+ IceGetHeaderExtra (iceConn, 0, ICE_ProtocolSetup,
+ SIZEOF (iceProtocolSetupMsg), WORD64COUNT (extra),
+ iceProtocolSetupMsg, pMsg, pData);
+
+ setup_sequence = iceConn->send_sequence;
+
+ pMsg->protocolOpcode = myOpcode;
+ pMsg->versionCount = myProtocol->orig_client->version_count;
+ pMsg->authCount = authCount;
+ pMsg->mustAuthenticate = mustAuthenticate;
+
+ STORE_STRING (pData, myProtocol->protocol_name);
+ STORE_STRING (pData, myProtocol->orig_client->vendor);
+ STORE_STRING (pData, myProtocol->orig_client->release);
+
+ for (i = 0; i < authCount; i++)
+ {
+ STORE_STRING (pData, myProtocol->orig_client->auth_names[
+ authIndices[i]]);
+ }
+
+ for (i = 0; i < myProtocol->orig_client->version_count; i++)
+ {
+ STORE_CARD16 (pData,
+ myProtocol->orig_client->version_recs[i].major_version);
+ STORE_CARD16 (pData,
+ myProtocol->orig_client->version_recs[i].minor_version);
+ }
+
+ IceFlush (iceConn);
+
+
+ /*
+ * Process messages until we get a Protocol Reply.
+ */
+
+ replyWait.sequence_of_request = setup_sequence;
+ replyWait.major_opcode_of_request = 0;
+ replyWait.minor_opcode_of_request = ICE_ProtocolSetup;
+ replyWait.reply = (IcePointer) &reply;
+
+ iceConn->protosetup_to_you = (_IceProtoSetupToYouInfo *) malloc (
+ sizeof (_IceProtoSetupToYouInfo));
+ iceConn->protosetup_to_you->my_opcode = myOpcode;
+ iceConn->protosetup_to_you->my_auth_count = authCount;
+ iceConn->protosetup_to_you->auth_active = 0;
+ iceConn->protosetup_to_you->my_auth_indices = authIndices;
+
+ gotReply = False;
+ ioErrorOccured = False;
+ accepted = 0;
+
+ while (!gotReply && !ioErrorOccured)
+ {
+ ioErrorOccured = (IceProcessMessages (
+ iceConn, &replyWait, &gotReply) == IceProcessMessagesIOError);
+
+ if (ioErrorOccured)
+ {
+ strncpy (errorStringRet,
+ "IO error occured doing Protocol Setup on connection",
+ errorLength);
+ return (IceProtocolSetupIOError);
+ }
+ else if (gotReply)
+ {
+ if (reply.type == ICE_PROTOCOL_REPLY)
+ {
+ if (reply.protocol_reply.version_index >=
+ myProtocol->orig_client->version_count)
+ {
+ strncpy (errorStringRet,
+ "Got a bad version index in the Protocol Reply",
+ errorLength);
+
+ free (reply.protocol_reply.vendor);
+ free (reply.protocol_reply.release);
+ }
+ else
+ {
+ versionRec = &(myProtocol->orig_client->version_recs[
+ reply.protocol_reply.version_index]);
+
+ accepted = 1;
+ }
+ }
+ else /* reply.type == ICE_PROTOCOL_ERROR */
+ {
+ /* Protocol Setup failed */
+
+ strncpy (errorStringRet, reply.protocol_error.error_message,
+ errorLength);
+
+ free (reply.protocol_error.error_message);
+ }
+
+ if (iceConn->protosetup_to_you->my_auth_indices)
+ free ((char *) iceConn->protosetup_to_you->my_auth_indices);
+ free ((char *) iceConn->protosetup_to_you);
+ iceConn->protosetup_to_you = NULL;
+ }
+ }
+
+ if (accepted)
+ {
+ _IceProcessMsgInfo *process_msg_info;
+
+ *majorVersionRet = versionRec->major_version;
+ *minorVersionRet = versionRec->minor_version;
+ *vendorRet = reply.protocol_reply.vendor;
+ *releaseRet = reply.protocol_reply.release;
+
+
+ /*
+ * Increase the reference count for the number of active protocols.
+ */
+
+ iceConn->proto_ref_count++;
+
+
+ /*
+ * We may be using a different major opcode for this protocol
+ * than the other client. Whenever we get a message, we must
+ * map to our own major opcode.
+ */
+
+ hisOpcode = reply.protocol_reply.major_opcode;
+
+ _IceAddOpcodeMapping (iceConn, hisOpcode, myOpcode);
+
+ process_msg_info = &iceConn->process_msg_info[hisOpcode -
+ iceConn->his_min_opcode];
+
+ process_msg_info->client_data = clientData;
+ process_msg_info->accept_flag = 0;
+
+ process_msg_info->process_msg_proc.orig_client =
+ versionRec->process_msg_proc;
+
+ return (IceProtocolSetupSuccess);
+ }
+ else
+ {
+ return (IceProtocolSetupFailure);
+ }
+}
diff --git a/src/register.c b/src/register.c
new file mode 100644
index 0000000..45ec62c
--- /dev/null
+++ b/src/register.c
@@ -0,0 +1,253 @@
+/* $Xorg: register.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+
+int
+IceRegisterForProtocolSetup (protocolName, vendor, release,
+ versionCount, versionRecs, authCount, authNames, authProcs, IOErrorProc)
+
+char *protocolName;
+char *vendor;
+char *release;
+int versionCount;
+IcePoVersionRec *versionRecs;
+int authCount;
+char **authNames;
+IcePoAuthProc *authProcs;
+IceIOErrorProc IOErrorProc;
+
+{
+ _IcePoProtocol *p;
+ int opcodeRet, i;
+
+ for (i = 1; i <= _IceLastMajorOpcode; i++)
+ if (strcmp (protocolName, _IceProtocols[i - 1].protocol_name) == 0)
+ {
+ if (_IceProtocols[i - 1].orig_client != NULL)
+ {
+ /*
+ * We've already registered this protocol.
+ */
+
+ return (i);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (i <= _IceLastMajorOpcode)
+ {
+ p = _IceProtocols[i - 1].orig_client =
+ (_IcePoProtocol *) malloc (sizeof (_IcePoProtocol));
+ opcodeRet = i;
+ }
+ else if (_IceLastMajorOpcode == 255 ||
+ versionCount < 1 ||
+ strlen (protocolName) == 0)
+ {
+ return (-1);
+ }
+ else
+ {
+ char *name;
+
+ _IceProtocols[_IceLastMajorOpcode].protocol_name = name =
+ (char *) malloc (strlen (protocolName) + 1);
+ strcpy (name, protocolName);
+
+ p = _IceProtocols[_IceLastMajorOpcode].orig_client =
+ (_IcePoProtocol *) malloc (sizeof (_IcePoProtocol));
+
+ _IceProtocols[_IceLastMajorOpcode].accept_client = NULL;
+
+ opcodeRet = ++_IceLastMajorOpcode;
+ }
+
+ p->vendor = (char *) malloc (strlen (vendor) + 1);
+ strcpy (p->vendor, vendor);
+
+ p->release = (char *) malloc (strlen (release) + 1);
+ strcpy (p->release, release);
+
+ p->version_count = versionCount;
+
+ p->version_recs = (IcePoVersionRec *) malloc (
+ versionCount * sizeof (IcePoVersionRec));
+ memcpy (p->version_recs, versionRecs,
+ versionCount * sizeof (IcePoVersionRec));
+
+ if ((p->auth_count = authCount) > 0)
+ {
+ p->auth_names = (char **) malloc (
+ authCount * sizeof (char *));
+
+ p->auth_procs = (IcePoAuthProc *) malloc (
+ authCount * sizeof (IcePoAuthProc));
+
+ for (i = 0; i < authCount; i++)
+ {
+ p->auth_names[i] =
+ (char *) malloc (strlen (authNames[i]) + 1);
+ strcpy (p->auth_names[i], authNames[i]);
+
+ p->auth_procs[i] = authProcs[i];
+ }
+ }
+ else
+ {
+ p->auth_names = NULL;
+ p->auth_procs = NULL;
+ }
+
+ p->io_error_proc = IOErrorProc;
+
+ return (opcodeRet);
+}
+
+
+
+int
+IceRegisterForProtocolReply (protocolName, vendor, release,
+ versionCount, versionRecs, authCount, authNames, authProcs,
+ hostBasedAuthProc, protocolSetupProc, protocolActivateProc,
+ IOErrorProc)
+
+char *protocolName;
+char *vendor;
+char *release;
+int versionCount;
+IcePaVersionRec *versionRecs;
+int authCount;
+char **authNames;
+IcePaAuthProc *authProcs;
+IceHostBasedAuthProc hostBasedAuthProc;
+IceProtocolSetupProc protocolSetupProc;
+IceProtocolActivateProc protocolActivateProc;
+IceIOErrorProc IOErrorProc;
+
+{
+ _IcePaProtocol *p;
+ int opcodeRet, i;
+
+ for (i = 1; i <= _IceLastMajorOpcode; i++)
+ if (strcmp (protocolName, _IceProtocols[i - 1].protocol_name) == 0)
+ {
+ if (_IceProtocols[i - 1].accept_client != NULL)
+ {
+ /*
+ * We've already registered this protocol.
+ */
+
+ return (i);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+
+ if (i <= _IceLastMajorOpcode)
+ {
+ p = _IceProtocols[i - 1].accept_client =
+ (_IcePaProtocol *) malloc (sizeof (_IcePaProtocol));
+ opcodeRet = i;
+ }
+ else if (_IceLastMajorOpcode == 255 ||
+ versionCount < 1 ||
+ strlen (protocolName) == 0)
+ {
+ return (-1);
+ }
+ else
+ {
+ char *name;
+
+ _IceProtocols[_IceLastMajorOpcode].protocol_name = name =
+ (char *) malloc (strlen (protocolName) + 1);
+ strcpy (name, protocolName);
+
+ _IceProtocols[_IceLastMajorOpcode].orig_client = NULL;
+
+ p = _IceProtocols[_IceLastMajorOpcode].accept_client =
+ (_IcePaProtocol *) malloc (sizeof (_IcePaProtocol));
+
+ opcodeRet = ++_IceLastMajorOpcode;
+ }
+
+ p->vendor = (char *) malloc (strlen (vendor) + 1);
+ strcpy (p->vendor, vendor);
+
+ p->release = (char *) malloc (strlen (release) + 1);
+ strcpy (p->release, release);
+
+ p->version_count = versionCount;
+
+ p->version_recs = (IcePaVersionRec *) malloc (
+ versionCount * sizeof (IcePaVersionRec));
+ memcpy (p->version_recs, versionRecs,
+ versionCount * sizeof (IcePaVersionRec));
+
+ p->protocol_setup_proc = protocolSetupProc;
+ p->protocol_activate_proc = protocolActivateProc;
+
+ if ((p->auth_count = authCount) > 0)
+ {
+ p->auth_names = (char **) malloc (
+ authCount * sizeof (char *));
+
+ p->auth_procs = (IcePaAuthProc *) malloc (
+ authCount * sizeof (IcePaAuthProc));
+
+ for (i = 0; i < authCount; i++)
+ {
+ p->auth_names[i] =
+ (char *) malloc (strlen (authNames[i]) + 1);
+ strcpy (p->auth_names[i], authNames[i]);
+
+ p->auth_procs[i] = authProcs[i];
+ }
+ }
+ else
+ {
+ p->auth_names = NULL;
+ p->auth_procs = NULL;
+ }
+
+ p->host_based_auth_proc = hostBasedAuthProc;
+
+ p->io_error_proc = IOErrorProc;
+
+ return (opcodeRet);
+}
+
diff --git a/src/replywait.c b/src/replywait.c
new file mode 100644
index 0000000..2c816f2
--- /dev/null
+++ b/src/replywait.c
@@ -0,0 +1,158 @@
+/* $Xorg: replywait.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+
+
+void
+_IceAddReplyWait (iceConn, replyWait)
+
+IceConn iceConn;
+IceReplyWaitInfo *replyWait;
+
+{
+ /*
+ * Add this replyWait to the end of the list (only if the
+ * replyWait is not already in the list).
+ */
+
+ _IceSavedReplyWait *savedReplyWait;
+ _IceSavedReplyWait *prev, *last;
+
+ prev = NULL;
+ last = iceConn->saved_reply_waits;
+
+ while (last)
+ {
+ if (last->reply_wait == replyWait)
+ return;
+
+ prev = last;
+ last = last->next;
+ }
+
+ savedReplyWait = (_IceSavedReplyWait *) malloc (
+ sizeof (_IceSavedReplyWait));
+
+ savedReplyWait->reply_wait = replyWait;
+ savedReplyWait->reply_ready = False;
+ savedReplyWait->next = NULL;
+
+ if (prev == NULL)
+ iceConn->saved_reply_waits = savedReplyWait;
+ else
+ prev->next = savedReplyWait;
+}
+
+
+
+IceReplyWaitInfo *
+_IceSearchReplyWaits (iceConn, majorOpcode)
+
+IceConn iceConn;
+int majorOpcode;
+
+{
+ /*
+ * Return the first replyWait in the list with the given majorOpcode
+ */
+
+ _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits;
+
+ while (savedReplyWait && !savedReplyWait->reply_ready &&
+ savedReplyWait->reply_wait->major_opcode_of_request != majorOpcode)
+ {
+ savedReplyWait = savedReplyWait->next;
+ }
+
+ return (savedReplyWait ? savedReplyWait->reply_wait : NULL);
+}
+
+
+
+void
+_IceSetReplyReady (iceConn, replyWait)
+
+IceConn iceConn;
+IceReplyWaitInfo *replyWait;
+
+{
+ /*
+ * The replyWait specified has a reply ready.
+ */
+
+ _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits;
+
+ while (savedReplyWait && savedReplyWait->reply_wait != replyWait)
+ savedReplyWait = savedReplyWait->next;
+
+ if (savedReplyWait)
+ savedReplyWait->reply_ready = True;
+}
+
+
+
+Bool
+_IceCheckReplyReady (iceConn, replyWait)
+
+IceConn iceConn;
+IceReplyWaitInfo *replyWait;
+
+{
+ _IceSavedReplyWait *savedReplyWait = iceConn->saved_reply_waits;
+ _IceSavedReplyWait *prev = NULL;
+ Bool found = False;
+ Bool ready;
+
+ while (savedReplyWait && !found)
+ {
+ if (savedReplyWait->reply_wait == replyWait)
+ found = True;
+ else
+ {
+ prev = savedReplyWait;
+ savedReplyWait = savedReplyWait->next;
+ }
+ }
+
+ ready = found && savedReplyWait->reply_ready;
+
+ if (ready)
+ {
+ if (prev == NULL)
+ iceConn->saved_reply_waits = savedReplyWait->next;
+ else
+ prev->next = savedReplyWait->next;
+
+ free ((char *) savedReplyWait);
+ }
+
+ return (ready);
+}
diff --git a/src/setauth.c b/src/setauth.c
new file mode 100644
index 0000000..5df13ec
--- /dev/null
+++ b/src/setauth.c
@@ -0,0 +1,113 @@
+/* $Xorg: setauth.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+#include <X11/ICE/ICEutil.h>
+
+
+/*
+ * IceSetPaAuthData is not a standard part of ICElib, it is specific
+ * to the sample implementation.
+ *
+ * For the client that initiates a Protocol Setup, we look in the
+ * .ICEauthority file to get authentication data.
+ *
+ * For the client accepting the Protocol Setup, we get the data
+ * from an in-memory database of authentication data (set by the
+ * application calling IceSetPaAuthData). We have to get the data
+ * from memory because getting it directly from the .ICEauthority
+ * file is not secure - someone can just modify the contents of the
+ * .ICEauthority file behind our back.
+ */
+
+int _IcePaAuthDataEntryCount = 0;
+IceAuthDataEntry _IcePaAuthDataEntries[ICE_MAX_AUTH_DATA_ENTRIES];
+
+
+void
+IceSetPaAuthData (numEntries, entries)
+
+int numEntries;
+IceAuthDataEntry *entries;
+
+{
+ /*
+ * _IcePaAuthDataEntries should really be a linked list.
+ * On my list of TO DO stuff.
+ */
+
+ int i, j;
+
+ for (i = 0; i < numEntries; i++)
+ {
+ for (j = 0; j < _IcePaAuthDataEntryCount; j++)
+ if (strcmp (entries[i].protocol_name,
+ _IcePaAuthDataEntries[j].protocol_name) == 0 &&
+ strcmp (entries[i].network_id,
+ _IcePaAuthDataEntries[j].network_id) == 0 &&
+ strcmp (entries[i].auth_name,
+ _IcePaAuthDataEntries[j].auth_name) == 0)
+ break;
+
+ if (j < _IcePaAuthDataEntryCount)
+ {
+ free (_IcePaAuthDataEntries[j].protocol_name);
+ free (_IcePaAuthDataEntries[j].network_id);
+ free (_IcePaAuthDataEntries[j].auth_name);
+ free (_IcePaAuthDataEntries[j].auth_data);
+ }
+ else
+ {
+ _IcePaAuthDataEntryCount++;
+ }
+
+ _IcePaAuthDataEntries[j].protocol_name = (char *) malloc (
+ strlen (entries[i].protocol_name) + 1);
+ strcpy (_IcePaAuthDataEntries[j].protocol_name,
+ entries[i].protocol_name);
+
+ _IcePaAuthDataEntries[j].network_id = (char *) malloc (
+ strlen (entries[i].network_id) + 1);
+ strcpy (_IcePaAuthDataEntries[j].network_id,
+ entries[i].network_id);
+
+ _IcePaAuthDataEntries[j].auth_name = (char *) malloc (
+ strlen (entries[i].auth_name) + 1);
+ strcpy (_IcePaAuthDataEntries[j].auth_name,
+ entries[i].auth_name);
+
+ _IcePaAuthDataEntries[j].auth_data_length =
+ entries[i].auth_data_length;
+ _IcePaAuthDataEntries[j].auth_data = (char *) malloc (
+ entries[i].auth_data_length);
+ memcpy (_IcePaAuthDataEntries[j].auth_data,
+ entries[i].auth_data, entries[i].auth_data_length);
+ }
+}
diff --git a/src/shutdown.c b/src/shutdown.c
new file mode 100644
index 0000000..94a7eb9
--- /dev/null
+++ b/src/shutdown.c
@@ -0,0 +1,325 @@
+/* $Xorg: shutdown.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+
+
+Status
+IceProtocolShutdown (iceConn, majorOpcode)
+
+IceConn iceConn;
+int majorOpcode;
+
+{
+ if (iceConn->proto_ref_count == 0 || iceConn->process_msg_info == NULL ||
+ majorOpcode < 1 || majorOpcode > _IceLastMajorOpcode)
+ {
+ return (0);
+ }
+ else
+ {
+ /*
+ * Make sure this majorOpcode is really being used.
+ */
+
+ int i;
+
+ for (i = iceConn->his_min_opcode; i <= iceConn->his_max_opcode; i++)
+ {
+ if (iceConn->process_msg_info[
+ i - iceConn->his_min_opcode].in_use &&
+ iceConn->process_msg_info[
+ i - iceConn->his_min_opcode].my_opcode == majorOpcode)
+ break;
+ }
+
+ if (i > iceConn->his_max_opcode)
+ {
+ return (0);
+ }
+ else
+ {
+ /*
+ * OK, we can shut down the protocol.
+ */
+
+ iceConn->process_msg_info[
+ i - iceConn->his_min_opcode].in_use = False;
+ iceConn->proto_ref_count--;
+
+ return (1);
+ }
+ }
+}
+
+
+
+void
+IceSetShutdownNegotiation (iceConn, negotiate)
+
+IceConn iceConn;
+Bool negotiate;
+
+{
+ iceConn->skip_want_to_close = negotiate ? False : True;
+}
+
+
+
+Bool
+IceCheckShutdownNegotiation (iceConn)
+
+IceConn iceConn;
+
+{
+ return (iceConn->skip_want_to_close ? False : True);
+}
+
+
+
+IceCloseStatus
+IceCloseConnection (iceConn)
+
+IceConn iceConn;
+
+{
+ int refCountReachedZero;
+ IceCloseStatus status;
+
+ /*
+ * If this connection object was never valid, we can close
+ * it right now. This happens if IceAcceptConnection was
+ * called, but after calling IceProcessMessages several times
+ * the connection was rejected (because of authentication or
+ * some other reason).
+ */
+
+ if (iceConn->listen_obj &&
+ iceConn->connection_status != IceConnectAccepted)
+ {
+ _IceConnectionClosed (iceConn); /* invoke watch procs */
+ _IceFreeConnection (iceConn);
+ return (IceClosedNow);
+ }
+
+
+ /*---------------------------------------------------------------
+
+ ACTIONS:
+
+ A = Invoke Watch Procedures
+ B = Set free-asap bit
+ C = Free connection
+ D = Initialize shutdown negotiation
+ N = do nothing
+
+
+ ACTION TABLE:
+
+ IO free- dispatch protocol shutdown
+ error asap bit level refcount negotiation ACTION
+ occured set reached 0 reached 0
+
+ 0 0 0 0 0 N
+ 0 0 0 0 1 N
+ 0 0 0 1 0 AB
+ 0 0 0 1 1 N
+ 0 0 1 0 0 N
+ 0 0 1 0 1 N
+ 0 0 1 1 0 AC
+ 0 0 1 1 1 D
+ 0 1 0 0 0 N
+ 0 1 0 0 1 N
+ 0 1 0 1 0 N
+ 0 1 0 1 1 N
+ 0 1 1 0 0 C
+ 0 1 1 0 1 D
+ 0 1 1 1 0 C
+ 0 1 1 1 1 D
+ 1 0 0 0 0 AB
+ 1 0 0 0 1 AB
+ 1 0 0 1 0 AB
+ 1 0 0 1 1 AB
+ 1 0 1 0 0 AC
+ 1 0 1 0 1 AC
+ 1 0 1 1 0 AC
+ 1 0 1 1 1 AC
+ 1 1 0 0 0 N
+ 1 1 0 0 1 N
+ 1 1 0 1 0 N
+ 1 1 0 1 1 N
+ 1 1 1 0 0 C
+ 1 1 1 0 1 C
+ 1 1 1 1 0 C
+ 1 1 1 1 1 C
+
+ ---------------------------------------------------------------*/
+
+ if (iceConn->open_ref_count > 0)
+ iceConn->open_ref_count--;
+
+ refCountReachedZero = iceConn->open_ref_count == 0 &&
+ iceConn->proto_ref_count == 0;
+
+ status = IceConnectionInUse;
+
+ if (!iceConn->free_asap && (!iceConn->io_ok ||
+ (iceConn->io_ok && refCountReachedZero &&
+ iceConn->skip_want_to_close)))
+ {
+ /*
+ * Invoke the watch procedures now.
+ */
+
+ _IceConnectionClosed (iceConn);
+ status = IceClosedNow; /* may be overwritten by IceClosedASAP */
+ }
+
+ if (!iceConn->free_asap && iceConn->dispatch_level != 0 &&
+ (!iceConn->io_ok ||
+ (iceConn->io_ok && refCountReachedZero &&
+ iceConn->skip_want_to_close)))
+ {
+ /*
+ * Set flag so we free the connection as soon as possible.
+ */
+
+ iceConn->free_asap = True;
+ status = IceClosedASAP;
+ }
+
+ if (iceConn->io_ok && iceConn->dispatch_level == 0 &&
+ !iceConn->skip_want_to_close && refCountReachedZero)
+ {
+ /*
+ * Initiate shutdown negotiation.
+ */
+
+ IceSimpleMessage (iceConn, 0, ICE_WantToClose);
+ IceFlush (iceConn);
+
+ iceConn->want_to_close = 1;
+
+ status = IceStartedShutdownNegotiation;
+ }
+ else if (iceConn->dispatch_level == 0 &&
+ (!iceConn->io_ok || (iceConn->io_ok && iceConn->skip_want_to_close &&
+ (iceConn->free_asap || (!iceConn->free_asap && refCountReachedZero)))))
+ {
+ /*
+ * Free the connection.
+ */
+
+ _IceFreeConnection (iceConn);
+
+ status = IceClosedNow;
+ }
+
+ return (status);
+}
+
+
+
+void
+_IceFreeConnection (iceConn)
+
+IceConn iceConn;
+
+{
+ if (iceConn->listen_obj == NULL)
+ {
+ /*
+ * This iceConn was created with IceOpenConnection.
+ * We keep track of all open IceConn's, so we need
+ * to remove it from the list.
+ */
+
+ int i;
+
+ for (i = 0; i < _IceConnectionCount; i++)
+ if (_IceConnectionObjs[i] == iceConn)
+ break;
+
+ if (i < _IceConnectionCount)
+ {
+ if (i < _IceConnectionCount - 1)
+ {
+ _IceConnectionObjs[i] =
+ _IceConnectionObjs[_IceConnectionCount - 1];
+ _IceConnectionStrings[i] =
+ _IceConnectionStrings[_IceConnectionCount - 1];
+ }
+
+ _IceConnectionCount--;
+ }
+ }
+
+ if (iceConn->trans_conn)
+ _IceTransClose (iceConn->trans_conn);
+
+ if (iceConn->connection_string)
+ free (iceConn->connection_string);
+
+ if (iceConn->vendor)
+ free (iceConn->vendor);
+
+ if (iceConn->release)
+ free (iceConn->release);
+
+ if (iceConn->inbuf)
+ free (iceConn->inbuf);
+
+ if (iceConn->outbuf)
+ free (iceConn->outbuf);
+
+ if (iceConn->scratch)
+ free (iceConn->scratch);
+
+ if (iceConn->process_msg_info)
+ free ((char *) iceConn->process_msg_info);
+
+ if (iceConn->connect_to_you)
+ free ((char *) iceConn->connect_to_you);
+
+ if (iceConn->protosetup_to_you)
+ free ((char *) iceConn->protosetup_to_you);
+
+ if (iceConn->connect_to_me)
+ free ((char *) iceConn->connect_to_me);
+
+ if (iceConn->protosetup_to_me)
+ free ((char *) iceConn->protosetup_to_me);
+
+ free ((char *) iceConn);
+}
+
+
+
+
diff --git a/src/watch.c b/src/watch.c
new file mode 100644
index 0000000..6c33192
--- /dev/null
+++ b/src/watch.c
@@ -0,0 +1,203 @@
+/* $Xorg: watch.c,v 1.4 2001/02/09 02:03:26 xorgcvs Exp $ */
+/******************************************************************************
+
+
+Copyright 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+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 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP 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 Open Group 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 Open Group.
+
+Author: Ralph Mor, X Consortium
+******************************************************************************/
+
+#include <X11/ICE/ICElib.h>
+#include "ICElibint.h"
+
+
+Status
+IceAddConnectionWatch (watchProc, clientData)
+
+IceWatchProc watchProc;
+IcePointer clientData;
+
+{
+ /*
+ * watchProc will be called each time an ICE connection is
+ * created/destroyed by ICElib.
+ */
+
+ _IceWatchProc *ptr = _IceWatchProcs;
+ _IceWatchProc *newWatchProc;
+ int i;
+
+ if ((newWatchProc = (_IceWatchProc *) malloc (
+ sizeof (_IceWatchProc))) == NULL)
+ {
+ return (0);
+ }
+
+ newWatchProc->watch_proc = watchProc;
+ newWatchProc->client_data = clientData;
+ newWatchProc->watched_connections = NULL;
+ newWatchProc->next = NULL;
+
+ while (ptr && ptr->next)
+ ptr = ptr->next;
+
+ if (ptr == NULL)
+ _IceWatchProcs = newWatchProc;
+ else
+ ptr->next = newWatchProc;
+
+
+ /*
+ * Invoke the watch proc with any previously opened ICE connections.
+ */
+
+ for (i = 0; i < _IceConnectionCount; i++)
+ {
+ _IceWatchedConnection *newWatchedConn = (_IceWatchedConnection *)
+ malloc (sizeof (_IceWatchedConnection));
+
+ newWatchedConn->iceConn = _IceConnectionObjs[i];
+ newWatchedConn->next = NULL;
+
+ newWatchProc->watched_connections = newWatchedConn;
+
+ (*newWatchProc->watch_proc) (_IceConnectionObjs[i],
+ newWatchProc->client_data, True, &newWatchedConn->watch_data);
+ }
+
+ return (1);
+}
+
+
+
+void
+IceRemoveConnectionWatch (watchProc, clientData)
+
+IceWatchProc watchProc;
+IcePointer clientData;
+
+{
+ _IceWatchProc *currWatchProc = _IceWatchProcs;
+ _IceWatchProc *prevWatchProc = NULL;
+
+ while (currWatchProc && (currWatchProc->watch_proc != watchProc ||
+ currWatchProc->client_data != clientData))
+ {
+ prevWatchProc = currWatchProc;
+ currWatchProc = currWatchProc->next;
+ }
+
+ if (currWatchProc)
+ {
+ _IceWatchProc *nextWatchProc = currWatchProc->next;
+ _IceWatchedConnection *watchedConn;
+
+ watchedConn = currWatchProc->watched_connections;
+ while (watchedConn)
+ {
+ _IceWatchedConnection *nextWatchedConn = watchedConn->next;
+ free ((char *) watchedConn);
+ watchedConn = nextWatchedConn;
+ }
+
+ if (prevWatchProc == NULL)
+ _IceWatchProcs = nextWatchProc;
+ else
+ prevWatchProc->next = nextWatchProc;
+
+ free ((char *) currWatchProc);
+ }
+}
+
+
+
+void
+_IceConnectionOpened (iceConn)
+
+IceConn iceConn;
+
+{
+ _IceWatchProc *watchProc = _IceWatchProcs;
+
+ while (watchProc)
+ {
+ _IceWatchedConnection *newWatchedConn = (_IceWatchedConnection *)
+ malloc (sizeof (_IceWatchedConnection));
+ _IceWatchedConnection *watchedConn;
+
+ watchedConn = watchProc->watched_connections;
+ while (watchedConn && watchedConn->next)
+ watchedConn = watchedConn->next;
+
+ newWatchedConn->iceConn = iceConn;
+ newWatchedConn->next = NULL;
+
+ if (watchedConn == NULL)
+ watchProc->watched_connections = newWatchedConn;
+ else
+ watchedConn->next = newWatchedConn;
+
+ (*watchProc->watch_proc) (iceConn,
+ watchProc->client_data, True, &newWatchedConn->watch_data);
+
+ watchProc = watchProc->next;
+ }
+}
+
+
+
+void
+_IceConnectionClosed (iceConn)
+
+IceConn iceConn;
+
+{
+ _IceWatchProc *watchProc = _IceWatchProcs;
+
+ while (watchProc)
+ {
+ _IceWatchedConnection *watchedConn = watchProc->watched_connections;
+ _IceWatchedConnection *prev = NULL;
+
+ while (watchedConn && watchedConn->iceConn != iceConn)
+ {
+ prev = watchedConn;
+ watchedConn = watchedConn->next;
+ }
+
+ if (watchedConn)
+ {
+ (*watchProc->watch_proc) (iceConn,
+ watchProc->client_data, False, &watchedConn->watch_data);
+
+ if (prev == NULL)
+ watchProc->watched_connections = watchedConn->next;
+ else
+ prev->next = watchedConn->next;
+
+ free ((char *) watchedConn);
+ }
+
+ watchProc = watchProc->next;
+ }
+}