Index: ChangeLog
==================================================================
--- ChangeLog
+++ ChangeLog
@@ -1,6 +1,18 @@
 2000-08-15  Jeff Hobbs  <hobbs@scriptics.com>
+
+	* README.txt: added notes about need to use 8.2.0+.
+
+	* tlsInt.h:
+	* tls.c:
+	* tlsIO.c: corrected structure initialization to work when
+	compiling with 8.2.  Now compiles with 8.2+ and tested to work
+	with 8.2+ and dynamically adjust to the version of Tcl it was
+	loaded into.  TLS will fail the test suite with Tcl 8.2-8.3.1.
+
+	* tests/all.tcl: added catch around ::tcltest::normalizePath
+	because it doesn't exist in pre-8.3 tcltest.
 
 	* tests/simpleClient.tcl: 
 	* tests/simpleServer.tcl: added simple client/server test scripts
 	that use test certs and can do simple stress tests.
 

Index: tls.c
==================================================================
--- tls.c
+++ tls.c
@@ -1,9 +1,10 @@
 /*
  * Copyright (C) 1997-1999 Matt Newman <matt@novadigm.com>
+ * Copyright (C) 2000 Ajuba Solutions
  *
- * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tls.c,v 1.9 2000/08/15 00:02:08 hobbs Exp $
+ * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tls.c,v 1.10 2000/08/15 18:49:30 hobbs Exp $
  *
  * TLS (aka SSL) Channel - can be layered on any bi-directional
  * Tcl_Channel (Note: Requires Trf Core Patch)
  *
  * This was built (almost) from scratch based upon observation of

Index: tlsIO.c
==================================================================
--- tlsIO.c
+++ tlsIO.c
@@ -1,9 +1,10 @@
 /*
  * Copyright (C) 1997-2000 Matt Newman <matt@novadigm.com>
+ * Copyright (C) 2000 Ajuba Solutions
  *
- * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.9 2000/08/15 00:02:08 hobbs Exp $
+ * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsIO.c,v 1.10 2000/08/15 18:49:30 hobbs Exp $
  *
  * TLS (aka SSL) Channel - can be layered on any bi-directional
  * Tcl_Channel (Note: Requires Trf Core Patch)
  *
  * This was built from scratch based upon observation of OpenSSL 0.9.2B
@@ -18,18 +19,10 @@
  *
  */
 
 #include "tlsInt.h"
 
-/*
- * External functions
- */
-
-/*
- * Local Defines
- */
-
 /*
  * Forward declarations
  */
 
 static int	TlsBlockModeProc _ANSI_ARGS_((ClientData instanceData,
@@ -52,20 +45,17 @@
 			int mask));
 static void	TlsChannelHandlerTimer _ANSI_ARGS_ ((ClientData clientData));
 
 /*
  * This structure describes the channel type structure for TCP socket
- * based IO:
+ * based IO.  These are what the structures should look like, but we
+ * have to build them up at runtime to be correct depending on whether
+ * we are loaded into an 8.2.0-8.3.1 or 8.3.2+ Tcl interpreter.
  */
+#ifdef TLS_STATIC_STRUCTURES_NOT_USED
 static Tcl_ChannelType tlsChannelType2 = {
     "tls",		/* Type name. */
-#ifndef TCL_CHANNEL_VERSION_2
-    /*
-     * Avoids warning in Windows compiler when compiling with 8.3.1-.
-     */
-    (Tcl_DriverBlockModeProc *)
-#endif
     TCL_CHANNEL_VERSION_2,	/* A v2 channel (8.3.2+) */
     TlsCloseProc,	/* Close proc. */
     TlsInputProc,	/* Input proc. */
     TlsOutputProc,	/* Output proc. */
     NULL,		/* Seek proc. */
@@ -79,16 +69,10 @@
     TlsNotifyProc,	/* handlerProc. */
 };
 
 static Tcl_ChannelType tlsChannelType1 = {
     "tls",		/* Type name. */
-#ifdef TCL_CHANNEL_VERSION_2
-    /*
-     * Avoids warning in Windows compiler when compiling with 8.3.2+.
-     */
-    (Tcl_ChannelTypeVersion)
-#endif
     TlsBlockModeProc,	/* Set blocking/nonblocking mode.*/
     TlsCloseProc,	/* Close proc. */
     TlsInputProc,	/* Input proc. */
     TlsOutputProc,	/* Output proc. */
     NULL,		/* Seek proc. */
@@ -95,18 +79,150 @@
     NULL,		/* Set option proc. */
     TlsGetOptionProc,	/* Get option proc. */
     TlsWatchProc,	/* Initialize notifier. */
     TlsGetHandleProc,	/* Get file handle out of channel. */
 };
+#else
+static Tcl_ChannelType *tlsChannelType = NULL;
+#endif
 
