From 60e0655b21e92e18c1a9dc20160f2c1a2164f069 Mon Sep 17 00:00:00 2001 From: Jinkun Jang Date: Wed, 13 Mar 2013 01:54:03 +0900 Subject: [PATCH] Tizen 2.1 base --- AUTHORS | 6 + COPYING | 23 + ChangeLog | 1206 ++++++++++++ INSTALL | 290 +++ Makefile.am | 21 + README | 30 + configure.ac | 53 + doc/ICElib.xml | 4581 ++++++++++++++++++++++++++++++++++++++++++++ doc/Makefile.am | 13 + docbook.am | 105 + ice.pc.in | 11 + include/X11/ICE/ICE.h | 101 + include/X11/ICE/ICEconn.h | 250 +++ include/X11/ICE/ICElib.h | 431 +++++ include/X11/ICE/ICEmsg.h | 316 +++ include/X11/ICE/ICEproto.h | 175 ++ include/X11/ICE/ICEutil.h | 124 ++ packaging/libICE.spec | 65 + specs/Makefile.am | 13 + specs/ice.xml | 2601 +++++++++++++++++++++++++ src/ICElibint.h | 541 ++++++ src/Makefile.am | 52 + src/accept.c | 183 ++ src/authutil.c | 504 +++++ src/connect.c | 533 ++++++ src/error.c | 629 ++++++ src/getauth.c | 257 +++ src/globals.h | 45 + src/iceauth.c | 247 +++ src/icetrans.c | 31 + src/listen.c | 273 +++ src/listenwk.c | 159 ++ src/locking.c | 65 + src/misc.c | 590 ++++++ src/ping.c | 64 + src/process.c | 2558 +++++++++++++++++++++++++ src/protosetup.c | 288 +++ src/register.c | 235 +++ src/replywait.c | 156 ++ src/setauth.c | 112 ++ src/shutdown.c | 323 ++++ src/watch.c | 201 ++ 42 files changed, 18461 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 README create mode 100644 configure.ac create mode 100644 doc/ICElib.xml create mode 100644 doc/Makefile.am create mode 100644 docbook.am create mode 100644 ice.pc.in create mode 100644 include/X11/ICE/ICE.h create mode 100644 include/X11/ICE/ICEconn.h create mode 100644 include/X11/ICE/ICElib.h create mode 100644 include/X11/ICE/ICEmsg.h create mode 100644 include/X11/ICE/ICEproto.h create mode 100644 include/X11/ICE/ICEutil.h create mode 100644 packaging/libICE.spec create mode 100644 specs/Makefile.am create mode 100644 specs/ice.xml create mode 100644 src/ICElibint.h create mode 100644 src/Makefile.am create mode 100644 src/accept.c create mode 100644 src/authutil.c create mode 100644 src/connect.c create mode 100644 src/error.c create mode 100644 src/getauth.c create mode 100644 src/globals.h create mode 100644 src/iceauth.c create mode 100644 src/icetrans.c create mode 100644 src/listen.c create mode 100644 src/listenwk.c create mode 100644 src/locking.c create mode 100644 src/misc.c create mode 100644 src/ping.c create mode 100644 src/process.c create mode 100644 src/protosetup.c create mode 100644 src/register.c create mode 100644 src/replywait.c create mode 100644 src/setauth.c create mode 100644 src/shutdown.c create mode 100644 src/watch.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..1352818 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,6 @@ +Ralph Mor, of the X Consortium is the original author. + +OS/2 support, Holger Veit, bug fixes by Keith Packard, Petter Reinholdtsen, +others. + +Our apologies if we've overlooked a contributor. diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..fa56591 --- /dev/null +++ b/COPYING @@ -0,0 +1,23 @@ +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 diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..ba78679 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,1206 @@ +commit f166e8bbf16ec214fefdcf02ce81f80442899cb7 +Author: Alan Coopersmith +Date: Fri Mar 2 19:59:50 2012 -0800 + + libICE 1.0.8 + + Signed-off-by: Alan Coopersmith + +commit c87ecd959d61ae97d8a2bd82efc761bb3e299061 +Author: Matt Dew +Date: Mon Jan 9 21:25:18 2012 -0700 + + informaltable cleanup + + On certain tables, add top and bottom borders to table header + and a bottom border to the table. This matches what those + tables in the old pdfs looked like. + + the prevents tables from + splitting across pages. Useful for tiny tables. + + Converting the colwidth to a floating point, IE, 1* -> 1.0* + cleans up these build errors: + WARNING: table-layout="fixed" and column-width unspecified => + falling back to proportional-column-width(1) + + Signed-off-by: Matt Dew + +commit 8b4321a37a9fa2ad24bf87afabba6b08dcfded12 +Author: Alan Coopersmith +Date: Thu Nov 24 12:42:36 2011 -0800 + + Plug minor memory leak in unusual path through ProcessConnectionSetup + + Error: Memory leak (CWE 401) + Memory leak of pointer 'release' allocated with malloc((_len + 1)) + at line 1100 of src/process.c in function 'ProcessConnectionSetup'. + 'release' allocated at line 920 with malloc((_len + 1)). + release leaks when _i >= hisAuthCount at line 925 + and i >= _IceAuthCount at line 973 + and found != 0 at line 998 + and status != 0 at line 1053 + and status != 1 at line 1070 + and accept_setup_now == 0 at line 1082 + and i >= hisAuthCount at line 1093. + Memory leak of pointer 'vendor' allocated with malloc((_len + 1)) + at line 1100 of src/process.c in function 'ProcessConnectionSetup'. + 'vendor' allocated at line 919 with malloc((_len + 1)). + vendor leaks when _i >= hisAuthCount at line 925 + and i >= _IceAuthCount at line 973 + and found != 0 at line 998 + and status != 0 at line 1053 + and status != 1 at line 1070 + and accept_setup_now == 0 at line 1082 + and i >= hisAuthCount at line 1093. + + [ This bug was found by the Parfait 0.3.7 bug checking tool. + For more information see http://labs.oracle.com/projects/parfait/ ] + + Signed-off-by: Alan Coopersmith + Reviewed-by: Jeremy Huddleston + +commit caf9e3393d5d517ea129392d001a2c46a7c1f325 +Author: Alan Coopersmith +Date: Sat Nov 19 00:26:29 2011 -0800 + + Constify protocol, vendor & release string args to IceRegisterForProtocol* + + Needed to resolve gcc -Wwrite-strings warnings in callers. + These functions only pass the strings to strcmp before calling + strdup to make their own private copy for storing away. + + While fixing the API docs to match, also fix them to match the existing + function prototypes, where there were several errors before (including + just plain missing most of the args to IceRegisterForProtocolReply). + + Signed-off-by: Alan Coopersmith + Reviewed-by: Jeremy Huddleston + +commit 59c1555dff34804c78c7e7443ad13f27300927eb +Author: Alan Coopersmith +Date: Wed Nov 9 22:07:34 2011 -0800 + + Remove ancient workaround for System V/386 Release 4.2 compiler bug + + Signed-off-by: Alan Coopersmith + Reviewed-by: Matthieu Herrb + Reviewed-by: walter + Reviewed-by: Jeremy Huddleston + +commit bec4e9c9089fa4cc5a50fc513a3544cf6fd59bf1 +Author: Alan Coopersmith +Date: Wed Nov 9 22:06:36 2011 -0800 + + Fix gcc -Wwrite-strings warnings in process.c + + Signed-off-by: Alan Coopersmith + Reviewed-by: Jeremy Huddleston + +commit ffa659dd6dd1fb8847bfdcc5e1e2be353b6395b6 +Author: Alan Coopersmith +Date: Wed Nov 9 21:37:48 2011 -0800 + + Fix gcc -Wwrite-strings warnings in AuthNames handling + + Signed-off-by: Alan Coopersmith + Reviewed-by: Jeremy Huddleston + +commit 902a52ea9d7b6e6f56f7023009859072854a0fc7 +Author: Alan Coopersmith +Date: Wed Nov 9 21:55:17 2011 -0800 + + constify arguments to IceGetAuthFileEntry + + Needed to clear gcc -Wwrite-strings warnings in callers + + Signed-off-by: Alan Coopersmith + Reviewed-by: Jeremy Huddleston + +commit 9ff1f97e46903f8f83363f07cf021989bfa6a9f0 +Author: Alan Coopersmith +Date: Wed Nov 9 21:43:59 2011 -0800 + + Fix gcc -Wwrite-strings warnings in _IceError* functions + + Signed-off-by: Alan Coopersmith + Reviewed-by: Jeremy Huddleston + +commit e8a16534a9406d5096d9c0ea515d979c7c15e084 +Author: Alan Coopersmith +Date: Wed Nov 9 21:23:33 2011 -0800 + + Fix gcc -Wwrite-strings warnings in _IceDefaultErrorHandler + + Had to split char *str into two variables, const char *str for the + string literals just being passed to fprintf etal. and char *estr + for use by EXTRACT_STRING for the results of malloc calls that get + written to and then freed. + + Signed-off-by: Alan Coopersmith + Reviewed-by: Jeremy Huddleston + +commit 4fbcba4ee19a49c05440861e1278bc97d29048e0 +Author: Matt Dew +Date: Tue Oct 4 23:32:02 2011 -0600 + + Cleanup IDs and links in doc + + 1 - fix the capitalization of the ID attributes to match either the + or <funcdef> string it goes with. + 2 - fix any <linkend>'s that were affected by 1. + 3 - any <function> in the docs that has an actual funcdef, + will become an olink. + + Signed-off-by: Matt Dew <marcoz@osource.org> + +commit d4e161e35335df82f412d2d2bb1ef95ff3e88401 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Mon Sep 19 15:34:47 2011 -0400 + + As of 1997, X Window System is a trademark of The Open Group. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit fc0fc948d25dfa0f6f445a3b55610ea5b864dd60 +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Fri Sep 16 22:09:18 2011 -0700 + + Strip trailing whitespace + + Performed with: find * -type f | xargs perl -i -p -e 's{[ \t]+$}{}' + git diff -w & git diff -b show no diffs from this change + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit 22601de3f38d035eb874d4bd9f649ddd2b3f0ae2 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Sep 11 17:20:20 2011 -0400 + + specs: remove <productnumber> which is not used by default + + This element is not rendered by default on the title. A template + customization is required to display it. + X Window System does not have a product number. + + Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com> + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 7f330738f1f5862950b3baa35ff08446093bfd4e +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Sep 11 17:06:00 2011 -0400 + + specs: use DocBook suggested markup for Copyrights + + Puts the statement on a single line, using commas to separate years + --> Copyright © 1993, 1994, 1996 X Consortium + + As opposed to 3 double-spaced lines. + + Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com> + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit d68d2d2031f623a969784e702c97a07b8cd99010 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Sep 11 16:56:21 2011 -0400 + + specs: remove orphan <corpname> + + It does not display on the title page and is redundant. + No visible change on the doc. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 87c934b9b7973a814763670e2dfad0579a8dcc78 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Sep 11 16:27:09 2011 -0400 + + specs: use the &fullrelvers; entity to set X11 release information + + Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com> + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 41f04fd8673db5c2d8e587ab2c169a694bd7528f +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Sep 11 14:13:35 2011 -0400 + + ice.xml: version number is 1.1, not 1.0 + + This is what it was before the conversion from roff to docbook. + + Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com> + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 9e2a596b4ff06fc9c70dfcd94506e536e351ee0b +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Sep 11 14:11:28 2011 -0400 + + ice.xml: fix orphan affiliation + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 1309d477a061d165345b602e122990eaab71a0d4 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Fri Sep 9 21:21:57 2011 -0400 + + ICElib doc: remove empty revision list and specify the doc version number + + Revision histories are not used, only 3 docs out of 63 have one. + + Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit e9d57773df26ad9440a49f58941b511e594605a4 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Thu Sep 8 20:00:00 2011 -0400 + + docbook.am: embed css styles inside the HTML HEAD element + + Rather than referring to the external xorg.css stylesheet, embed the content + of the file in the html output produced. This is accomplished by using + version 1.10 of xorg-xhtml.xsl. + + This makes the whole html docs tree much more relocatable. + In addition, it eliminates xorg.css as a runtime file which makes + xorg-sgml-doctools a build time only package. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit b83cbed755315f6300133f2621cbe99bdc06345a +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Wed Sep 7 10:31:04 2011 -0400 + + docbook.am: global maintenance update - entities, images and olinking + + Adding support in libX11 for html chunking caused a reorg of docbook.am + as well as the xorg-sgml-doctools masterdb for olinking. + The parameter img.src.path is added for pdf images. + A searchpath to the root builddir is added for local entities, if present. + + The docbook.am makefile hides all the details and is identical for + all 22 modules having DocBook documentation. It is included by a thin + Makefile.am which requires no docbook knowledge. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit f35b8b8be16f1903beed34fe23fa53d102329342 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Jun 12 17:54:50 2011 -0400 + + Install xml versions of specs even if HAVE_XMLTO is false + + DocBook/XML input source is also a usefull output format that can be viewed + with an XML viewer or editor and by some O/S help system. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 4c9cbdb1b40799121456c692d960135d741f13c7 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Jun 5 16:27:36 2011 -0400 + + Install target dbs alongside generated documents + + This matches a change in xorg-sgml-docs whereby the masterdb will look for + the target dbs into the same location as the generated documents. + + The target dbs are now installed alongside the generated documents. + Previously they are installed in $prefix/sgml/X11/dbs alongside masterdb which + has the potential of installing outside the package prefix and cause + distcheck to fail when user does not have write permission in this package. + + Requires XORG_CHECK_SGML_DOCTOOLS(1.8) which was released 2011-06-11 + +commit 72d668dd2ec4db9b75973ba24f42ab49851dbc6d +Author: Matt Dew <marcoz@osource.org> +Date: Wed May 25 22:54:51 2011 -0600 + + add id attributes to funcsynopsis to allow other docs to olink to them + + Signed-off-by: Matt Dew <marcoz@osource.org> + Reviewed-by: Alan Coopersmith <alan.coopersmith@oracle.com> + Reviewed-by: Gaetan Nadon <memsize@videotron.ca> + +commit dd7f2beaa753541aefba499813f25de38cbd17b7 +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Tue Apr 19 18:36:58 2011 -0700 + + IceWritePad: Zero fill pad bytes used when buffer is full + + Should be rarely hit, since it's only in the case where most of the + message fits in the buffer, but there's not room left for the padding + bytes, but better than sending uninitialized bytes off the stack when + it happens. + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com> + +commit 663782989be82e7893c99eaa7cbe98ec25a23c38 +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Tue Apr 19 18:19:19 2011 -0700 + + Fix reads outside array bounds in error handlers + + Error: Buffer overrun + Read outside array bounds (CWE 125): In call to memcpy(<unknown>, &mOp, 8), (size(&mOp) < (unsigned) 8) + Array size is 1 bytes + at line 296 of src/error.c in function '_IceErrorMajorOpcodeDuplicate'. + Error: Buffer overrun + Read outside array bounds (CWE 125): In call to memcpy(<unknown>, &maj, 8), (size(&maj) < (unsigned) 8) + Array size is 1 bytes + at line 346 of src/error.c in function '_IceErrorBadMajor'. + + [ This bug was found by the Parfait 0.3.7 bug checking tool. + For more information see http://labs.oracle.com/projects/parfait/ ] + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com> + +commit daf686b7639919289b07a575a0d88efcb91d9732 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Wed Mar 30 20:15:07 2011 -0400 + + doc: xorg-sgml-doctools package at version 1.7 is required + + This version contains support for external references + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit fadb927532556adb471300c89de29d268aae9102 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Sun Feb 27 15:06:18 2011 -0500 + + Documentation: add Docbook external references support + + When writing technical documentation, it is often necessary to cross + reference to other information. When that other information is not in the + current document, additional support is needed, namely <olink>. + + A new feature with version 1.7 of xorg-sgml-doctools adds references to + other documents within or outside this package. + + This patch adds technical support for this feature but does not change + the content of the documentation as seen by the end user. + + Each book or article must generate a database containing the href + of sections that can be referred to from another document. This database + is installed in DATAROOTDIR/sgml/X11/dbs. There is a requirement that + the value of DATAROOTDIR for xorg-sgml-doctools and for the package + documentation is the same. This forms a virtual document tree. + + This database is consulted by other documents while they are being generated + in order to fulfill the missing information for linking. + Refer to the xorg-sgml-doctools for further technical information. + + Co-authored-by: Matt Dew <marcoz@osource.org> + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 483d32621c06bcba0c7aa7794633b46b151fd5bf +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Fri Feb 25 08:58:54 2011 -0500 + + Docbook: change the book id to match the xml file basename + + This is required for the up-coming external references support. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 4852c5bb1603fb6d401fe6895d9318555a8d4523 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Wed Feb 2 19:13:54 2011 -0500 + + config: splitting ICE and XTRANS compiler options is not required + + Simplify configuration by using a single PKG_CHECK_MODULES statement. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 87d34a2f04c9d920da01802cd9707c8107746fa5 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Wed Feb 2 11:43:40 2011 -0500 + + config: comment, minor upgrade, quote and layout configure.ac + + Group statements per section as per Autoconf standard layout + Quote statements where appropriate. + Autoconf recommends not using dnl instead of # for comments + + Use AC_CONFIG_FILES to replace the deprecated AC_OUTPUT with parameters. + + This helps automated maintenance and release activities. + Details can be found in http://wiki.x.org/wiki/NewModuleGuidelines + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 548eded10385ccc336e66dac8bbabe05f3225ec2 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Fri Jan 28 14:42:12 2011 -0500 + + config: remove unrequired AC_HEADER_STDC + + Autoconf says: + "This macro is obsolescent, as current systems have conforming + header files. New programs need not use this macro". + +commit 78b8e6b772685a2ed567ac2d30f96116f050dad5 +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Fri Jan 7 19:29:03 2011 -0800 + + Resync fallback asprintf with updated version put into xrdb + + Fixes issues found during xrdb review on xorg-devel + Also make sure <stdarg.h> is #included for varargs macros + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit dc63c253e33b1012c08cd274e6e37bf0fa87c624 +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Tue Dec 21 18:28:36 2010 -0800 + + Add AC_USE_SYSTEM_EXTENSIONS to make asprintf() visible in GNU libc + + asprintf is considered a GNU extension and thus one needs to define + _GNU_SOURCE before including stdio.h. + + Reported-by: Cyril Brulebois <kibi@debian.org> + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + Reviewed-by: Mark Kettenis <kettenis@openbsd.org> + Reviewed-by: Gaetan Nadon <memsize@videotron.ca> + +commit 4b4ec3aeaa7cf5f5a6490ad2ddc2b07d090214cb +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Sun Dec 19 09:57:05 2010 -0800 + + Use correct string pointer in asprintf() fallback + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit 308c8d3d5fbf96c1d4f313def50d4b001ac0d685 +Author: Paulo Zanoni <przanoni@gmail.com> +Date: Fri Dec 17 14:59:22 2010 -0200 + + Remove useless line from a table in specs/ice.xml + + This seems to be a leftover from a manpage/groff conversion. + + Signed-off-by: Paulo Zanoni <pzanoni@mandriva.com> + Reviewed-by: Matt Dew + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit a72467b21662a63c81418731b540a8843d138750 +Author: Paulo Zanoni <pzanoni@mandriva.com> +Date: Thu Dec 16 13:59:52 2010 -0200 + + Use docbookx.dtd version 4.3 for all docs + + Signed-off-by: Paulo Zanoni <pzanoni@mandriva.com> + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit e0280caf7cc9d0e1c2df3ab7c5a4fbe4e42696a9 +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Sun Dec 5 01:15:42 2010 -0800 + + Convert src/process.c from malloc + sprintf to asprintf + + Includes simple local implemenation of asprintf if configure doesn't + find one in system libraries + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + Reviewed-by: Julien Cristau <jcristau@debian.org> + +commit a5669dcb488db19b1ba4f1ef4d4565b6c3d1ea09 +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Sat Nov 20 19:47:53 2010 -0800 + + config: replace deprecated AM_CONFIG_HEADER with AC_CONFIG_HEADERS + + Regroup AC statements under the Autoconf initialization section. + Regroup AM statements under the Automake initialization section. + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit d902a9f27369fc8388774e73f4bee6ab0ad86ef5 +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Sat Nov 20 19:45:42 2010 -0800 + + config: Remove unnecessary calls from configure.ac + + AC_PROG_CC is provided by XORG_DEFAULT_OPTIONS now + PKG_CONFIG_MODULES handles AC_SUBST of the CFLAGS & LIBS variables + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit fd56c4e00a564d6385ccb2f8fadf10de201ae411 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Tue Nov 9 11:28:48 2010 -0500 + + config: HTML file generation: use the installed copy of xorg.css + + Currenlty the xorg.css file is copied in each location + where a DocBook/XML file resides. This produces about + 70 copies in the $(docdir) install tree. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 9856f5679b2b2d458cf830c1e8fdd206c724dfc5 +Author: Adam Jackson <ajax@redhat.com> +Date: Tue Oct 19 11:19:08 2010 -0400 + + libICE 1.0.7 + + Signed-off-by: Adam Jackson <ajax@redhat.com> + +commit 59a8d5609398824c81b72deb82735a55332ca239 +Author: Jeremy Huddleston <jeremyhu@apple.com> +Date: Sun Oct 17 21:26:31 2010 -0700 + + Fix include ordering, so -I../include precedes $CPPFLAGS which could + cause us to include installed rather than packaged headers. + + Signed-off-by: Jeremy Huddleston <jeremyhu@apple.com> + +commit 4a6f7a357222b2c1fa289d6e7b5fcc8c361e20e9 +Author: Jesse Adkins <jesserayadkins@gmail.com> +Date: Tue Sep 28 13:30:01 2010 -0700 + + Purge cvs tags. + + Signed-off-by: Jesse Adkins <jesserayadkins@gmail.com> + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit 5bb806a65bf23a507b135abe1e4a8b3cabc7b8aa +Author: Matt Dew <matt@osource.org> +Date: Wed Jun 30 16:52:22 2010 -0400 + + specs: convert ICE doc/specs from xorg-docs module to DocBook XML + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 9b54f509832c50c1fac0edc0cb78e1a3454a56dc +Author: Alan Coopersmith <alan.coopersmith@oracle.com> +Date: Tue Jun 8 20:12:53 2010 -0700 + + Move ICE protocol & API specs from xorg-docs module + + For now, just checked in and included in dist tarballs, not processed + into a usable format - same as it was in xorg-docs + + Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> + +commit 1967c04c021a4cfd7b3cdd4efdc13610b4385a65 +Author: Julien Cristau <jcristau@debian.org> +Date: Tue May 11 16:36:20 2010 +0200 + + Set the close-on-exec flag for listening sockets + + This prevents xsm from leaking file descriptors to the processes it + starts. + + X.Org bug#22932 <http://bugs.freedesktop.org/show_bug.cgi?id=22932> + + Reported-by: Kalle Olavi Niemitalo <kon@iki.fi> + Signed-off-by: Julien Cristau <jcristau@debian.org> + +commit b6478dbedcca4d4cf44bd588c050bcc70c2f4963 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Mon Apr 5 19:50:40 2010 -0400 + + config: update AC_PREREQ statement to 2.60 + + Unrelated to the previous patches, the new value simply reflects + the reality that the minimum level for autoconf to configure + all x.org modules is 2.60 dated June 2006. + + ftp://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 8e175ff18649bd30e862b6a6a5f82a4ed4d5241a +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Mon Mar 29 14:53:48 2010 -0400 + + config: remove the pkgconfig pc.in file from EXTRA_DIST + + Automake always includes it in the tarball. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 09d61dc024d9846525e4c97d33cdf03c9f06c151 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Tue Feb 16 10:37:21 2010 -0500 + + config: move CWARNFLAGS from configure.ac to Makefile.am + + Compiler warning flags should be explicitly set in the makefile + rather than being merged with other packages compiler flags. + + Signed-off-by: Gaetan Nadon <memsize@videotron.ca> + +commit 72b8a2d39a57eb0640929b9bb9f276c6032f8213 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Fri Nov 27 20:56:03 2009 -0500 + + Makefile.am: add ChangeLog and INSTALL on MAINTAINERCLEANFILES + + Now that the INSTALL file is generated. + Allows running make maintainer-clean. + +commit 68231f8574e197a12eff1ddde37166d101567269 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Wed Oct 28 14:09:10 2009 -0400 + + INSTALL, NEWS, README or AUTHORS files are missing/incorrect #24206 + + Add missing INSTALL file. Use standard GNU file on building tarball + README may have been updated + Remove AUTHORS file as it is empty and no content available yet. + Remove NEWS file as it is empty and no content available yet. + +commit b5cfc1cdd367c93660259a86b3b6683c57e5d76a +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Tue Oct 27 15:07:25 2009 -0400 + + Deploy the new XORG_DEFAULT_OPTIONS #24242 + + This macro aggregate a number of existing macros that sets commmon + X.Org components configuration options. It shields the configuration file from + future changes. + +commit 5524fa4d543932e4565b2235515fef9a5d9a501d +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Mon Oct 26 22:08:41 2009 -0400 + + Makefile.am: ChangeLog not required: EXTRA_DIST or *CLEANFILES #24432 + + ChangeLog filename is known to Automake and requires no further + coding in the makefile. + +commit 82ad2d2053af2ad37697793b9718721aa3ff80a0 +Author: Gaetan Nadon <memsize@videotron.ca> +Date: Thu Oct 22 12:34:18 2009 -0400 + + .gitignore: use common defaults with custom section # 24239 + + Using common defaults will reduce errors and maintenance. + Only the very small or inexistent custom section need periodic maintenance + when the structure of the component changes. Do not edit defaults. + +commit 4b2289ad5481de7fa51941cf6c2ca7a2a3202690 +Author: Jeremy Huddleston <jeremyhu@freedesktop.org> +Date: Wed Oct 21 12:47:23 2009 -0700 + + This is not a GNU project, so declare it foreign. + + On Wed, 2009-10-21 at 13:36 +1000, Peter Hutterer wrote: + > On Tue, Oct 20, 2009 at 08:23:55PM -0700, Jeremy Huddleston wrote: + > > I noticed an INSTALL file in xlsclients and libXvMC today, and it + > > was quite annoying to work around since 'autoreconf -fvi' replaces + > > it and git wants to commit it. Should these files even be in git? + > > Can I nuke them for the betterment of humanity and since they get + > > created by autoreconf anyways? + > + > See https://bugs.freedesktop.org/show_bug.cgi?id=24206 + + As an interim measure, replace AM_INIT_AUTOMAKE([dist-bzip2]) with + AM_INIT_AUTOMAKE([foreign dist-bzip2]). This will prevent the generation + of the INSTALL file. It is also part of the 24206 solution. + + Signed-off-by: Jeremy Huddleston <jeremyhu@freedesktop.org> + +commit 94992c686a6850f2303aa78057a64a6369b64692 +Author: Peter Hutterer <peter.hutterer@who-t.net> +Date: Fri Aug 28 14:17:50 2009 +1000 + + libICE 1.0.6 + + Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> + +commit 7a8bb2a2c991919bcdef63359c74e239045a3f4c +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Mon Feb 2 20:34:30 2009 -0800 + + Add README with pointers to mailing list, bugzilla & git repos + + Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com> + +commit dbb950061f185e1ccf27bff9c71adc34ab4cfae0 +Author: Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> +Date: Wed Jan 28 16:55:37 2009 -0200 + + Janitor: Correct sparse warnings. + + Also reorders some code in configure.ac and Makefile.am to + match pattern used on other packages. + +commit 2f41ddb3a917c4e71184452b68561a15593d33b8 +Author: Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> +Date: Tue Jan 6 17:25:25 2009 -0200 + + Update .gitignore. + + Don't warn about files left after a build and/or make distcheck + in 'git status -a'. + +commit ab9dff549534c6d7b33f440bff7a841d60c1206c +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Mon Dec 8 18:45:44 2008 +0100 + + bump to 1.0.5 + +commit 71695c4bf7ae07228605683f6cdeca0457c8495a +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Mon Dec 8 18:44:26 2008 +0100 + + remove ChangeLog from EXTRA_DIST and CLEANFILES + +commit 653f659fe65ae8c2a9fe5b1fdbfc78da43f2cf90 +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Mon Dec 8 18:41:34 2008 +0100 + + use memcmp instead of binaryEqual + + suggested by Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> + http://lists.freedesktop.org/archives/xorg/2008-December/041222.html + +commit bf138553afe6eecd0e6c218dc6ae4f63065e4196 +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Tue Dec 2 22:06:15 2008 +0100 + + Use NULL, not zero, for pointers + + From Magnus Kessler <Magnus.Kessler@gmx.net> + http://lists.freedesktop.org/archives/xorg/2008-October/039799.html + http://lists.freedesktop.org/archives/xorg/attachments/20081030/b2ea5b1c/attachment-0001.bin + +commit b01e82ce1deedb36c9696d4d27a3b9a5d5a52d08 +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Thu Oct 30 12:01:06 2008 +0100 + + ANSI C + + convert all old style function declarations + + see also: Paulo Cesar Pereira de Andrade <pcpa@mandriva.com.br> + http://bugs.freedesktop.org/show_bug.cgi?id=14683 + http://bugs.freedesktop.org/attachment.cgi?id=14582 + + see also: Magnus Kessler <Magnus.Kessler@gmx.net> + http://lists.freedesktop.org/archives/xorg/2008-October/039799.html + http://lists.freedesktop.org/archives/xorg/attachments/20081030/b2ea5b1c/attachment-0001.bin + +commit 2aba1bc0583aeb3ee6e26e3bfacd123abef744d9 +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Mon Dec 1 23:06:22 2008 +0100 + + towards ANSI C + + make _IceProcessCoreMessage and default error handlers static + +commit 69a1b4b6d34291738dfbc3aa19d0ce3f2842ec8f +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Mon Dec 1 22:22:12 2008 +0100 + + Activate CWARNFLAGS with lots of gcc warnings + +commit 898ed95cad1133940a83dcf428865c5d3fb2c939 +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Mon Dec 1 22:18:45 2008 +0100 + + use xorg-macros-1.2.1 + + Use XORG_CHANGELOG for rule to generate ChangeLog from git log + Use XORG_CWARNFLAGS for compiler warning flags, leave CFLAGS to user + +commit a99fbad09ab850e65ddd57e4d4488e4726295e14 +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Tue Oct 7 13:21:48 2008 -0700 + + Constify some arguments in libICE to clear warnings in libSM + + This patch avoids the gcc (3.4.6) warnings: + ../../libSM-1.0.3/src/sm_client.c:104: warning: passing arg 7 of `IceRegisterForProtocolSetup' from incompatible pointer type + ../../libSM-1.0.3/src/sm_manager.c:168: warning: passing arg 7 of `IceRegisterForProtocolReply' from incompatible pointer type + when compiling libSM + +commit 3bceaeb3192ca75a14854d614e1621d28fb82274 +Author: Peter Breitenlohner <peb@mppmu.mpg.de> +Date: Tue Oct 7 11:25:42 2008 -0700 + + define macros to 1 in icetrans.c to avoid redefined macro warnings + + X.Org Bug #17947 <http://bugs.freedesktop.org/show_bug.cgi?id=17947> + Patch #19444 <http://bugs.freedesktop.org/attachment.cgi?id=19444> + + Define as 1 (one) as done by autoconf and the command line + option, e.g. -DICE_t, not as empty. + + This avoids the gcc (3.4.6) warnings: + ../../libICE-1.0.4/src/icetrans.c:29:1: warning: "ICE_t" redefined + ../config.h:38:1: warning: this is the location of the previous definition + ../../libICE-1.0.4/src/icetrans.c:30:1: warning: "TRANS_CLIENT" redefined + <command line>:6:1: warning: this is the location of the previous definition + ../../libICE-1.0.4/src/icetrans.c:31:1: warning: "TRANS_SERVER" redefined + <command line>:7:1: warning: this is the location of the previous definition + +commit b707104f4dba0963ab17c1d6a29c1e3a848ea408 +Author: Alan Hourihane <alanh@tungstengraphics.com> +Date: Tue Apr 29 00:41:40 2008 +0100 + + silence warning + +commit e6b525aefc05b5203391699b00053ad52243cc6b +Author: Colin Harrison <colin.harrison-at-virgin.net> +Date: Tue Apr 29 00:40:48 2008 +0100 + + include for sleep() + +commit ef58f37724b841ef2246757be27111775aa86559 +Author: Matthieu Herrb <matthieu.herrb@laas.fr> +Date: Sun Mar 9 09:02:40 2008 +0100 + + nuke RCS Ids + +commit 47d86e8343d3d0201166c4d75da2ec9c12638cc1 +Author: James Cloos <cloos@jhcloos.com> +Date: Thu Dec 6 15:51:13 2007 -0500 + + Add missing PHONY line for automatic ChangeLog generation + +commit f415da71dd26f128df7d550ecd7631f8888eb1d2 +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Mon Aug 20 13:21:07 2007 -0700 + + Version bump: 1.0.4 + +commit 8e08d3e4b8f00151b3a8b7eb88015dc15170e154 +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Mon Jun 4 15:40:22 2007 -0700 + + Add $(AM_CFLAGS) to lint flags to get correct Xtrans flags + +commit cd900e40b5676874d076c35466fd7baa6a49b1f6 +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Thu Apr 5 15:05:52 2007 -0700 + + Replace many malloc(strlen()); strcpy() pairs with strdup() + +commit 27f9a9324d58c9a7472c724c62f5b7ea0e1f4681 +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Thu Apr 5 14:43:05 2007 -0700 + + Provide ANSI C prototypes for more static functions + +commit bb639803a779ceace05d183b653da88f010ab29c +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Thu Apr 5 14:32:31 2007 -0700 + + Convert authutil.c static helpers to ANSI C prototypes to clear sparse warnings + +commit 2179b2d467d69e45559b8e4f161a904a21f05321 +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Thu Apr 5 14:28:06 2007 -0700 + + Add hooks for checking source code with lint/sparse/etc. + +commit 6b361c028b5ad931b61df86fae570f3ef9f41c15 +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Thu Apr 5 14:19:56 2007 -0700 + + Coverity #1086: Double free of pointer "*listenObjsRet" + + Same bug, different function. + +commit c9b3d016681d81aff32c74cdad75151bd538e6ab +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Thu Apr 5 14:07:42 2007 -0700 + + Coverity #1085: Double free of pointer "*listenObjsRet" + + If malloc failed in the loop in IceListenForConnections, the error path + would free all previous allocations, then loop around and try again, and + if it failed again, free the previous allocations again. On the other + hand, if it succeeded on the later tries, then the memory would just be + leaked, since the error would be returned and not the pointer to them. + +commit 6039e865470af23948b0fe7d5dc0ea72da436b0e +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Thu Apr 5 14:04:01 2007 -0700 + + Add *~ to .gitignore to skip emacs/patch droppings + +commit bed718894bed98cbd45b02bd57fb7fc6fd5089aa +Author: Daniel Stone <daniel@fooishbar.org> +Date: Sat Dec 16 01:21:17 2006 +0200 + + bump to 1.0.3 + +commit cac788981906186442ddfb57a41f45911eb8223b +Author: Daniel Stone <daniel@fooishbar.org> +Date: Wed Dec 6 18:58:09 2006 +0200 + + Makefile.am: make ChangeLog hook safer + Make ChangeLog hook as safe as possible. + +commit 011d632e8ef3f738b9158e66d6da6876e3b53905 +Author: Adam Jackson <ajax@benzedrine.nwnk.net> +Date: Fri Oct 13 15:49:52 2006 -0400 + + Bump to 1.0.2 + +commit 445661cd714685009ee9ba2358a274351381eabf +Author: Adam Jackson <ajax@benzedrine.nwnk.net> +Date: Thu Oct 12 18:37:57 2006 -0400 + + Fix ChangeLog hook to distcheck. + +commit 5cba1c763ac9f79062523227b49a29f72e6069cf +Author: Matthieu Herrb <matthieu.herrb@laas.fr> +Date: Sun Jul 16 10:52:30 2006 +0200 + + set GIT_DIR=${srcdir}/.git for git-log + +commit 86e0a93714a6ccdb8555fc2c48231d958cba383d +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Thu Jul 13 14:58:44 2006 -0700 + + renamed: .cvsignore -> .gitignore + +commit c87cb98979356fc55607c05a2b23207afc9beeb1 +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Tue Jul 11 13:48:08 2006 -0700 + + Replace static ChangeLog with rule copied from libX11 to generate from git log + +commit 6066ab9b9914ec0cca3b8f36fa3f5ba323414621 +Author: Derek Wang <derek.wang@sun.com> +Date: Tue Nov 23 12:00:32 2004 -0800 + + Sun bug #6193975: kde session manager core dumps in _IceWrite() + +commit be25425ca38d23655a5a854c053e750e1cbd3dea +Author: Alan Coopersmith <alan.coopersmith@sun.com> +Date: Tue Jul 11 13:42:07 2006 -0700 + + renamed: .cvsignore -> .gitignore + +commit 9b1bb5ab99bd386cc030cd456a576b37406da91c +Author: Adam Jackson <ajax@nwnk.net> +Date: Wed Apr 26 23:57:50 2006 +0000 + + Bump to 1.0.1 + +commit 96d7763487da6624ed85bee10b081e7138d2060d +Author: Alan Coopersmith <Alan.Coopersmith@sun.com> +Date: Mon Apr 10 16:44:40 2006 +0000 + + Coverity #664: Free memory allocated by EXTRACT_STRING in + _IceDefaultErrorHandler after we're done fprintf()'ing it. + +commit 2a30ec82f3bd2aa1f2566e97fee70403a8448de8 +Author: Kevin E Martin <kem@kem.org> +Date: Thu Dec 15 00:24:27 2005 +0000 + + Update package version number for final X11R7 release candidate. + +commit 881573d429c0a9ecfa2d6286d4eaece36ee50675 +Author: Kevin E Martin <kem@kem.org> +Date: Sat Dec 3 05:49:42 2005 +0000 + + Update package version number for X11R7 RC3 release. + +commit a15b179f2e8e359161d9133bac58dde57b7e78ae +Author: Kevin E Martin <kem@kem.org> +Date: Sat Nov 19 07:15:39 2005 +0000 + + Update pkgconfig files to separate library build-time dependencies from + application build-time dependencies, and update package deps to work + with separate build roots. + +commit c386a08047582240adefafd3afc062e52fccae6f +Author: Kevin E Martin <kem@kem.org> +Date: Wed Nov 9 21:19:12 2005 +0000 + + Update package version number for X11R7 RC2 release. + +commit c361e3919f2de3f4742904b04e73178edc76bf95 +Author: Adam Jackson <ajax@nwnk.net> +Date: Sun Oct 23 20:12:19 2005 +0000 + + Bug #1893: Fix replies when peers use different major opcodes for the same + subprotocol. (016_ICE_subprotocol_reply_fix.diff from Debian, by Jochen + Voss) + +commit 0b8ff6fbd8cd7f47ab9e6ccb6d4917564a2d13ee +Author: Alan Coopersmith <Alan.Coopersmith@sun.com> +Date: Sat Jul 30 19:15:15 2005 +0000 + + Add -D flags to clear various warnings (Stefan Dirsch) + +commit 260d470a128c7eaa6d7484bb143aab353c4e98ec +Author: Kevin E Martin <kem@kem.org> +Date: Fri Jul 29 21:22:50 2005 +0000 + + Various changes preparing packages for RC0: + - Verify and update package version numbers as needed + - Implement versioning scheme + - Change bug address to point to bugzilla bug entry form + - Disable loadable i18n in libX11 by default (use --enable-loadable-i18n to + reenable it) + - Fix makedepend to use pkgconfig and pass distcheck + - Update build script to build macros first + - Update modular Xorg version + +commit cf687b775f580a84a4a8e962814abe7bc47a3c52 +Author: Daniel Stone <daniel@fooishbar.org> +Date: Sat Jul 16 06:22:34 2005 +0000 + + Set soversion to 6.3.0. + +commit 6d1704defa0e57715bd22d30d6e789b36233dcf8 +Author: Keith Packard <keithp@keithp.com> +Date: Sat Jul 9 05:59:01 2005 +0000 + + Add .cvsignore files + +commit 2b6b8e40a63dd69a13f87c19dcf8dc2f477c304d +Author: Daniel Stone <daniel@fooishbar.org> +Date: Sun Jul 3 07:00:55 2005 +0000 + + Add Xtrans definitions (FONT_t, TRANS_CLIENT) to clean up warnings. + Add XSERV_t, TRANS_SERVER, TRANS_REOPEN to quash warnings. + Add #include <dix-config.h> or <xorg-config.h>, as appropriate, to all + source files in the xserver/xorg tree, predicated on defines of + HAVE_{DIX,XORG}_CONFIG_H. Change all Xfont includes to + <X11/fonts/foo.h>. + +commit 608ad35f102b188f554daf8c160a5edcf4e8031c +Author: Daniel Stone <daniel@fooishbar.org> +Date: Fri Jun 10 14:11:36 2005 +0000 + + Remove pointless include of Xlib.h. + Fix #include path to bigreqstr.h. + +commit 795460992b0dcd4aa2591be462a94942415c6028 +Author: Alexander Gottwald <alexander.gottwald@s1999.tu-chemnitz.de> +Date: Thu Jun 9 15:54:47 2005 +0000 + + Replace <X11/transport.c> with <X11/Xtrans/transport.c> + +commit ae7b4cca6bd5c1f4edea8cde80d7a3dfaaf2c4d3 +Author: Alexander Gottwald <alexander.gottwald@s1999.tu-chemnitz.de> +Date: Thu Jun 9 15:52:02 2005 +0000 + + Replace <X11/Xtrans.h> with <X11/Xtrans/Xtrans.h> + Copy Xtrans.h to exports/include/X11/Xtrans only + +commit a0637be926e6da5db8d131e7914f1300f484c626 +Author: Alan Coopersmith <Alan.Coopersmith@sun.com> +Date: Sat May 21 23:07:47 2005 +0000 + + xtrans: + Create autoconf macro XTRANS_CONNECTION_FLAGS to provide standard set of + --enable flags for which transports to support and common place to + update for required libraries for platforms that need certain libs for + certain transports + ICE: + Add ICE_t #define required by Xtrans headers. Replace static defines of + LOCALCONN & UNIXCONN with new XTRANS_CONNECTION_FLAGS macro. + X11: + Moved transport type checks to new macro XTRANS_CONNECTION_FLAGS in + xtrans.m4 in xtrans module so they can be shared by all modules using + xtrans. + +commit efdb2468119be0c62a379d91088a708ca8d37e1b +Author: Adam Jackson <ajax@nwnk.net> +Date: Thu May 19 00:22:32 2005 +0000 + + revert last change, didn't do right thing at all, sorry for the noise + +commit ccf4efa5e204d4569b9b590f72baae807ec19903 +Author: Adam Jackson <ajax@nwnk.net> +Date: Thu May 19 00:10:02 2005 +0000 + + Require automake 1.7 in AM_INIT_AUTOMAKE + +commit 3458da101c943530861485c798538ce014eee6b0 +Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk> +Date: Tue May 17 21:25:15 2005 +0000 + + - Conditionally include config.h in xc/lib/SM + - Add libSM to symlink.sh + - Add SM build system + +commit cae06ca0ce523eeb9a667ce3ae5bff066cf6ecd7 +Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk> +Date: Tue May 17 20:53:58 2005 +0000 + + - Conditionally include config.h in the ICE source. + - Add ICE to symlink.sh + +commit 9dd90f8f8e29bb1dd6fe84b4b1d2d75ef91bc336 +Author: Søren Sandmann Pedersen <sandmann@daimi.au.dk> +Date: Tue May 17 20:52:35 2005 +0000 + + Add ICE directory + build system. + +commit d1cfe2a6d4a392f64b6b9d9255ec329fb2a6a39a +Author: Daniel Stone <daniel@fooishbar.org> +Date: Fri Jan 28 19:15:39 2005 +0000 + + Move _IceGetPeerName into the ICE public API as IceGetPeerName; bump ICE + soversion to 6.4 accordingly. Change SM's use to the public version. + The old version will be retained for compatibility. + +commit 8f0babf8450aa8097e063e13c95b1581843b2dd8 +Author: Egbert Eich <eich@suse.de> +Date: Fri Apr 23 18:43:22 2004 +0000 + + Merging XORG-CURRENT into trunk + +commit 111949a4a1d5b62e26016b555e12f8862c90ae44 +Author: Egbert Eich <eich@suse.de> +Date: Sun Mar 14 08:31:52 2004 +0000 + + Importing vendor version xf86-4_4_99_1 on Sun Mar 14 00:26:39 PST 2004 + +commit d4054eea34b2f4d345796ecadec8a96af93c4d0d +Author: Egbert Eich <eich@suse.de> +Date: Wed Mar 3 12:11:10 2004 +0000 + + Importing vendor version xf86-4_4_0 on Wed Mar 3 04:09:24 PST 2004 + +commit 569bf16d182b043e7ab914202d4195baf4a8413a +Author: Egbert Eich <eich@suse.de> +Date: Thu Feb 26 13:35:18 2004 +0000 + + readding XFree86's cvs IDs + +commit 14c9e41e551ab1b3a00807dbb8f2f215b96bcc81 +Author: Egbert Eich <eich@suse.de> +Date: Thu Feb 26 09:22:34 2004 +0000 + + Importing vendor version xf86-4_3_99_903 on Wed Feb 26 01:21:00 PST 2004 + +commit 45b73c360dc68b023194758bbb1cc59c021742a6 +Author: Kaleb Keithley <kaleb@freedesktop.org> +Date: Thu Dec 4 22:02:52 2003 +0000 + + XFree86 4.3.99.901 (RC 1) + +commit c919c3d0b355ef67dfa0b511eb1da488e5786d1b +Author: Kaleb Keithley <kaleb@freedesktop.org> +Date: Tue Nov 25 19:28:07 2003 +0000 + + XFree86 4.3.99.16 Bring the tree up to date for the Cygwin folks + +commit 72e353567f8927996a26e72848d86f692c3f0737 +Author: Kaleb Keithley <kaleb@freedesktop.org> +Date: Fri Nov 14 16:48:46 2003 +0000 + + XFree86 4.3.0.1 + +commit ee452992357329f7af846eba8f5bbe61c5d27bfa +Author: Kaleb Keithley <kaleb@freedesktop.org> +Date: Fri Nov 14 15:54:36 2003 +0000 + + R6.6 is the Xorg base-line diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..c9fd2c0 --- /dev/null +++ b/INSTALL @@ -0,0 +1,290 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008 Free Software Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 6. Often, you can also type `make uninstall' to remove the installed + files again. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `<wchar.h>' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *Note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..c2110ec --- /dev/null +++ b/Makefile.am @@ -0,0 +1,21 @@ +SUBDIRS = doc specs src + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = ice.pc + +MAINTAINERCLEANFILES = ChangeLog INSTALL + +.PHONY: ChangeLog INSTALL + +INSTALL: + $(INSTALL_CMD) + +ChangeLog: + $(CHANGELOG_CMD) + +dist-hook: ChangeLog INSTALL + +if LINT +lint: + (cd src && $(MAKE) $(MFLAGS) lint) +endif LINT diff --git a/README b/README new file mode 100644 index 0000000..0b6ffac --- /dev/null +++ b/README @@ -0,0 +1,30 @@ +libICE - Inter-Client Exchange Library + +Documentation for this API can be found in the doc directory of the source +code, or online at: + + http://xorg.freedesktop.org/releases/X11R7.0/doc/PDF/ICElib.pdf + +All questions regarding this software should be directed at the +Xorg mailing list: + + http://lists.freedesktop.org/mailman/listinfo/xorg + +Please submit bug reports to the Xorg bugzilla: + + https://bugs.freedesktop.org/enter_bug.cgi?product=xorg + +The master development code repository can be found at: + + git://anongit.freedesktop.org/git/xorg/lib/libICE + + http://cgit.freedesktop.org/xorg/lib/libICE + +For patch submission instructions, see: + + http://www.x.org/wiki/Development/Documentation/SubmittingPatches + +For more information on the git code manager, see: + + http://wiki.x.org/wiki/GitPage + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..ad42a56 --- /dev/null +++ b/configure.ac @@ -0,0 +1,53 @@ + +# Initialize Autoconf +AC_PREREQ([2.60]) +AC_INIT([libICE], [1.0.8], + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [libICE]) +AC_CONFIG_SRCDIR([Makefile.am]) +AC_CONFIG_HEADERS([config.h]) + +# Set common system defines for POSIX extensions, such as _GNU_SOURCE +# Must be called before any macros that run the compiler (like +# AC_PROG_LIBTOOL or XORG_DEFAULT_OPTIONS) to avoid autoconf errors. +AC_USE_SYSTEM_EXTENSIONS + +# Initialize Automake +AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AM_MAINTAINER_MODE + +# Initialize libtool +AC_PROG_LIBTOOL + +# Require xorg-macros minimum of 1.12 for DocBook external references +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.12 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.12) +XORG_DEFAULT_OPTIONS +XORG_ENABLE_DOCS +XORG_ENABLE_SPECS +XORG_WITH_XMLTO(0.0.22) +XORG_WITH_FOP +XORG_WITH_XSLTPROC +XORG_CHECK_SGML_DOCTOOLS(1.8) + +# Obtain compiler/linker options for depedencies +PKG_CHECK_MODULES(ICE, xproto xtrans) + +# Transport selection macro from xtrans.m4 +XTRANS_CONNECTION_FLAGS +AC_DEFINE(ICE_t, 1, [Xtrans transport type]) + +# Checks for library functions. +AC_CHECK_FUNCS([asprintf]) + +# Allow checking code with lint, sparse, etc. +XORG_WITH_LINT +XORG_LINT_LIBRARY([ICE]) +LINT_FLAGS="${LINT_FLAGS} ${ICE_CFLAGS} ${XTRANS_CFLAGS}" + +AC_CONFIG_FILES([Makefile + doc/Makefile + specs/Makefile + src/Makefile + ice.pc]) +AC_OUTPUT diff --git a/doc/ICElib.xml b/doc/ICElib.xml new file mode 100644 index 0000000..5837e89 --- /dev/null +++ b/doc/ICElib.xml @@ -0,0 +1,4581 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" + "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" +[ +<!ENTITY % defs SYSTEM "defs.ent"> %defs; +]> + + +<book id="ICElib"> + +<bookinfo> + <title>Inter-Client Exchange Library + X Consortium Standard + X Version 11, Release &fullrelvers; + Version 1.0 + + + RalphMor + X Consortium + + + + 199319941996 + X Consortium + + + + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and +to permit persons to whom the Software is furnished to do so, subject to +the following conditions: + + +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 +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + + + + + +Overview of ICE + + +There are numerous possible inter-client protocols, with many similarities +and common needs - authentication, version negotiation, byte +order negotiation, and so on. +The Inter-Client Exchange (ICE) protocol is intended to provide a framework +for building such protocols, allowing them to make use of common negotiation +mechanisms and to be multiplexed over a single transport connection. + + + + +The ICE Library - C Language Interface to ICE + + +A client that wishes to utilize ICE must first register the protocols it +understands with the ICE library. Each protocol is dynamically assigned +a major opcode ranging from 1-255 (two clients can use different +major opcodes for the same protocol). The next step for the client is either +to open a connection with another client or to wait for connections made +by other clients. Authentication may be required. A client can both +initiate connections with other clients and be +waiting for clients to connect to itself (a nested session manager is an +example). Once an ICE connection is established between the two clients, one +of the clients needs to initiate a +ProtocolSetup +in order to +"activate" a given protocol. Once the other client accepts the +ProtocolSetup +(once again, authentication may be required), the +two clients are ready to start passing messages specific to that protocol to +each other. Multiple protocols may be active on a single ICE connection. +Clients are responsible for notifying the ICE library when a protocol is no +longer active on an ICE connection, although ICE does not define how each +subprotocol triggers a protocol shutdown. + + + +The ICE library utilizes callbacks to process incoming messages. Using +callbacks allows +ProtocolSetup +messages and authentication to happen +behind the scenes. An additional benefit is that messages never need +to be buffered up by the library when the client blocks waiting for a +particular message. + + + + +Intended Audience + +This document is intended primarily for implementors of protocol libraries +layered on top of ICE. Typically, applications that wish to utilize ICE +will make calls into individual protocol libraries rather than directly +make calls into the ICE library. However, some applications will have to +make some initial calls into the ICE library in order to accept ICE +connections (for example, a session manager accepting connections from +clients). But in general, protocol libraries should be designed to hide +the inner details of ICE from applications. + + + +Header Files and Library Name + + +The header file +<X11/ICE/ICElib.h> +defines all of the ICElib data structures and function prototypes. +ICElib.h +includes the header file +<X11/ICE/ICE.h>, +which defines all of the ICElib constants. +Protocol libraries that need to read and write messages should include +the header file +<X11/ICE/ICEmsg.h>. + +Applications should link against ICElib using -lICE. + + + +Note on Prefixes + + +The following name prefixes are used in the library to distinguish between +a client that initiates a +ProtocolSetup +and a client that +responds with a +ProtocolReply + + + +IcePo +- Ice Protocol Originator + + +IcePa +- Ice Protocol Acceptor + + + + + +Protocol Registration + + +In order for two clients to exchange messages for a given protocol, each +side must register the protocol with the ICE library. The purpose of +registration is for each side to obtain a major opcode for the protocol +and to provide callbacks for processing messages and handling authentication. +There are two separate registration functions: + + + + + +One to handle the side that does a +ProtocolSetup + + + + +One to handle the side that responds with a +ProtocolReply + + + + + +It is recommended that protocol registration occur before the two clients +establish an ICE connection. If protocol registration occurs after an +ICE connection is created, there can be a brief interval of time in which a +ProtocolSetup +is received, but the protocol is not registered. +If it is not possible to register a protocol before the creation of an +ICE connection, proper precautions should be taken to avoid the above race +condition. + + + + +The +function should be called for the client that initiates a +ProtocolSetup + + + + + int IceRegisterForProtocolSetup + const char *protocol_name + const char *vendor + const char *release + int version_count + IcePoVersionRec *version_recs + int auth_count + char **auth_names + IcePoAuthProc *auth_procs + IceIOErrorProc io_error_proc + + + + + + + protocol_name + + +A string specifying the name of the protocol to register. + + + + + vendor + + A vendor string with semantics specified by the protocol. + + + + release + + A release string with semantics specified by the protocol. + + + + version_count + + The number of different versions of the protocol supported. + + + + version_recs + + List of versions and associated callbacks. + + + + auth_count + + The number of authentication methods supported. + + + + auth_names + + The list of authentication methods supported. + + + + auth_procs + + +The list of authentication callbacks, one for each authentication method. + + + + + io_error_proc + + IO error handler, or NULL. + + + + + + + returns the major +opcode reserved or -1 if an error occurred. In order to actually activate +the protocol, the +function needs to be called with this major opcode. Once the protocol is +activated, all messages for the protocol should be sent using this major +opcode. + + + +A protocol library may support multiple versions of the same protocol. +The version_recs argument specifies a list of supported versions of the +protocol, which are prioritized in decreasing order of preference. +Each version record consists of a major and minor version of the protocol +as well as a callback to be used for processing incoming messages. + + + + +typedef struct { + int major_version; + int minor_version; + IcePoProcessMsgProc process_msg_proc; +} IcePoVersionRec; + + +The +IcePoProcessMsgProc +callback is responsible for processing the set of messages that can be +received by the client that initiated the +ProtocolSetup +For further information, +see + + + +Authentication may be required before the protocol can become active. +The protocol library must register the authentication methods that it +supports with the ICE library. +The auth_names and auth_procs arguments are a list of authentication names +and callbacks that are prioritized in decreasing order of preference. +For information on the +IcePoAuthProc +callback, see + + + +The + +callback is invoked if the ICE connection unexpectedly breaks. +You should pass NULL for io_error_proc if not interested in being notified. +For further information, + + + + +The + +function should be called for the client that responds to a +ProtocolSetup +with a +ProtocolReply + + + + + Bool IceRegisterForProtocolReply + const char *protocol_name + const char *vendor + const char *release + int version_count + IcePoVersionRec *version_recs + int auth_count + const char **auth_names + IcePoAuthProc *auth_procs + IceHostBasedAuthProc host_based_auth_proc + IceProtocolSetupProc protocol_setup_proc + IceProtocolActivateProc protocol_activate_proc + IceIOErrorProc io_error_proc + + + + + + protocol_name + A string specifying the name of the protocol to register. + + + vendor + +A vendor string with semantics specified by the protocol. + + + + release + +A release string with semantics specified by the protocol. + + + + version_count + +The number of different versions of the protocol supported. + + + + version_recs + +List of versions and associated callbacks. + + + + auth_count + +The number of authentication methods supported. + + + + auth_names + +The list of authentication methods supported. + + + + auth_procs + +The list of authentication callbacks, one for each authentication method. + + + + host_based_auth_proc + +Host based authentication callback. + + + + protocol_setup_proc + +A callback to be invoked when authentication has succeeded for a +ProtocolSetup +but before the +ProtocolReply +is sent. + + + + protocol_activate_proc + +A callback to be invoked after the +ProtocolReply +is sent. + + + + io_error_proc + +IO error handler, or NULL. + + + + + + +returns the major opcode reserved or -1 if an error occurred. The major +opcode should be used in all subsequent messages sent for this protocol. + +A protocol library may support multiple versions of the same protocol. +The version_recs argument specifies a list of supported versions of the protocol, +which are prioritized in decreasing order of preference. +Each version record consists of a major and minor version of the protocol +as well as a callback to be used for processing incoming messages. + + + +typedef struct { + int major_version; + int minor_version; + IcePaProcessMsgProc process_msg_proc; +} IcePaVersionRec; + + + +The + +callback is responsible for processing the set of messages that can be +received by the client that accepted the +ProtocolSetup +For further information, +see + + + +Authentication may be required before the protocol can become active. +The protocol library must register the authentication methods that it +supports with the ICE library. +The auth_names and auth_procs arguments are a list of authentication names +and callbacks that are prioritized in decreasing order of preference. +For information on the +IcePaAuthProc, +See + + + + +If authentication fails and the client attempting to initiate +the +ProtocolSetup +has not required authentication, the +IceHostBasedAuthProc +callback is invoked with the host name of the originating client. +If the callback returns +True +the +ProtocolSetup +will succeed, even though the original +authentication failed. +Note that authentication can effectively be disabled by registering an +IceHostBasedAuthProc +which always returns +True +If no host based +authentication is allowed, you should pass NULL for host_based_auth_proc. + + + + Bool HostBasedAuthProc + char *host_name + + + + + + protocol_name + The host name of the client that sent the ProtocolSetup + + + + +The host_name argument is a string of the form protocol/hostname, +where protocol is one of {tcp, decnet, local}. + +Because +ProtocolSetup +messages and authentication happen behind the scenes +via callbacks, the protocol library needs some way of being notified when the +ProtocolSetup +has completed. +This occurs in two phases. +In the first phase, the +IceProtocolSetupProc +callback is invoked after authentication has +successfully completed but before the ICE library sends a +ProtocolReply +Any resources required for this protocol should be allocated at this time. +If the +IceProtocolSetupProc +returns a successful status, the ICE library will +send the +ProtocolReply +and then invoke the +IceProtocolActivateProc +callback. Otherwise, an error will be sent to the +other client in response to the +ProtocolSetup + +The +IceProtocolActivateProc +is an optional callback and should be registered only if the protocol +library intends to generate a message immediately following the +ProtocolReply +You should pass NULL for protocol_activate_proc if not interested +in this callback. + + + + Status ProtocolSetupProc + IceConn ice_conn + int major_version + int minor_version + char *vendor + char *release + IcePointer *client_data_ret + char **failure_reason_ret + + + + + + protocol_name + +The ICE connection object. + + + + major_version + +The major version of the protocol. + + + + minor_version + +The minor version of the protocol. + + + + vendor + +The vendor string registered by the protocol originator. + + + + release + +The release string registered by the protocol originator. + + + + client_data_ret + +Client data to be set by callback. + + + + failure_reason_ret + +Failure reason returned. + + + + +The pointer stored in the client_data_ret argument will be passed +to the + +callback whenever a message has arrived for this protocol on the +ICE connection. + +The vendor and release strings should be freed with +free +when they are no longer needed. + +If a failure occurs, the +IceProtocolSetupProc +should return a zero status as well as allocate and return a failure +reason string in failure_reason_ret. +The ICE library will be responsible for freeing this memory. + +The +IceProtocolActivateProc +callback is defined as follows: + + + + void ProtocolActivateProc + IceConn ice_conn + IcePointer client_data + + + + + + ice_conn + The ICE connection object. + + + client_data + + +The client data set in the IceProtocolSetupProc callback. + + + + + + +The + +callback is invoked if the ICE connection unexpectedly breaks. +You should pass NULL for io_error_proc if not interested in being notified. +For further information, +see + + + + +Callbacks for Processing Messages + +When an application detects that there is new data to read on an ICE +connection (via +select +it calls the + +function + + +When + +reads an ICE message header with a major opcode other than +zero (reserved for the ICE protocol), it needs to call a function that will +read the rest of the message, unpack it, and process it accordingly. + +If the message arrives at the client that initiated the +ProtocolSetup +the +IcePoProcessMsgProc +callback is invoked. + + + + void PoProcessMsgProc + IceConn ice_conn + IcePointer client_data + int opcode + unsigned long length + Bool swap + IceReplyWaitInfo *reply_wait + Bool *reply_ready_ret + + + + + + ice_conn + The ICE connection object. + + + client_data + +Client data associated with this protocol on the ICE connection. + + + + opcode + +The minor opcode of the message. + + + + length + +The length (in 8-byte units) of the message beyond the ICE header. + + + + swap + +A flag that indicates if byte swapping is necessary. + + + + reply_wait + +Indicates if the invoking client is waiting for a reply. + + + + reply_ready_ret + +If set to +True +a reply is ready. + + + + + +If the message arrives at the client that accepted the +ProtocolSetup +the + +callback is invoked. + + + + + void IcePaProcessMsgProc + IceConn ice_conn + IcePointer client_data + int opcode + unsigned long length + Bool swap + + + + + + ice_conn + The ICE connection object. + + + client_data + +Client data associated with this protocol on the ICE connection. + + + + opcode + +The minor opcode of the message. + + + + length + +The length (in 8-byte units) of the message beyond the ICE header. + + + + swap + +A flag that indicates if byte swapping is necessary. + + + + + +In order to read the message, both of these callbacks should use the +macros defined for this purpose (see +.). +Note that byte swapping may be necessary. +As a convenience, the length field in the ICE header will be swapped by ICElib +if necessary. + +In both of these callbacks, the client_data argument is a pointer to client +data that was registered at +ProtocolSetup +time. +In the case of +IcePoProcessMsgProc +the client data was set in the call to + +In the case of + +the client data was set in the +IceProtocolSetupProc +callback. + +The +IcePoProcessMsgProc +callback needs to check the reply_wait argument. +If reply_wait is NULL , +the ICE library expects the function to +pass the message to the client via a callback. +For example, if this is a Session Management "Save Yourself" message, +this function should notify the client of the "Save Yourself" via a callback. +The details of how such a callback would be defined +are implementation-dependent. + +However, if reply_wait is not NULL , +then the client is waiting for +a reply or an error for a message it previously sent. +The reply_wait is of type +IceReplyWaitInfo + + + +typedef struct { + unsigned long sequence_of_request; + int major_opcode_of_request; + int minor_opcode_of_request; + IcePointer reply; +} IceReplyWaitInfo; + + +IceReplyWaitInfo +contains the major/minor opcodes and sequence number of +the message for which a reply is being awaited. +It also contains a pointer to the reply message to be filled in +(the protocol library should cast this +IcePointer +to the appropriate reply type). +In most cases, the reply will have some fixed-size part, and the client waiting +for the reply will have provided a pointer to a structure to hold +this fixed-size data. If there is variable-length data, it would be +expected that the +IcePoProcessMsgProc +callback will have to allocate additional +memory and store pointer(s) to that memory in the fixed-size +structure. If the entire data is variable length (for example., a single +variable-length string), then the client waiting for the reply would probably +just pass a pointer to fixed-size space to hold a pointer, and the +IcePoProcessMsgProc +callback would allocate the storage and store the pointer. +It is the responsibility of the client receiving the reply to +free any memory allocated on its behalf. + +If reply_wait is not NULL and +IcePoProcessMsgProc +has a reply or error to return in response to this reply_wait +(that is, no callback was generated), then the reply_ready_ret argument +should be set to +True +Note that an error should only be returned +if it corresponds to the reply being waited for. Otherwise, the +IcePoProcessMsgProc +should either handle the error internally or invoke an error handler +for its library. + +If reply_wait is NULL, +then care must be taken not to store any value in reply_ready_ret, +because this pointer may also be NULL. + +The + +callback, on the other hand, should always pass +the message to the client via a callback. For example, if this is a Session +Management "Interact Request" message, this function should notify the +client of the "Interact Request" via a callback. + +The reason the + +callback does not have a reply_wait, like +IcePoProcessMsgProc +does, is because a process that is acting as +a server should never block for a reply (infinite blocking can +occur if the connecting client does not act properly, denying access +to other clients). + + + +Authentication Methods + +As already stated, a protocol library must register the authentication +methods that it supports with the ICE library. For each authentication +method, there are two callbacks that may be registered: + + + +One to handle the side that initiates a ProtocolSetup + + + + +One to handle the side that accepts or rejects this request + + + + +IcePoAuthProc +is the callback invoked for the client that initiated the +ProtocolSetup +This callback must be able to respond +to the initial "Authentication Required" message or subsequent +"Authentication Next Phase" messages sent by the other client. + + + + + IcePoAuthStatus IcePoAuthStatus + IceConn ice_conn + IcePointer client_data + int opcode + + + + + + + ice_conn + The ICE connection object. + + + auth_state_ptr + +A pointer to state for use by the authentication callback procedure. + + + + clean_up + +If +True +authentication is over, and the function +should clean up any state it was maintaining. The +last 6 arguments should be ignored. + + + + swap + +If +True +the auth_data may have to be byte swapped +(depending on its contents). + + + + auth_datalen + +The length (in bytes) of the authenticator data. + + + + auth_data + +The data from the authenticator. + + + + reply_datalen_ret + +The length (in bytes) of the reply data returned. + + + + reply_data_ret + +The reply data returned. + + + + error_string_ret + +If the authentication procedure encounters an error during +authentication, it should allocate and return +an error string. + + + + + +Authentication may require several phases, depending on the authentication +method. As a result, the +IcePoAuthProc +may be called more than once when authenticating a client, and +some state will have to be maintained between each invocation. +At the start of each +ProtocolSetup +*auth_state_ptr is NULL, +and the function should initialize its state and set +this pointer. In subsequent invocations of the callback, the pointer +should be used to get at any state previously stored by the callback. + +If needed, the network ID of the client accepting the +ProtocolSetup +can be obtained by calling the +IceConnectionString +function. + +ICElib will be responsible for freeing the reply_data_ret and +error_string_ret pointers with +free + +The auth_data pointer may point to a volatile block of memory. +If the data must be kept beyond this invocation of the callback, be sure +to make a copy of it. + +The +IcePoAuthProc +should return one of four values: + + +IcePoAuthHaveReply +- a reply is available. + + +IcePoAuthRejected +- authentication rejected. + + +IcePoAuthFailed +- authentication failed. + + +IcePoAuthDoneCleanup +- done cleaning up. + + + +IcePaAuthProc +is the callback invoked for the client that received the +ProtocolSetup + + + + IcePoAuthStatus PoAuthStatus + IceConn ice_conn + IcePointer *auth_state_ptr + Bool swap + int auth_datalen + IcePointer auth_data + int *reply_datalen_ret + IcePointer *reply_data_ret + char **error_string_ret + + + + + + ice_conn + The ICE connection object. + + + auth_state_ptr + +A pointer to state for use by the authentication callback procedure. + + + + swap + +If +True +auth_data may have to be byte swapped +(depending on its contents). + + + + auth_datalen + +The length (in bytes) of the protocol originator authentication data. + + + + auth_data + +The authentication data from the protocol originator. + + + + reply_datalen_ret + +The length of the authentication data returned. + + + + reply_data_ret + +The authentication data returned. + + + + error_string_ret + +If authentication is rejected or fails, an error +string is returned. + + + + + +Authentication may require several phases, depending on the authentication +method. As a result, the +IcePaAuthProc +may be called more than once when authenticating a client, and +some state will have to be maintained between each invocation. +At the start of each +ProtocolSetup +auth_datalen is zero, +*auth_state_ptr is NULL, +and the function should initialize its state and set +this pointer. In subsequent invocations of the callback, the pointer +should be used to get at any state previously stored by the callback. + +If needed, the network ID of the client accepting the +ProtocolSetup +can be obtained by calling the +IceConnectionString +function. + +The auth_data pointer may point to a volatile block of memory. +If the data must be kept beyond this invocation of the callback, be sure +to make a copy of it. + +ICElib will be responsible for transmitting and freeing the reply_data_ret and +error_string_ret pointers with +free + + +The IcePaAuthProc should return one of four values: + + + + + + +IcePaAuthContinue - continue (or start) authentication. + + + + +IcePaAuthAccepted - authentication accepted. + + + + +IcePaAuthRejected - authentication rejected. + + + + +IcePaAuthFailed - authentication failed. + + + + + + + + +ICE Connections + + +In order for two clients to establish an ICE connection, one client has to be +waiting for connections, and the other client has to initiate the connection. +Most clients will initiate connections, so we discuss that first. + + + +Opening an ICE Connection + + + +To open an ICE connection with another client (that is, waiting +for connections), use + + + + + IceConn IceOpenConnection + char *network_ids_list + IcePointer context + Bool must_authenticate + int major_opcode_check + int error_length + char *error_string_ret + + + + + + network_ids_list + + +Specifies the network ID(s) of the other client. + + + + + context + + +A pointer to an opaque object or NULL. Used to determine if an +ICE connection can be shared (see below). + + + + + must_authenticate + + +If True the other client may not bypass authentication. + + + + + major_opcode_check + + +Used to force a new ICE connection to be created (see below). + + + + + error_length + + Length of the error_string_ret argument passed in. + + + + error_string_ret + + +Returns a null-terminated error message, if any. The error_string_ret +argument points to user supplied memory. No more than error_length bytes +are used. + + + + + + + + +returns an opaque ICE connection object if it succeeds; +otherwise, it returns NULL. + + + +The network_ids_list argument contains a list of network IDs separated +by commas. An attempt will be made to use the first network ID. If +that fails, an attempt will be made using the second network ID, and so on. +Each network ID has the following format: + + + + + + + + + + tcp/<hostname>:<portnumber> + or + + + decnet/<hostname>::<objname> + or + + + local/<hostname>:<path> + + + + + + + +Most protocol libraries will have some sort of open function that should +internally make a call into + +When + +is called, it may be possible to use a previously opened ICE connection (if +the target client is the same). However, there are cases in which shared +ICE connections are not desired. + +The context argument is used to determine if an ICE connection can +be shared. +If context is NULL, +then the caller is always willing to share the connection. +If context is not NULL, +then the caller is not willing to use a previously opened ICE connection +that has a different non-NULL context associated with it. + +In addition, if major_opcode_check contains a nonzero major opcode value, +a previously created ICE connection will be used only if the major opcode +is not active on the connection. This can be used to force multiple ICE +connections between two clients for the same protocol. + +Any authentication requirements are handled internally by the ICE library. +The method by which the authentication data is obtained +is implementation-dependent. + +The X Consortium's ICElib implementation uses an .ICEauthority file (see +Appendix A). + + +After + +is called, the client is ready to send a +ProtocolSetup +(provided that + +was called) or receive a +ProtocolSetup +(provided that + +was called). + + + +Listening for ICE Connections + +Clients wishing to accept ICE connections must first call + +or + +so that they can listen for connections. A list of opaque "listen" objects are +returned, one for each type of transport method that is available +(for example, Unix Domain, TCP, DECnet, and so on). + +Normally clients will let ICElib allocate an available name in each +transport and return listen objects. Such a client will then use + +to extract the chosen names and make them +available to other clients for opening the connection. In certain +cases it may be necessary for a client to listen for connections +on pre-arranged transport object names. Such a client may use + +to specify the names for the listen objects. + + + + Status IceListenForConnections + int *count_ret + IceListenObj **listen_objs_ret + int error_length + char *error_string_ret + + + + + + count_ret + Returns the number of listen objects created. + + + listen_objs_ret + Returns a list of pointers to opaque listen objects. + + + error_length + +The length of the error_string_ret argument passed in. + + + + error_string_ret + +Returns a null-terminated error message, if any. +The error_string_ret points to user supplied memory. +No more than error_length bytes are used. + + + + + +The return value of + +is zero for failure and a positive value for success. + + + + Status IceListenForWellKnownConnections + char *port_id + int *count_ret + IceListenObj **listen_objs_ret + int error_length + char *error_string_ret + + + + + + port_id + + +Specifies the port identification for the address(es) to be opened. The +value must not contain the slash ("/"> or comma (".") character; thse are +reserved for future use. + + + + + count_ret + + Returns the number of listen objects created. + + + + listen_objs_ret + + +Returns a list of pointers to opaque listen objects. + + + + + listen_objs_ret + + +Returns a list of pointers to opaque listen objects. + + + + + error_length + + +The length of the error_string_ret argument passed in. + + + + + error_string_ret + + +Returns a null-terminated error message, if any. The error_string_ret +points to user supplied memory. No more than error_length bytes are used. + + + + + + + constructs a list +of network IDs by prepending each known transport to port_id and then +attempts to create listen objects for the result. Port_id is the portnumber, +objname, or path portion of the ICE network ID. If a listen object for +a particular network ID cannot be created the network ID is ignored. +If no listen objects are created + +returns failure. + + + +The return value of +is zero for failure and a positive value for success. + + + +To close and free the listen objects, use + + + + + + void IceFreeListenObjs + int count + IceListenObj *listen_objs + + + + + + count + + The number of listen objects. + + + + listen_objs + + The listen objects. + + + + + + +To detect a new connection on a listen object, use +select on the descriptor associated with +the listen object. + + + +To obtain the descriptor, use + + + + + + int IceGetListenConnectionNumber + IceListenObj *listen_objs + + + + + + listen_obj + + The listen objects. + + + + + +To obtain the network ID string associated with a listen object, use + + + + + + + char IceGetListenConnectionString + IceListenObj listen_obj + + + + + + listen_obj + + The listen objects. + + + + +A network ID has the following format: + + + + + + + + + tcp/<hostname>:<portnumber> + or + + + decnet/<hostname>::<objname> + or + + + local/<hostname>:<path> + + + + + + + +To compose a string containing a list of network IDs separated by commas +(the format recognized by +use + + + + + char IceComposeNetworkIdList + int count + IceListenObj *listen_objs + + + + + + count + + The number of listen objects. + + + + listen_objs + + The listen objects. + + + + + + + +Host Based Authentication for ICE Connections + + +If authentication fails when a client attempts to open an +ICE connection and the initiating client has not required authentication, +a host based authentication procedure may be invoked to provide +a last chance for the client to connect. Each listen object has such a +callback associated with it, and this callback is set using the + +function. + + + + + void IceSetHostBasedAuthProc + IceListenObj listen_obj + IceHostBasedAuthProc host_based_auth_proc + + + + + + IceListenObj + + The listen object. + + + + host_based_auth_proc + + The host based authentication procedure. + + + + + + +By default, each listen object has no host based authentication procedure +associated with it. Passing NULL for host_based_auth_proc turns off +host based authentication if it was previously set. + + + + + + Bool HostBasedAuthProc + char *host_name + + + + + + host_name + + +The host name of the client that tried to open an ICE connection. + + + + + + + +The host_name argument is a string in the form +protocol/ +hostname, +where protocol is one of +{tcp, decnet, local}. + + + +If IceHostBasedAuthProc returns +True +access will be granted, even though the original authentication failed. +Note that authentication can effectively be disabled by registering an +IceHostBasedAuthProc +which always returns True + + + +Host based authentication is also allowed at +ProtocolSetup time. +The callback is specified in the + +function (see +). + + + + +Accepting ICE Connections + + + +After a connection attempt is detected on a listen object returned by + +you should call +This returns a new opaque ICE connection object. + + + + + IceConn IceAcceptConnection + IceListenObj listen_obj + IceAcceptStatus *status_ret + + + + + + + listen_obj + +The listen object on which a new connection was detected. + + + + + + status_ret + +Return status information. + + + + + +The status_ret argument is set to one of the following values: + + +IceAcceptSuccess +- the accept operation succeeded, +and the function returns a new connection object. + + +IceAcceptFailure +- the accept operation failed, and the function returns NULL. + + +IceAcceptBadMalloc +- a memory allocation failed, and the function returns NULL. + + + +In general, to detect new connections, you should call +select +on the file descriptors associated with the listen objects. +When a new connection is detected, the + +function should be called. + +may return a new ICE connection that is in a pending state. This is because +before the connection can become valid, authentication may be necessary. +Because the ICE library cannot block and wait for the connection to +become valid (infinite blocking can occur if the connecting client +does not act properly), the application must wait for the connection status +to become valid. + +The following pseudo-code demonstrates how connections are accepted: + + +new_ice_conn = IceAcceptConnection (listen_obj, &accept_status); +if (accept_status != IceAcceptSuccess) +{ + close the file descriptor and return +} + +status = IceConnectionStatus (new_ice_conn); +time_start = time_now; + +while (status == IceConnectPending) +{ + select() on {new_ice_conn, all open connections} + + for (each ice_conn in the list of open connections) + if (data ready on ice_conn) + { + status = IceProcessMessages (ice_conn, NULL, NULL); + if (status == IceProcessMessagesIOError) + IceCloseConnection(ice_conn); + } + if data ready on new_ice_conn + { + /* + * IceProcessMessages is called until the connection + * is non-pending. Doing so handles the connection + * setup request and any authentication requirements. + */ + + IceProcessMessages ( new_ice_conn, NULL, NULL); + status = IceConnectionStatus (new_ice_conn); + } + else + { + if (time_now - time_start > MAX_WAIT_TIME) + status = IceConnectRejected; + } +} + +if (status == IceConnectAccepted) +{ + Add new_ice_conn to the list of open connections +} +else +{ + IceCloseConnection + new_ice_conn +} + + +After + +is called and the connection has been +validated, the client is ready to receive a +ProtocolSetup +(provided +that + +was called) or send a +ProtocolSetup +(provided that + +was called). + + + +Closing ICE Connections + +To close an ICE connection created with + +or + +use + + + + + IceCloseStatus IceCloseConnection + IceConn ice_conn + + + + + + ice_conn + + The ICE connection to close. + + + + +To actually close an ICE connection, the following conditions +must be met: + + + +The open reference count must have reached zero on this ICE connection. +When + +is called, it tries to use a previously opened +ICE connection. If it is able to use an existing connection, it increments +the open reference count on the connection by one. +So, to close an ICE connection, each call to + +must be matched with a call to + +The connection can be closed only +on the last call to + + + +The active protocol count must have reached zero. Each time a +ProtocolSetup +succeeds on the connection, the active protocol count +is incremented by one. When the client no longer expects to use the +protocol on the connection, the + +function should be called, which decrements the active protocol count +by one (see +). + + + +If shutdown negotiation is enabled on the connection, the client on the other +side of the ICE connection must agree to have the connection closed. + + +returns one of the following values: + + +IceClosedNow +- the ICE connection was closed at this time. The watch procedures were +invoked and the connection was freed. + + +IceClosedASAP +- an IO error had occurred on the connection, but + +is being called within a nested + +The watch procedures have been invoked at this time, but the connection +will be freed as soon as possible (when the nesting level reaches zero and + +returns a status of +IceProcessMessagesConnectionClosed + + +IceConnectionInUse +- the connection was not closed at this time, because it is being used by +other active protocols. + + +IceStartedShutdownNegotiation +- the connection was not closed at this time and shutdown negotiation started +with the client on the other side of the ICE connection. When the connection +is actually closed, + +will return a status of +IceProcessMessagesConnectionClosed + + + +When it is known that the client on the other side of the ICE connection +has terminated the connection without initiating shutdown negotiation, the + +function should be called to turn off shutdown negotiation. This will prevent + +from writing to a broken connection. + + + + void IceSetShutdownNegotiation + IceConn ice_conn + Bool negotiate + + + + + + ice_conn + + A valid ICE connection object. + + + + negotiate + +If +False +shutdown negotiating will be turned off. + + + + +To check the shutdown negotiation status of an ICE connection, use + + + + + Bool IceCheckShutdownNegotiation + IceConn ice_conn + + + + + + ice_conn + + A valid ICE connection object. + + + + + + +returns +True +if shutdown negotiation will take place on the connection; +otherwise, it returns +False +Negotiation is on by default for a connection. It +can only be changed with the + +function. + + + +Connection Watch Procedures + +To add a watch procedure that will be called +each time ICElib opens a new connection via + +or + +or closes a connection via + +use + + + + + Status IceAddConnectionWatch + IceWatchProc watch_proc + IcePointer client_data + + + + + + watch_proc + + +The watch procedure to invoke when ICElib opens or closes a connection. + + + + + client_data + + This pointer will be passed to the watch procedure. + + + + + + +The return value of +is zero for failure, and a positive value for success. + + + +Note that several calls to +might share the same ICE connection. In such a case, the watch procedure +is only invoked when the connection is first created (after authentication +succeeds). Similarly, because connections might be shared, the +watch procedure is called only if +actually closes the connection (right before the IceConn is freed). + + + +The watch procedures are very useful for applications that +need to add a file descriptor to a select mask when a new connection +is created and remove the file descriptor when the connection is destroyed. +Because connections are shared, knowing when to add and remove the file +descriptor from the select mask would be difficult without the watch +procedures. + + + +Multiple watch procedures may be registered with the ICE library. +No assumptions should be made about their order of invocation. + + + +If one or more ICE connections were already created by the ICE library at the +time the watch procedure is registered, the watch procedure will instantly +be invoked for each of these ICE connections (with the opening argument +set to True + + + +The watch procedure is of type IceWatchProc + + + + + void WatchProc + IceConn ice_conn + IcePointer client_data + Bool opening + IcePointer *watch_data + + + + + + ice_conn + + +The opened or closed ICE connection. Call +IceConnectionNumber +to get the file descriptor associated with this connection. + + + + + client_data + + +Client data specified in the call to + + + + + + opening + + +If True the connection is being opened. If +False the connection is being closed. + + + + + watch_data + + Can be used to save a pointer to client data. + + + + + +If opening is True the client should set the +*watch_data pointer to any data it may need to save until the connection +is closed and the watch procedure is invoked again with opening set to +False + + + +To remove a watch procedure, use + + + + + + void IceRemoveConnectionWatch + IceWatchProc watch_proc + IcePointer client_data + + + + + + watch_proc + + +The watch procedure that was passed to + + + + + + client_data + + +The client_data pointer that was passed to + + + + + + + + + + +Protocol Setup and Shutdown + + +To activate a protocol on a given ICE connection, use + + + + + + IceProtocolSetupStatus IceProtocolSetup + IceConn ice_conn + int my_opcode + IcePointer client_data + Bool must_authenticate + int *major_version_ret + int *minor_version_ret + char **vendor_ret + char **release_ret + int error_length + char *error_string_ret + + + + + + ice_conn + + A valid ICE connection object. + + + + my_opcode + + +The major opcode of the protocol to be set up, as returned by + + + + + + client_data + + +The client data stored in this pointer will be passed to the +IcePoProcessMsgProc callback. + + + + + must_authenticate + + +If True the other client may +not bypass authentication. + + + + + major_version_ret + + The major version of the protocol to be used is returned. + + + + minor_version_ret + + The minor version of the protocol to be used is returned. + + + + vendor_ret + + The vendor string specified by the protocol acceptor. + + + + release_ret + + The release string specified by the protocol acceptor. + + + + error_length + + +Specifies the length of the error_string_ret argument passed in. + + + + + error_string_ret + + +Returns a null-terminated error message, if any. +The error_string_ret argument points to user supplied memory. +No more than error_length bytes are used. + + + + + + +The vendor_ret and release_ret strings should be freed with +free when no longer needed. + + + + returns one of the following values: + + + + + +IceProtocolSetupSuccess - the major_version_ret, +minor_version_ret, vendor_ret, release_ret are set. + + + + +IceProtocolSetupFailure or +IceProtocolSetupIOError +- check error_string_ret for failure reason. The major_version_ret, +minor_version_ret, vendor_ret, release_ret are not set. + + + + +IceProtocolAlreadyActive +- this protocol is already active on this connection. +The major_version_ret, minor_version_ret, vendor_ret, release_ret +are not set. + + + + + +To notify the ICE library when a given protocol will no longer be used +on an ICE connection, use + + + + + Status IceProtocolShutdown + IceConn ice_conn + int major_opcode + + + + + + ice_conn + + A valid ICE connection object. + + + + major_opcode + + The major opcode of the protocol to shut down. + + + + + + +The return value of +is zero for failure and a positive value for success. + + + +Failure will occur if the major opcode was never registered OR the protocol +of the major opcode was never activated on the connection. By activated, +we mean that a ProtocolSetup succeeded on the connection. +Note that ICE does not define how each sub-protocol triggers a +protocol shutdown. + + + + +Processing Messages + + +To process incoming messages on an ICE connection, use + + + + + IceProcessMessagesStatus IceProcessMessages + IceConn ice_conn + IceReplyWaitInfo *reply_wait + Bool *reply_ready_ret + + + + + + ice_conn + + A valid ICE connection object. + + + + reply_wait + + Indicates if a reply is being waited for. + + + + reply_ready_ret + + +If set to True on return, a reply is ready. + + + + + + + is used in two ways: + + + + + +In the first, a client may generate a message and block by calling + repeatedly until it gets its reply. + + + + +In the second, a client calls +with reply_wait set to NULL in response to select +showing that there is data to read on the ICE connection. +The ICE library may process zero or more complete messages. +Note that messages that are not blocked for are always processed by +invoking callbacks. + + + + + +IceReplyWaitInfo contains the major/minor opcodes +and sequence number of the message for which a reply is being awaited. +It also contains a pointer to the reply message to be filled in (the +protocol library should cast this IcePointer +to the appropriate reply type). In most +cases, the reply will have some fixed-size part, and the client waiting +for the reply will have provided a pointer to a structure to hold +this fixed-size data. If there is variable-length data, it would be +expected that the +IcePoProcessMsgProc +callback will have to allocate additional +memory and store pointer(s) to that memory in the fixed-size +structure. If the entire data is variable length (for example, a single +variable-length string), then the client waiting for the reply would probably +just pass a pointer to fixed-size space to hold a pointer, and the +IcePoProcessMsgProc +callback would allocate the storage and store the pointer. +It is the responsibility of the client receiving the reply to +free up any memory allocated on its behalf. + + + +typedef struct { + unsigned long sequence_of_request; + int major_opcode_of_request; + int minor_opcode_of_request; + IcePointer reply; +} IceReplyWaitInfo; + + + +If reply_wait is not NULL and + +has a reply or error to return in response to this reply_wait +(that is, no callback was generated), then the reply_ready_ret argument +will be set to True + + + +If reply_wait is NULL, then the caller may also pass NULL for +reply_ready_ret and be guaranteed that no value will be stored in +this pointer. + + + + returns one of the following values: + + + + + +IceProcessMessagesSuccess - no error occurred. + + + + +IceProcessMessagesIOError - an IO error occurred, +and the caller must explicitly close the connection by calling + + + + + +IceProcessMessagesConnectionClosed +- the ICE connection has been closed (closing of the connection was deferred +because of shutdown negotiation, or because the + +nesting level was not zero). Do not attempt +to access the ICE connection at this point, since it has been freed. + + + + + + + +Ping + + +To send a "Ping" message to the client on the other side of the +ICE connection, use + + + + + Status IcePing + IceConn ice_conn + IcePingReplyProc ping_reply_proc + IcePointer client_data + + + + + + ice_conn + + A valid ICE connection object. + + + + ping_reply_proc + + The callback to invoke when the Ping reply arrives. + + + + client_data + + +This pointer will be passed to the IcePingReplyProc +callback. + + + + + + + +returns zero for failure and a positive value for success. + +When + +processes the Ping reply, it will invoke the +IcePingReplyProc +callback. + + + + void PingReplyProc + IceConn ice_conn + IcePointer client_data + + + + + + ice_conn + +A valid ICE connection object. + + + + client_data + +The client data specified in the call to + + + + + + + + +Using ICElib Informational Functions + + + + IceConnectStatus IceConnectionStatus + IceConn ice_conn + + + + +returns the status of an ICE connection. The possible return values are: + + + +IceConnectPending +- the connection is not valid yet (that is, authentication is taking place). +This is only relevant to connections created by + + + +IceConnectAccepted +- the connection has been accepted. +This is only relevant to connections created by + + + +IceConnectRejected +- the connection had been rejected (that is, authentication failed). +This is only relevant to connections created by + + + +IceConnectIOError +- an IO error has occurred on the connection. + + + + + + char *IceVendor + IceConn ice_conn + + + +IceVendor +returns the ICE library vendor identification +for the other side of the connection. +The string should be freed with a call to +free +when no longer needed. + + + + char *IceRelease + IceConn ice_conn + + + +IceRelease +returns the release identification of the ICE library +on the other side of the connection. +The string should be freed with a call to +free +when no longer needed. + + + + int IceProtocolVersion + IceConn ice_conn + + + + +returns the major version of the ICE protocol on this connection. + + + + int IceProtocolRevision + IceConn ice_conn + + + + + +returns the minor version of the ICE protocol on this connection. + + + + int IceConnectionNumber + IceConn ice_conn + + + + +IceConnectionNumber +returns the file descriptor of this ICE connection. + + + + char *IceConnectionString + IceConn ice_conn + + + +IceConnectionString +returns the network ID of the client that +accepted this connection. The string should be freed with a call to +free +when no longer needed. + + + + unsigned long IceLastSentSequenceNumber + IceConn ice_conn + + + + + +returns the sequence number of the last message sent on this ICE connection. + + + + unsigned long IceLastReceivedSequenceNumber + IceConn ice_conn + + + +IceLastReceivedSequenceNumber +returns the sequence number of the last message received on this +ICE connection. + + + + Bool IceSwapping + IceConn ice_conn + + + + + +returns +True +if byte swapping is necessary when reading messages on the ICE connection. + + + + IcePointer IceGetContext + IceConn ice_conn + + + + +returns the context associated with a connection created by + + + + +ICE Messages + + +All ICE messages have a standard 8-byte header. The ICElib macros that +read and write messages rely on the following naming convention for message +headers: + + + + CARD8 major_opcode; + CARD8 minor_opcode; + CARD8 data[2]; + CARD32 length B32; + + + +The 3rd and 4th bytes of the message header can be used as needed. +The length field is specified in units of 8 bytes. + + + +Sending ICE Messages + + +The ICE library maintains an output buffer used for generating messages. +Protocol libraries layered on top of ICE may choose to batch messages +together and flush the output buffer at appropriate times. + + + +If an IO error has occurred on an ICE connection, all write operations +will be ignored. For further information, see +. + + + + +To get the size of the ICE output buffer, use + + + + + + int IceGetOutBufSize + IceConn ice_conn + + + + + + ice_conn + + A valid ICE connection object. + + + + + + +To flush the ICE output buffer, use + + + + + int IceFlush + IceConn ice_conn + + + + + + ice_conn + + A valid ICE connection object. + + + + + +Note that the output buffer may be implicitly flushed if there is +insufficient space to generate a message. + + +The following macros can be used to generate ICE messages: + + + + IceGetHeader + IceConn ice_conn + int major_opcode + int minor_opcode + int header_size + <C_data_type> *pmsg + + + + + + ice_conn + + A valid ICE connection object. + + + + major_opcode + + The major opcode of the message. + + + + minor_opcode + + The minor opcode of the message. + + + + header_size + + The size of the message header (in bytes). + + + + <C_data_type> + + The actual C data type of the message header. + + + + pmsg + + +The message header pointer. After this macro is called, the +library can store data in the message header. + + + + + + + + +is used to set up a message header on an ICE connection. +It sets the major and minor opcodes of the message, and initializes +the message's length to the length of the header. If additional +variable length data follows, the message's length field should be +updated. + + + + + + IceGetHeaderExtra + IceConn ice_conn + int major_opcode + int minor_opcode + int header_size + int extra + <C_data_type> *pmsg + char *pdata + + + + + + ice_conn + + A valid ICE connection object. + + + + major_opcode + + The major opcode of the message. + + + + minor_opcode + + The minor opcode of the message. + + + + header_size + + The size of the message header (in bytes). + + + + extra + + +The size of the extra data beyond the header (in 8-byte units). + + + + + <C_data_type> + + The actual C data type of the message header. + + + + pmsg + + +The message header pointer. After this macro is called, the +library can store data in the message header. + + + + + pdata + + +Returns a pointer to the ICE output buffer that points +immediately after the message header. The variable length +data should be stored here. If there was not enough room +in the ICE output buffer, pdata is set to NULL. + + + + + + + + +is used to generate a message with a fixed (and relatively small) amount +of variable length data. The complete message must fit in the ICE output +buffer. + + + + + IceSimpleMessage + IceConn ice_conn + int major_opcode + int minor_opcode + + + + + + ice_conn + + A valid ICE connection object. + + + + major_opcode + + The major opcode of the message. + + + + minor_opcode + + The minor opcode of the message. + + + + + + +is used to generate a message that is identical +in size to the ICE header message, and has no additional data. + + + + + IceErrorHeader + IceConn ice_conn + int offending_major_opcode + int offending_minor_opcode + int offending_sequence_num + int severity + int error_class + int data_length + + + + + + ice_conn + + A valid ICE connection object. + + + + offending_major_opcode + + +The major opcode of the protocol in which an error was detected. + + + + + offending_minor_opcode + + +The minor opcode of the protocol in which an error was detected. + + + + + offending_sequence_num + + The sequence number of the message that caused the error. + + + + severity + + +IceCanContinue +IceFatalToProtocol +or +IceFatalToConnection + + + + + error_class + + The error class. + + + + data_length + + +Length of data (in 8-byte units) to be written after the header. + + + + + + + sets up an error message header. + + + +Note that the two clients connected by ICE may be using different +major opcodes for a given protocol. The offending_major_opcode passed +to this macro is the major opcode of the protocol for the client +sending the error message. + + + +Generic errors, which are common to all protocols, have classes +in the range 0x8000..0xFFFF. +See the Inter-Client Exchange Protocol +standard for more details. + + + + + + + + + + IceBadMinor + 0x8000 + + + IceBadState + 0x8001 + + + IceBadLength + 0x8002 + + + IceBadValue + 0x8003 + + + + + +Per-protocol errors have classes in the range 0x0000-0x7fff. + + +To write data to an ICE connection, use the + macro. If the data fits into the +ICE output buffer, it is copied there. Otherwise, the ICE output buffer +is flushed and the data is directly sent. + + + +This macro is used in conjunction with + and + + + + + + IceWriteData + IceConn ice_conn + int bytes + char *data + + + + + + ice_conn + + A valid ICE connection object. + + + + bytes + + The number of bytes to write. + + + + data + + The data to write. + + + + + + +To write data as 16-bit quantities, use + + + + + IceWriteData16 + IceConn ice_conn + int bytes + char *data + + + + + + ice_conn + + A valid ICE connection object. + + + + bytes + + The number of bytes to write. + + + + data + + The data to write. + + + + + +To write data as 32-bit quantities, use + + + + + + IceWriteData32 + IceConn ice_conn + int bytes + char *data + + + + + + ice_conn + + A valid ICE connection object. + + + + bytes + + The number of bytes to write. + + + + data + + The data to write. + + + + + +To write data as 32-bit quantities, use + + + +To bypass copying data to the ICE output buffer, use + to directly send data over the network +connection. If necessary, the ICE output buffer is first flushed. + + + + + IceSendData + IceConn ice_conn + int bytes + char *data + + + + + + ice_conn + + A valid ICE connection object. + + + + bytes + + The number of bytes to send. + + + + data + + The data to send. + + + + + + +To force 32-bit or 64-bit alignment, use +A maximum of 7 pad bytes can be specified. + + + + + IceWritePad + IceConn ice_conn + int bytes + char *data + + + + + + ice_conn + + A valid ICE connection object. + + + + bytes + + The number of bytes to write. + + + + data + + The number of pad bytes to write. + + + + + + + +Reading ICE Messages + + + +The ICE library maintains an input buffer used for reading messages. +If the ICE library chooses to perform nonblocking reads (this is +implementation-dependent), then for every read operation that it makes, +zero or more complete messages may be read into the input buffer. As +a result, for all of the macros described in this section that read +messages, an actual read operation will occur on the connection only if +the data is not already present in the input buffer. + + + + +To get the size of the ICE input buffer, use + + + + + + int IceGetInBufSize + IceConn ice_conn + + + + + + ice_conn + + A valid ICE connection object. + + + + + +When reading messages, care must be taken to check for IO errors. If +any IO error occurs in reading any part of a message, the message should +be thrown out. After using any of the macros described below for reading +messages, the +macro can be used to check if an IO error occurred on the +connection. After an IO error has occurred on an ICE connection, all +read operations will be ignored. For further information, see +. + + + + + + Bool IceValidIO + IceConn ice_conn + + + + + + ice_conn + + A valid ICE connection object. + + + + +The following macros can be used to read ICE messages. + + + + IceReadSimpleMessage + IceConn ice_conn + <C_data_type> *pmsg + + + + + + ice_conn + + A valid ICE connection object. + + + + <C_data_type> + + The actual C data type of the message header. + + + + pmsg + + This pointer is set to the message header. + + + + + + +is used for messages that are identical in size to the 8-byte ICE header, but +use the spare 2 bytes in the header to encode additional data. Note that the +ICE library always reads in these first 8 bytes, so it can obtain the major +opcode of the message. +simply returns a pointer to these 8 bytes; it does not actually read any data +into the input buffer. + + + +For a message with variable length data, there are two ways of reading +the message. One method involves reading the complete message in one +pass using +The second method involves reading the message header (note that this may +be larger than the 8-byte ICE header), then reading +the variable length data in chunks (see + and + + + + + + + IceReadCompleteMessage + IceConn ice_conn + int header_size + <C_data_type> *pmsg + char *pdata + + + + + + ice_conn + + A valid ICE connection object. + + + + header_size + + The size of the message header (in bytes). + + + + <C_data_type> + + The actual C data type of the message header. + + + + pmsg + + This pointer is set to the message header. + + + + pdata + + +This pointer is set to the variable length data of the message. + + + + + + +If the ICE input buffer has sufficient space, + +will read the complete message into the +ICE input buffer. Otherwise, a buffer will be allocated to hold the +variable length data. After the call, the pdata argument should +be checked against NULL to make sure that there was sufficient memory +to allocate the buffer. + + + +After calling +and processing the message, +should be called. + + + + + + IceDisposeCompleteMessage + IceConn ice_conn + char *pdata + + + + + + ice_conn + + A valid ICE connection object. + + + + pdata + + +The pointer to the variable length data returned in + + + + + + + +If a buffer had to be allocated to hold the variable length data (because +it did not fit in the ICE input buffer), it is freed here by ICElib. + + + + + + IceReadMessageHeader + IceConn ice_conn + int header_size + <C_data_type> *pmsg + + + + + + ice_conn + + A valid ICE connection object. + + + + header_size + + The size of the message header (in bytes). + + + + <C_data_type> + + The actual C data type of the message header. + + + + pmsg + + This pointer is set to the message header. + + + + + + reads just the message header. +The rest of the data should be read with the + +family of macros. This method of reading a message should be used when the +variable length data must be read in chunks. + + + + +To read data directly into a user supplied buffer, use + + + + + + IceReadData + IceConn ice_conn + int bytes + char *pdata + + + + + + ice_conn + + A valid ICE connection object. + + + + bytes + + The number of bytes to read. + + + + pdata + + The data is read into this user supplied buffer. + + + + + + +To read data as 16-bit quantities, use + + + + + IceReadData16 + IceConn ice_conn + Bool swap + int bytes + char *pdata + + + + + + ice_conn + + A valid ICE connection object. + + + + swap + + +If True, the values will be byte swapped. + + + + + bytes + + The number of bytes to read. + + + + pdata + + The data is read into this user supplied buffer. + + + + + + +To read data as 32-bit quantities, use + + + + + IceReadData32 + IceConn ice_conn + Bool swap + int bytes + char *pdata + + + + + + ice_conn + + A valid ICE connection object. + + + + swap + + +If True, the values will be byte swapped. + + + + + bytes + + The number of bytes to read. + + + + pdata + + The data is read into this user supplied buffer. + + + + +To force 32-bit or 64-bit alignment, use + +A maximum of 7 pad bytes can be specified. + + + + IceReadPad + IceConn ice_conn + int bytes + + + + + + ice_conn + + A valid ICE connection object. + + + + bytes + + The number of pad bytes. + + + + + + + + +Error Handling + + +There are two default error handlers in ICElib: + + + + +One to handle typically fatal conditions (for example, +a connection dying because a machine crashed) + + + + One to handle ICE-specific protocol errors + + + + +These error handlers can be changed to user-supplied routines if you +prefer your own error handling and can be changed as often as you like. + + + + +To set the ICE error handler, use + + + + + IceSetErrorHandler + IceConn ice_conn + int bytes + + + + + + handler + + +The ICE error handler. You should pass NULL to restore the default handler. + + + + + + + returns the previous error handler. + + + +The ICE error handler is invoked when an unexpected ICE protocol +error (major opcode 0) is encountered. The action of the default +handler is to print an explanatory message to +stderr +and if the severity is fatal, call +exit +with a nonzero value. If exiting +is undesirable, the application should register its own error handler. + + + +Note that errors in other protocol +domains should be handled by their respective libraries (these libraries +should have their own error handlers). + + + +An ICE error handler has the type of + + + + + void IceErrorHandler + IceConn ice_conn + Bool swap + int offending_minor_opcode + unsigned long offending_sequence_num + int error_class + int severity + IcePointer values + + + + + + handler + + The ICE connection object. + + + + swap + + A flag that indicates if the values need byte swapping. + + + + offending_minor_opcode + + The ICE minor opcode of the offending message. + + + + offending_sequence_num + + The sequence number of the offending message. + + + + error_class + + The error class of the offending message. + + + + severity + + +IceCanContinue +IceFatalToProtocol +or +IceFatalToConnection + + + + + values + + +Any additional error values specific to the minor opcode and class. + + + + + + +The following error classes are defined at the ICE level: + + +IceBadMinor +IceBadState +IceBadLength +IceBadValue +IceBadMajor +IceNoAuth +IceNoVersion +IceSetupFailed +IceAuthRejected +IceAuthFailed +IceProtocolDuplicate +IceMajorOpcodeDuplicate +IceUnknownProtocol + + + +For further information, see +the Inter-Client Exchange Protocol standard. + + + + +To handle fatal I/O errors, use + + + + + + IceIOErrorHandler IceSetIOErrorHandler + IceIOErrorHandler handler + + + + + + handler + + +The I/O error handler. You should pass NULL to restore the default handler. + + + + + + + returns the previous +IO error handler. + + + +An ICE I/O error handler has the type of + + + + + + void IceIOErrorHandler + IceConn ice_conn + + + + + + ice_conn + The ICE connection object. + + + + + There are two ways of handling IO errors in ICElib: + + + + +In the first, the IO error handler does whatever is necessary +to respond to the IO error and then returns, but it does not call + +The ICE connection is given a "bad IO" status, and all future reads +and writes to the connection are ignored. The next time + +is called it will return a status of +IceProcessMessagesIOError +At that time, the application should call + + + + + +In the second, the IO error handler does call + +and then uses the longjmp +call to get back to the application's main event loop. The +setjmp and +longjmp +calls may not work properly on all platforms, +and special care must be taken to avoid memory leaks. +Therefore, this second model is less desirable. + + + + + +Before the application I/O error handler is invoked, protocol libraries +that were interested in being notified of I/O errors will have their + +handlers invoked. This handler is set up in the protocol registration +functions (see and + +and could be used to clean up state specific to the protocol. + + + + + + void IceIOErrorProc + IceConn ice_conn + + + + + + ice_conn + The ICE connection object. + + + + +Note that every +callback must return. This is required +because each active protocol must be notified of the broken connection, +and the application IO error handler must be invoked afterwards. + + + + +Multi-Threading Support + + +To declare that multiple threads in an application will be using the ICE +library, use +IceInitThreads + + +Status IceInitThreads() + + + +The +IceInitThreads +function must be the first ICElib function a +multi-threaded program calls. It must complete before any other ICElib +call is made. +IceInitThreads +returns a nonzero status if and only if it was able +to initialize the threads package successfully. +It is safe to call +IceInitThreads +more than once, although the threads package will only be initialized once. + +Protocol libraries layered on top of ICElib will have to lock critical +sections of code that access an ICE connection (for example, when +generating messages). Two calls, which are generally implemented as +macros, are provided: + + + + void IceLockConn + IceConn ice_conn + + + + + + void IceUnlockConn + IceConn ice_conn + + + + + + ice_conn + The ICE connection object. + + + +To keep an ICE connection locked across several ICElib calls, applications use + +and + + + + + void IceAppLockConn + IceConn ice_conn + + + + + + ice_conn + The ICE connection object. + + + + +The + +function completely locks out other threads using the connection +until + +is called. Other threads attempting to use ICElib +calls on the connection will block. +If the program has not previously called +IceInitThreads + +has no effect. + + + + void IceAppUnlockConn + IceConn ice_conn + + + + + + ice_conn + The ICE connection object. + + + +The + +function allows other threads to complete ICElib +calls on the connection that were blocked by a previous call to + +from this thread. If the program has not previously called +IceInitThreads + +has no effect. + + + +Miscellaneous Functions + + + + +To allocate scratch space (for example, when generating +messages with variable data), use +IceAllocScratch +Each ICE connection has one scratch space associated with it. +The scratch space starts off as empty and grows as needed. +The contents of the scratch space is not guaranteed to be preserved +after any ICElib function is called. + + + + + char *IceAllocScratch + IceConn ice_conn + unsigned long size + + + + + + ice_conn + The ICE connection object. + + + size + The number of bytes required. + + + +Note that the memory returned by +IceAllocScratch +should not be freed by the caller. +The ICE library will free the memory when the ICE connection is closed. + + + +Acknowledgements + + + +Thanks to Bob Scheifler for his thoughtful input on the design +of the ICE library. Thanks also to Jordan Brown, Larry Cable, Donna Converse, +Clive Feather, Stephen Gildea, Vania Joloboff, Kaleb Keithley, +Stuart Marks, Hiro Miyamoto, Ralph Swick, Jim VanGilder, and Mike Wexler. + + + + +Authentication Utility Functions + + + +As discussed in this document, the means by which authentication data +is obtained by the ICE library (for +ConnectionSetup +messages or +ProtocolSetup +messages) is implementation-dependent.† + +The X Consortium's ICElib implementation assumes the presence of an +ICE authority file. + + + + +This appendix describes some utility functions that manipulate an +ICE authority file. The authority file can be used to pass authentication +data between clients. + + +The basic operations on the .ICEauthority file are: + + + + Get file name + + + Lock + + + Unlock + + + Read entry + + + Write entry + + + Search for entry + + + + +These are fairly low-level operations, and it is expected that a program, +like "iceauth", would exist to add, remove, and display entries in the file. + + + +In order to use these utility functions, the +<X11/ICE/ICEutil.h> +header file must be included. + + + +An entry in the .ICEauthority file is defined by the following data structure: + + + + +typedef struct { + char *protocol_name; + unsigned short protocol_data_length; + char *protocol_data; + char *network_id; + char *auth_name; + unsigned short auth_data_length; + char *auth_data; +} IceAuthFileEntry; + + + + +The protocol_name member is either "ICE" for connection setup authentication +or the subprotocol name, such as "XSMP". For each entry, protocol specific +data can be specified in the protocol_data member. This can be used +to search for old entries that need to be removed from the file. + + + +The network_id member is the network ID of the client accepting +authentication (for example, the network ID of a session manager). +A network ID has the following form: + + + + + + + + + + tcp/<hostname>:<portnumber> + or + + + decnet/<hostname>::<objname> + or + + + local/<hostname>:<path> + + + + + + + +The auth_name member is the name of the authentication method. +The auth_data member is the actual authentication data, +and the auth_data_length member is the number of bytes in the data. + + + +To obtain the default authorization file name, use +IceAuthFileName + + + +char *IceAuthFileName() + + + +If the ICEAUTHORITY environment variable if set, this value is returned. +Otherwise, the default authorization file name is $HOME/.ICEauthority. +This name is statically allocated and should not be freed. + + + +To synchronously update the authorization file, the file must +be locked with a call to + +This function takes advantage of the fact that the +link +system call will fail if the name of the new link already exists. + + + + + int IceLockAuthFile + char *file_name + int retries + int timeout + long dead + + + + + + file_name + The authorization file to lock. + + + retries + + The number of retries. + + + + timeout + + The number of seconds before each retry. + + + + dead + + +If a lock already exists that is the specified dead seconds old, +it is broken. +A value of zero is used to unconditionally break an old lock. + + + + + +One of three values is returned: + + + + +IceAuthLockSuccess - the lock succeeded. + + + + +IceAuthLockError - a system error occurred, and +errno may prove useful. + + + + +IceAuthLockTimeout - the specified number of +retries failed. + + + + + +To unlock an authorization file, use + + + + + int IceUnlockAuthFile + char *file_name + + + + + + file_name + The authorization file to unlock. + + + + +To read the next entry in an authorization file, use +IceReadAuthFileEntry + + + + + IceAuthFileEntry *IceReadAuthFileEntry + FILE *auth_file + + + + + + auth_file + The authorization file. + + + + +Note that it is the responsibility of the application to open the file +for reading before calling this function. If an error is encountered, +or there are no more entries to read, NULL is returned. + + + +Entries should be free with a call to + + + + +To write an entry in an authorization file, use + + + + + + Status IceWriteAuthFileEntry + FILE *auth_file + IceAuthFileEntry *entry + + + + + + auth_file + The authorization file. + + + entry + The entry to write. + + + + +Note that it is the responsibility of the application to open the file +for writing before calling this function. The function returns a nonzero +status if the operation was successful. + + + + +To search the default authorization file for an entry that matches a given +protocol_name/network_id/auth_name tuple, use +IceGetAuthFileEntry + + + + + IceAuthFileEntry *IceGetAuthFileEntry + const char *protocol_name + const char *network_id + const char *auth_name + + + + + + auth_file + The name of the protocol to search on. + + + network_id + + The network ID to search on. + + + + auth_name + + The authentication method to search on. + + + + + +If IceGetAuthFileEntry +fails to find such an entry, NULL is returned. + + + + +To free an entry returned by +IceReadAuthFileEntry or +IceGetAuthFileEntry use + + + + + + void IceFreeAuthFileEntry + IceAuthFileEntry *entry + + + + + + entry + The entry to free. + + + + + + +MIT-MAGIC-COOKIE-1 Authentication + + +The X Consortium's ICElib implementation supports a simple +MIT-MAGIC-COOKIE-1 authentication scheme using the authority file utilities +described in Appendix A. + +In this model, an application, such as a session manager, obtains a +magic cookie by calling +IceGenerateMagicCookie +and then stores it in the user's local .ICEauthority file +so that local clients can connect. In order to allow remote clients to +connect, some remote execution mechanism should be used to store the +magic cookie in the user's .ICEauthority file on a remote machine. + +In addition to storing the magic cookie in the .ICEauthority file, the +application needs to call the + +function in order to store the magic cookie in memory. When it comes time +for the MIT-MAGIC-COOKIE-1 authentication procedure to accept or reject the +connection, it will compare the magic cookie presented by the requestor to +the magic cookie in memory. + + + + char *IceGenerateMagicCookie + int length + + + + + + length + The desired length of the magic cookie. + + + + +The magic cookie returned will be null-terminated. If memory can not be +allocated for the magic cookie, the function will return NULL. +Otherwise, the magic cookie should be freed with a call to +free + + +To store the authentication data in memory, use + +Currently, this function is only used for MIT-MAGIC-COOKIE-1 +authentication, but it may be used for additional authentication +methods in the future. + + + + void IceSetPaAuthData + int num_entries + IceAuthDataEntry *entries + + + + + + num_entries + The number of authentication data entries. + + + entries + The list of authentication data entries. + + + +Each entry has associated with it a protocol name +(for example, "ICE" for ICE connection setup authentication, +"XSMP" for session management authentication), a network ID for the +"accepting" client, an authentication name (for example, MIT-MAGIC-COOKIE-1), +and authentication data. The ICE library +will merge these entries with previously set entries, based on the +(protocol_name, network_id, auth_name) tuple. + + + + +typedef struct { + char *protocol_name; + char *network_id; + char *auth_name; + unsigned short auth_data_length; + char *auth_data; +} IceAuthDataEntry; + + + + + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..3d1b0ba --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,13 @@ + +if ENABLE_DOCS + +# Main DocBook/XML files (DOCTYPE book) +docbook = ICElib.xml + +# The location where the DocBook/XML files and their generated formats are installed +shelfdir = $(docdir) + +# Generate DocBook/XML output formats with or without stylesheets +include $(top_srcdir)/docbook.am + +endif ENABLE_DOCS diff --git a/docbook.am b/docbook.am new file mode 100644 index 0000000..bba4d54 --- /dev/null +++ b/docbook.am @@ -0,0 +1,105 @@ +# +# Generate output formats for a single DocBook/XML with/without chapters +# +# Variables set by the calling Makefile: +# shelfdir: the location where the docs/specs are installed. Typically $(docdir) +# docbook: the main DocBook/XML file, no chapters, appendix or image files +# chapters: all files pulled in by an XInclude statement and images. +# + +# +# This makefile is intended for Users Documentation and Functional Specifications. +# Do not use for Developer Documentation which is not installed and does not require olink. +# Refer to http://www.x.org/releases/X11R7.6/doc/xorg-docs/ReleaseNotes.html#id2584393 +# for an explanation on documents classification. +# + +# DocBook/XML generated output formats to be installed +shelf_DATA = + +# DocBook/XML file with chapters, appendix and images it includes +dist_shelf_DATA = $(docbook) $(chapters) + +if HAVE_XMLTO +if HAVE_STYLESHEETS + +XMLTO_SEARCHPATH_FLAGS = \ + --searchpath "$(XORG_SGML_PATH)/X11" \ + --searchpath "$(abs_top_builddir)" +XMLTO_HTML_OLINK_FLAGS = \ + --stringparam target.database.document=$(XORG_SGML_PATH)/X11/dbs/masterdb.html.xml \ + --stringparam current.docid="$(<:.xml=)" +XMLTO_HTML_STYLESHEET_FLAGS = -x $(STYLESHEET_SRCDIR)/xorg-xhtml.xsl +XMLTO_HTML_FLAGS = \ + $(XMLTO_SEARCHPATH_FLAGS) \ + $(XMLTO_HTML_STYLESHEET_FLAGS) \ + $(XMLTO_HTML_OLINK_FLAGS) + +shelf_DATA += $(docbook:.xml=.html) +%.html: %.xml $(chapters) + $(AM_V_GEN)$(XMLTO) $(XMLTO_HTML_FLAGS) xhtml-nochunks $< + +if HAVE_XMLTO_TEXT + +shelf_DATA += $(docbook:.xml=.txt) +%.txt: %.xml $(chapters) + $(AM_V_GEN)$(XMLTO) $(XMLTO_HTML_FLAGS) txt $< +endif HAVE_XMLTO_TEXT + +if HAVE_FOP +XMLTO_FO_IMAGEPATH_FLAGS = --stringparam img.src.path=$(abs_builddir)/ +XMLTO_PDF_OLINK_FLAGS = \ + --stringparam target.database.document=$(XORG_SGML_PATH)/X11/dbs/masterdb.pdf.xml \ + --stringparam current.docid="$(<:.xml=)" +XMLTO_FO_STYLESHEET_FLAGS = -x $(STYLESHEET_SRCDIR)/xorg-fo.xsl + +XMLTO_FO_FLAGS = \ + $(XMLTO_SEARCHPATH_FLAGS) \ + $(XMLTO_FO_STYLESHEET_FLAGS) \ + $(XMLTO_FO_IMAGEPATH_FLAGS) \ + $(XMLTO_PDF_OLINK_FLAGS) + +shelf_DATA += $(docbook:.xml=.pdf) +%.pdf: %.xml $(chapters) + $(AM_V_GEN)$(XMLTO) $(XMLTO_FO_FLAGS) --with-fop pdf $< + +shelf_DATA += $(docbook:.xml=.ps) +%.ps: %.xml $(chapters) + $(AM_V_GEN)$(XMLTO) $(XMLTO_FO_FLAGS) --with-fop ps $< +endif HAVE_FOP + +# Generate documents cross-reference target databases +if HAVE_XSLTPROC + +XSLT_SEARCHPATH_FLAGS = \ + --path "$(XORG_SGML_PATH)/X11" \ + --path "$(abs_top_builddir)" +XSLT_OLINK_FLAGS = \ + --stringparam targets.filename "$@" \ + --stringparam collect.xref.targets "only" \ + --stringparam olink.base.uri "$(@:.db=)" + +XSLT_HTML_FLAGS = \ + $(XSLT_SEARCHPATH_FLAGS) \ + $(XSLT_OLINK_FLAGS) \ + --nonet --xinclude \ + $(STYLESHEET_SRCDIR)/xorg-xhtml.xsl +XSLT_PDF_FLAGS = \ + $(XSLT_SEARCHPATH_FLAGS) \ + $(XSLT_OLINK_FLAGS) \ + --nonet --xinclude \ + $(STYLESHEET_SRCDIR)/xorg-fo.xsl + +shelf_DATA += $(docbook:.xml=.html.db) +%.html.db: %.xml $(chapters) + $(AM_V_GEN)$(XSLTPROC) $(XSLT_HTML_FLAGS) $< + +shelf_DATA += $(docbook:.xml=.pdf.db) +%.pdf.db: %.xml $(chapters) + $(AM_V_GEN)$(XSLTPROC) $(XSLT_PDF_FLAGS) $< + +endif HAVE_XSLTPROC +endif HAVE_STYLESHEETS +endif HAVE_XMLTO + +CLEANFILES = $(shelf_DATA) diff --git a/ice.pc.in b/ice.pc.in new file mode 100644 index 0000000..b96c9f8 --- /dev/null +++ b/ice.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: ICE +Description: X Inter Client Exchange Library +Version: @PACKAGE_VERSION@ +Requires: xproto +Cflags: -I${includedir} +Libs: -L${libdir} -lICE diff --git a/include/X11/ICE/ICE.h b/include/X11/ICE/ICE.h new file mode 100644 index 0000000..7560647 --- /dev/null +++ b/include/X11/ICE/ICE.h @@ -0,0 +1,101 @@ +/****************************************************************************** + + +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 _ICE_H_ +#define _ICE_H_ + +/* + * Protocol Version + */ + +#define IceProtoMajor 1 +#define IceProtoMinor 0 + + +/* + * Byte Order + */ + +#define IceLSBfirst 0 +#define IceMSBfirst 1 + + +/* + * ICE minor opcodes + */ + +#define ICE_Error 0 +#define ICE_ByteOrder 1 +#define ICE_ConnectionSetup 2 +#define ICE_AuthRequired 3 +#define ICE_AuthReply 4 +#define ICE_AuthNextPhase 5 +#define ICE_ConnectionReply 6 +#define ICE_ProtocolSetup 7 +#define ICE_ProtocolReply 8 +#define ICE_Ping 9 +#define ICE_PingReply 10 +#define ICE_WantToClose 11 +#define ICE_NoClose 12 + + +/* + * Error severity + */ + +#define IceCanContinue 0 +#define IceFatalToProtocol 1 +#define IceFatalToConnection 2 + + +/* + * ICE error classes that are common to all protocols + */ + +#define IceBadMinor 0x8000 +#define IceBadState 0x8001 +#define IceBadLength 0x8002 +#define IceBadValue 0x8003 + + +/* + * ICE error classes that are specific to the ICE protocol + */ + +#define IceBadMajor 0 +#define IceNoAuth 1 +#define IceNoVersion 2 +#define IceSetupFailed 3 +#define IceAuthRejected 4 +#define IceAuthFailed 5 +#define IceProtocolDuplicate 6 +#define IceMajorOpcodeDuplicate 7 +#define IceUnknownProtocol 8 + +#endif /* _ICE_H_ */ diff --git a/include/X11/ICE/ICEconn.h b/include/X11/ICE/ICEconn.h new file mode 100644 index 0000000..e5d493a --- /dev/null +++ b/include/X11/ICE/ICEconn.h @@ -0,0 +1,250 @@ +/****************************************************************************** + + +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 _ICECONN_H_ +#define _ICECONN_H_ + +#include + +/* + * Data structures for ICE connection object + */ + +typedef struct _IceSavedReplyWait { + IceReplyWaitInfo *reply_wait; + Bool reply_ready; + struct _IceSavedReplyWait *next; +} _IceSavedReplyWait; + +typedef struct _IcePingWait { + IcePingReplyProc ping_reply_proc; + IcePointer client_data; + struct _IcePingWait *next; +} _IcePingWait; + +typedef struct { + char *vendor; + char *release; + int version_count; + IcePoVersionRec *version_recs; + int auth_count; + char **auth_names; + IcePoAuthProc *auth_procs; + IceIOErrorProc io_error_proc; +} _IcePoProtocol; + +typedef struct { + char *vendor; + char *release; + int version_count; + IcePaVersionRec *version_recs; + IceProtocolSetupProc protocol_setup_proc; + IceProtocolActivateProc protocol_activate_proc; + int auth_count; + char **auth_names; + IcePaAuthProc *auth_procs; + IceHostBasedAuthProc host_based_auth_proc; + IceIOErrorProc io_error_proc; +} _IcePaProtocol; + +typedef struct { + char *protocol_name; + _IcePoProtocol *orig_client; + _IcePaProtocol *accept_client; +} _IceProtocol; + +typedef struct { + Bool in_use; + int my_opcode; + _IceProtocol *protocol; + IcePointer client_data; + Bool accept_flag; + union { + IcePaProcessMsgProc accept_client; + IcePoProcessMsgProc orig_client; + } process_msg_proc; +} _IceProcessMsgInfo; + +typedef struct { + int his_version_index; + int my_version_index; + char *his_vendor; + char *his_release; + char my_auth_index; + IcePointer my_auth_state; + Bool must_authenticate; +} _IceConnectToMeInfo; + +typedef struct { + int his_opcode; + int my_opcode; + int his_version_index; + int my_version_index; + char *his_vendor; + char *his_release; + char my_auth_index; + IcePointer my_auth_state; + Bool must_authenticate; +} _IceProtoSetupToMeInfo; + +typedef struct { + Bool auth_active; + char my_auth_index; + IcePointer my_auth_state; +} _IceConnectToYouInfo; + +typedef struct { + int my_opcode; + int my_auth_count; + int *my_auth_indices; + Bool auth_active; + char my_auth_index; + IcePointer my_auth_state; +} _IceProtoSetupToYouInfo; + + +struct _IceConn { + + unsigned int io_ok : 1; /* did an IO error occur? */ + unsigned int swap : 1; /* do we need to swap on reads? */ + unsigned int waiting_for_byteorder : 1; /* waiting for a ByteOrder msg? */ + unsigned int skip_want_to_close : 1; /* avoid shutdown negotiation? */ + unsigned int want_to_close : 1; /* did we send a WantToClose? */ + unsigned int free_asap : 1; /* free as soon as possible */ + unsigned int unused1 : 2; /* future use */ + unsigned int unused2 : 8; /* future use */ + + IceConnectStatus connection_status; /* pending, accepted, rejected */ + + unsigned char my_ice_version_index; /* which version are we using? */ + + struct _XtransConnInfo *trans_conn; /* transport connection object */ + unsigned long send_sequence; /* Sequence # of last msg sent */ + unsigned long receive_sequence; /* Sequence # of last msg received */ + + char *connection_string; /* network connection string */ + char *vendor; /* other client's vendor */ + char *release; /* other client's release */ + + char *inbuf; /* Input buffer starting address */ + char *inbufptr; /* Input buffer index pointer */ + char *inbufmax; /* Input buffer maximum+1 address */ + + char *outbuf; /* Output buffer starting address */ + char *outbufptr; /* Output buffer index pointer */ + char *outbufmax; /* Output buffer maximum+1 address */ + + char *scratch; /* scratch buffer */ + unsigned long scratch_size; /* scratch size */ + + int dispatch_level; /* IceProcessMessages dispatch level */ + + IcePointer context; /* context associated with caller + of IceOpenConnection */ + + /* + * Before we read a message, the major opcode of the message must be + * mapped to our corresponding major opcode (the two clients can use + * different opcodes for the same protocol). In order to save space, + * we keep track of the mininum and maximum major opcodes used by the + * other client. To get the information on how to process this message, + * we do the following... + * + * processMsgInfo = iceConn->process_msg_info[ + * message->majorOpcode - iceConn->his_min_opcode] + * + * Note that the number of elements in the iceConn->process_msg_info + * array is always (iceConn->his_max_opcode - iceConn->his_min_opcode + 1). + * We check process_msg_info->in_use to see if the opcode is being used. + */ + + _IceProcessMsgInfo *process_msg_info; + char his_min_opcode; /* [1..255] */ + char his_max_opcode; /* [1..255] */ + + + /* + * Number of times this iceConn was returned in IceOpenConnection + * or IceAcceptConnection. + */ + + unsigned char open_ref_count; + + + /* + * Number of active protocols. + */ + + unsigned char proto_ref_count; + + + /* + * If this ICE connection was created with IceAcceptConnection, + * the listen_obj field is set to the listen object. Otherwise, + * the listen_obj field is NULL. + */ + + IceListenObj listen_obj; + + + + + /* + * We need to keep track of all the replies we're waiting for. + * Check the comments in process.c for how this works. + */ + + _IceSavedReplyWait *saved_reply_waits; + + + /* + * We keep track of all Pings sent from the client. When the Ping reply + * arrives, we remove it from the list. + */ + + _IcePingWait *ping_waits; + + + /* + * Some state for a client doing a Connection/Protocol Setup + */ + + _IceConnectToYouInfo *connect_to_you; + _IceProtoSetupToYouInfo *protosetup_to_you; + + + /* + * Some state for a client receiving a Connection/Protocol Setup + */ + + _IceConnectToMeInfo *connect_to_me; + _IceProtoSetupToMeInfo *protosetup_to_me; + +}; + +#endif /* _ICECONN_H_ */ diff --git a/include/X11/ICE/ICElib.h b/include/X11/ICE/ICElib.h new file mode 100644 index 0000000..402cbc8 --- /dev/null +++ b/include/X11/ICE/ICElib.h @@ -0,0 +1,431 @@ +/****************************************************************************** + + +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 _ICELIB_H_ +#define _ICELIB_H_ + +#include +#include + +#define Bool int +#define Status int +#define True 1 +#define False 0 + +typedef void *IcePointer; + +typedef enum { + IcePoAuthHaveReply, + IcePoAuthRejected, + IcePoAuthFailed, + IcePoAuthDoneCleanup +} IcePoAuthStatus; + +typedef enum { + IcePaAuthContinue, + IcePaAuthAccepted, + IcePaAuthRejected, + IcePaAuthFailed +} IcePaAuthStatus; + +typedef enum { + IceConnectPending, + IceConnectAccepted, + IceConnectRejected, + IceConnectIOError +} IceConnectStatus; + +typedef enum { + IceProtocolSetupSuccess, + IceProtocolSetupFailure, + IceProtocolSetupIOError, + IceProtocolAlreadyActive +} IceProtocolSetupStatus; + +typedef enum { + IceAcceptSuccess, + IceAcceptFailure, + IceAcceptBadMalloc +} IceAcceptStatus; + +typedef enum { + IceClosedNow, + IceClosedASAP, + IceConnectionInUse, + IceStartedShutdownNegotiation +} IceCloseStatus; + +typedef enum { + IceProcessMessagesSuccess, + IceProcessMessagesIOError, + IceProcessMessagesConnectionClosed +} IceProcessMessagesStatus; + +typedef struct { + unsigned long sequence_of_request; + int major_opcode_of_request; + int minor_opcode_of_request; + IcePointer reply; +} IceReplyWaitInfo; + +typedef struct _IceConn *IceConn; +typedef struct _IceListenObj *IceListenObj; + +typedef void (*IceWatchProc) ( + IceConn /* iceConn */, + IcePointer /* clientData */, + Bool /* opening */, + IcePointer * /* watchData */ +); + +typedef void (*IcePoProcessMsgProc) ( + IceConn /* iceConn */, + IcePointer /* clientData */, + int /* opcode */, + unsigned long /* length */, + Bool /* swap */, + IceReplyWaitInfo * /* replyWait */, + Bool * /* replyReadyRet */ +); + +typedef void (*IcePaProcessMsgProc) ( + IceConn /* iceConn */, + IcePointer /* clientData */, + int /* opcode */, + unsigned long /* length */, + Bool /* swap */ +); + +typedef struct { + int major_version; + int minor_version; + IcePoProcessMsgProc process_msg_proc; +} IcePoVersionRec; + +typedef struct { + int major_version; + int minor_version; + IcePaProcessMsgProc process_msg_proc; +} IcePaVersionRec; + +typedef IcePoAuthStatus (*IcePoAuthProc) ( + IceConn /* iceConn */, + IcePointer * /* authStatePtr */, + Bool /* cleanUp */, + Bool /* swap */, + int /* authDataLen */, + IcePointer /* authData */, + int * /* replyDataLenRet */, + IcePointer * /* replyDataRet */, + char ** /* errorStringRet */ +); + +typedef IcePaAuthStatus (*IcePaAuthProc) ( + IceConn /* iceConn */, + IcePointer * /* authStatePtr */, + Bool /* swap */, + int /* authDataLen */, + IcePointer /* authData */, + int * /* replyDataLenRet */, + IcePointer * /* replyDataRet */, + char ** /* errorStringRet */ +); + +typedef Bool (*IceHostBasedAuthProc) ( + char * /* hostName */ +); + +typedef Status (*IceProtocolSetupProc) ( + IceConn /* iceConn */, + int /* majorVersion */, + int /* minorVersion */, + char * /* vendor */, + char * /* release */, + IcePointer * /* clientDataRet */, + char ** /* failureReasonRet */ +); + +typedef void (*IceProtocolActivateProc) ( + IceConn /* iceConn */, + IcePointer /* clientData */ +); + +typedef void (*IceIOErrorProc) ( + IceConn /* iceConn */ +); + +typedef void (*IcePingReplyProc) ( + IceConn /* iceConn */, + IcePointer /* clientData */ +); + +typedef void (*IceErrorHandler) ( + IceConn /* iceConn */, + Bool /* swap */, + int /* offendingMinorOpcode */, + unsigned long /* offendingSequence */, + int /* errorClass */, + int /* severity */, + IcePointer /* values */ +); + +typedef void (*IceIOErrorHandler) ( + IceConn /* iceConn */ +); + + +/* + * Function prototypes + */ + +_XFUNCPROTOBEGIN + +extern int IceRegisterForProtocolSetup ( + const char * /* protocolName */, + const char * /* vendor */, + const char * /* release */, + int /* versionCount */, + IcePoVersionRec * /* versionRecs */, + int /* authCount */, + const char ** /* authNames */, + IcePoAuthProc * /* authProcs */, + IceIOErrorProc /* IOErrorProc */ +); + +extern int IceRegisterForProtocolReply ( + const char * /* protocolName */, + const char * /* vendor */, + const char * /* release */, + int /* versionCount */, + IcePaVersionRec * /* versionRecs */, + int /* authCount */, + const char ** /* authNames */, + IcePaAuthProc * /* authProcs */, + IceHostBasedAuthProc /* hostBasedAuthProc */, + IceProtocolSetupProc /* protocolSetupProc */, + IceProtocolActivateProc /* protocolActivateProc */, + IceIOErrorProc /* IOErrorProc */ +); + +extern IceConn IceOpenConnection ( + char * /* networkIdsList */, + IcePointer /* context */, + Bool /* mustAuthenticate */, + int /* majorOpcodeCheck */, + int /* errorLength */, + char * /* errorStringRet */ +); + +extern IcePointer IceGetConnectionContext ( + IceConn /* iceConn */ +); + +extern Status IceListenForConnections ( + int * /* countRet */, + IceListenObj ** /* listenObjsRet */, + int /* errorLength */, + char * /* errorStringRet */ +); + +extern Status IceListenForWellKnownConnections ( + char * /* port */, + int * /* countRet */, + IceListenObj ** /* listenObjsRet */, + int /* errorLength */, + char * /* errorStringRet */ +); + +extern int IceGetListenConnectionNumber ( + IceListenObj /* listenObj */ +); + +extern char *IceGetListenConnectionString ( + IceListenObj /* listenObj */ +); + +extern char *IceComposeNetworkIdList ( + int /* count */, + IceListenObj * /* listenObjs */ +); + +extern void IceFreeListenObjs ( + int /* count */, + IceListenObj * /* listenObjs */ +); + +extern void IceSetHostBasedAuthProc ( + IceListenObj /* listenObj */, + IceHostBasedAuthProc /* hostBasedAuthProc */ +); + +extern IceConn IceAcceptConnection ( + IceListenObj /* listenObj */, + IceAcceptStatus * /* statusRet */ +); + +extern void IceSetShutdownNegotiation ( + IceConn /* iceConn */, + Bool /* negotiate */ +); + +extern Bool IceCheckShutdownNegotiation ( + IceConn /* iceConn */ +); + +extern IceCloseStatus IceCloseConnection ( + IceConn /* iceConn */ +); + +extern Status IceAddConnectionWatch ( + IceWatchProc /* watchProc */, + IcePointer /* clientData */ +); + +extern void IceRemoveConnectionWatch ( + IceWatchProc /* watchProc */, + IcePointer /* clientData */ +); + +extern IceProtocolSetupStatus IceProtocolSetup ( + IceConn /* iceConn */, + int /* myOpcode */, + IcePointer /* clientData */, + Bool /* mustAuthenticate */, + int * /* majorVersionRet */, + int * /* minorVersionRet */, + char ** /* vendorRet */, + char ** /* releaseRet */, + int /* errorLength */, + char * /* errorStringRet */ +); + +extern Status IceProtocolShutdown ( + IceConn /* iceConn */, + int /* majorOpcode */ +); + +extern IceProcessMessagesStatus IceProcessMessages ( + IceConn /* iceConn */, + IceReplyWaitInfo * /* replyWait */, + Bool * /* replyReadyRet */ +); + +extern Status IcePing ( + IceConn /* iceConn */, + IcePingReplyProc /* pingReplyProc */, + IcePointer /* clientData */ +); + +extern char *IceAllocScratch ( + IceConn /* iceConn */, + unsigned long /* size */ +); + +extern int IceFlush ( + IceConn /* iceConn */ +); + +extern int IceGetOutBufSize ( + IceConn /* iceConn */ +); + +extern int IceGetInBufSize ( + IceConn /* iceConn */ +); + +extern IceConnectStatus IceConnectionStatus ( + IceConn /* iceConn */ +); + +extern char *IceVendor ( + IceConn /* iceConn */ +); + +extern char *IceRelease ( + IceConn /* iceConn */ +); + +extern int IceProtocolVersion ( + IceConn /* iceConn */ +); + +extern int IceProtocolRevision ( + IceConn /* iceConn */ +); + +extern int IceConnectionNumber ( + IceConn /* iceConn */ +); + +extern char *IceConnectionString ( + IceConn /* iceConn */ +); + +extern unsigned long IceLastSentSequenceNumber ( + IceConn /* iceConn */ +); + +extern unsigned long IceLastReceivedSequenceNumber ( + IceConn /* iceConn */ +); + +extern Bool IceSwapping ( + IceConn /* iceConn */ +); + +extern IceErrorHandler IceSetErrorHandler ( + IceErrorHandler /* handler */ +); + +extern IceIOErrorHandler IceSetIOErrorHandler ( + IceIOErrorHandler /* handler */ +); + +extern char *IceGetPeerName ( + IceConn /* iceConn */ +); + +/* + * Multithread Routines + */ + +extern Status IceInitThreads ( + void +); + +extern void IceAppLockConn ( + IceConn /* iceConn */ +); + +extern void IceAppUnlockConn ( + IceConn /* iceConn */ +); + +_XFUNCPROTOEND + +#endif /* _ICELIB_H_ */ diff --git a/include/X11/ICE/ICEmsg.h b/include/X11/ICE/ICEmsg.h new file mode 100644 index 0000000..8ca3e5f --- /dev/null +++ b/include/X11/ICE/ICEmsg.h @@ -0,0 +1,316 @@ +/****************************************************************************** + + +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 _ICEMSG_H_ +#define _ICEMSG_H_ + +#include + +#include + +_XFUNCPROTOBEGIN + +/* + * Function prototypes for internal ICElib functions + */ + +extern Status _IceRead ( + IceConn /* iceConn */, + unsigned long /* nbytes */, + char * /* ptr */ +); + +extern void _IceReadSkip ( + IceConn /* iceConn */, + unsigned long /* nbytes */ +); + +extern void _IceWrite ( + IceConn /* iceConn */, + unsigned long /* nbytes */, + char * /* ptr */ +); + + +extern void _IceErrorBadMinor ( + IceConn /* iceConn */, + int /* majorOpcode */, + int /* offendingMinor */, + int /* severity */ +); + +extern void _IceErrorBadState ( + IceConn /* iceConn */, + int /* majorOpcode */, + int /* offendingMinor */, + int /* severity */ +); + +extern void _IceErrorBadLength ( + IceConn /* iceConn */, + int /* majorOpcode */, + int /* offendingMinor */, + int /* severity */ +); + +extern void _IceErrorBadValue ( + IceConn /* iceConn */, + int /* majorOpcode */, + int /* offendingMinor */, + int /* offset */, + int /* length */, + IcePointer /* value */ +); + +extern IcePoAuthStatus _IcePoMagicCookie1Proc ( + IceConn /* iceConn */, + IcePointer * /* authStatePtr */, + Bool /* cleanUp */, + Bool /* swap */, + int /* authDataLen */, + IcePointer /* authData */, + int * /* replyDataLenRet */, + IcePointer * /* replyDataRet */, + char ** /* errorStringRet */ +); + +extern IcePaAuthStatus _IcePaMagicCookie1Proc ( + IceConn /* iceConn */, + IcePointer * /* authStatePtr */, + Bool /* swap */, + int /* authDataLen */, + IcePointer /* authData */, + int * /* replyDataLenRet */, + IcePointer * /* replyDataRet */, + char ** /* errorStringRet */ +); + + +/* + * Macro to check if IO operations are valid on an ICE connection. + */ + +#define IceValidIO(_iceConn) _iceConn->io_ok + + +/* + * Macros for writing messages. + */ + +#define IceGetHeader(_iceConn, _major, _minor, _headerSize, _msgType, _pMsg) \ + if ((_iceConn->outbufptr + _headerSize) > _iceConn->outbufmax) \ + IceFlush (_iceConn); \ + _pMsg = (_msgType *) _iceConn->outbufptr; \ + _pMsg->majorOpcode = _major; \ + _pMsg->minorOpcode = _minor; \ + _pMsg->length = (_headerSize - SIZEOF (iceMsg)) >> 3; \ + _iceConn->outbufptr += _headerSize; \ + _iceConn->send_sequence++ + +#define IceGetHeaderExtra(_iceConn, _major, _minor, _headerSize, _extra, _msgType, _pMsg, _pData) \ + if ((_iceConn->outbufptr + \ + _headerSize + ((_extra) << 3)) > _iceConn->outbufmax) \ + IceFlush (_iceConn); \ + _pMsg = (_msgType *) _iceConn->outbufptr; \ + if ((_iceConn->outbufptr + \ + _headerSize + ((_extra) << 3)) <= _iceConn->outbufmax) \ + _pData = (char *) _pMsg + _headerSize; \ + else \ + _pData = NULL; \ + _pMsg->majorOpcode = _major; \ + _pMsg->minorOpcode = _minor; \ + _pMsg->length = ((_headerSize - SIZEOF (iceMsg)) >> 3) + (_extra); \ + _iceConn->outbufptr += (_headerSize + ((_extra) << 3)); \ + _iceConn->send_sequence++ + +#define IceSimpleMessage(_iceConn, _major, _minor) \ +{ \ + iceMsg *_pMsg; \ + IceGetHeader (_iceConn, _major, _minor, SIZEOF (iceMsg), iceMsg, _pMsg); \ +} + +#define IceErrorHeader(_iceConn, _offendingMajorOpcode, _offendingMinorOpcode, _offendingSequenceNum, _severity, _errorClass, _dataLength) \ +{ \ + iceErrorMsg *_pMsg; \ +\ + IceGetHeader (_iceConn, _offendingMajorOpcode, ICE_Error, \ + SIZEOF (iceErrorMsg), iceErrorMsg, _pMsg); \ + _pMsg->length += (_dataLength); \ + _pMsg->offendingMinorOpcode = _offendingMinorOpcode; \ + _pMsg->severity = _severity; \ + _pMsg->offendingSequenceNum = _offendingSequenceNum; \ + _pMsg->errorClass = _errorClass; \ +} + + +/* + * Write data into the ICE output buffer. + */ + +#define IceWriteData(_iceConn, _bytes, _data) \ +{ \ + if ((_iceConn->outbufptr + (_bytes)) > _iceConn->outbufmax) \ + { \ + IceFlush (_iceConn); \ + _IceWrite (_iceConn, (unsigned long) (_bytes), _data); \ + } \ + else \ + { \ + memcpy (_iceConn->outbufptr, _data, _bytes); \ + _iceConn->outbufptr += (_bytes); \ + } \ +} + +#ifndef WORD64 + +#define IceWriteData16(_iceConn, _bytes, _data) \ + IceWriteData (_iceConn, _bytes, (char *) _data) + +#define IceWriteData32(_iceConn, _bytes, _data) \ + IceWriteData (_iceConn, _bytes, (char *) _data) + +#else /* WORD64 */ + +/* IceWriteData16 and IceWriteData32 defined in misc.c for WORD64 */ + +#endif /* WORD64 */ + + +/* + * The IceSendData macro bypasses copying the data to the + * ICE connection buffer and sends the data directly. If necessary, + * the ICE connection buffer is first flushed. + */ + +#define IceSendData(_iceConn, _bytes, _data) \ +{ \ + if (_iceConn->outbufptr > _iceConn->outbuf) \ + IceFlush (_iceConn); \ + _IceWrite (_iceConn, (unsigned long) (_bytes), _data); \ +} + + +/* + * Write pad bytes. Used to force 32 or 64 bit alignment. + * A maximum of 7 pad bytes can be specified. + */ + +#define IceWritePad(_iceConn, _bytes) \ +{ \ + if ((_iceConn->outbufptr + (_bytes)) > _iceConn->outbufmax) \ + { \ + char _dummy[7] = { 0 }; \ + IceFlush (_iceConn); \ + _IceWrite (_iceConn, (unsigned long) (_bytes), _dummy); \ + } \ + else \ + { \ + _iceConn->outbufptr += (_bytes); \ + } \ +} + + +/* + * Macros for reading messages. + */ + +#define IceReadCompleteMessage(_iceConn, _headerSize, _msgType, _pMsg, _pData)\ +{ \ + unsigned long _bytes; \ + IceReadMessageHeader (_iceConn, _headerSize, _msgType, _pMsg); \ + _bytes = (_pMsg->length << 3) - (_headerSize - SIZEOF (iceMsg)); \ + if ((_iceConn->inbufmax - _iceConn->inbufptr) >= _bytes) \ + { \ + _IceRead (_iceConn, _bytes, _iceConn->inbufptr); \ + _pData = _iceConn->inbufptr; \ + _iceConn->inbufptr += _bytes; \ + } \ + else \ + { \ + _pData = (char *) malloc ((unsigned) _bytes); \ + if (_pData) \ + _IceRead (_iceConn, _bytes, _pData); \ + else \ + _IceReadSkip (_iceConn, _bytes); \ + } \ +} + +#define IceDisposeCompleteMessage(_iceConn, _pData) \ + if ((char *) _pData < _iceConn->inbuf || \ + (char *) _pData >= _iceConn->inbufmax) \ + free ((char *) _pData); + + +#define IceReadSimpleMessage(_iceConn, _msgType, _pMsg) \ + _pMsg = (_msgType *) (_iceConn->inbuf); + +#define IceReadMessageHeader(_iceConn, _headerSize, _msgType, _pMsg) \ +{ \ + _IceRead (_iceConn, \ + (unsigned long) (_headerSize - SIZEOF (iceMsg)), \ + _iceConn->inbufptr); \ + _pMsg = (_msgType *) (_iceConn->inbuf); \ + _iceConn->inbufptr += (_headerSize - SIZEOF (iceMsg)); \ +} + +#define IceReadData(_iceConn, _bytes, _pData) \ + _IceRead (_iceConn, (unsigned long) (_bytes), (char *) _pData); \ + +#ifndef WORD64 + +#define IceReadData16(_iceConn, _swap, _bytes, _pData) \ +{ \ + _IceRead (_iceConn, (unsigned long) (_bytes), (char *) _pData); \ +} + +#define IceReadData32(_iceConn, _swap, _bytes, _pData) \ +{ \ + _IceRead (_iceConn, (unsigned long) (_bytes), (char *) _pData); \ +} + +#else /* WORD64 */ + +/* IceReadData16 and IceReadData32 defined in misc.c for WORD64 */ + +#endif /* WORD64 */ + + +/* + * Read pad bytes (for 32 or 64 bit alignment). + * A maxium of 7 pad bytes can be specified. + */ + +#define IceReadPad(_iceConn, _bytes) \ +{ \ + char _dummy[7]; \ + _IceRead (_iceConn, (unsigned long) (_bytes), _dummy); \ +} + +_XFUNCPROTOEND + +#endif /* _ICEMSG_H_ */ diff --git a/include/X11/ICE/ICEproto.h b/include/X11/ICE/ICEproto.h new file mode 100644 index 0000000..1fcbe6b --- /dev/null +++ b/include/X11/ICE/ICEproto.h @@ -0,0 +1,175 @@ +/****************************************************************************** + + +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 _ICEPROTO_H_ +#define _ICEPROTO_H_ + +#include + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 data[2]; + CARD32 length B32; +} iceMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD16 errorClass B16; + CARD32 length B32; + CARD8 offendingMinorOpcode; + CARD8 severity; + CARD16 unused B16; + CARD32 offendingSequenceNum B32; + /* n varying values */ + /* p p = pad (n, 8) */ +} iceErrorMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 byteOrder; + CARD8 unused; + CARD32 length B32; +} iceByteOrderMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 versionCount; + CARD8 authCount; + CARD32 length B32; + CARD8 mustAuthenticate; + CARD8 unused[7]; + /* i STRING vendor */ + /* j STRING release */ + /* k LIST of STRING authentication-protocol-names */ + /* m LIST of VERSION version-list */ + /* p p = pad (i+j+k+m, 8) */ +} iceConnectionSetupMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 authIndex; + CARD8 unused1; + CARD32 length B32; + CARD16 authDataLength B16; + CARD8 unused2[6]; + /* n varying data */ + /* p p = pad (n, 8) */ +} iceAuthRequiredMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 unused1[2]; + CARD32 length B32; + CARD16 authDataLength B16; + CARD8 unused2[6]; + /* n varying data */ + /* p p = pad (n, 8) */ +} iceAuthReplyMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 unused1[2]; + CARD32 length B32; + CARD16 authDataLength B16; + CARD8 unused2[6]; + /* n varying data */ + /* p p = pad (n, 8) */ +} iceAuthNextPhaseMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 versionIndex; + CARD8 unused; + CARD32 length B32; + /* i STRING vendor */ + /* j STRING release */ + /* p p = pad (i+j, 8) */ +} iceConnectionReplyMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 protocolOpcode; + CARD8 mustAuthenticate; + CARD32 length B32; + CARD8 versionCount; + CARD8 authCount; + CARD8 unused[6]; + /* i STRING protocol-name */ + /* j STRING vendor */ + /* k STRING release */ + /* m LIST of STRING authentication-protocol-names */ + /* n LIST of VERSION version-list */ + /* p p = pad (i+j+k+m+n, 8) */ +} iceProtocolSetupMsg; + +typedef struct { + CARD8 majorOpcode; + CARD8 minorOpcode; + CARD8 versionIndex; + CARD8 protocolOpcode; + CARD32 length B32; + /* i STRING vendor */ + /* j STRING release */ + /* p p = pad (i+j, 8) */ +} iceProtocolReplyMsg; + +typedef iceMsg icePingMsg; +typedef iceMsg icePingReplyMsg; +typedef iceMsg iceWantToCloseMsg; +typedef iceMsg iceNoCloseMsg; + + +/* + * SIZEOF values. These better be multiples of 8. + */ + +#define sz_iceMsg 8 +#define sz_iceErrorMsg 16 +#define sz_iceByteOrderMsg 8 +#define sz_iceConnectionSetupMsg 16 +#define sz_iceAuthRequiredMsg 16 +#define sz_iceAuthReplyMsg 16 +#define sz_iceAuthNextPhaseMsg 16 +#define sz_iceConnectionReplyMsg 8 +#define sz_iceProtocolSetupMsg 16 +#define sz_iceProtocolReplyMsg 8 +#define sz_icePingMsg 8 +#define sz_icePingReplyMsg 8 +#define sz_iceWantToCloseMsg 8 +#define sz_iceNoCloseMsg 8 + +#endif /* _ICEPROTO_H_ */ diff --git a/include/X11/ICE/ICEutil.h b/include/X11/ICE/ICEutil.h new file mode 100644 index 0000000..9c6b12f --- /dev/null +++ b/include/X11/ICE/ICEutil.h @@ -0,0 +1,124 @@ +/****************************************************************************** + + +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 _ICEUTIL_H_ +#define _ICEUTIL_H_ + +#include + +#include + +_XFUNCPROTOBEGIN + +/* + * Data structure for entry in ICE authority file + */ + +typedef struct { + char *protocol_name; + unsigned short protocol_data_length; + char *protocol_data; + char *network_id; + char *auth_name; + unsigned short auth_data_length; + char *auth_data; +} IceAuthFileEntry; + + +/* + * Authentication data maintained in memory. + */ + +typedef struct { + char *protocol_name; + char *network_id; + char *auth_name; + unsigned short auth_data_length; + char *auth_data; +} IceAuthDataEntry; + + +/* + * Return values from IceLockAuthFile + */ + +#define IceAuthLockSuccess 0 /* lock succeeded */ +#define IceAuthLockError 1 /* lock unexpectely failed, check errno */ +#define IceAuthLockTimeout 2 /* lock failed, timeouts expired */ + + +/* + * Function Prototypes + */ + +extern char *IceAuthFileName ( + void +); + +extern int IceLockAuthFile ( + char * /* file_name */, + int /* retries */, + int /* timeout */, + long /* dead */ +); + +extern void IceUnlockAuthFile ( + char * /* file_name */ +); + +extern IceAuthFileEntry *IceReadAuthFileEntry ( + FILE * /* auth_file */ +); + +extern void IceFreeAuthFileEntry ( + IceAuthFileEntry * /* auth */ +); + +extern Status IceWriteAuthFileEntry ( + FILE * /* auth_file */, + IceAuthFileEntry * /* auth */ +); + +extern IceAuthFileEntry *IceGetAuthFileEntry ( + const char * /* protocol_name */, + const char * /* network_id */, + const char * /* auth_name */ +); + +extern char *IceGenerateMagicCookie ( + int /* len */ +); + +extern void IceSetPaAuthData ( + int /* numEntries */, + IceAuthDataEntry * /* entries */ +); + +_XFUNCPROTOEND + +#endif /* _ICEUTIL_H_ */ diff --git a/packaging/libICE.spec b/packaging/libICE.spec new file mode 100644 index 0000000..8362837 --- /dev/null +++ b/packaging/libICE.spec @@ -0,0 +1,65 @@ +Summary: X.Org X11 ICE runtime library +Name: libICE +Version: 1.0.8 +Release: 1 +License: MIT +Group: System Environment/Libraries +URL: http://www.x.org + +Source0: %{name}-%{version}.tar.gz + +BuildRequires: pkgconfig +BuildRequires: pkgconfig(xproto) +BuildRequires: pkgconfig(xorg-macros) +BuildRequires: xorg-x11-xtrans-devel >= 1.0.3-5 + +%description +The X.Org X11 ICE (Inter-Client Exchange) runtime library. + +%package devel +Summary: X.Org X11 ICE development package +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} + +%description devel +The X.Org X11 ICE (Inter-Client Exchange) development package. + +%prep +%setup -q + +%build +%reconfigure --disable-static \ + LDFLAGS="${LDFLAGS} -Wl,--hash-style=both -Wl,--as-needed" +make %{?jobs:-j%jobs} + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p %{buildroot}/usr/share/license +cp -af COPYING %{buildroot}/usr/share/license/%{name} + +make install DESTDIR=$RPM_BUILD_ROOT + +# We intentionally don't ship *.la files +rm -f $RPM_BUILD_ROOT%{_libdir}/*.la + +%remove_docs + +%clean +rm -rf $RPM_BUILD_ROOT + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%files +%defattr(-,root,root,-) +/usr/share/license/%{name} +#%doc AUTHORS COPYING ChangeLog +%{_libdir}/libICE.so.6 +%{_libdir}/libICE.so.6.3.0 + +%files devel +%defattr(-,root,root,-) +#%{_docdir}/%{name} +%{_includedir}/X11/ICE +%{_libdir}/libICE.so +%{_libdir}/pkgconfig/ice.pc diff --git a/specs/Makefile.am b/specs/Makefile.am new file mode 100644 index 0000000..2937cb7 --- /dev/null +++ b/specs/Makefile.am @@ -0,0 +1,13 @@ + +if ENABLE_SPECS + +# Main DocBook/XML files (DOCTYPE book) +docbook = ice.xml + +# The location where the DocBook/XML files and their generated formats are installed +shelfdir = $(docdir) + +# Generate DocBook/XML output formats with or without stylesheets +include $(top_srcdir)/docbook.am + +endif ENABLE_SPECS diff --git a/specs/ice.xml b/specs/ice.xml new file mode 100644 index 0000000..439c2f6 --- /dev/null +++ b/specs/ice.xml @@ -0,0 +1,2601 @@ + + %defs; +]> + + + + + + + Inter-Client Exchange (ICE) Protocol + X Consortium Standard + X Version 11, Release &fullrelvers; + + + RobertScheifler + X Consortium + + + JordanBrown + Quarterdeck Office Systems + + + Version 1.1 + + 19931994 + X Consortium + + + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +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 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. + +X Window System is a trademark of The Open Group. + + + + +There are numerous possible protocols that can be used for communication +among clients. They have many similarities and common needs, including +authentication, version negotiation, data typing, and connection management. The Inter-Client Exchange (ICE) protocol +is intended to provide a framework for building such protocols. Using +ICE reduces the complexity of designing new protocols and +allows the sharing of many aspects of the implementation. + + + + + +Purpose and Goals + + +In discussing a variety of protocols -- existing, under development, and +hypothetical -- it was noted that they have many elements in common. Most +protocols need mechanisms for authentication, for +version negotiation, +and for setting up and taking down connections. There are also +cases where the same two parties need to talk to each other using multiple +protocols. For example, an embedding relationship between two parties is +likely to require the simultaneous use of session management, data transfer, +focus negotiation, and command notification protocols. While these are +logically separate protocols, it is desirable for them to share as many +pieces of implementation as possible. + +The + +Inter-Client Exchange + +(ICE) protocol provides a generic framework for building protocols on top of +reliable, byte-stream transport connections. It provides basic mechanisms +for setting up and shutting down connections, for performing authentication, +for negotiating +versions, +and for reporting errors. The +protocols running within an ICE connection are referred to here as +subprotocols. +ICE provides facilities for each subprotocol to do its own version +negotiation, authentication, and error reporting. In addition, if two +parties are communicating using several different subprotocols, ICE will +allow them to share the same transport layer connection. + + + + +Overview of the Protocol + + +Through some mechanism outside ICE, two parties make themselves known to +each other and agree that they would like to communicate using an ICE +subprotocol. ICE assumes that this negotation includes some notion by which +the parties will decide which is the \*Qoriginating\*U party and which is +the \*Qanswering\*U party. The negotiation will also need to provide the +originating party with a name or address of the answering party. Examples +of mechanisms by which parties can make themselves known to each other are +the X selection mechanism, environment +variables, and shared files. + +The originating party first determines whether there is an existing ICE +connection between the two parties. If there is, it can re-use the existing +connection and move directly to the setup of the subprotocol. If no ICE +connection exists, the originating party will open a transport connection to +the answering party and will start ICE connection setup. + +The ICE connection setup dialog consists of three major parts: byte order +exchange, authentication, and connection information exchange. The first +message in each direction is a +ByteOrder +message telling which byte order will be used by the sending party in +messages that it sends. After that, the originating party sends a +ConnectionSetup +message giving information about itself (vendor name and release number) and +giving a list of ICE version numbers it is capable of supporting and a list +of authentication schemes it is willing to accept. Authentication is +optional. If no authentication is required, the answering party responds +with a +ConnectionReply +message giving information about itself, and the connection setup is complete. + +If the connection setup is to be authenticated, the answering party will +respond with an +AuthenticationRequired +message instead of a +ConnectionReply +message. The parties then exchange +AuthenticationReply +and +AuthenticationNextPhase +messages until authentication is complete, at which time the answering party +finally sends its +ConnectionReply +message. + +Once an ICE connection is established (or an existing connection reused), +the originating party starts subprotocol negotiation by sending a +ProtocolSetup +message. This message gives the name of the subprotocol that the parties +have agreed to use, along with the ICE major opcode that the originating +party has assigned to that subprotocol. Authentication can also occur for +the subprotocol, independently of authentication for the connection. +Subprotocol authentication is optional. If there is no subprotocol +authentication, the answering party responds with a +ProtocolReply +message, giving the ICE major opcode that it has assigned +for the subprotocol. + +Subprotocols are authenticated independently of each other, because they may +have differing security requirements. If there is authentication for this +particular subprotocol, it takes place before the answering party emits the +ProtocolReply +message, and it uses the +AuthenticationRequired +AuthenticationReply +and +AuthenticationNextPhase +messages, just as for the connection authentication. Only when subprotocol +authentication is complete does the answering party send its +ProtocolReply +message. + +When a subprotocol has been set up and authenticated, the two parties can +communicate using messages defined by the subprotocol. Each message has two +opcodes: a major opcode and a minor opcode. Each party will send messages +using the major opcode it has assigned in its +ProtocolSetup +or +ProtocolReply +message. These opcodes will, in general, not be the same. For a particular +subprotocol, each party will need to keep track of two major opcodes: the +major opcode it uses when it sends messages, and the major opcode it expects +to see in messages it receives. The minor opcode values and semantics are +defined by each individual subprotocol. + +Each subprotocol will have one or more messages whose semantics are that the +subprotocol is to be shut down. Whether this is done unilaterally or is +performed through negotiation is defined by each subprotocol. Once a +subprotocol is shut down, its major opcodes are removed from +use; no further messages on this subprotocol should be sent until the +opcode is reestablished with +ProtocolSetup + + +ICE has a facility to negotiate the closing of the connection when there are +no longer any active subprotocols. When either party decides that no +subprotocols are active, it can send a +WantToClose +message. If the other party agrees to close the connection, it can simply +do so. If the other party wants to keep the connection open, it can +indicate its desire by replying with a +NoClose +message. + + +It should be noted that the party that initiates the connection isn't +necessarily the same as the one that initiates setting up a subprotocol. +For example, suppose party A connects to party B. Party A will issue the +ConnectionSetup +message and party B will respond with a +ConnectionReply +message. (The authentication steps are omitted here for brevity.) +Typically, party A will also issue the +ProtocolSetup +message and expect a +ProtocolReply +from party B. Once the connection is established, however, either party may +initiate the negotiation of a subprotocol. Continuing this example, party B +may decide that it needs to set up a subprotocol for communication with +party A. Party B would issue the +ProtocolSetup +message and expect a +ProtocolReply +from party A. + + + + +Data Types + +ICE messages contain several types of data. Byte order is negotiated in +the initial connection messages; in general data is sent in the sender's +byte order and the receiver is required to swap it appropriately. +In order to support 64-bit machines, ICE messages +are padded to multiples of 8 bytes. All messages are designed so that +fields are \*Qnaturally\*U aligned on 16-, 32-, and 64-bit boundaries. +The following formula gives the number of bytes necessary +to pad E bytes to the next multiple of +b: + + +pad(E, b) = (b - (E mod b)) mod b + + + +Primitive Types + + + + + + + + + Type Name + Description + + + + + CARD8 + 8-bit unsigned integer + + + CARD16 + 16-bit unsigned integer + + + CARD32 + 32-bit unsigned integer + + + BOOL + False +or +True + + + LPCE + A character from the X Portable Character Set in Latin Portable Character +Encoding + + + + + + + + +Complex Types + + + + + + + + + Type Name + Type + + + + + VERSION + [Major, minor: CARD16] + + + STRING + LISTofLPCE + + + + + + +LISTof<type> denotes a counted collection of <type>. The exact encoding +varies depending on the context; see the encoding section. + + + + +Message Format + +All ICE messages include the following information: + + + + + + + + + Field Type + Description + + + + + CARD8 + protocol major opcode + + + CARD8 + protocol minor opcode + + + CARD32 + length of remaining data in 8-byte units + + + + + + +The fields are as follows: + + + + Protocol major opcode + + +This specifies what subprotocol the message is intended for. Major opcode +0 is reserved for ICE control messages. The major opcodes of other +subprotocols are dynamically assigned and exchanged at protocol +negotiation time. + + + + + Protocol minor opcode + + +This specifies what protocol-specific operation is to be performed. +Minor opcode 0 is reserved for Errors; other values are protocol-specific. + + + + + Length of data in 8-byte units + + +This specifies the length of the information following the first 8 bytes. +Each message-type has a different format, and will need to be separately +length-checked against this value. As every data item has either an +explicit length, or an implicit length, this can be easily accomplished. +Messages that have too little or too much data indicate a serious +protocol failure, and should result in a BadLength +error. + + + + + + + + + +Overall Protocol Description + + +Every message sent in a given direction has an implicit sequence number, +starting with 1. Sequence numbers are global to the connection; independent +sequence numbers are not maintained for each protocol. + +Messages of a given major-opcode (i.e., of a given protocol) must be +responded to (if a response is called for) in order by the receiving party. +Messages from different protocols can be responded to in arbitrary order. + +Minor opcode 0 in every protocol is for reporting errors. At most one error +is generated per request. If more than one error condition is encountered +in processing a request, the choice of which error is returned is +implementation-dependent. + + +Error + + + offending-minor-opcode: + + CARD8 + + + + severity: + + +{CanContinue, +FatalToProtocol +FatalToConnection + + + + + sequence-number: + + CARD32 + + + + class: + + CARD16 + + + + value(s): + + <dependent on major/minor opcode and class> + + + + + +This message is sent to report an error in response to a message +from any protocol. The Error message +exists in all protocol major-opcode spaces; it +is minor-opcode zero in every protocol. The minor opcode of the +message that caused the error is reported, as well as the sequence +number of that message. +The severity indicates the sender's behavior following +the identification of the error. CanContinue +indicates the sender is willing to accept additional messages for this +protocol. FatalToProcotol +indicates the sender is unwilling to accept further messages for this +protocol but that messages for other protocols may be accepted. +FatalToConnection +indicates the sender is unwilling to accept any further +messages for any protocols on the connection. The sender +is required to conform to specified severity conditions +for generic and ICE (major opcode 0) errors; see + + +. +The class defines the generic class of +error. Classes are specified separately for each protocol (numeric +values can mean different things in different protocols). The error +values, if any, and their types vary with the specific error class +for the protocol. + + + + +ICE Control Subprotocol -- Major Opcode 0 + + +Each of the ICE control opcodes is described below. +Most of the messages have additional information included beyond the +description above. The additional information is appended to the message +header and the length field is computed accordingly. + + + +In the following message descriptions, \*QExpected errors\*U indicates +errors that may occur in the normal course of events. Other errors +(in particular +BadMajor +BadMinor +BadState +BadLength +BadValue +ProtocolDuplicate and +MajorOpcodeDuplicate +might occur, but generally indicate a serious implementation failure on +the part of the errant peer. + +ByteOrder + + + + byte-order: + + +{MSBfirst, +LSBfirst + + + + + + +Both parties must send this message before sending any other, +including errors. This message specifies the byte order that +will be used on subsequent messages sent by this party. + + + + +Note: If the receiver detects an error in this message, +it must be sure to send its own +ByteOrder message before sending the +Error. + + + +ConnectionSetup + + + + versions: + + LISTofVERSION + + + + must-authenticate: + + BOOL + + + + authentication-protocol-names: + + LISTofSTRING + + + + vendor: + + STRING + + + + release: + + STRING + + + + Responses: + + +ConnectionReply, +AuthenticationRequired (See note) + + + + + Expected errors: + + +NoVersion, +SetupFailed, +NoAuthentication, +AuthenticationRejected, +AuthenticationFailed + + + + + + +The party that initiates the connection (the one that does the +"connect()") must send this message as the second message (after +ByteOrder on startup. + + + +Versions gives a list, in decreasing order of preference, of the +protocol versions this party is capable of speaking. This document +specifies major version 1, minor version 0. + + + +If must-authenticate is True the initiating +party demands authentication; the accepting party +must pick an authentication scheme +and use it. In this case, the only valid response is +AuthenticationRequired + + + +If must-authenticate is False the accepting +party may choose an authentication mechanism, use a host-address-based +authentication scheme, or skip authentication. When must-authenticate +is False ConnectionReply and +AuthenticationRequired are both valid responses. +If a host-address-based authentication scheme is used, +AuthenticationRejected and +AuthenticationFailed errors are possible. + + + +Authentication-protocol-names specifies a (possibly null, if +must-authenticate is False +list of authentication protocols the party is willing to perform. If +must-authenticate is True +presumably the party will offer only authentication mechanisms +allowing mutual authentication. + + + +Vendor gives the name of the vendor of this ICE implementation. + + + +Release gives the release identifier of this ICE implementation. + + +AuthenticationRequired + + + + authentication-protocol-index: + + CARD8 + + + + data: + + <specific to authentication protocol> + + + + Response: + + AuthenticationReply + + + + Expected errors: + + +AuthenticationRejected, +AuthenticationFailed + + + + + + +This message is sent in response to a ConnectionSetup +or ProtocolSetup +message to specify that authentication is to be done and what +authentication mechanism is to be used. + + + +The authentication protocol is specified by a 0-based index into the list +of names given in the ConnectionSetup or +ProtocolSetup +Any protocol-specific data that might be required is also sent. + + + +AuthenticationReply + + + data: + + <specific to authentication protocol> + + + + Responses: + + +AuthenticationNextPhase, +ConnectionReply, +ProtocolReply + + + + + Expected errors: + + +AuthenticationRejected, +AuthenticationFailed, +SetupFailed + + + + + + +This message is sent in response to an +AuthenticationRequired or +AuthenticationNextPhase message, to +supply authentication data as defined by the authentication protocol +being used. + + + +Note that this message is sent by the party that initiated the current +negotiation -- the party that sent the +ConnectionSetup or +ProtocolSetup message. + + + +AuthenticationNextPhase +indicates that more is to be done to complete the authentication. +If the authentication is complete, +ConnectionReply +is appropriate if the current authentication handshake is the result of a +ConnectionSetup and a +ProtocolReply +is appropriate if it is the result of a +ProtocolSetup. + + +AuthenticationNextPhase + + + + data: + + <specific to authentication protocol> + + + + Response: + + AuthenticationReply + + + + Expected errors: + + +AuthenticationRejected, +AuthenticationFailed + + + + + + +This message is sent in response to an +AuthenticationReply +message, to supply authentication data as defined by the authentication +protocol being used. + + +ConnectionReply + + + version-index: + + CARD8 + + + + vendor: + + STRING + + + + release: + + STRING + + + + + +This message is sent in response to a +ConnectionSetup or +AuthenticationReply +message to indicate that the authentication handshake is complete. + + + +Version-index gives a 0-based index into the list of versions offered in +the ConnectionSetup message; it specifies the +version of the ICE protocol that both parties +should speak for the duration of the connection. + + +Vendor gives the name of the vendor of this ICE implementation. + + +Release gives the release identifier of this ICE implementation. + + +ProtocolSetup + + + + protocol-name: + + STRING + + + + major-opcode: + + CARD8 + + + + versions: + + LISTofVERSION + + + + vendor: + + STRING + + + + release: + + STRING + + + + must-authenticate: + + BOOL + + + + authentication-protocol-names: + + LISTofSTRING + + + + Responses: + + +AuthenticationRequired, +ProtocolReply + + + + + Expected errors: + + +UnknownProtocol, +NoVersion, +SetupFailed, +NoAuthentication, +AuthenticationRejected, +AuthenticationFailed + + + + + + +This message is used to initiate negotiation of a protocol and +establish any authentication specific to it. + + + +Protocol-name gives the name of the protocol the party wishes +to speak. + + + +Major-opcode gives the opcode that the party will use in messages +it sends. + + + +Versions gives a list of version numbers, in decreasing order of +preference, that the party is willing to speak. + + + +Vendor and release are identification strings with semantics defined +by the specific protocol being negotiated. + + + +If must-authenticate is True, +the initiating party demands authentication; the accepting party +must pick an authentication scheme +and use it. In this case, the only valid response is +AuthenticationRequired + + + +If must-authenticate is False, +the accepting party may choose an authentication mechanism, use a +host-address-based authentication scheme, or skip authentication. +When must-authenticate is False, +ProtocolReply and +AuthenticationRequired +are both valid responses. If a host-address-based authentication +scheme is used, AuthenticationRejected and +AuthenticationFailed errors are possible. + + + +Authentication-protocol-names specifies a (possibly null, if +must-authenticate is False +list of authentication protocols the party is willing to perform. If +must-authenticate is True +presumably the party will offer only authentication mechanisms +allowing mutual authentication. + + +ProtocolReply + + + major-opcode: + + CARD8 + + + + version-index: + + CARD8 + + + + vendor: + + STRING + + + + release: + + STRING + + + + + +This message is sent in response to a ProtocolSetup +or AuthenticationReply +message to indicate that the authentication handshake is complete. + + + +Major-opcode gives the opcode that this party will use in +messages that it sends. + + + +Version-index gives a 0-based index into the list of versions offered in the +ProtocolSetup message; it specifies the version +of the protocol that both parties should speak for the duration of +the connection. + + + +Vendor and release are identification strings with semantics defined +by the specific protocol being negotiated. + + +Ping + + + Response: + + PingReply + + + + + +This message is used to test if the connection is still functioning. + + +PingReply + + +This message is sent in response to a Ping +message, indicating that the connection is still functioning. + + +WantToClose + + + Responses: + + +WantToClose, +NoClose, +ProtocolSetup + + + + + + + +This message is used to initiate a possible close of the connection. +The sending party has noticed that, as a result of mechanisms specific +to each protocol, there are no active protocols left. +There are four possible scenarios arising from this request: + + + + + +The receiving side noticed too, and has already sent a +WantToClose On receiving a +WantToClose while already attempting to +shut down, each party should simply close the connection. + + + + +The receiving side hasn't noticed, but agrees. It closes the connection. + + + + +The receiving side has a ProtocolSetup +"in flight," in which case it is to ignore +WantToClose and the party sending +WantToClose is to abandon the shutdown attempt +when it receives the ProtocolSetup + + + + +The receiving side wants the connection kept open for some +reason not specified by the ICE protocol, in which case it +sends NoClose + + + + + +See the state transition diagram for additional information. + + +NoClose + + +This message is sent in response to a WantToClose +message to indicate that the responding party does not want the +connection closed at this time. The receiving party should not close the +connection. Either party may again initiate +WantToClose at some future time. + + + +Generic Error Classes + + +These errors should be used by all protocols, as applicable. +For ICE (major opcode 0), FatalToProtocol +should be interpreted as FatalToConnection. + + +BadMinor + + + + offending-minor-opcode: + + <any> + + + + severity: + + +FatalToProtocol or +CanContinue +(protocol's discretion) + + + + + values: + + (none) + + + + + +Received a message with an unknown minor opcode. + + +BadState + + + offending-minor-opcode: + + <any> + + + + severity: + + +FatalToProtocol or +CanContinue (protocol's discretion) + + + + + values: + + (none) + + + + + +Received a message with a valid minor opcode which is not appropriate +for the current state of the protocol. + + +BadLength + + + + offending-minor-opcode: + + <any> + + + + severity: + + +FatalToProtocol or +CanContinue (protocol's discretion) + + + + + values: + + (none) + + + + + +Received a message with a bad length. The length of the message is +longer or shorter than required to contain the data. + + +BadValue + + + + offending-minor-opcode: + + <any> + + + + severity: + + CanContinue + + + + values: + + +CARD32 Byte offset to offending value in offending message. +CARD32 Length of offending value. +<varies> Offending value + + + + + +Received a message with a bad value specified. + + + + +ICE Error Classes + +These errors are all major opcode 0 errors. + +BadMajor + + + offending-minor-opcode: + + <any> + + + + severity: + + CanContinue + + + + values: + + CARD8 Opcode + + + + +The opcode given is not one that has been registered. + + +NoAuthentication + + + + offending-minor-opcode: + + +ConnectionSetup, +ProtocolSetup + + + + + severity: + + +ConnectionSetup \(-> +FatalToConnection +ProtocolSetup \(-> +FatalToProtocol + + + + + values: + + (none) + + + + +None of the authentication protocols offered are available. + +NoVersion + + + + offending-minor-opcode: + + +ConnectionSetup, +ProtocolSetup + + + + + severity: + + +ConnectionSetup \(-> +FatalToConnection +ProtocolSetup \(-> +FatalToProtocol + + + + + values: + + (none) + + + + +None of the protocol versions offered are available. + +SetupFailed + + + + offending-minor-opcode: + + +ConnectionSetup, +ProtocolSetup, +AuthenticationReply + + + + + severity: + + +ConnectionSetup \(-> +FatalToConnection +ProtocolSetup \(-> +FatalToProtocol +AuthenticationReply \(-> +FatalToConnection if authenticating a connection, +otherwise FatalToProtocol + + + + + values: + + STRING reason + + + + + +The sending side is unable to accept the +new connection or new protocol for a reason other than authentication +failure. Typically this error will be a result of inability to allocate +additional resources on the sending side. The reason field will give a +human-interpretable message providing further detail on the type of failure. + + +AuthenticationRejected + + + offending-minor-opcode: + + +AuthenticationReply, +AuthenticationRequired, +AuthenticationNextPhase + + + + + severity: + + FatalToProtocol + + + + values: + + STRING reason + + + + + +Authentication rejected. The peer has failed to properly +authenticate itself. The reason field will give a human-interpretable +message providing further detail. + + +AuthenticationFailed + + + offending-minor-opcode: + + +AuthenticationReply, +AuthenticationRequired, +AuthenticationNextPhase + + + + + severity: + + FatalToProtocol + + + + values: + + STRING reason + + + + + +Authentication failed. AuthenticationFailed +does not imply that the authentication was rejected, as +AuthenticationRejected +does. Instead it means that the sender was unable to complete +the authentication for some other reason. (For instance, it +may have been unable to contact an authentication server.) +The reason field will give a human-interpretable message +providing further detail. + + +ProtocolDuplicate + + + offending-minor-opcode: + + ProtocolSetup + + + + severity: + + FatalToProtocol (but see note) + + + + values: + + STRING protocol name + + + + + +The protocol name was already registered. This is fatal to +the "new" protocol being set up by ProtocolSetup +but it does not affect the existing registration. + + +MajorOpcodeDuplicate + + + offending-minor-opcode: + + ProtocolSetup + + + + severity: + + FatalToProtocol (but see note) + + + + values: + + CARD8 opcode + + + + + +The major opcode specified was already registered. This is +fatal to the \*Qnew\*U protocol being set up by +ProtocolSetup but it does not affect the +existing registration. + + +UnknownProtocol + + + offending-minor-opcode: + + ProtocolSetup + + + + severity: + + FatalToProtocol + + + + values: + + STRING protocol name + + + + +The protocol specified is not supported. + + + + + +State Diagrams + + +Here are the state diagrams for the party that initiates the connection: + + + +start: + connect to other end, send ByteOrder ConnectionSetup -> conn_wait + +conn_wait: + receive ConnectionReply -> stasis + receive AuthenticationRequired -> conn_auth1 + receive Error -> quit + receive <other>, send Error -> quit + +conn_auth1: + if good auth data, send AuthenticationReply -> conn_auth2 + if bad auth data, send Error -> quit + +conn_auth2: + receive ConnectionReply -> stasis + receive AuthenticationNextPhase -> conn_auth1 + receive Error -> quit + receive <other>, send Error -> quit + + + +Here are top-level state transitions for the party +that accepts connections. + + + +listener: + accept connection -> init_wait + +init_wait: + receive ByteOrder ConnectionSetup -> auth_ask + receive <other>, send Error -> quit + +auth_ask: + send ByteOrder ConnectionReply +-> stasis + + send AuthenticationRequired -> auth_wait + + send Error -> quit + +auth_wait: + receive AuthenticationReply -> auth_check + + receive <other>, send Error -> quit + +auth_check: + if no more auth needed, send ConnectionReply -> stasis + if good auth data, send AuthenticationNextPhase -> auth_wait + if bad auth data, send Error -> quit + + + +Here are the top-level state transitions for all parties after the initial +connection establishment subprotocol. + + + + +Note: this is not quite the truth for branches out from stasis, in +that multiple conversations can be interleaved on the connection. + + + + +stasis: + send ProtocolSetup -> proto_wait + receive ProtocolSetup -> proto_reply + send Ping -> ping_wait + receive Ping send PingReply -> stasis + receive WantToClose -> shutdown_attempt + receive <other>, send Error -> stasis + all protocols shut down, send WantToClose -> close_wait + +proto_wait: + receive ProtocolReply -> stasis + receive AuthenticationRequired -> give_auth1 + receive Error give up on this protocol -> stasis + receive WantToClose -> proto_wait + +give_auth1: + if good auth data, send AuthenticationReply -> give_auth2 + if bad auth data, send Error give up on this protocol -> stasis + receive WantToClose -> give_auth1 + +give_auth2: + receive ProtocolReply -> stasis + receive AuthenticationNextPhase -> give_auth1 + receive Error give up on this protocol -> stasis + receive WantToClose -> give_auth2 + +proto_reply: + send ProtocolReply -> stasis + send AuthenticationRequired -> take_auth1 + send Error give up on this protocol -> stasis + +take_auth1: + receive AuthenticationReply -> take_auth2 + receive Error give up on this protocol -> stasis + +take_auth2: + if good auth data \(-> take_auth3 + if bad auth data, send Error give up on this protocol -> stasis + +take_auth3: + if no more auth needed, send ProtocolReply -> stasis + if good auth data, send AuthenticationNextPhase -> take_auth1 + if bad auth data, send Error give up on this protocol -> stasis + +ping_wait: + receive PingReply -> stasis + +quit: + -> close connection + + + +Here are the state transitions for shutting down the connection: + + + +shutdown_attempt: + if want to stay alive anyway, send NoClose -> stasis + else -> quit + +close_wait: + receive ProtocolSetup -> proto_reply + receive NoClose -> stasis + receive WantToClose -> quit + connection close -> quit + + + +Protocol Encoding + + +In the encodings below, the first column is the number of bytes occupied. +The second column is either the type (if the value is variable) or the +actual value. The third column is the description of the value (e.g., +the parameter name). Receivers must ignore bytes that are designated +as unused or pad bytes. + + + +This document describes major version 1, minor version 0 +of the ICE protocol. + + + +LISTof<type> indicates some number of repetitions of +<type>, with no +additional padding. The number of repetitions must be specified elsewhere +in the message. + + + +Primitives + + + + + + + + + + Type Name + Length (bytes) + Description + + + + + CARD8 + 1 + 8-bit unsigned integer + + + CARD16 + 2 + 16-bit unsigned integer + + + CARD32 + 4 + 32-bit unsigned integer + + + LPCE + 1 + A character from the X Portable Character Set in Latin Portable Character +Encoding + + + + + + + + +Enumerations + + + + + + + + + + + Type Name + Value + Description + + + + + BOOL + 0 + False + + + + 1 + True + + + + + + + + +Compound Types + + + + + + + + + + + Type Name + Length (bytes) + Type + Description + + + + + VERSION + + + + + + + 2 + CARD16 + Major version number + + + + 2 + CARD16 + Minor version number + + + STRING + + + + + + + 2 + CARD16 + length of string in bytes + + + + n + LISTofLPCE + string + + + + p + + unused, p = pad(n+2, 4) + + + + + + + + +ICE Minor opcodes + + + + + + + + Message Name + Encoding + + + + + Error + 0 + + + ByteOrder + 1 + + + ConnectionSetup + 2 + + + AuthenticationRequired + 3 + + + AuthenticationReply + 4 + + + AuthenticationNextPhase + 5 + + + ConnectionReply + 6 + + + ProtocolSetup + 7 + + + ProtocolReply + 8 + + + Ping + 9 + + + PingReply + 10 + + + WantToClose + 11 + + + NoClose + 12 + + + + + + + + +Message Encoding + + +Error + 1 CARD8 major-opcode + 1 0 Error + 2 CARD16 class + 4 (n+p)/8+1 length + 1 CARD8 offending-minor-opcode + 1 severity: + 0 CanContinue + 1 FatalToProtocol + 2 FatalToConnection + 2 unused + 4 CARD32 sequence number of erroneous message + n <varies> value(s) + p pad, p = pad(n,8) + + + + +ByteOrder + 1 0 ICE + 1 1 ByteOrder + 1 byte-order: + 0 LSBfirst + 1 MSBfirst + 1 unused + 4 0 length + + + +ConnectionSetup + 1 0 ICE + 1 2 ConnectionSetup + 1 CARD8 Number of versions offered + 1 CARD8 Number of authentication protocol names offered + 4 (i+j+k+m+p)/8+1 length + 1 BOOL must-authenticate + 7 unused + i STRING vendor + j STRING release + k LISTofSTRING authentication-protocol-names + m LISTofVERSION version-list + p unused, p = pad(i+j+k+m,8) + + + +AuthenticationRequired + 1 0 ICE + 1 3 AuthenticationRequired + 1 CARD8 authentication-protocol-index + 1 unused + 4 (n+p)/8+1 length + 2 n length of authentication data + 6 unused + n <varies> data + p unused, p = pad(n,8) + + + +AuthenticationReply + 1 0 ICE + 1 4 AuthenticationReply + 2 unused + 4 (n+p)/8+1 length + 2 n length of authentication data + 6 unused + n <varies> data + p unused, p = pad(n,8) + + + +AuthenticationNextPhase + 1 0 ICE + 1 5 AuthenticationNextPhase + 2 unused + 4 (n+p)/8+1 length + 2 n length of authentication data + 6 unused + n <varies> data + p unused, p = pad(n,8) + + + +ConnectionReply + 1 0 ICE + 1 6 ConnectionReply + 1 CARD8 version-index + 1 unused + 4 (i+j+p)/8 length + i STRING vendor + j STRING release + p unused, p = pad(i+j,8) + + + +ProtocolSetup + 1 0 ICE + 1 7 ProtocolSetup + 1 CARD8 major-opcode + 1 BOOL must-authenticate + 4 (i+j+k+m+n+p)/8+1 length + 1 CARD8 Number of versions offered + 1 CARD8 Number of authentication protocol names offered + 6 unused + i STRING protocol-name + j STRING vendor + k STRING release + m LISTofSTRING authentication-protocol-names + n LISTofVERSION version-list + p unused, p = pad(i+j+k+m+n,8) + + + +ProtocolReply + 1 0 ICE + 1 8 ProtocolReply + 1 CARD8 version-index + 1 CARD8 major-opcode + 4 (i+j+p)/8 length + i STRING vendor + j STRING release + p unused, p = pad(i+j, 8) + + + +Ping + 1 0 ICE + 1 9 Ping + 2 0 unused + 4 0 length + + + +PingReply + 1 0 ICE + 1 10 PingReply + 2 0 unused + 4 0 length + + + +WantToClose + 1 0 ICE + 1 11 WantToClose + 2 0 unused + 4 0 length + + + +NoClose + 1 0 ICE + 1 12 NoClose + 2 0 unused + 4 0 length + + + + + +Error Class Encoding + + +Generic errors have classes in the range 0x8000-0xFFFF, and +subprotocol-specific errors are in the range 0x0000-0x7FFF. + + + +Generic Error Class Encoding + + + + + + + + + Class + Encoding + + + + + BadMinor + 0x8000 + + + BadState + 0x8001 + + + BadLength + 0x8002 + + + BadValue + 0x8003 + + + + + + + +ICE-specific Error Class Encoding + + + + + + + + + Class + Encoding + + + + + BadMajor + 0 + + + NoAuthentication + 1 + + + NoVersion + 2 + + + SetupFailed + 3 + + + AuthenticationRejected + 4 + + + AuthenticationFailed + 5 + + + ProtocolDuplicate + 6 + + + MajorOpcodeDuplicate + 7 + + + UnknownProtocol + 8 + + + + + + + + + + + +Modification History + + +Release 6 to Release 6.1 + +Release 6.1 added the ICE X rendezvous protocol (Appendix B) and +updated the document version to 1.1. + + + + +Release 6.1 to Release 6.3 +Release 6.3 added the listen on well known ports feature. + + + + + +ICE X Rendezvous Protocol + + +Introduction + +The ICE X rendezvous protocol is designed to answer the need posed +in Section 2 for one mechanism by which two clients interested in +communicating via ICE are able to exchange the necessary information. +This protocol is appropriate for any two ICE clients who also have X +connections to the same X server. + + + + +Overview of ICE X Rendezvous + + +The ICE X Rendezvous Mechanism requires clients willing to act as ICE +originating parties to pre-register the ICE subprotocols they support in an +ICE_PROTOCOLS property on their top-level window. Clients willing to +act as ICE answering parties then send an ICE_PROTOCOLS X +ClientMessage +event to the ICE originating parties. This +ClientMessage +event identifies +the ICE network IDs of the ICE answering party as well as the ICE +subprotocol it wishes to speak. Upon receipt of this message the ICE +originating party uses the information to establish an ICE connection +with the ICE answering party. + + + + +Registering Known Protocols + + +Clients willing to act as ICE originating parties preregister +the ICE subprotocols they support in a list of atoms held by an +ICE_PROTOCOLS property on their top-level window. The name of each +atom listed in ICE_PROTOCOLS must be of the form +ICE_INITIATE_pname where +pname is the name of the ICE +subprotocol the ICE originating party is willing to speak, as would be +specified in an ICE +ProtocolSetup +message. + + + +Clients with an ICE_INITIATE_pname atom +in the ICE_PROTOCOLS property on their top-level windows must respond to +ClientMessage events of +type ICE_PROTOCOLS specifying ICE_INITIATE_ +pname. If a client does not +want to respond to these client message events, it should +remove the ICE_INITIATE_pname +atom from its ICE_PROTOCOLS property +or remove the ICE_PROTOCOLS property entirely. + + + + +Initiating the Rendezvous + + +To initiate the rendezvous a client acting as an ICE answering +party sends an X +ClientMessage +event of type ICE_PROTOCOLS to an ICE +originating party. This ICE_PROTOCOLS client message contains the +information the ICE originating party needs to identify the ICE +subprotocol the two parties will use as well as the ICE network +identification string of the ICE answering party. + + + +Before the ICE answering party sends the client message event it must +define a text property on one of its windows. This text property +contains the ICE answering party's ICE network identification string +and will be used by ICE originating parties to determine the ICE +answering party's list of ICE network IDs. + + + +The property name will normally be ICE_NETWORK_IDS, but may be any +name of the ICE answering party's choosing. The format for this text +property is as follows: + + + + + + + + + + Field + Value + + + + + type + XA_STRING + + + format + 8 + + + value + comma-separated list of ICE network IDs + + + + + + + + +Once the ICE answering party has established this text property on one +of its windows, it initiates the rendezvous by sending an +ICE_PROTOCOLS +ClientMessage +event to an ICE originating party's +top-level window. This event has the following format +and must only be sent to windows that have pre-registered the ICE +subprotocol in an ICE_PROTOCOLS property on their top-level window. + + + + + + + + + + Field + Value + + + + + message_type + Atom = "ICE_PROTOCOLS" + + + format + 32 + + + data.l[0] + Atom identifying the ICE subprotocol to speak + + + data.l[1] + Timestamp + + + data.l[2] + ICE answering party's window ID with +ICE network IDs text property + + + data.l[3] + Atom naming text property containing the ICE +answering party's ICE network IDs + + + data.l[4] + Reserved. Must be 0. + + + + + + + +The name of the atom in data.l[0] must be of the form +ICE_INITIATE_pname, where +pname is the name of the ICE +subprotocol the ICE answering party wishes to speak. + + + +When an ICE originating party receives a +ClientMessage +event of type +ICE_PROTOCOLS specifying ICE_INITIATE_pname +it can initiate an ICE connection with the ICE answering party. +To open this connection the client retrieves the ICE answering +party's ICE network IDs from the window specified in data.l[2] using +the text property specified in data.l[3]. + + + +If the connection attempt fails for any reason, the client must +respond to the client message event by sending a return +ClientMessage +event to the window specified in data.l[2]. This return +event has the following format: + + + + + + + + + + Field + Value + + + + + message_type + Atom = "ICE_INITIATE_FAILED" + + + format + 32 + + + data.l[0] + Atom identifying the ICE subprotocol requested + + + data.l[1] + Timestamp + + + data.l[2] + Initiating party's window ID +(holding ICE_PROTOCOLS) + + + data.l[3] + int: reason for failure + + + data.l[4] + Reserved, must be 0 + + + + + + + +The values of data.l[0] and data.l[1] are copied directly from the +client message event the client received. + + + +The value in data.l[2] is +the id of the window to which the +ICE_PROTOCOLS.ICE_INITIATE_pname +client message event was sent. + + +Data.l[3] has one of the following values: + + + + + + + + + + + Value + Encoding + Description + + + + + OpenFailed + 1 + +The client was unable to open the connection +(e.g. a call to IceOpenConnection() failed). If the +client is able to distinguish authentication or +authorization errors from general errors, then +the preferred reply is AuthenticationFailed +for authorization errors. + + + + AuthenticationFailed + 2 + Authentication or authorization of the +connection or protocol setup was refused. +This reply will be given only if the client is +able to distinguish it from +OpenFailed +otherwise +OpenFailed +will be returned. + + + SetupFailed + 3 + The client was unable to initiate the specified +protocol on the connection (e.g. a call to +IceProtocolSetup() failed). + + + UnknownProtocol + 4 + The client does not recognize the requested +protocol. (This represents a semantic error +on the part of the answering party.) + + + Refused + 5 + +The client was in the process of removing +ICE_INITIATE_pname +from its ICE_PROTOCOLS list +when the client message was sent; the client no +longer is willing to establish the specified ICE +communication. + + + + + + + + +Clients willing to act as ICE originating parties must update the +ICE_PROTOCOLS property on their top-level windows to include the +ICE_INITIATE_pname atom(s) identifying +the ICE subprotocols they +speak. The method a client uses to update the ICE_PROTOCOLS property +to include ICE_INITIATE_pname atoms is +implementation dependent, but +the client must ensure the integrity of the list to prevent the +accidental omission of any atoms previously in the list. + + + +When setting up the ICE network IDs text property on one of its +windows, the ICE answering party can determine its comma-separated +list of ICE network IDs by calling IceComposeNetworkIdList() after +making a call to IceListenForConnections(). The method an ICE +answering party uses to find the top-level windows of clients willing +to act as ICE originating parties is dependent upon the nature of the +answering party. Some may wish to use the approach of requiring the +user to click on a client's window. Others wishing to find existing +clients without requiring user interaction might use something similar +to the XQueryTree() method used by several freely-available +applications. In order for the ICE answering party to become +automatically aware of new clients willing to originate ICE +connections, the ICE answering party might register for +SubstructureNotify events on the root window of the display. When it +receives a SubstructureNotify event, the ICE answering party can check +to see if it was the result of the creation of a new client top-level +window with an ICE_PROTOCOLS property. + + + +In any case, before attempting to use this ICE X Rendezvous Mechanism +ICE answering parties wishing to speak ICE subprotocol +pname should +check for the ICE_INITIATE_pname atom +in the ICE_PROTOCOLS property on +a client's top-level window. A client that does not include an +ICE_INITIATE_pname atom in a +ICE_PROTOCOLS property on some top-level window should be assumed to ignore +ClientMessage +events of type +ICE_PROTOCOLS specifying ICE_INITIATE_pname +for ICE subprotocol pname. + + + + + +ICE Subprotocol Versioning + + +Although the version of the ICE subprotocol could be passed in the +client message event, ICE provides more a flexible version negotiation +mechanism than will fit within a single +ClientMessage +event. Because +of this, ICE subprotocol versioning is handled within the ICE protocol +setup phase. + +Clients wish to communicate with each other via an ICE subprotocol +known as "RAP V1.0". In RAP terminology one party, the "agent", +communicates with other RAP-enabled applications on demand. The +user may direct the agent to establish communication with a specific +application by clicking on the application's window, or the agent may +watch for new application windows to be created and automatically +establish communication. + + + +During startup the ICE answering party (the agent) first calls +IceRegisterForProtocolReply() with a list of +the versions (i.e., 1.0) of RAP the agent can speak. The answering +party then calls IceListenForConnections() followed by +IceComposeNetworkIdList() and stores the resulting ICE network IDs +string in a text property on one of its windows. + + + +When the answering party (agent) finds a client with which it wishes to +speak, it checks to see if the ICE_INITIATE_RAP atom is in the ICE_PROTOCOLS +property on the client's top-level window. If it is present the agent +sends the client's top-level window an ICE_PROTOCOLS client +message event as described above. When the client receives the client +message event and is willing to originate an ICE connection using RAP, +it performs an IceRegisterForProtocolSetup() with a list of the +versions of RAP the client can speak. The client then retrieves +the agent's ICE network ID from the property and window specified by +the agent in the client message event and calls IceOpenConnection(). +After this call succeeds the client calls IceProtocolSetup() specifying +the RAP protocol. During this +process, ICE calls the RAP protocol routines that handle the version +negotiation. + + + +Note that it is not necessary for purposes of this rendezvous that +the client application call any ICElib functions prior to receipt +of the client message event. + + + + + diff --git a/src/ICElibint.h b/src/ICElibint.h new file mode 100644 index 0000000..0638fb0 --- /dev/null +++ b/src/ICElibint.h @@ -0,0 +1,541 @@ +/****************************************************************************** + + +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 +#include +#include +#include +#include +#include +#include +#ifdef WIN32 +#include +#endif + +#include +#include + + +/* + * 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) ( + IceConn /* iceConn */, + int /* opcode */, + unsigned long /* length */, + Bool /* swap */, + IceReplyWaitInfo * /* replyWait */, + Bool * /* replyReadyRet */, + Bool * /* connectionClosedRet */ +); + +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, _end, _bail) \ +{ \ + CARD16 _len; \ + EXTRACT_CARD16 (_pBuf, _swap, _len); \ + _pBuf += _len + PAD32(2+_len); \ + if (_pBuf > _end) { \ + _bail; \ + } \ +} + +#define SKIP_LISTOF_STRING(_pBuf, _swap, _count, _end, _bail) \ +{ \ + int _i; \ + for (_i = 0; _i < _count; _i++) \ + SKIP_STRING (_pBuf, _swap, _end, _bail); \ +} + + + +/* + * 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 const char *_IceAuthNames[]; +extern IcePoAuthProc _IcePoAuthProcs[]; +extern IcePaAuthProc _IcePaAuthProcs[]; + +extern int _IceVersionCount; +extern _IceVersion _IceVersions[]; + +extern _IceWatchProc *_IceWatchProcs; + +extern IceErrorHandler _IceErrorHandler; +extern IceIOErrorHandler _IceIOErrorHandler; + +extern IceAuthDataEntry _IcePaAuthDataEntries[]; +extern int _IcePaAuthDataEntryCount; + +extern void _IceErrorBadMajor ( + IceConn /* iceConn */, + int /* offendingMajor */, + int /* offendingMinor */, + int /* severity */ +); + +extern void _IceErrorNoAuthentication ( + IceConn /* iceConn */, + int /* offendingMinor */ +); + +extern void _IceErrorNoVersion ( + IceConn /* iceConn */, + int /* offendingMinor */ +); + +extern void _IceErrorSetupFailed ( + IceConn /* iceConn */, + int /* offendingMinor */, + const char * /* reason */ +); + +extern void _IceErrorAuthenticationRejected ( + IceConn /* iceConn */, + int /* offendingMinor */, + const char * /* reason */ +); + +extern void _IceErrorAuthenticationFailed ( + IceConn /* iceConn */, + int /* offendingMinor */, + const char * /* reason */ +); + +extern void _IceErrorProtocolDuplicate ( + IceConn /* iceConn */, + const char * /* protocolName */ +); + +extern void _IceErrorMajorOpcodeDuplicate ( + IceConn /* iceConn */, + int /* majorOpcode */ +); + +extern void _IceErrorUnknownProtocol ( + IceConn /* iceConn */, + const char * /* protocolName */ +); + +extern void _IceAddOpcodeMapping ( + IceConn /* iceConn */, + int /* hisOpcode */, + int /* myOpcode */ +); + +extern char *_IceGetPeerName ( + IceConn /* iceConn */ +); + +extern void _IceFreeConnection ( + IceConn /* iceConn */ +); + +extern void _IceAddReplyWait ( + IceConn /* iceConn */, + IceReplyWaitInfo * /* replyWait */ +); + +extern IceReplyWaitInfo *_IceSearchReplyWaits ( + IceConn /* iceConn */, + int /* majorOpcode */ +); + +extern void _IceSetReplyReady ( + IceConn /* iceConn */, + IceReplyWaitInfo * /* replyWait */ +); + +extern Bool _IceCheckReplyReady ( + IceConn /* iceConn */, + IceReplyWaitInfo * /* replyWait */ +); + +extern void _IceConnectionOpened ( + IceConn /* iceConn */ +); + +extern void _IceConnectionClosed ( + IceConn /* iceConn */ +); + +extern void _IceGetPoAuthData ( + const char * /* protocol_name */, + const char * /* address */, + const char * /* auth_name */, + unsigned short * /* auth_data_length_ret */, + char ** /* auth_data_ret */ +); + +extern void _IceGetPaAuthData ( + const char * /* protocol_name */, + const char * /* address */, + const char * /* auth_name */, + unsigned short * /* auth_data_length_ret */, + char ** /* auth_data_ret */ +); + +extern void _IceGetPoValidAuthIndices ( + const char * /* protocol_name */, + const char * /* address */, + int /* num_auth_names */, + const char ** /* auth_names */, + int * /* num_indices_ret */, + int * /* indices_ret */ +); + +extern void _IceGetPaValidAuthIndices ( + const char * /* protocol_name */, + const char * /* address */, + int /* num_auth_names */, + const char ** /* auth_names */, + int * /* num_indices_ret */, + int * /* indices_ret */ +); + +#endif /* _ICELIBINT_H_ */ diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..3cbe9c6 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,52 @@ +lib_LTLIBRARIES=libICE.la + +AM_CPPFLAGS = -I${top_srcdir}/include + +AM_CFLAGS = \ + $(ICE_CFLAGS) \ + $(CWARNFLAGS) \ + -DICE_t -DTRANS_CLIENT -DTRANS_SERVER + +libICE_la_LDFLAGS = -version-number 6:3:0 -no-undefined + +libICE_la_LIBADD = $(ICE_LIBS) + +libICE_la_SOURCES = \ + ICElibint.h \ + accept.c \ + authutil.c \ + connect.c \ + error.c \ + getauth.c \ + globals.h \ + iceauth.c \ + icetrans.c \ + listen.c \ + listenwk.c \ + locking.c \ + misc.c \ + ping.c \ + process.c \ + protosetup.c \ + register.c \ + replywait.c \ + setauth.c \ + shutdown.c \ + watch.c + +iceincludedir=$(includedir)/X11/ICE +iceinclude_HEADERS=\ + $(top_srcdir)/include/X11/ICE/ICE.h \ + $(top_srcdir)/include/X11/ICE/ICEconn.h \ + $(top_srcdir)/include/X11/ICE/ICElib.h \ + $(top_srcdir)/include/X11/ICE/ICEmsg.h \ + $(top_srcdir)/include/X11/ICE/ICEproto.h \ + $(top_srcdir)/include/X11/ICE/ICEutil.h + +if LINT +ALL_LINT_FLAGS=$(LINT_FLAGS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) + +lint: + $(LINT) $(ALL_LINT_FLAGS) $(libICE_la_SOURCES) $(XINERAMA_LIBS) +endif LINT diff --git a/src/accept.c b/src/accept.c new file mode 100644 index 0000000..6bc40ad --- /dev/null +++ b/src/accept.c @@ -0,0 +1,183 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include + + +IceConn +IceAcceptConnection ( + IceListenObj listenObj, + IceAcceptStatus *statusRet +) +{ + IceConn iceConn; + XtransConnInfo newconn; + iceByteOrderMsg *pMsg; + int endian, status; + + /* + * Accept the connection. + */ + + if ((newconn = _IceTransAccept (listenObj->trans_conn, &status)) == NULL) + { + 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 = strdup(listenObj->network_id); + + if (iceConn->connection_string == NULL) + { + _IceTransClose (newconn); + free ((char *) iceConn); + *statusRet = IceAcceptBadMalloc; + return (NULL); + } + + 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..6c00482 --- /dev/null +++ b/src/authutil.c @@ -0,0 +1,504 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include +#include +#include +#include + +#include +#define Time_t time_t +#ifdef __UNIXOS2__ +extern char* getenv(const char*); +#define link rename +#endif +#ifndef X_NOT_POSIX +#include +#else +#ifndef WIN32 +extern unsigned sleep (); +#else +#define link rename +#endif +#endif + +static Status read_short (FILE *file, unsigned short *shortp); +static Status read_string (FILE *file, char **stringp); +static Status read_counted_string (FILE *file, unsigned short *countp, char **stringp); +static Status write_short (FILE *file, unsigned short s); +static Status write_string (FILE *file, char *string); +static Status write_counted_string (FILE *file, unsigned short count, char *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 (void) +{ + static char slashDotICEauthority[] = "/.ICEauthority"; + char *name; + static char *buf; + static int bsize; + int size; +#if defined(WIN32) || defined(__UNIXOS2__) +#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 +#ifdef __UNIXOS2__ + strcpy (dir,"c:"); + 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 ( + 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 ( + 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 ( + 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 ( + 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 ( + 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 ( + const char *protocol_name, + const char *network_id, + const 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 *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 *file, char **stringp) + +{ + unsigned short len; + char *data; + + if (!read_short (file, &len)) + return (0); + + data = malloc ((unsigned) len + 1); + + if (!data) + return (0); + + if (len != 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 *file, unsigned short *countp, char **stringp) +{ + unsigned short len; + char *data; + + if (!read_short (file, &len)) + return (0); + + if (len == 0) + { + data = NULL; + } + 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 *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 *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 *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..b59e94c --- /dev/null +++ b/src/connect.c @@ -0,0 +1,533 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include +#include "globals.h" + +static XtransConnInfo ConnectToPeer(char *networkIdsList, + char **actualConnectionRet); + +#define Strstr strstr + +IceConn +IceOpenConnection ( + 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 *) calloc (1, 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 +) +{ + return (iceConn->context); +} + + + +/* ------------------------------------------------------------------------- * + * local routines * + * ------------------------------------------------------------------------- */ + +#define ICE_CONNECTION_RETRIES 5 + + +static XtransConnInfo +ConnectToPeer (char *networkIdsList, char **actualConnectionRet) +{ + char addrbuf[256]; + char* address; + char *ptr, *endptr, *delim; + int madeConnection = 0; + int len, retry; + int connect_stat; + int address_size; + XtransConnInfo trans_conn = NULL; + + *actualConnectionRet = NULL; + + ptr = networkIdsList; + len = strlen (networkIdsList); + endptr = networkIdsList + len; + + if (len < sizeof addrbuf) + { + address = addrbuf; + address_size = 256; + } + else + { + address = malloc (len + 1); + address_size = len; + } + + while (ptr < endptr && !madeConnection) + { + if ((delim = (char *) strchr (ptr, ',')) == NULL) + delim = endptr; + + len = delim - ptr; + if (len > address_size - 1) + len = address_size - 1; + 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 = strdup(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..3e5e5e9 --- /dev/null +++ b/src/error.c @@ -0,0 +1,629 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include + +#include + + +void +_IceErrorBadMinor ( + IceConn iceConn, + int majorOpcode, + int offendingMinor, + int severity +) +{ + IceErrorHeader (iceConn, + majorOpcode, offendingMinor, + iceConn->receive_sequence, + severity, + IceBadMinor, + 0); + + IceFlush (iceConn); +} + + +void +_IceErrorBadState ( + IceConn iceConn, + int majorOpcode, + int offendingMinor, + int severity +) +{ + IceErrorHeader (iceConn, + majorOpcode, offendingMinor, + iceConn->receive_sequence, + severity, + IceBadState, + 0); + + IceFlush (iceConn); +} + + +void +_IceErrorBadLength ( + IceConn iceConn, + int majorOpcode, + int offendingMinor, + int severity +) +{ + IceErrorHeader (iceConn, + majorOpcode, offendingMinor, + iceConn->receive_sequence, + severity, + IceBadLength, + 0); + + IceFlush (iceConn); +} + + +void +_IceErrorBadValue ( + 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 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 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 iceConn, + int offendingMinor, + const 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 iceConn, + int offendingMinor, + const 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 iceConn, + int offendingMinor, + const 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 iceConn, + const 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 iceConn, + int majorOpcode +) +{ + char mOp[8] = { (char) majorOpcode }; + + IceErrorHeader (iceConn, + 0, ICE_ProtocolSetup, + iceConn->receive_sequence, + IceFatalToProtocol, + IceMajorOpcodeDuplicate, + 1 /* length */); + + IceWriteData (iceConn, 8, mOp); + IceFlush (iceConn); +} + + +void +_IceErrorUnknownProtocol ( + IceConn iceConn, + const 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 iceConn, + int offendingMajor, + int offendingMinor, + int severity +) +{ + char maj[8] = { (char) offendingMajor }; + + IceErrorHeader (iceConn, + 0, offendingMinor, + iceConn->receive_sequence, + severity, + IceBadMajor, + 1 /* length */); + + IceWriteData (iceConn, 8, maj); + IceFlush (iceConn); +} + + + +/* + * Default error handler. + */ + +static void +_IceDefaultErrorHandler ( + IceConn iceConn, + Bool swap, + int offendingMinorOpcode, + unsigned long offendingSequence, + int errorClass, + int severity, + IcePointer values +) +{ + const char *str; + char *estr; + 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 = %lu\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, estr); + fprintf (stderr, "Reason : %s\n", estr); + free(estr); + break; + + case IceAuthRejected: + + EXTRACT_STRING (pData, swap, estr); + fprintf (stderr, "Reason : %s\n", estr); + free(estr); + break; + + case IceAuthFailed: + + EXTRACT_STRING (pData, swap, estr); + fprintf (stderr, "Reason : %s\n", estr); + free(estr); + break; + + case IceProtocolDuplicate: + + EXTRACT_STRING (pData, swap, estr); + fprintf (stderr, "Protocol name : %s\n", estr); + free(estr); + break; + + case IceMajorOpcodeDuplicate: + + fprintf (stderr, "Major opcode : %d\n", (int) *pData); + break; + + case IceUnknownProtocol: + + EXTRACT_STRING (pData, swap, estr); + fprintf (stderr, "Protocol name : %s\n", estr); + free(estr); + break; + + default: + break; + } + + fprintf (stderr, "\n"); + + if (severity != IceCanContinue) + exit (1); +} + +IceErrorHandler _IceErrorHandler = _IceDefaultErrorHandler; + + +/* + * 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 ( + IceErrorHandler handler +) +{ + IceErrorHandler oldHandler = _IceErrorHandler; + + if (handler != NULL) + _IceErrorHandler = handler; + else + _IceErrorHandler = _IceDefaultErrorHandler; + + return (oldHandler); +} + + + +/* + * Default IO error handler. + */ + +static void +_IceDefaultIOErrorHandler ( + IceConn iceConn +) +{ + fprintf (stderr, + "ICE default IO error handler doing an exit(), pid = %ld, errno = %d\n", + (long)getpid(), errno); + + exit (1); +} + +IceIOErrorHandler _IceIOErrorHandler = _IceDefaultIOErrorHandler; + + +/* + * 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 ( + 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..e127206 --- /dev/null +++ b/src/getauth.c @@ -0,0 +1,257 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" + +static Bool auth_valid (const char *auth_name, int num_auth_names, + const char **auth_names, int *index_ret); + + +/* + * 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 ( + const char *protocolName, + const char *networkId, + const 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 ( + const char *protocolName, + const char *networkId, + const char *authName, + unsigned short *authDataLenRet, + char **authDataRet +) +{ + IceAuthDataEntry *entry = NULL; + 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 ( + const char *protocol_name, + const char *network_id, + int num_auth_names, + const 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 ( + const char *protocol_name, + const char *network_id, + int num_auth_names, + const 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 (const char *auth_name, int num_auth_names, + const 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..965386f --- /dev/null +++ b/src/globals.h @@ -0,0 +1,45 @@ +/****************************************************************************** + + +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 __UNIXOS2__ +IceConn _IceConnectionObjs[256]; +char *_IceConnectionStrings[256]; +_IceProtocol _IceProtocols[255]; +#else +IceConn _IceConnectionObjs[256] = {0}; +char *_IceConnectionStrings[256] = {0}; +_IceProtocol _IceProtocols[255] = {0}; +#endif +int _IceConnectionCount = 0; + +int _IceLastMajorOpcode = 0; + +int _IceAuthCount = 1; +const char *_IceAuthNames[] = {"MIT-MAGIC-COOKIE-1"}; + +_IceWatchProc *_IceWatchProcs = NULL; diff --git a/src/iceauth.c b/src/iceauth.c new file mode 100644 index 0000000..14370e2 --- /dev/null +++ b/src/iceauth.c @@ -0,0 +1,247 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include + +#include +#define Time_t time_t + +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 ( + 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 + { +#ifndef __UNIXOS2__ + long time (); +#endif + 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 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) + { + const char *tempstr = + "Could not find correct MIT-MAGIC-COOKIE-1 authentication"; + + *errorStringRet = strdup(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. + */ + + const char *tempstr = + "MIT-MAGIC-COOKIE-1 authentication internal error"; + + *errorStringRet = strdup(tempstr); + + return (IcePoAuthFailed); + } +} + +IcePoAuthProc _IcePoAuthProcs[] = {_IcePoMagicCookie1Proc}; + + +IcePaAuthStatus +_IcePaMagicCookie1Proc ( + 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 && + memcmp (authData, data, authDataLen) == 0) + { + stat = IcePaAuthAccepted; + } + else + { + const char *tempstr + = "MIT-MAGIC-COOKIE-1 authentication rejected"; + + *errorStringRet = strdup(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. + */ + + const char *tempstr = + "MIT-MAGIC-COOKIE-1 authentication internal error"; + + *errorStringRet = strdup(tempstr); + + return (IcePaAuthFailed); + } + } +} + +IcePaAuthProc _IcePaAuthProcs[] = {_IcePaMagicCookie1Proc}; diff --git a/src/icetrans.c b/src/icetrans.c new file mode 100644 index 0000000..52e432b --- /dev/null +++ b/src/icetrans.c @@ -0,0 +1,31 @@ +/* + * Copyright © 2003 Keith Packard + * + * 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, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define ICE_t 1 +#define TRANS_CLIENT 1 +#define TRANS_SERVER 1 + +#include diff --git a/src/listen.c b/src/listen.c new file mode 100644 index 0000000..0348fec --- /dev/null +++ b/src/listen.c @@ -0,0 +1,273 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include +#include + + +Status +IceListenForConnections ( + 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++) + { + _IceTransSetOption(transConns[i], TRANS_CLOSEONEXEC, 1); + + 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); + *listenObjsRet = NULL; + + status = 0; + break; + } + 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 ( + IceListenObj listenObj +) +{ + return (_IceTransGetConnectionNumber (listenObj->trans_conn)); +} + + + +char * +IceGetListenConnectionString ( + IceListenObj listenObj +) +{ + return strdup(listenObj->network_id); +} + + + +char * +IceComposeNetworkIdList ( + 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 ( + 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 ( + 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..06b56a3 --- /dev/null +++ b/src/listenwk.c @@ -0,0 +1,159 @@ +/* + +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 */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include +#include + + +Status +IceListenForWellKnownConnections ( + 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); + *listenObjsRet = NULL; + + status = 0; + break; + } + 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..79a0a74 --- /dev/null +++ b/src/locking.c @@ -0,0 +1,65 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" + + +/* + * NOT IMPLEMENTED YET + */ + + +Status +IceInitThreads ( + void +) +{ + return (0); +} + + +void +IceAppLockConn ( + IceConn iceConn +) +{ + IceLockConn (iceConn); +} + + +void +IceAppUnlockConn ( + IceConn iceConn +) +{ + IceUnlockConn (iceConn); +} diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 0000000..e201fda --- /dev/null +++ b/src/misc.c @@ -0,0 +1,590 @@ +/****************************************************************************** + + +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 +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include +#include +#ifdef WIN32 +#include +#include +#endif + + +/* + * scratch buffer + */ + +char * +IceAllocScratch ( + 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 + */ + +int +IceFlush ( + IceConn iceConn +) +{ + _IceWrite (iceConn, + (unsigned long) (iceConn->outbufptr - iceConn->outbuf), + iceConn->outbuf); + + iceConn->outbufptr = iceConn->outbuf; + return 1; +} + + +int +IceGetOutBufSize ( + IceConn iceConn +) +{ + return (iceConn->outbufmax - iceConn->outbuf); +} + + +int +IceGetInBufSize ( + IceConn iceConn +) +{ + return (iceConn->inbufmax - iceConn->inbuf); +} + + + +/* + * informational functions + */ + +IceConnectStatus +IceConnectionStatus ( + IceConn iceConn +) +{ + return (iceConn->connection_status); +} + + +char * +IceVendor ( + IceConn iceConn +) +{ + return strdup(iceConn->vendor); +} + + +char * +IceRelease ( + IceConn iceConn +) +{ + return strdup(iceConn->release); +} + + +int +IceProtocolVersion ( + IceConn iceConn +) +{ + return (_IceVersions[iceConn->my_ice_version_index].major_version); +} + + +int +IceProtocolRevision ( + IceConn iceConn +) +{ + return (_IceVersions[iceConn->my_ice_version_index].minor_version); +} + + +int +IceConnectionNumber ( + IceConn iceConn +) +{ + return (_IceTransGetConnectionNumber (iceConn->trans_conn)); +} + + +char * +IceConnectionString ( + IceConn iceConn +) +{ + if (iceConn->connection_string) + { + return strdup(iceConn->connection_string); + } + else + return (NULL); +} + + +unsigned long +IceLastSentSequenceNumber ( + IceConn iceConn +) +{ + return (iceConn->send_sequence); +} + + +unsigned long +IceLastReceivedSequenceNumber ( + IceConn iceConn +) +{ + return (iceConn->receive_sequence); +} + + +Bool +IceSwapping ( + IceConn iceConn +) +{ + return (iceConn->swap); +} + + + +/* + * Read "n" bytes from a connection. + * + * Return Status 0 if we detected an EXPECTED closed connection. + * + */ + +Status +_IceRead ( + 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 != NULL) && 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 ( + 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 ( + 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 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 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 iceConn, + Bool swap, + unsigned long nbytes, + short *data +) +{ + /* NOT IMPLEMENTED YET */ +} + + +IceReadData32 ( + IceConn iceConn, + Bool swap, + unsigned long nbytes, + int *data +) +{ + /* NOT IMPLEMENTED YET */ +} + +#endif /* WORD64 */ + + + +void +_IceAddOpcodeMapping ( + 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) +{ + return (_IceTransGetPeerNetworkId (iceConn->trans_conn)); +} + + +char * +_IceGetPeerName (IceConn iceConn) +{ + return (IceGetPeerName(iceConn)); +} diff --git a/src/ping.c b/src/ping.c new file mode 100644 index 0000000..93d82de --- /dev/null +++ b/src/ping.c @@ -0,0 +1,64 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" + +Status +IcePing ( + 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..2708ee8 --- /dev/null +++ b/src/process.c @@ -0,0 +1,2558 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" + +#include /* sprintf */ + +/* + * Check for bad length + */ + +#define CHECK_SIZE_MATCH(_iceConn, _opcode, _expected_len, _actual_len, _severity, _return) \ + if ((((_actual_len) - SIZEOF (iceMsg)) >> 3) != _expected_len) \ + { \ + _IceErrorBadLength (_iceConn, 0, _opcode, _severity); \ + return (_return); \ + } + +#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); \ + } + +#define BAIL_STRING(_iceConn, _opcode, _pStart) {\ + _IceErrorBadLength (_iceConn, 0, _opcode, IceFatalToConnection);\ + IceDisposeCompleteMessage (_iceConn, _pStart);\ + return (0);\ +} + +#ifndef HAVE_ASPRINTF +# include + +/* sprintf variant found in newer libc's which allocates string to print to */ +static int _X_ATTRIBUTE_PRINTF(2,3) +asprintf(char ** ret, const char *format, ...) +{ + char buf[256]; + int len; + va_list ap; + + va_start(ap, format); + len = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + if (len < 0) + return -1; + + if (len < sizeof(buf)) + { + *ret = strdup(buf); + } + else + { + *ret = malloc(len + 1); /* snprintf doesn't count trailing '\0' */ + if (*ret != NULL) + { + va_start(ap, format); + len = vsnprintf(*ret, len + 1, format, ap); + va_end(ap); + if (len < 0) { + free(*ret); + *ret = NULL; + } + } + } + + if (*ret == NULL) + return -1; + + return len; +} +#endif + + +/* + * 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 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, IceProcessMessagesIOError); + + 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". + * + * Also, when two hosts communicate over an ICE connection and use + * different major opcodes for a subprotocol, it is impossible + * to use message replies unless we translate opcodes before + * comparing them. + */ + + { + int op; + + if (header->majorOpcode == 0) + { + op = 0; + } + else + { + int idx = header->majorOpcode - iceConn->his_min_opcode; + op = iceConn->process_msg_info[idx].my_opcode; + } + useThisReplyWait = _IceSearchReplyWaits (iceConn, op); + } + } + + 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 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 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 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 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 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 +) +{ + IceSimpleMessage (iceConn, 0, ICE_PingReply); + IceFlush (iceConn); +} + + + +static Bool +ProcessError ( + IceConn iceConn, + unsigned long length, + Bool swap, + IceReplyWaitInfo *replyWait +) +{ + int invokeHandler = 0; + 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; + const char *tempstr, *prefix; + char *temp; + + invokeHandler = 0; + errorReturned = True; + + switch (message->errorClass) + { + case IceNoVersion: + + tempstr = + "None of the ICE versions specified are supported"; + errorStr = strdup(tempstr); + break; + + case IceNoAuth: + + tempstr = + "None of the authentication protocols specified are supported"; + errorStr = strdup(tempstr); + break; + + case IceSetupFailed: + + prefix = "Connection Setup Failed, reason : "; + + EXTRACT_STRING (pData, swap, temp); + if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) + errorStr = NULL; + free (temp); + break; + + case IceAuthRejected: + + prefix = "Authentication Rejected, reason : "; + EXTRACT_STRING (pData, swap, temp); + if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) + errorStr = NULL; + free (temp); + break; + + case IceAuthFailed: + + prefix = "Authentication Failed, reason : "; + EXTRACT_STRING (pData, swap, temp); + if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) + errorStr = NULL; + 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 = ""; + const char *prefix; + char *temp; + + invokeHandler = 0; + errorReturned = True; + + switch (message->errorClass) + { + case IceNoVersion: + + errorStr = strdup( + "None of the protocol versions specified are supported"); + break; + + case IceNoAuth: + + errorStr = strdup( + "None of the authentication protocols specified are supported"); + + break; + + case IceSetupFailed: + + prefix = "Protocol Setup Failed, reason : "; + + EXTRACT_STRING (pData, swap, temp); + if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) + errorStr = NULL; + free (temp); + break; + + case IceAuthRejected: + + prefix = "Authentication Rejected, reason : "; + EXTRACT_STRING (pData, swap, temp); + if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) + errorStr = NULL; + free (temp); + break; + + case IceAuthFailed: + + prefix = "Authentication Failed, reason : "; + EXTRACT_STRING (pData, swap, temp); + if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) + errorStr = NULL; + free (temp); + break; + + case IceProtocolDuplicate: + + prefix = "Protocol was already registered : "; + EXTRACT_STRING (pData, swap, temp); + if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) + errorStr = NULL; + free (temp); + break; + + case IceMajorOpcodeDuplicate: + + prefix = "The major opcode was already used : "; + if (asprintf (&errorStr, "%s%d", prefix, (int) *pData) == -1) + errorStr = NULL; + break; + + case IceUnknownProtocol: + + prefix = "Unknown Protocol : "; + EXTRACT_STRING (pData, swap, temp); + if (asprintf (&errorStr, "%s%s", prefix, temp) == -1) + errorStr = NULL; + 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[(int) + (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[(int)(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 int +ProcessConnectionSetup ( + 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 **hisAuthNames = NULL; + char *pData, *pStart, *pEnd; + 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; + pEnd = pStart + (length << 3); + + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING(iceConn, ICE_ConnectionSetup, + pStart)); /* vendor */ + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING(iceConn, ICE_ConnectionSetup, + pStart)); /* release */ + SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd, + BAIL_STRING(iceConn, ICE_ConnectionSetup, + pStart)); /* 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]) + { + const char *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; + } + else + { + free (vendor); + free (release); + } + + 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 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 = 0; + + 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); + + const char *tempstr + = "Received bad authIndex in the AuthRequired message"; + char errIndex = (int) message->authIndex; + + errorString = strdup(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); + + const char *tempstr + = "Received bad authIndex in the AuthRequired message"; + char errIndex = (int) message->authIndex; + + errorString = strdup(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) + { + const char *prefix; + char *returnErrorString; + + if (status == IcePoAuthRejected) + { + _IceErrorAuthenticationRejected (iceConn, + ICE_AuthRequired, errorString); + + prefix = "Authentication Rejected, reason : "; + } + else + { + _IceErrorAuthenticationFailed (iceConn, + ICE_AuthRequired, errorString); + + prefix = "Authentication Failed, reason : "; + } + + if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1) + returnErrorString = NULL; + 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 int +ProcessAuthReply ( + 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[(int) + (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[(int) + (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 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[(int) + (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[(int) + (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) + { + const char *prefix = NULL; + char *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 : "; + } + + if (asprintf (&returnErrorString, "%s%s", prefix, errorString) == -1) + returnErrorString = NULL; + 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 iceConn, + unsigned long length, + Bool swap, + IceReplyWaitInfo *replyWait +) +{ + iceConnectionReplyMsg *message; + char *pData, *pStart, *pEnd; + Bool replyReady; + +#if 0 /* No-op */ + CHECK_AT_LEAST_SIZE (iceConn, ICE_ConnectionReply, + length, SIZEOF (iceConnectionReplyMsg), IceFatalToConnection); +#endif + + IceReadCompleteMessage (iceConn, SIZEOF (iceConnectionReplyMsg), + iceConnectionReplyMsg, message, pStart); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + pEnd = pStart + (length << 3); + + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING (iceConn, ICE_ConnectionReply, + pStart)); /* vendor */ + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING (iceConn, ICE_ConnectionReply, + pStart)); /* 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[(int) + (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 int +ProcessProtocolSetup ( + 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 **hisAuthNames = NULL; + char *protocolName; + char *pData, *pStart, *pEnd; + 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; + pEnd = pStart + (length << 3); + + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING(iceConn, ICE_ProtocolSetup, + pStart)); /* proto name */ + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING(iceConn, ICE_ProtocolSetup, + pStart)); /* vendor */ + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING(iceConn, ICE_ProtocolSetup, + pStart)); /* release */ + SKIP_LISTOF_STRING (pData, swap, (int) message->authCount, pEnd, + BAIL_STRING(iceConn, ICE_ProtocolSetup, + pStart)); /* 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, + (const char **) 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]) + { + const char *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 iceConn, + unsigned long length, + Bool swap, + IceReplyWaitInfo *replyWait +) +{ + iceProtocolReplyMsg *message; + char *pData, *pStart, *pEnd; + Bool replyReady; + +#if 0 /* No-op */ + CHECK_AT_LEAST_SIZE (iceConn, ICE_ProtocolReply, + length, SIZEOF (iceProtocolReplyMsg), IceFatalToProtocol); +#endif + + IceReadCompleteMessage (iceConn, SIZEOF (iceProtocolReplyMsg), + iceProtocolReplyMsg, message, pStart); + + if (!IceValidIO (iceConn)) + { + IceDisposeCompleteMessage (iceConn, pStart); + return (0); + } + + pData = pStart; + pEnd = pStart + (length << 3); + + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING(iceConn, ICE_ProtocolReply, + pStart)); /* vendor */ + SKIP_STRING (pData, swap, pEnd, + BAIL_STRING(iceConn, ICE_ProtocolReply, + pStart)); /* 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[(int) + (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 ((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 int +ProcessPing ( + IceConn iceConn, + unsigned long length +) +{ + CHECK_SIZE_MATCH (iceConn, ICE_Ping, + length, SIZEOF (icePingMsg), IceFatalToConnection, 0); + + PingReply (iceConn); + + return (0); +} + + + +static int +ProcessPingReply ( + IceConn iceConn, + unsigned long length +) +{ + CHECK_SIZE_MATCH (iceConn, ICE_PingReply, + length, SIZEOF (icePingReplyMsg), IceFatalToConnection, 0); + + 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 int +ProcessWantToClose ( + IceConn iceConn, + unsigned long length, + Bool *connectionClosedRet +) +{ + *connectionClosedRet = False; + + CHECK_SIZE_MATCH (iceConn, ICE_WantToClose, + length, SIZEOF (iceWantToCloseMsg), IceFatalToConnection, 0); + + 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 int +ProcessNoClose ( + IceConn iceConn, + unsigned long length +) +{ + CHECK_SIZE_MATCH (iceConn, ICE_NoClose, + length, SIZEOF (iceNoCloseMsg), IceFatalToConnection, 0); + + 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); +} + + + +static void +_IceProcessCoreMessage ( + 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; +} + +int _IceVersionCount = 1; +_IceVersion _IceVersions[] = { + {IceProtoMajor, IceProtoMinor, _IceProcessCoreMessage}}; + diff --git a/src/protosetup.c b/src/protosetup.c new file mode 100644 index 0000000..255b912 --- /dev/null +++ b/src/protosetup.c @@ -0,0 +1,288 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" + + +IceProtocolSetupStatus +IceProtocolSetup ( + 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 = NULL; + 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, + (const char **) 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..20a6ad0 --- /dev/null +++ b/src/register.c @@ -0,0 +1,235 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" + +int +IceRegisterForProtocolSetup ( + const char *protocolName, + const char *vendor, + const char *release, + int versionCount, + IcePoVersionRec *versionRecs, + int authCount, + const 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 = + strdup(protocolName); + + p = _IceProtocols[_IceLastMajorOpcode].orig_client = + (_IcePoProtocol *) malloc (sizeof (_IcePoProtocol)); + + _IceProtocols[_IceLastMajorOpcode].accept_client = NULL; + + opcodeRet = ++_IceLastMajorOpcode; + } + + p->vendor = strdup(vendor); + p->release = strdup(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] = strdup(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 ( + const char *protocolName, + const char *vendor, + const char *release, + int versionCount, + IcePaVersionRec *versionRecs, + int authCount, + const 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 = + strdup(protocolName); + + _IceProtocols[_IceLastMajorOpcode].orig_client = NULL; + + p = _IceProtocols[_IceLastMajorOpcode].accept_client = + (_IcePaProtocol *) malloc (sizeof (_IcePaProtocol)); + + opcodeRet = ++_IceLastMajorOpcode; + } + + p->vendor = strdup(vendor); + p->release = strdup(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] = strdup(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..eb3a814 --- /dev/null +++ b/src/replywait.c @@ -0,0 +1,156 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" + + +void +_IceAddReplyWait ( + 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 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 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 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..d190de5 --- /dev/null +++ b/src/setauth.c @@ -0,0 +1,112 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include + + +/* + * 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; +#ifndef __UNIXOS2__ +IceAuthDataEntry _IcePaAuthDataEntries[ICE_MAX_AUTH_DATA_ENTRIES]; +#else +IceAuthDataEntry _IcePaAuthDataEntries[ICE_MAX_AUTH_DATA_ENTRIES] = {0}; +#endif + + +void +IceSetPaAuthData ( + 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 + = strdup(entries[i].protocol_name); + + _IcePaAuthDataEntries[j].network_id + = strdup(entries[i].network_id); + + _IcePaAuthDataEntries[j].auth_name + = strdup(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..14874a0 --- /dev/null +++ b/src/shutdown.c @@ -0,0 +1,323 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" +#include + + +Status +IceProtocolShutdown ( + 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 iceConn, + Bool negotiate +) +{ + iceConn->skip_want_to_close = negotiate ? False : True; +} + + + +Bool +IceCheckShutdownNegotiation ( + IceConn iceConn +) +{ + return (iceConn->skip_want_to_close ? False : True); +} + + + +IceCloseStatus +IceCloseConnection ( + 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 +) +{ + 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..e414e19 --- /dev/null +++ b/src/watch.c @@ -0,0 +1,201 @@ +/****************************************************************************** + + +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 HAVE_CONFIG_H +#include +#endif +#include +#include "ICElibint.h" + + +Status +IceAddConnectionWatch ( + 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 ( + 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 +) +{ + _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 +) +{ + _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; + } +} -- 2.7.4