+/*
+ *-------------------------------------------------------------------
+ *
+ * Tls_ChannelType --
+ *
+ *	Return the correct TLS channel driver info
+ *
+ * Results:
+ *	The correct channel driver for the current version of Tcl.
+ *
+ * Side effects:
+ *	None.
+ *
+ *-------------------------------------------------------------------
+ */
 Tcl_ChannelType *Tls_ChannelType()
 {
-    if (channelTypeVersion == TLS_CHANNEL_VERSION_2) {
-	return &tlsChannelType2;
-    } else {
-	return &tlsChannelType1;
+    /*
+     * Initialize the channel type if necessary
+     */
+    if (tlsChannelType == NULL) {
+	/*
+	 * Allocation of a new channeltype structure is not easy, because of
+	 * the various verson of the core and subsequent changes to the
+	 * structure. The main challenge is to allocate enough memory for
+	 * odern versions even if this extyension is compiled against one
+	 * of the older variant!
+	 *
+	 * (1) Versions before stubs (8.0.x) are simple, because they are
+	 *     supported only if the extension is compiled against exactly
+	 *     that version of the core.
+	 *
+	 * (2) With stubs we just determine the difference between the older
+	 *     and modern variant and overallocate accordingly if compiled
+	 *     against an older variant.
+	 */
+
+	int size = sizeof(Tcl_ChannelType); /* Base size */
+
+	/*
+	 * Size of a procedure pointer. We assume that all procedure
+	 * pointers are of the same size, regardless of exact type
+	 * (arguments and return values).
+	 *
+	 * 8.2.   First version containing close2proc. Baseline.
+	 * 8.3.2  Three additional vectors. Moved blockMode, new flush- and
+	 *        handlerProc's.
+	 *
+	 * => Compilation against earlier version has to overallocate three
+	 *    procedure pointers.
+	 */
+
+#ifdef EMULATE_CHANNEL_VERSION_2
+	size += 3 * procPtrSize;
+#endif
+
+	tlsChannelType = (Tcl_ChannelType *) ckalloc(size);
+	memset((VOID *) tlsChannelType, 0, size);
+
+	/*
+	 * Common elements of the structure (no changes in location or name)
+	 * close2Proc, seekProc, setOptionProc stay NULL.
+	 */
+
+	tlsChannelType->closeProc        = TlsCloseProc;
+	tlsChannelType->inputProc        = TlsInputProc;
+	tlsChannelType->outputProc       = TlsOutputProc;
+	tlsChannelType->getOptionProc    = TlsGetOptionProc;
+	tlsChannelType->watchProc        = TlsWatchProc;
+	tlsChannelType->getHandleProc    = TlsGetHandleProc;
+
+	/*
+	 * blockModeProc is a twister.  We have to make some runtime-choices,
+	 * depending on the version we compiled against.
+	 */
+
+#ifdef EMULATE_CHANNEL_VERSION_2
+	/*
+	 * We are compiling against an 8.3.1- core.  We have to create some
+	 * definitions for the new elements as the compiler does not know them
+	 * by name.
+	 */
+
+	if (channelTypeVersion == TLS_CHANNEL_VERSION_1) {
+	    /*
+	     * The 'version' element of 8.3.2 is in the the place of the
+	     * blockModeProc. For 8.2.0-8.3.1 we have to set our blockModeProc
+	     * into this place.
+	     */
+	    tlsChannelType->blockModeProc = TlsBlockModeProc;
+	} else /* channelTypeVersion == TLS_CHANNEL_VERSION_2 */ {
+	    /*
+	     * For the 8.3.2 core we present ourselves as a version 2
+	     * driver. This means a special value in version (ex
+	     * blockModeProc), blockModeProc in a different place and of
+	     * course usage of the handlerProc.  The last two have to
+	     * referenced with pointer magic because they aren't defined
+	     * otherwise.
+	     */
+
+	    tlsChannelType->blockModeProc =
+		(Tcl_DriverBlockModeProc*) TLS_CHANNEL_VERSION_2;
+	    (*((Tcl_DriverBlockModeProc**)(&(tlsChannelType->close2Proc)+1)))
+		= TlsBlockModeProc;
+	    (*((TlsDriverHandlerProc**)(&(tlsChannelType->close2Proc)+3)))
+		= TlsNotifyProc;
+	}
+#else
+	/*
+	 * Compiled against 8.3.2+. Direct access to all elements possible. Use
+	 * channelTypeVersion information to select the values to use.
+	 */
+
+	if (channelTypeVersion == TLS_CHANNEL_VERSION_1) {
+	    /*
+	     * The 'version' element of 8.3.2 is in the the place of the
+	     * blockModeProc. For the original patch in 8.1.x and the firstly
+	     * included (8.2) we have to set our blockModeProc into this
+	     * place.
+	     */
+	    tlsChannelType->version = (Tcl_ChannelTypeVersion)TlsBlockModeProc;
+	} else /* channelTypeVersion == TLS_CHANNEL_VERSION_2 */ {
+	    /*
+	     * For the 8.3.2 core we present ourselves as a version 2
+	     * driver. This means a special value in version (ex
+	     * blockModeProc), blockModeProc in a different place and of
+	     * course usage of the handlerProc.
+	     */
+
+	    tlsChannelType->version       = TCL_CHANNEL_VERSION_2;
+	    tlsChannelType->blockModeProc = TlsBlockModeProc;
+	    tlsChannelType->handlerProc   = TlsNotifyProc;
+	}
+#endif
     }
+    return tlsChannelType;
 }
 
 /*
  *-------------------------------------------------------------------
  *

Index: tlsInt.h
==================================================================
--- tlsInt.h
+++ tlsInt.h
@@ -1,9 +1,9 @@
 /*
  * Copyright (C) 1997-2000 Matt Newman <matt@novadigm.com>
  *
- * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsInt.h,v 1.6 2000/08/15 00:02:08 hobbs Exp $
+ * $Header: /home/rkeene/tmp/cvs2fossil/../tcltls/tls/tls/tlsInt.h,v 1.7 2000/08/15 18:49:31 hobbs Exp $
  *
  * TLS (aka SSL) Channel - can be layered on any bi-directional
  * Tcl_Channel (Note: Requires Trf Core Patch)
  *
  * This was built from scratch based upon observation of OpenSSL 0.9.2B
@@ -102,12 +102,12 @@
 
     char *err;
 } State;
 
 /*
- * The following definitions have to be usable for 8.0.x, 8.1.x, 8.2.x,
- * 8.3.[01], 8.3.2 and beyond. The differences between these versions:
+ * The following definitions have to be usable for 8.2.0-8.3.1 and 8.3.2+.
+ * The differences between these versions:
  *
  * 8.0-8.1:	There is no support for these in TLS 1.4 (get 1.3).  This
  *		was the version with the original patch.
  *
  * 8.2.0-	Changed semantics for Tcl_StackChannel (Tcl_ReplaceChannel).
@@ -115,11 +115,11 @@
  *		of the core from now on.
  *
  * 8.3.2+:	Stacked channels rewritten for better behaviour in some
  *		situations (closing). Some new API's, semantic changes.
  *
- * The following magic was taken from Trf 2.1 (Kupries).
+ * The following magic was adapted from Trf 2.1 (Kupries).
  */
 
 #define TLS_CHANNEL_VERSION_1	0x1
 #define TLS_CHANNEL_VERSION_2	0x2
 extern int channelTypeVersion;
@@ -162,16 +162,22 @@
 #define Tcl_GetStackedChannel ((tls_GetStackedChannel*) tclStubsPtr->reserved283)
 
 #endif /* Tcl_GetStackedChannel */
 
 
-#ifndef Tcl_WriteRaw
+#ifndef TCL_CHANNEL_VERSION_2
 /*
  * Core is older than 8.3.2.  Supply the missing definitions for
  * the new API's in 8.3.2.
  */
+#define EMULATE_CHANNEL_VERSION_2
+
+typedef struct TlsChannelTypeVersion_* TlsChannelTypeVersion;
+#define TCL_CHANNEL_VERSION_2	((TlsChannelTypeVersion) 0x2)
 
+typedef int (TlsDriverHandlerProc) _ANSI_ARGS_((ClientData instanceData,
+					int interestMask));
 /* 394 */
 typedef int (tls_ReadRaw)  _ANSI_ARGS_((Tcl_Channel chan, char *dst,
 					int bytesToRead));
 /* 395 */
 typedef int (tls_WriteRaw) _ANSI_ARGS_((Tcl_Channel chan, char *src,
@@ -195,19 +201,16 @@
 
 #define Tcl_ReadRaw		(*((tls_ReadRaw**)	(SLOT(394))))
 #define Tcl_WriteRaw		(*((tls_WriteRaw**)	(SLOT(395))))
 #define Tcl_GetTopChannel	(*((tls_GetTopChannel**)(SLOT(396))))
 
-typedef struct TlsChannelTypeVersion_* TlsChannelTypeVersion;
-#define TCL_CHANNEL_VERSION_2	((TlsChannelTypeVersion) 0x2)
-
 /*
  * Required, easy emulation.
  */
 #define Tcl_ChannelGetOptionProc(chanDriver) ((chanDriver)->getOptionProc)
 
-#endif /* Tcl_WriteRaw */
+#endif /* TCL_CHANNEL_VERSION_2 */
 
 #endif /* USE_TCL_STUBS */
 
 /*
  * Forward declarations