Initial revision

phil [2003-11-10 22:41:09]
Initial revision
Filename
csharp/MEET-2/App.ico
csharp/MEET-2/AssemblyInfo.cs
csharp/MEET-2/Connect.cs
csharp/MEET-2/Connect.resx
csharp/MEET-2/MEET-2.csproj
csharp/MEET-2/MEET-2.csproj.user
csharp/MEET-2/MEET-2.sln
csharp/MEET-2/MEET-2.suo
csharp/MEET-2/MEET-2.xml
csharp/MEET-2/MEETForm.cs
csharp/MEET-2/MEETForm.resx
csharp/MEET-2/Structure.txt
csharp/MEET-2/TODO.txt
csharp/MEET-2/bin/Debug/MEET-2.pdb
csharp/MEET-2/bin/Debug/MEET-2.xml
csharp/MEET-2/bin/Debug/MEETLib.dll
csharp/MEET-2/bin/Debug/MEETLib.pdb
csharp/MEET-2/bin/Release/MEETLib.dll
csharp/MEET-2/obj/Debug/MEET-2.exe.incr
csharp/MEET-2/obj/Debug/MEET-2.pdb
csharp/MEET-2/obj/Debug/MEET-2.projdata
csharp/MEET-2/obj/Debug/MEET_2.Connect.resources
csharp/MEET-2/obj/Debug/MEET_2.MEETForm.resources
csharp/MEET-2/obj/Debug/MEET_PPC.Connect.resources
csharp/MEET-2/obj/Debug/MEET_PPC.MEETForm.resources
csharp/MEET-2/obj/Interop.MediaPlayer.dll
csharp/MEET-2/obj/Release/MEET-2.projdata
csharp/MEETLib/App.config
csharp/MEETLib/AssemblyInfo.cs
csharp/MEETLib/IMEETInputQueue.cs
csharp/MEETLib/MEETChannel.cs
csharp/MEETLib/MEETClock.cs
csharp/MEETLib/MEETContainer.cs
csharp/MEETLib/MEETDataPacket.cs
csharp/MEETLib/MEETException.cs
csharp/MEETLib/MEETIFace.cs
csharp/MEETLib/MEETIPEndPoint.cs
csharp/MEETLib/MEETInDespatch.cs
csharp/MEETLib/MEETLib.csproj
csharp/MEETLib/MEETLib.csproj.user
csharp/MEETLib/MEETModule.cs
csharp/MEETLib/MEETNode.cs
csharp/MEETLib/MEETPCQueue.cs
csharp/MEETLib/MEETPacket.cs
csharp/MEETLib/MEETQModule.cs
csharp/MEETLib/MEETRecvPacket.cs
csharp/MEETLib/MEETSockConnection.cs
csharp/MEETLib/MEETSockListener.cs
csharp/MEETLib/MEETSockSender.cs
csharp/MEETLib/MEETTcpSockListener.cs
csharp/MEETLib/MEETTcpSockSender.cs
csharp/MEETLib/MEETUdpSockListener.cs
csharp/MEETLib/MEETUdpSockSender.cs
csharp/MEETLib/bin/Debug/MEETLib.dll
csharp/MEETLib/bin/Debug/MEETLib.pdb
csharp/MEETLib/bin/Release/MEETLib.dll
csharp/MEETLib/obj/Debug/MEETLib.dll
csharp/MEETLib/obj/Debug/MEETLib.pdb
csharp/MEETLib/obj/Debug/MEETLib.projdata
csharp/MEETLib/obj/Release/MEETLib.dll
csharp/MEETLib/obj/Release/MEETLib.projdata
csharp/MEETTest/App.ico
csharp/MEETTest/AssemblyInfo.cs
csharp/MEETTest/MEETTest.cs
csharp/MEETTest/MEETTest.csproj
csharp/MEETTest/MEETTest.csproj.user
csharp/MEETTest/bin/Debug/MEETLib.dll
csharp/MEETTest/bin/Debug/MEETLib.pdb
csharp/MEETTest/bin/Debug/MEETTest.pdb
csharp/MEETTest/bin/Debug/doc.xml
csharp/MEETTest/bin/Release/MEETLib.dll
csharp/MEETTest/doc.xml
csharp/MEETTest/obj/Debug/MEETTest.pdb
csharp/MEETTest/obj/Debug/MEETTest.projdata
csharp/MEETTest/obj/Release/MEETTest.projdata
diff --git a/csharp/MEET-2/App.ico b/csharp/MEET-2/App.ico
new file mode 100644
index 0000000..3a5525f
Binary files /dev/null and b/csharp/MEET-2/App.ico differ
diff --git a/csharp/MEET-2/AssemblyInfo.cs b/csharp/MEET-2/AssemblyInfo.cs
new file mode 100644
index 0000000..f9970f4
--- /dev/null
+++ b/csharp/MEET-2/AssemblyInfo.cs
@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("MEET-2")]
+[assembly: AssemblyDescription("C# Windows Forms interface to MEET")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("(c)2003 The Trustees of Columbia University in the City of New York")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
diff --git a/csharp/MEET-2/Connect.cs b/csharp/MEET-2/Connect.cs
new file mode 100644
index 0000000..72ce6da
--- /dev/null
+++ b/csharp/MEET-2/Connect.cs
@@ -0,0 +1,355 @@
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Net;
+using System.Net.Sockets;
+using MEETLib;
+
+namespace MEET_2
+{
+	/// <summary>
+	/// Summary description for Connect.
+	/// </summary>
+	public class Connect : System.Windows.Forms.Form {
+		private System.Windows.Forms.Button bConnect;
+		private System.Windows.Forms.Button bCancel;
+		private System.Windows.Forms.TextBox tbPort;
+		private System.Windows.Forms.ListBox lbLocalIP;
+
+		private System.Windows.Forms.CheckBox cbMulticast;
+		private System.Windows.Forms.Label label3;
+
+		private ushort m_LocalPort = 0;
+		private ushort m_RemotePort = 0;
+		private MEETIPEndPoint m_mipLocalEndPoint = null;
+		private MEETIPEndPoint m_mipRemoteEndPoint = null;
+
+		private MEETNode m_node = null;
+		private System.Windows.Forms.Label lLocalIP;
+		private System.Windows.Forms.Label lLocalPort;
+		private System.Windows.Forms.ComboBox cbRemoteIP;
+		private System.Windows.Forms.Label lRemotePort;
+		private System.Windows.Forms.TextBox tbRemotePort;
+		private System.Windows.Forms.Label label2;
+		private IList m_log = null;
+
+		/// <summary>
+		/// local endpoint
+		/// </summary>
+		public MEETIPEndPoint MipLocalEndPoint {
+			get { return m_mipLocalEndPoint;}
+		}
+		/// <summary>
+		/// remote we're talking to
+		/// </summary>
+		public MEETIPEndPoint MipRemoteEndPoint {
+			get { return m_mipRemoteEndPoint;}
+		}
+
+		/// <summary>
+		/// Connect socket to remote system
+		/// </summary>
+		/// <param name="node"></param>
+		public Connect(MEETNode node) {
+			//
+			// Required for Windows Form Designer support
+			//
+			InitializeComponent();
+
+			//
+			// TODO: Add any constructor code after InitializeComponent call
+			//
+
+			m_node = node;
+			m_log = m_node.Log;
+
+
+			// discover local IPs
+			IPHostEntry localHE = null;
+			try {
+				localHE = Dns.GetHostByName(Dns.GetHostName());
+			} catch (SocketException se) {
+				MessageBox.Show("Error getting list of local IPs: " + se.Message,
+					"Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			for (int i=0; i<localHE.AddressList.Length; ++i) {
+				lbLocalIP.Items.Add(localHE.AddressList[i]);
+			}
+			lbLocalIP.SelectedItem = lbLocalIP.Items[0];
+
+			// PNG - make dialog buttons work as expected
+			bConnect.DialogResult = DialogResult.OK;
+			bCancel.DialogResult = DialogResult.Cancel;
+			cbRemoteIP.Items.AddRange(new object[] {
+																							 "128.59.14.137",
+																							 "128.59.14.140",
+																							 "128.59.14.153",
+																							 "10.0.0.100",
+																							 "10.0.0.102"
+																						 });
+		}
+
+		/// <summary>
+		/// Clean up any resources being used.
+		/// </summary>
+		protected override void Dispose( bool disposing ) {
+			base.Dispose( disposing );
+		}
+
+		#region Windows Form Designer generated code
+		/// <summary>
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// </summary>
+		private void InitializeComponent() {
+			this.bConnect = new System.Windows.Forms.Button();
+			this.bCancel = new System.Windows.Forms.Button();
+			this.lLocalIP = new System.Windows.Forms.Label();
+			this.lLocalPort = new System.Windows.Forms.Label();
+			this.tbPort = new System.Windows.Forms.TextBox();
+			this.cbMulticast = new System.Windows.Forms.CheckBox();
+			this.label3 = new System.Windows.Forms.Label();
+			this.cbRemoteIP = new System.Windows.Forms.ComboBox();
+			this.lRemotePort = new System.Windows.Forms.Label();
+			this.tbRemotePort = new System.Windows.Forms.TextBox();
+			this.label2 = new System.Windows.Forms.Label();
+			this.lbLocalIP = new System.Windows.Forms.ListBox();
+			this.SuspendLayout();
+			//
+			// bConnect
+			//
+			this.bConnect.Location = new System.Drawing.Point(8, 208);
+			this.bConnect.Name = "bConnect";
+			this.bConnect.Size = new System.Drawing.Size(56, 20);
+			this.bConnect.TabIndex = 7;
+			this.bConnect.Text = "Connect";
+			this.bConnect.Click += new System.EventHandler(this.bConnect_Click);
+			//
+			// bCancel
+			//
+			this.bCancel.Location = new System.Drawing.Point(88, 208);
+			this.bCancel.Name = "bCancel";
+			this.bCancel.Size = new System.Drawing.Size(56, 20);
+			this.bCancel.TabIndex = 6;
+			this.bCancel.Text = "Cancel";
+			this.bCancel.Click += new System.EventHandler(this.bCancel_Click);
+			//
+			// lLocalIP
+			//
+			this.lLocalIP.Location = new System.Drawing.Point(8, 12);
+			this.lLocalIP.Name = "lLocalIP";
+			this.lLocalIP.Size = new System.Drawing.Size(56, 16);
+			this.lLocalIP.TabIndex = 4;
+			this.lLocalIP.Text = " Local IP";
+			//
+			// lLocalPort
+			//
+			this.lLocalPort.Location = new System.Drawing.Point(8, 42);
+			this.lLocalPort.Name = "lLocalPort";
+			this.lLocalPort.Size = new System.Drawing.Size(56, 16);
+			this.lLocalPort.TabIndex = 2;
+			this.lLocalPort.Text = "Local Port";
+			//
+			// tbPort
+			//
+			this.tbPort.Location = new System.Drawing.Point(80, 40);
+			this.tbPort.Name = "tbPort";
+			this.tbPort.Size = new System.Drawing.Size(112, 20);
+			this.tbPort.TabIndex = 3;
+			this.tbPort.Text = "61166";
+			//
+			// cbMulticast
+			//
+			this.cbMulticast.Location = new System.Drawing.Point(88, 176);
+			this.cbMulticast.Name = "cbMulticast";
+			this.cbMulticast.Size = new System.Drawing.Size(16, 16);
+			this.cbMulticast.TabIndex = 1;
+			this.cbMulticast.Text = "checkBox1";
+			//
+			// label3
+			//
+			this.label3.Location = new System.Drawing.Point(8, 176);
+			this.label3.Name = "label3";
+			this.label3.Size = new System.Drawing.Size(72, 20);
+			this.label3.TabIndex = 0;
+			this.label3.Text = "Multicast?";
+			//
+			// cbRemoteIP
+			//
+			this.cbRemoteIP.Location = new System.Drawing.Point(80, 88);
+			this.cbRemoteIP.Name = "cbRemoteIP";
+			this.cbRemoteIP.Size = new System.Drawing.Size(144, 21);
+			this.cbRemoteIP.TabIndex = 12;
+			//
+			// lRemotePort
+			//
+			this.lRemotePort.Location = new System.Drawing.Point(0, 136);
+			this.lRemotePort.Name = "lRemotePort";
+			this.lRemotePort.Size = new System.Drawing.Size(72, 16);
+			this.lRemotePort.TabIndex = 9;
+			this.lRemotePort.Text = "Remote Port";
+			//
+			// tbRemotePort
+			//
+			this.tbRemotePort.Location = new System.Drawing.Point(80, 128);
+			this.tbRemotePort.Name = "tbRemotePort";
+			this.tbRemotePort.Size = new System.Drawing.Size(112, 20);
+			this.tbRemotePort.TabIndex = 10;
+			this.tbRemotePort.Text = "61166";
+			//
+			// label2
+			//
+			this.label2.Location = new System.Drawing.Point(8, 96);
+			this.label2.Name = "label2";
+			this.label2.Size = new System.Drawing.Size(59, 16);
+			this.label2.TabIndex = 11;
+			this.label2.Text = "Remote IP";
+			//
+			// lbLocalIP
+			//
+			this.lbLocalIP.Location = new System.Drawing.Point(80, 12);
+			this.lbLocalIP.Name = "lbLocalIP";
+			this.lbLocalIP.Size = new System.Drawing.Size(112, 17);
+			this.lbLocalIP.TabIndex = 13;
+			//
+			// Connect
+			//
+			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+			this.ClientSize = new System.Drawing.Size(234, 239);
+			this.ControlBox = false;
+			this.Controls.Add(this.lbLocalIP);
+			this.Controls.Add(this.cbRemoteIP);
+			this.Controls.Add(this.lRemotePort);
+			this.Controls.Add(this.tbRemotePort);
+			this.Controls.Add(this.label2);
+			this.Controls.Add(this.label3);
+			this.Controls.Add(this.cbMulticast);
+			this.Controls.Add(this.lLocalPort);
+			this.Controls.Add(this.tbPort);
+			this.Controls.Add(this.lLocalIP);
+			this.Controls.Add(this.bCancel);
+			this.Controls.Add(this.bConnect);
+			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+			this.MaximizeBox = false;
+			this.MinimizeBox = false;
+			this.Name = "Connect";
+			this.Text = "Connect";
+			this.Load += new System.EventHandler(this.Connect_Load);
+			this.ResumeLayout(false);
+
+		}
+		#endregion
+
+		private void Connect_Load(object sender, System.EventArgs e) {
+
+		}
+
+		private void bCancel_Click(object sender, System.EventArgs e) {
+		}
+
+		private void bConnect_Click(object sender, System.EventArgs e) {
+			IPHostEntry iphe;
+			IPAddress locIpaddr;
+			m_log.Add("Checking local address...");
+
+			if (lbLocalIP.Text.Length == 0) {
+				MessageBox.Show("Local IP address required", "Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			try {
+				iphe = Dns.Resolve(lbLocalIP.Text);
+			}
+			catch (Exception ex) {
+				MessageBox.Show("Invalid Local IP Address: " + ex.Message,
+					"Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			locIpaddr = iphe.AddressList[0];
+			m_log.Add("\tdone.");
+			m_log.Add("Checking local port...");
+
+			if (tbPort.Text.Length == 0) {
+				MessageBox.Show("Local UDP Port Required", "Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			try {
+				m_LocalPort = UInt16.Parse(tbPort.Text);
+			}
+			catch (Exception ex) {
+				MessageBox.Show("0 < local port < 65536: " + ex.Message,
+					"Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			m_mipLocalEndPoint = new MEETIPEndPoint(locIpaddr, m_LocalPort);
+
+			m_log.Add("\tdone.");
+
+			IPAddress remIpaddr;
+			m_log.Add("Checking remote address...");
+
+			if (cbRemoteIP.Text.Length == 0) {
+				MessageBox.Show("Remote IP address required", "Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			try {
+				iphe = Dns.Resolve(cbRemoteIP.Text);
+			}
+			catch (Exception ex) {
+				MessageBox.Show("Invalid Remote IP Address: " + ex.Message,
+					"Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			remIpaddr = iphe.AddressList[0];
+			m_log.Add("\tdone.");
+			m_log.Add("Checking remote port...");
+
+			if (tbRemotePort.Text.Length == 0) {
+				MessageBox.Show("UDP Remote Port Required", "Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			try {
+				m_RemotePort = UInt16.Parse(tbRemotePort.Text);
+			}
+			catch (Exception ex) {
+				MessageBox.Show("0 < remote port < 65536: " + ex.Message,
+					"Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				return;
+			}
+			m_mipRemoteEndPoint = new MEETIPEndPoint(remIpaddr, m_RemotePort);
+			m_log.Add("\tdone.");
+
+		}
+
+	}
+
+}
diff --git a/csharp/MEET-2/Connect.resx b/csharp/MEET-2/Connect.resx
new file mode 100644
index 0000000..24799d6
--- /dev/null
+++ b/csharp/MEET-2/Connect.resx
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema
+
+    Version 1.3
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">1.3</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1">this is my long string</data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        [base64 mime encoded serialized .NET Framework object]
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        [base64 mime encoded string representing a byte array form of the .NET Framework object]
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used forserialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>1.3</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="bConnect.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="bConnect.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="bConnect.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="bCancel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="bCancel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="bCancel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lLocalIP.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="lLocalIP.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lLocalIP.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lLocalPort.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="lLocalPort.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lLocalPort.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="tbPort.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="tbPort.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="tbPort.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="cbMulticast.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="cbMulticast.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="cbMulticast.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="label3.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="label3.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="label3.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="cbRemoteIP.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="cbRemoteIP.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="cbRemoteIP.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lRemotePort.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="lRemotePort.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lRemotePort.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="tbRemotePort.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="tbRemotePort.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="tbRemotePort.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="label2.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="label2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="label2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lbLocalIP.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lbLocalIP.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="lbLocalIP.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>(Default)</value>
+  </data>
+  <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>8, 8</value>
+  </data>
+  <data name="$this.Name">
+    <value>Connect</value>
+  </data>
+  <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </data>
+  <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>80</value>
+  </data>
+  <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </data>
+  <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/csharp/MEET-2/MEET-2.csproj b/csharp/MEET-2/MEET-2.csproj
new file mode 100644
index 0000000..a081a11
--- /dev/null
+++ b/csharp/MEET-2/MEET-2.csproj
@@ -0,0 +1,150 @@
+<VisualStudioProject>
+    <CSHARP
+        ProjectType = "Local"
+        ProductVersion = "7.10.3077"
+        SchemaVersion = "2.0"
+        ProjectGuid = "{6EE49AE9-0B70-430A-B58F-2DFEC0663AD5}"
+    >
+        <Build>
+            <Settings
+                ApplicationIcon = "App.ico"
+                AssemblyKeyContainerName = ""
+                AssemblyName = "MEET-2"
+                AssemblyOriginatorKeyFile = ""
+                DefaultClientScript = "JScript"
+                DefaultHTMLPageLayout = "Grid"
+                DefaultTargetSchema = "IE50"
+                DelaySign = "false"
+                OutputType = "WinExe"
+                PreBuildEvent = ""
+                PostBuildEvent = ""
+                RootNamespace = "MEET_2"
+                RunPostBuildEvent = "OnBuildSuccess"
+                StartupObject = ""
+            >
+                <Config
+                    Name = "Debug"
+                    AllowUnsafeBlocks = "true"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "DEBUG;TRACE"
+                    DocumentationFile = "MEET-2.xml"
+                    DebugSymbols = "true"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "true"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "false"
+                    OutputPath = "bin\Debug\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+                <Config
+                    Name = "Release"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "TRACE"
+                    DocumentationFile = ""
+                    DebugSymbols = "false"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "true"
+                    OutputPath = "bin\Release\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+            </Settings>
+            <References>
+                <Reference
+                    Name = "System"
+                    AssemblyName = "System"
+                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.dll"
+                />
+                <Reference
+                    Name = "System.Data"
+                    AssemblyName = "System.Data"
+                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Data.dll"
+                />
+                <Reference
+                    Name = "System.Drawing"
+                    AssemblyName = "System.Drawing"
+                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Drawing.dll"
+                />
+                <Reference
+                    Name = "System.Windows.Forms"
+                    AssemblyName = "System.Windows.Forms"
+                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.Windows.Forms.dll"
+                />
+                <Reference
+                    Name = "System.XML"
+                    AssemblyName = "System.Xml"
+                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.0.3705\System.XML.dll"
+                />
+                <Reference
+                    Name = "MEETLib"
+                    Project = "{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}"
+                    Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+                />
+                <Reference
+                    Name = "stdole"
+                    Guid = "{00020430-0000-0000-C000-000000000046}"
+                    VersionMajor = "2"
+                    VersionMinor = "0"
+                    Lcid = "0"
+                    WrapperTool = "primary"
+                />
+            </References>
+        </Build>
+        <Files>
+            <Include>
+                <File
+                    RelPath = "App.ico"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "AssemblyInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Connect.cs"
+                    SubType = "Form"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "Connect.resx"
+                    DependentUpon = "Connect.cs"
+                    BuildAction = "EmbeddedResource"
+                />
+                <File
+                    RelPath = "MEETForm.cs"
+                    SubType = "Form"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETForm.resx"
+                    DependentUpon = "MEETForm.cs"
+                    BuildAction = "EmbeddedResource"
+                />
+                <File
+                    RelPath = "Structure.txt"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "TODO.txt"
+                    BuildAction = "Content"
+                />
+            </Include>
+        </Files>
+    </CSHARP>
+</VisualStudioProject>
+
diff --git a/csharp/MEET-2/MEET-2.csproj.user b/csharp/MEET-2/MEET-2.csproj.user
new file mode 100644
index 0000000..69ac193
--- /dev/null
+++ b/csharp/MEET-2/MEET-2.csproj.user
@@ -0,0 +1,48 @@
+<VisualStudioProject>
+    <CSHARP LastOpenVersion = "7.10.3077" >
+        <Build>
+            <Settings ReferencePath = "" >
+                <Config
+                    Name = "Debug"
+                    EnableASPDebugging = "false"
+                    EnableASPXDebugging = "false"
+                    EnableUnmanagedDebugging = "false"
+                    EnableSQLServerDebugging = "false"
+                    RemoteDebugEnabled = "false"
+                    RemoteDebugMachine = ""
+                    StartAction = "Project"
+                    StartArguments = ""
+                    StartPage = ""
+                    StartProgram = ""
+                    StartURL = ""
+                    StartWorkingDirectory = ""
+                    StartWithIE = "false"
+                />
+                <Config
+                    Name = "Release"
+                    EnableASPDebugging = "false"
+                    EnableASPXDebugging = "false"
+                    EnableUnmanagedDebugging = "false"
+                    EnableSQLServerDebugging = "false"
+                    RemoteDebugEnabled = "false"
+                    RemoteDebugMachine = ""
+                    StartAction = "Project"
+                    StartArguments = ""
+                    StartPage = ""
+                    StartProgram = ""
+                    StartURL = ""
+                    StartWorkingDirectory = ""
+                    StartWithIE = "false"
+                />
+            </Settings>
+        </Build>
+        <OtherProjectSettings
+            CopyProjectDestinationFolder = ""
+            CopyProjectUncPath = ""
+            CopyProjectOption = "0"
+            ProjectView = "ProjectFiles"
+            ProjectTrust = "0"
+        />
+    </CSHARP>
+</VisualStudioProject>
+
diff --git a/csharp/MEET-2/MEET-2.sln b/csharp/MEET-2/MEET-2.sln
new file mode 100644
index 0000000..ad0fd77
--- /dev/null
+++ b/csharp/MEET-2/MEET-2.sln
@@ -0,0 +1,38 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MEETLib", "..\MEETLib\MEETLib.csproj", "{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MEET-2", "MEET-2.csproj", "{6EE49AE9-0B70-430A-B58F-2DFEC0663AD5}"
+	ProjectSection(ProjectDependencies) = postProject
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MEETTest", "..\MEETTest\MEETTest.csproj", "{AE73A884-5D4E-4BB2-B866-47DFF2907845}"
+	ProjectSection(ProjectDependencies) = postProject
+		{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362} = {DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}
+	EndProjectSection
+EndProject
+Global
+	GlobalSection(SolutionConfiguration) = preSolution
+		Debug = Debug
+		Release = Release
+	EndGlobalSection
+	GlobalSection(ProjectConfiguration) = postSolution
+		{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}.Debug.ActiveCfg = Debug|.NET
+		{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}.Debug.Build.0 = Debug|.NET
+		{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}.Release.ActiveCfg = Release|.NET
+		{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}.Release.Build.0 = Release|.NET
+		{6EE49AE9-0B70-430A-B58F-2DFEC0663AD5}.Debug.ActiveCfg = Debug|.NET
+		{6EE49AE9-0B70-430A-B58F-2DFEC0663AD5}.Debug.Build.0 = Debug|.NET
+		{6EE49AE9-0B70-430A-B58F-2DFEC0663AD5}.Release.ActiveCfg = Release|.NET
+		{6EE49AE9-0B70-430A-B58F-2DFEC0663AD5}.Release.Build.0 = Release|.NET
+		{AE73A884-5D4E-4BB2-B866-47DFF2907845}.Debug.ActiveCfg = Debug|.NET
+		{AE73A884-5D4E-4BB2-B866-47DFF2907845}.Debug.Build.0 = Debug|.NET
+		{AE73A884-5D4E-4BB2-B866-47DFF2907845}.Release.ActiveCfg = Release|.NET
+		{AE73A884-5D4E-4BB2-B866-47DFF2907845}.Release.Build.0 = Release|.NET
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+	EndGlobalSection
+	GlobalSection(ExtensibilityAddIns) = postSolution
+	EndGlobalSection
+EndGlobal
diff --git a/csharp/MEET-2/MEET-2.suo b/csharp/MEET-2/MEET-2.suo
new file mode 100644
index 0000000..3599f1b
--- /dev/null
+++ b/csharp/MEET-2/MEET-2.suo
@@ -0,0 +1 @@
+ÐÏࡱ
\ No newline at end of file
diff --git a/csharp/MEET-2/MEET-2.xml b/csharp/MEET-2/MEET-2.xml
new file mode 100644
index 0000000..fc19f86
--- /dev/null
+++ b/csharp/MEET-2/MEET-2.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>MEET-2</name>
+    </assembly>
+    <members>
+        <member name="T:MEET_2.Connect">
+            <summary>
+            Summary description for Connect.
+            </summary>
+        </member>
+        <member name="M:MEET_2.Connect.#ctor(MEETLib.MEETNode)">
+            <summary>
+            Connect socket to remote system
+            </summary>
+            <param name="node"></param>
+        </member>
+        <member name="M:MEET_2.Connect.Dispose(System.Boolean)">
+            <summary>
+            Clean up any resources being used.
+            </summary>
+        </member>
+        <member name="M:MEET_2.Connect.InitializeComponent">
+            <summary>
+            Required method for Designer support - do not modify
+            the contents of this method with the code editor.
+            </summary>
+        </member>
+        <member name="P:MEET_2.Connect.MipLocalEndPoint">
+            <summary>
+            local endpoint
+            </summary>
+        </member>
+        <member name="P:MEET_2.Connect.MipRemoteEndPoint">
+            <summary>
+            remote we're talking to
+            </summary>
+        </member>
+        <member name="T:MEET_2.MEETForm">
+            <summary>
+            Summary description for Form1.
+            </summary>
+        </member>
+        <member name="F:MEET_2.MEETForm.m_name">
+            <summary>
+            Class name
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.#ctor">
+            <summary>
+            Input form for demo
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.Dispose(System.Boolean)">
+            <summary>
+            Clean up any resources being used.
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.InitializeComponent">
+            <summary>
+            Required method for Designer support - do not modify
+            the contents of this method with the code editor.
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.Main">
+            <summary>
+            The main entry point for the application.
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.Scroller(System.Object,System.EventArgs)">
+            <summary>
+            Keep bottom of list in view
+            </summary>
+            <param name="sender"></param>
+            <param name="ea"></param>
+        </member>
+    </members>
+</doc>
diff --git a/csharp/MEET-2/MEETForm.cs b/csharp/MEET-2/MEETForm.cs
new file mode 100644
index 0000000..8f3b39a
--- /dev/null
+++ b/csharp/MEET-2/MEETForm.cs
@@ -0,0 +1,388 @@
+using System;
+using System.Configuration;
+using System.IO;
+using System.Drawing;
+using System.Collections;
+using System.Windows.Forms;
+using System.Data;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using System.Text;
+using MEETLib;
+
+namespace MEET_2
+{
+	/// <summary>
+	/// Summary description for Form1.
+	/// </summary>
+	public class MEETForm : System.Windows.Forms.Form {
+
+		private System.Windows.Forms.MainMenu mainMenu1;
+
+		private System.Windows.Forms.MenuItem mnuFile;
+		private System.Windows.Forms.MenuItem mnuConnections;
+		private System.Windows.Forms.MenuItem mnuConnect;
+		private System.Windows.Forms.MenuItem mnuExit;
+
+		private System.Windows.Forms.MenuItem mnuChannels;
+		private System.Windows.Forms.MenuItem mnuAdvertise;
+		private System.Windows.Forms.MenuItem mnuUnadvertise;
+		private System.Windows.Forms.MenuItem SepChan1;
+		private System.Windows.Forms.MenuItem mnuSubscribe;
+		private System.Windows.Forms.MenuItem mnuUnsubscribe;
+		private System.Windows.Forms.MenuItem SepChan2;
+		private System.Windows.Forms.MenuItem mnuPublish;
+
+		private System.Windows.Forms.ListBox lbConnections;
+		private System.Windows.Forms.ComboBox cbChannel;
+		private System.Windows.Forms.Label lChannel;
+		private System.Windows.Forms.Label lText;
+		private System.Windows.Forms.TextBox tbText;
+		private System.Windows.Forms.ListBox lbLog;
+
+		/// <summary>
+		/// Class name
+		/// </summary>
+		public const string m_name = "MEETForm";
+		private IList m_log, m_error;
+		private MEETNode m_node = null;
+		internal string s_hostname = null;
+
+
+		/// <summary>
+		/// Input form for demo
+		/// </summary>
+		public MEETForm() {
+			//
+			// Required for Windows Form Designer support
+			//
+			InitializeComponent();
+
+			//
+			// TODO: Add any constructor code after InitializeComponent call
+			//
+			m_node = new MEETNode("RootNode");
+			m_log = m_node.Log = lbLog.Items;
+			m_error = m_node.Log = lbLog.Items; // same one, for now
+			try {
+				s_hostname = Dns.GetHostName();
+			} catch (SocketException se) {
+				MessageBox.Show("Error getting local hostname: " + se.Message,
+					"Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				s_hostname = "<unknown>";
+			}
+
+			cbChannel.Items.AddRange(new object[] {
+													  "http://www.example.com/namespace/types/foo",
+													  "MyTypeName",
+													  "ChannelZero",
+													  "7thCav3rdInf",
+													  "Sector12"
+												  });
+
+		}
+		/// <summary>
+		/// Clean up any resources being used.
+		/// </summary>
+		protected override void Dispose( bool disposing ) {
+			base.Dispose( disposing );
+		}
+		#region Windows Form Designer generated code
+		/// <summary>
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// </summary>
+		private void InitializeComponent() {
+			this.mainMenu1 = new System.Windows.Forms.MainMenu();
+			this.mnuFile = new System.Windows.Forms.MenuItem();
+			this.mnuConnect = new System.Windows.Forms.MenuItem();
+			this.mnuConnections = new System.Windows.Forms.MenuItem();
+			this.mnuExit = new System.Windows.Forms.MenuItem();
+			this.mnuChannels = new System.Windows.Forms.MenuItem();
+			this.mnuAdvertise = new System.Windows.Forms.MenuItem();
+			this.mnuUnadvertise = new System.Windows.Forms.MenuItem();
+			this.SepChan1 = new System.Windows.Forms.MenuItem();
+			this.mnuSubscribe = new System.Windows.Forms.MenuItem();
+			this.mnuUnsubscribe = new System.Windows.Forms.MenuItem();
+			this.SepChan2 = new System.Windows.Forms.MenuItem();
+			this.mnuPublish = new System.Windows.Forms.MenuItem();
+			this.tbText = new System.Windows.Forms.TextBox();
+			this.lChannel = new System.Windows.Forms.Label();
+			this.lText = new System.Windows.Forms.Label();
+			this.cbChannel = new System.Windows.Forms.ComboBox();
+			this.lbLog = new System.Windows.Forms.ListBox();
+			this.lbConnections = new System.Windows.Forms.ListBox();
+			this.SuspendLayout();
+			//
+			// mainMenu1
+			//
+			this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+																					  this.mnuFile,
+																					  this.mnuChannels});
+			//
+			// mnuFile
+			//
+			this.mnuFile.Index = 0;
+			this.mnuFile.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+																					this.mnuConnect,
+																					this.mnuConnections,
+																					this.mnuExit});
+			this.mnuFile.Text = "File";
+			//
+			// mnuConnect
+			//
+			this.mnuConnect.Index = 0;
+			this.mnuConnect.Text = "Connect...";
+			this.mnuConnect.Click += new System.EventHandler(this.mnuConnect_Click);
+			//
+			// mnuConnections
+			//
+			this.mnuConnections.Index = 1;
+			this.mnuConnections.Text = "Connections...";
+			this.mnuConnections.Click += new System.EventHandler(this.mnuConnections_Click);
+			//
+			// mnuExit
+			//
+			this.mnuExit.Index = 2;
+			this.mnuExit.Text = "Exit";
+			this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click);
+			//
+			// mnuChannels
+			//
+			this.mnuChannels.Index = 1;
+			this.mnuChannels.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
+																						this.mnuAdvertise,
+																						this.mnuUnadvertise,
+																						this.SepChan1,
+																						this.mnuSubscribe,
+																						this.mnuUnsubscribe,
+																						this.SepChan2,
+																						this.mnuPublish});
+			this.mnuChannels.Text = "Channels";
+			//
+			// mnuAdvertise
+			//
+			this.mnuAdvertise.Index = 0;
+			this.mnuAdvertise.Text = "Advertise";
+			//
+			// mnuUnadvertise
+			//
+			this.mnuUnadvertise.Index = 1;
+			this.mnuUnadvertise.Text = "Unadvertise";
+			//
+			// SepChan1
+			//
+			this.SepChan1.Index = 2;
+			this.SepChan1.Text = "-";
+			//
+			// mnuSubscribe
+			//
+			this.mnuSubscribe.Index = 3;
+			this.mnuSubscribe.Text = "Subscribe";
+			//
+			// mnuUnsubscribe
+			//
+			this.mnuUnsubscribe.Index = 4;
+			this.mnuUnsubscribe.Text = "Unsubscribe";
+			//
+			// SepChan2
+			//
+			this.SepChan2.Index = 5;
+			this.SepChan2.Text = "-";
+			//
+			// mnuPublish
+			//
+			this.mnuPublish.Index = 6;
+			this.mnuPublish.Text = "Publish";
+			this.mnuPublish.Click += new System.EventHandler(this.mnuPublish_Click);
+			//
+			// tbText
+			//
+			this.tbText.Location = new System.Drawing.Point(72, 192);
+			this.tbText.Multiline = true;
+			this.tbText.Name = "tbText";
+			this.tbText.Size = new System.Drawing.Size(128, 64);
+			this.tbText.TabIndex = 1;
+			this.tbText.Text = "";
+			//
+			// lChannel
+			//
+			this.lChannel.Location = new System.Drawing.Point(8, 160);
+			this.lChannel.Name = "lChannel";
+			this.lChannel.Size = new System.Drawing.Size(48, 16);
+			this.lChannel.TabIndex = 3;
+			this.lChannel.Text = "Channel";
+			this.lChannel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+			//
+			// lText
+			//
+			this.lText.Location = new System.Drawing.Point(16, 192);
+			this.lText.Name = "lText";
+			this.lText.Size = new System.Drawing.Size(40, 16);
+			this.lText.TabIndex = 4;
+			this.lText.Text = "Text";
+			this.lText.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+			//
+			// cbChannel
+			//
+			this.cbChannel.Location = new System.Drawing.Point(72, 158);
+			this.cbChannel.Name = "cbChannel";
+			this.cbChannel.Size = new System.Drawing.Size(160, 21);
+			this.cbChannel.TabIndex = 9;
+			//
+			// lbLog
+			//
+			this.lbLog.HorizontalScrollbar = true;
+			this.lbLog.Location = new System.Drawing.Point(0, 0);
+			this.lbLog.Name = "lbLog";
+			this.lbLog.Size = new System.Drawing.Size(424, 69);
+			this.lbLog.TabIndex = 10;
+			//
+			// lbConnections
+			//
+			this.lbConnections.HorizontalScrollbar = true;
+			this.lbConnections.Location = new System.Drawing.Point(0, 72);
+			this.lbConnections.Name = "lbConnections";
+			this.lbConnections.Size = new System.Drawing.Size(424, 69);
+			this.lbConnections.TabIndex = 11;
+			//
+			// MEETForm
+			//
+			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
+			this.ClientSize = new System.Drawing.Size(440, 270);
+			this.Controls.Add(this.lbConnections);
+			this.Controls.Add(this.lbLog);
+			this.Controls.Add(this.cbChannel);
+			this.Controls.Add(this.lText);
+			this.Controls.Add(this.lChannel);
+			this.Controls.Add(this.tbText);
+			this.Menu = this.mainMenu1;
+			this.Name = "MEETForm";
+			this.Text = "MEET";
+			this.ResumeLayout(false);
+
+		}
+		#endregion
+
+		/// <summary>
+		/// The main entry point for the application.
+		/// </summary>
+
+		static void Main() {
+			Application.Run(new MEETForm());
+		}
+
+		private void mnuExit_Click(object sender, System.EventArgs e) {
+			m_node.Shutdown();
+			Application.Exit();
+		}
+
+		private void mnuConnect_Click(object sender, EventArgs e) {
+			Connect _connect = new Connect(m_node);
+			_connect.ShowDialog();
+			if (_connect.DialogResult == DialogResult.Cancel) {
+				m_log.Add("User selected cancel");
+				_connect.Dispose();
+				return;
+			}
+
+			MEETIPEndPoint ipepLoc = _connect.MipLocalEndPoint;
+			MEETIFace iface = (MEETIFace) m_node.IFaces[ipepLoc.Address];
+			if (iface == null) {
+
+				iface = new MEETIFace(ipepLoc.Address.ToString(), ipepLoc.Address, m_node);
+				m_node.IFaces[ipepLoc.Address] = iface;
+
+			}
+			MEETIPEndPoint ipepRem = _connect.MipRemoteEndPoint;
+
+			// create connection
+			MEETPCQueue inQ = new MEETPCQueue();
+			MEETPCQueue outQ = new MEETPCQueue();
+			MEETSockConnection conn = new MEETSockConnection(iface, ipepLoc, ipepRem, inQ, outQ, false);
+
+			// see if it failed
+			if (conn.Sock == null) {
+				MessageBox.Show("failed to connect to " + ipepRem + ":" +
+					conn.ErrorSrc.Message,
+					"Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				conn.Close();
+				return;
+			}
+
+			// check to see if already listed
+			if (iface.htConns[conn] != null)
+				{
+				MessageBox.Show("Already connected to " + ipepRem,
+					"Error",
+					MessageBoxButtons.OK,
+					MessageBoxIcon.Exclamation,
+					MessageBoxDefaultButton.Button1);
+				conn.Close();
+				return;
+			}
+
+			// add connection to interface
+			// note stupid syntax; brain dead Collection class only sorts Dict objects...
+			iface.htConns[conn] = conn;
+
+			_connect.Dispose();
+
+			MEETInDespatch indesp = new MEETInDespatch("udp" + conn.IpepRemote, iface, inQ);
+			indesp.Start();
+			conn.StartBidirectional();
+			m_log.Add("\tdone.");
+		}
+
+		private void mnuConnections_Click(object sender, System.EventArgs e) {
+			/*
+			m_log.Add("current inbound connections:");
+			foreach (IPEndPoint ipep in m_node.HtInConnections.Keys) {
+				m_log.Add("\t" + ipep);
+			}
+			m_log.Add("current outbound connections:");
+			foreach (IPEndPoint ipep in m_node.HtInConnections.Keys) {
+				m_log.Add("\t" + ipep);
+			}
+*/
+		}
+
+		private void mnuPublish_Click(object sender, System.EventArgs e) {
+			String s = s_hostname + " says \"" + tbText.Text + "\" at " + DateTime.UtcNow;
+			Byte [] buffer = new Byte[s.Length + 1];
+			int len = Encoding.UTF8.GetBytes( s.ToCharArray(), 0, s.Length, buffer, 0);
+			MEETDataPacket msp = new MEETDataPacket(MType.Announce, buffer);
+			// manual broadcast...
+			foreach (DictionaryEntry ifEntry in m_node.IFaces) {
+				MEETIFace iface = (MEETIFace) ifEntry.Value;
+				foreach (DictionaryEntry connEntry in iface.htConns) {
+					MEETSockConnection conn = (MEETSockConnection)connEntry.Key;
+					m_log.Add("sending to " + conn.IpepRemote);
+					conn.OutQ.Enqueue(msp);
+				}
+			}
+
+		}
+
+		/// <summary>
+		/// Keep bottom of list in view
+		/// </summary>
+		/// <param name="sender"></param>
+		/// <param name="ea"></param>
+		public void Scroller(object sender, EventArgs ea) {
+			ListBox lb = (ListBox) sender;
+			ArrayList al = (ArrayList)lb.DataSource;
+			lb.TopIndex = Math.Max(0, al.Count - 3);
+		}
+
+
+
+	}
+}
diff --git a/csharp/MEET-2/MEETForm.resx b/csharp/MEET-2/MEETForm.resx
new file mode 100644
index 0000000..9d1149b
--- /dev/null
+++ b/csharp/MEET-2/MEETForm.resx
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!--
+    Microsoft ResX Schema
+
+    Version 1.3
+
+    The primary goals of this format is to allow a simple XML format
+    that is mostly human readable. The generation and parsing of the
+    various data types are done through the TypeConverter classes
+    associated with the data types.
+
+    Example:
+
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">1.3</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1">this is my long string</data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        [base64 mime encoded serialized .NET Framework object]
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        [base64 mime encoded string representing a byte array form of the .NET Framework object]
+    </data>
+
+    There are any number of "resheader" rows that contain simple
+    name/value pairs.
+
+    Each data row contains a name, and value. The row also contains a
+    type or mimetype. Type corresponds to a .NET class that support
+    text/value conversion through the TypeConverter architecture.
+    Classes that don't support this are serialized and stored with the
+    mimetype set.
+
+    The mimetype is used forserialized objects, and tells the
+    ResXResourceReader how to depersist the object. This is currently not
+    extensible. For a given mimetype the value must be set accordingly:
+
+    Note - application/x-microsoft.net.object.binary.base64 is the format
+    that the ResXResourceWriter will generate, however the reader can
+    read any of the formats listed below.
+
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>1.3</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="mainMenu1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mainMenu1.Location" type="System.Drawing.Point, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </data>
+  <data name="mainMenu1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuFile.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuFile.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuConnect.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuConnect.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuConnections.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuConnections.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuExit.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuExit.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuChannels.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuChannels.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuAdvertise.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuAdvertise.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuUnadvertise.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuUnadvertise.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="SepChan1.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="SepChan1.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuSubscribe.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuSubscribe.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuUnsubscribe.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuUnsubscribe.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="SepChan2.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="SepChan2.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuPublish.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="mnuPublish.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="tbText.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="tbText.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="tbText.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lChannel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="lChannel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lChannel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lText.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="lText.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lText.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="cbChannel.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="cbChannel.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="cbChannel.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lbLog.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lbLog.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="lbLog.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lbConnections.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="lbConnections.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="lbConnections.Modifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+  <data name="$this.Locked" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.Language" type="System.Globalization.CultureInfo, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>(Default)</value>
+  </data>
+  <data name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.Localizable" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </data>
+  <data name="$this.GridSize" type="System.Drawing.Size, System.Drawing, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>8, 8</value>
+  </data>
+  <data name="$this.DrawGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </data>
+  <data name="$this.TrayHeight" type="System.Int32, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>80</value>
+  </data>
+  <data name="$this.Name">
+    <value>MEETForm</value>
+  </data>
+  <data name="$this.SnapToGrid" type="System.Boolean, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </data>
+  <data name="$this.DefaultModifiers" type="System.CodeDom.MemberAttributes, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>Private</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/csharp/MEET-2/Structure.txt b/csharp/MEET-2/Structure.txt
new file mode 100644
index 0000000..c4dbc45
--- /dev/null
+++ b/csharp/MEET-2/Structure.txt
@@ -0,0 +1,11 @@
+MEET architecture is based around container components that can hold one or more modules.
+Modules can be dynamically loaded and unloaded.  Theoretically an arbitrary graph of
+container components is possible, but a specific skeletal structure may make the system
+more conceptually tractable.
+
+MEET itself represents individual instances as a compute-node container, attached to one
+or more interface containers.  The compute-node is responsible for packet classification,
+forwarding, and routing, as well as administrative control, security policy, and
+measurement.  The interfaces handle interface-bound sending and receiving, as well as
+channel-level security.  For instance, one interface may have TCP and UDP modules,
+while another has TCP and raw Ethernet modules.
\ No newline at end of file
diff --git a/csharp/MEET-2/TODO.txt b/csharp/MEET-2/TODO.txt
new file mode 100644
index 0000000..7d79a55
--- /dev/null
+++ b/csharp/MEET-2/TODO.txt
@@ -0,0 +1,37 @@
+TODO
+
+ReFactoring
+
+MEETNode -> MEETContainer
+
+MEETSockConnection -> MEETModule
+
+
+////
+
+Containers need to be able to really manage their associated modules
+	list names
+	names + status (MEETModuleInfo?)
+
+Two phase shutdown for PCqueues?
+	block incoming
+	wait a while
+	kill queue
+
+associate bidirectional sockets + thread pair with interfaces
+	default per IF is listen on 0xEEEE, send to broadcast
+	broadcast announcement, Replies suggest port numbers
+
+web service config interface
+
+need to model initial tree after bridging algorithm
+
+resizable controls in forms
+
+subscriptions can have timeouts
+
+stream subscriptions
+
+measure during connect and after, via advertise and publish
+
+module restart?
\ No newline at end of file
diff --git a/csharp/MEET-2/bin/Debug/MEET-2.pdb b/csharp/MEET-2/bin/Debug/MEET-2.pdb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/csharp/MEET-2/bin/Debug/MEET-2.pdb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/csharp/MEET-2/bin/Debug/MEET-2.xml b/csharp/MEET-2/bin/Debug/MEET-2.xml
new file mode 100644
index 0000000..fc19f86
--- /dev/null
+++ b/csharp/MEET-2/bin/Debug/MEET-2.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>MEET-2</name>
+    </assembly>
+    <members>
+        <member name="T:MEET_2.Connect">
+            <summary>
+            Summary description for Connect.
+            </summary>
+        </member>
+        <member name="M:MEET_2.Connect.#ctor(MEETLib.MEETNode)">
+            <summary>
+            Connect socket to remote system
+            </summary>
+            <param name="node"></param>
+        </member>
+        <member name="M:MEET_2.Connect.Dispose(System.Boolean)">
+            <summary>
+            Clean up any resources being used.
+            </summary>
+        </member>
+        <member name="M:MEET_2.Connect.InitializeComponent">
+            <summary>
+            Required method for Designer support - do not modify
+            the contents of this method with the code editor.
+            </summary>
+        </member>
+        <member name="P:MEET_2.Connect.MipLocalEndPoint">
+            <summary>
+            local endpoint
+            </summary>
+        </member>
+        <member name="P:MEET_2.Connect.MipRemoteEndPoint">
+            <summary>
+            remote we're talking to
+            </summary>
+        </member>
+        <member name="T:MEET_2.MEETForm">
+            <summary>
+            Summary description for Form1.
+            </summary>
+        </member>
+        <member name="F:MEET_2.MEETForm.m_name">
+            <summary>
+            Class name
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.#ctor">
+            <summary>
+            Input form for demo
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.Dispose(System.Boolean)">
+            <summary>
+            Clean up any resources being used.
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.InitializeComponent">
+            <summary>
+            Required method for Designer support - do not modify
+            the contents of this method with the code editor.
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.Main">
+            <summary>
+            The main entry point for the application.
+            </summary>
+        </member>
+        <member name="M:MEET_2.MEETForm.Scroller(System.Object,System.EventArgs)">
+            <summary>
+            Keep bottom of list in view
+            </summary>
+            <param name="sender"></param>
+            <param name="ea"></param>
+        </member>
+    </members>
+</doc>
diff --git a/csharp/MEET-2/bin/Debug/MEETLib.dll b/csharp/MEET-2/bin/Debug/MEETLib.dll
new file mode 100644
index 0000000..48090e8
Binary files /dev/null and b/csharp/MEET-2/bin/Debug/MEETLib.dll differ
diff --git a/csharp/MEET-2/bin/Debug/MEETLib.pdb b/csharp/MEET-2/bin/Debug/MEETLib.pdb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/csharp/MEET-2/bin/Debug/MEETLib.pdb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/csharp/MEET-2/bin/Release/MEETLib.dll b/csharp/MEET-2/bin/Release/MEETLib.dll
new file mode 100644
index 0000000..c66a84b
Binary files /dev/null and b/csharp/MEET-2/bin/Release/MEETLib.dll differ
diff --git a/csharp/MEET-2/obj/Debug/MEET-2.exe.incr b/csharp/MEET-2/obj/Debug/MEET-2.exe.incr
new file mode 100644
index 0000000..43445e2
Binary files /dev/null and b/csharp/MEET-2/obj/Debug/MEET-2.exe.incr differ
diff --git a/csharp/MEET-2/obj/Debug/MEET-2.pdb b/csharp/MEET-2/obj/Debug/MEET-2.pdb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/csharp/MEET-2/obj/Debug/MEET-2.pdb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/csharp/MEET-2/obj/Debug/MEET-2.projdata b/csharp/MEET-2/obj/Debug/MEET-2.projdata
new file mode 100644
index 0000000..965ef17
Binary files /dev/null and b/csharp/MEET-2/obj/Debug/MEET-2.projdata differ
diff --git a/csharp/MEET-2/obj/Debug/MEET_2.Connect.resources b/csharp/MEET-2/obj/Debug/MEET_2.Connect.resources
new file mode 100644
index 0000000..5a9f627
Binary files /dev/null and b/csharp/MEET-2/obj/Debug/MEET_2.Connect.resources differ
diff --git a/csharp/MEET-2/obj/Debug/MEET_2.MEETForm.resources b/csharp/MEET-2/obj/Debug/MEET_2.MEETForm.resources
new file mode 100644
index 0000000..167fb78
Binary files /dev/null and b/csharp/MEET-2/obj/Debug/MEET_2.MEETForm.resources differ
diff --git a/csharp/MEET-2/obj/Debug/MEET_PPC.Connect.resources b/csharp/MEET-2/obj/Debug/MEET_PPC.Connect.resources
new file mode 100644
index 0000000..8b3a575
Binary files /dev/null and b/csharp/MEET-2/obj/Debug/MEET_PPC.Connect.resources differ
diff --git a/csharp/MEET-2/obj/Debug/MEET_PPC.MEETForm.resources b/csharp/MEET-2/obj/Debug/MEET_PPC.MEETForm.resources
new file mode 100644
index 0000000..4e892e6
Binary files /dev/null and b/csharp/MEET-2/obj/Debug/MEET_PPC.MEETForm.resources differ
diff --git a/csharp/MEET-2/obj/Interop.MediaPlayer.dll b/csharp/MEET-2/obj/Interop.MediaPlayer.dll
new file mode 100644
index 0000000..e0faabf
Binary files /dev/null and b/csharp/MEET-2/obj/Interop.MediaPlayer.dll differ
diff --git a/csharp/MEET-2/obj/Release/MEET-2.projdata b/csharp/MEET-2/obj/Release/MEET-2.projdata
new file mode 100644
index 0000000..ab589e4
Binary files /dev/null and b/csharp/MEET-2/obj/Release/MEET-2.projdata differ
diff --git a/csharp/MEETLib/App.config b/csharp/MEETLib/App.config
new file mode 100644
index 0000000..4a3996f
--- /dev/null
+++ b/csharp/MEETLib/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+	<appSettings>
+		<add key="machineName" value="oogy.philgross.com" />
+	</appSettings>
+</configuration>
diff --git a/csharp/MEETLib/AssemblyInfo.cs b/csharp/MEETLib/AssemblyInfo.cs
new file mode 100644
index 0000000..ce8e31b
--- /dev/null
+++ b/csharp/MEETLib/AssemblyInfo.cs
@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("MEETLib")]
+[assembly: AssemblyDescription("C# library for supporting MEET")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("(c)2003 The Trustees of Columbia University in the City of New York")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("0.1.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
diff --git a/csharp/MEETLib/IMEETInputQueue.cs b/csharp/MEETLib/IMEETInputQueue.cs
new file mode 100644
index 0000000..49821fb
--- /dev/null
+++ b/csharp/MEETLib/IMEETInputQueue.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace MEETLib
+{
+	/// <summary>
+	/// Enqueue-only (i.e. sink) interface to MEETPCQueues, for module clients
+	/// </summary>
+	public interface IMEETInputQueue
+	{
+		void Enqueue(object obj);
+	}
+}
diff --git a/csharp/MEETLib/MEETChannel.cs b/csharp/MEETLib/MEETChannel.cs
new file mode 100644
index 0000000..36faab8
--- /dev/null
+++ b/csharp/MEETLib/MEETChannel.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Text;
+using System.Security.Cryptography;
+using System.IO;
+
+namespace MEETLib
+{
+	/// <summary>
+	/// Represents a channel name.
+	/// Hash code is always first four bytes of m_guid.
+	///
+	/// If name (rendered in UTF-8) 16 chars or less,
+	/// m_guid is concatenation of standard string hashcode and
+	/// the string itself.
+	///
+	/// Otherwise, m_guid is the SHA1 hash of the (UTF-8) name.
+	/// </summary>
+
+	public class MEETChannel
+	{
+
+		private string m_name = null;
+		public string Name {
+			get { return m_name; }
+		}
+
+		/// <summary>
+		/// 20 byte fixed-length version
+		/// </summary>
+		private byte[] m_guid = null;
+		public byte[] Guid {
+			get { return m_guid; }
+		}
+
+		public MEETChannel(string name)
+		{
+			m_name = name;
+			byte [] buffer = Encoding.UTF8.GetBytes(m_name);
+			if (buffer.Length > 16) {
+				SHA1 sha = new SHA1CryptoServiceProvider();  // note: not in WinCE :-(
+				m_guid = sha.ComputeHash(buffer);
+			} else {
+				m_guid = new byte[20];
+				MemoryStream ms = new MemoryStream(m_guid);
+				BinaryWriter bw = new BinaryWriter(ms);
+				bw.Write(m_name.GetHashCode());
+				bw.Write(m_name);
+			}
+		}
+
+		/// <summary>
+		/// little-endian?
+		/// </summary>
+		/// <returns></returns>
+		public override int GetHashCode() {
+			return
+				(m_guid[3]<<24) |
+				(m_guid[2]<<16) |
+				(m_guid[1]<<8) |
+				m_guid[0];
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETClock.cs b/csharp/MEETLib/MEETClock.cs
new file mode 100644
index 0000000..94b224d
--- /dev/null
+++ b/csharp/MEETLib/MEETClock.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Threading;
+
+namespace MEETLib
+{
+	/// <summary>
+	/// Lower-resolution clock to save unneccessary system calls.
+	/// Possibly a useless and premature optimization.
+	/// </summary>
+	public class MEETClock : MEETModule
+	{
+		public static DateTime Now = DateTime.Now;
+
+		protected int m_sleepTime = 50;
+		public int SleepTime { get { return m_sleepTime; } }
+
+		public MEETClock(string theName, MEETContainer theContainer) :
+			base(theName, theContainer)
+		{}
+
+		protected override void innerloop() {
+			Now = DateTime.Now;
+			Thread.Sleep(m_sleepTime);
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETContainer.cs b/csharp/MEETLib/MEETContainer.cs
new file mode 100644
index 0000000..42d1ccb
--- /dev/null
+++ b/csharp/MEETLib/MEETContainer.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections;
+
+namespace MEETLib {
+
+	/// <summary>
+	/// levels following log4j model
+	/// </summary>
+	public enum LogLevel {FATAL=0, ERROR, WARN, INFO, DEBUG}
+
+
+	/// <summary>
+	/// Generic holder of MEETModules.  Only services provided
+	/// are shutting everything down and providing a sink for log messages.
+	/// </summary>
+	public abstract class MEETContainer {
+		public virtual string ClassName {get {return "MEETContainer";}}
+
+		/// <summary>
+		/// Allows messages with a log level of DEBUG
+		/// </summary>
+		protected bool m_debug = true;
+
+		/// <summary>
+		/// Instance name
+		/// </summary>
+		protected string m_name = "AbstractContainer";
+		public virtual string Name { get { return m_name; } }
+
+
+		/// <summary>
+		/// Write a message to the log
+		/// </summary>
+		/// <param name="level">level of this message</param>
+		/// <param name="msg">String to write to the log</param>
+		public abstract void WriteLog(LogLevel level, string msg);
+
+		/// <summary>
+		/// property to be defined by subclass
+		/// </summary>
+		private IList dummy = null;
+		public virtual IList Log {
+			get {return dummy;}
+			set {dummy = value;}
+		}
+
+		/// <summary>
+		/// should only hold MEETModules.  Someday my generics will come...
+		/// </summary>
+		protected IDictionary m_modules = null;
+
+		public MEETContainer() {
+			m_modules = SortedList.Synchronized(new SortedList());
+		}
+
+		/// <summary>
+		/// create an instance with the given name
+		/// </summary>
+		/// <param name="theName"></param>
+		public MEETContainer (string theName) : this() {
+			m_name = theName;
+		}
+
+		/// <summary>
+		/// Add a module to this container and start it.
+		/// Requires that the instance have a unique name.
+		/// Don't add a single module instance to more than
+		/// one container.
+		/// </summary>
+		/// <param name="theModule">the MEETModule to be added to this container</param>
+		/// <returns>true on success</returns>
+		public bool AddModule (MEETModule theModule) {
+			if (m_modules.Contains(theModule.Name)) {
+				WriteLog(LogLevel.ERROR, String.Format(
+					"{0}: module {1} already exists", m_name, theModule.Name));
+				return false;
+			}
+			m_modules.Add(theModule.Name, theModule);
+			WriteLog(LogLevel.DEBUG, String.Format("{0} added {1}", m_name, theModule.Name));
+			return true;
+		}
+
+
+		/// <summary>
+		/// Stop and unregister a module.
+		/// </summary>
+		/// <param name="theModule"></param>
+		/// <returns></returns>
+		public bool RemoveModule (MEETModule theModule) {
+			if (!m_modules.Contains(theModule.Name)) {
+				WriteLog(LogLevel.ERROR, String.Format(
+					"{0}: module {1} not loaded", m_name, theModule.Name));
+				return false;
+			}
+			if (theModule.Status != ModStatus.STOPPED) {
+				WriteLog(LogLevel.ERROR, String.Format(
+					"{0}: module {1} still running", m_name, theModule.Name));
+				return false;
+			}
+			m_modules.Remove(theModule.Name);
+			WriteLog(LogLevel.DEBUG, String.Format("{0} removing {1}", m_name, theModule.Name));
+			return true;
+		}
+
+		public virtual void Shutdown() {
+			foreach (DictionaryEntry de in m_modules) {
+				WriteLog(LogLevel.DEBUG, String.Format("{0} shutting down {1}", m_name, de.Key));
+				((MEETModule)de.Value).Stop();
+			}
+			m_modules.Clear();
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETDataPacket.cs b/csharp/MEETLib/MEETDataPacket.cs
new file mode 100644
index 0000000..8057bfe
--- /dev/null
+++ b/csharp/MEETLib/MEETDataPacket.cs
@@ -0,0 +1,49 @@
+using System;
+using System.IO;
+
+
+namespace MEETLib
+{
+
+
+	/// <summary>
+	/// Short packet structure: m_Type = 1
+	/// Constructor from byte array assumes that magic and type have
+	/// already been checked
+	///
+	/// MEET_MAGIC: 2 bytes 0xEEEE
+	///
+	/// then a ushort with top level type info for fastest cut-through
+	///		0 = non-propagating peer discovery/negotiation
+	///		1-1024 = MEET well-known types
+	///		1025-65535 = user types
+	///	This virtual port will determine the format of the rest of the
+	///	header (post-length), as well as payload.
+	///
+	///	then an int length, negatives and 0 reserved
+	///
+	///
+	/// </summary>
+	public class MEETDataPacket : MEETPacket {
+
+		public const string m_className = "MEETDataPacket";
+		const int MAX_DATA_SIZE=1024;
+		// const int HDR_SIZE = 16; // header stuff in bytes
+
+		public byte[] Data { get { return m_data; } }
+		private byte [] m_data = null;
+
+		public int DataLength { get { return m_dataLength; } }
+		private int m_dataLength = 0;
+
+		public MEETDataPacket(MType type, byte[] input) : base(type) {
+			if (input.Length > MAX_DATA_SIZE) {
+				throw new MEETException(String.Format(
+					"{0}: data too long: {1} > {2}",
+					m_className, input.Length, MAX_DATA_SIZE));
+			} else {
+				m_data = input;
+			}
+		}
+	}
+}
diff --git a/csharp/MEETLib/MEETException.cs b/csharp/MEETLib/MEETException.cs
new file mode 100644
index 0000000..e002921
--- /dev/null
+++ b/csharp/MEETLib/MEETException.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace MEETLib
+{
+	/// <summary>
+	/// Summary description for MEETException.
+	/// </summary>
+	public class MEETException : Exception
+	{
+		public MEETException() : base() {}
+		public MEETException(string s) : base(s) {}
+		public MEETException(string s, Exception inner) : base(s, inner) {}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETIFace.cs b/csharp/MEETLib/MEETIFace.cs
new file mode 100644
index 0000000..a4ddbb7
--- /dev/null
+++ b/csharp/MEETLib/MEETIFace.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections;
+using System.Net;
+using System.Net.Sockets;
+
+namespace MEETLib
+{
+	/// <summary>
+	/// The physical interface, along with associated list of connections.
+	/// </summary>
+	public class MEETIFace : MEETContainer
+	{
+		private MEETNode m_node;
+
+		public Hashtable htConns {
+			get { return m_htConns; }
+		}
+		private Hashtable m_htConns = null;
+
+		public IPAddress ipaLocal {
+			get { return m_ipaLocal; }
+		}
+		private IPAddress m_ipaLocal = null;
+
+		public override string ToString() {
+			return m_ipaLocal.ToString();
+		}
+
+		public MEETIFace(string theName, IPAddress local, MEETNode theNode) :
+			base(theName) {
+			m_node = theNode;
+			m_ipaLocal = local;
+			m_htConns = Hashtable.Synchronized(new Hashtable());
+			WriteLog(LogLevel.INFO, String.Format("IFace {0} created", theName));
+		}
+
+		public override void Shutdown() {
+			WriteLog(LogLevel.INFO, String.Format("\t{0} shutting down...", m_name));
+			base.Shutdown ();
+			foreach (DictionaryEntry de in m_htConns) {
+				( (MEETSockConnection)(de.Key)).Close();
+			}
+			WriteLog(LogLevel.INFO, String.Format("\t{0} shutdown.", m_name));
+
+
+		}
+
+
+		public override void WriteLog(LogLevel level, string msg) {
+			m_node.WriteLog(level, msg);
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETIPEndPoint.cs b/csharp/MEETLib/MEETIPEndPoint.cs
new file mode 100644
index 0000000..b7e4b43
--- /dev/null
+++ b/csharp/MEETLib/MEETIPEndPoint.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Net;
+
+namespace MEETLib
+{
+	/// <summary>
+	/// Clonable IPEndPoint for those incoming packets
+	/// </summary>
+	public class MEETIPEndPoint : IPEndPoint, ICloneable {
+
+		public object Clone() {
+			return new MEETIPEndPoint(Address, Port);
+		}
+
+		public MEETIPEndPoint(long address, int port) : base(address, port) {}
+		public MEETIPEndPoint(IPAddress address, int port) : base(address, port) {}
+		public MEETIPEndPoint(IPEndPoint ipep) :
+			base(ipep.Address, ipep.Port) {}
+	}
+}
diff --git a/csharp/MEETLib/MEETInDespatch.cs b/csharp/MEETLib/MEETInDespatch.cs
new file mode 100644
index 0000000..7f90c87
--- /dev/null
+++ b/csharp/MEETLib/MEETInDespatch.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Threading;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using System.Collections;
+using System.Text;
+
+
+namespace MEETLib {
+	/// <summary>
+	/// despatch incoming packets.
+	/// </summary>
+	public class MEETInDespatch : MEETQModule {
+
+		private static int m_count = 0;
+		public static int Count { get { return m_count; } }
+
+		public override string ClassName {get {return "MEETInDespatch";}}
+
+		public MEETInDespatch(string theName, MEETContainer theContainer, MEETPCQueue theQ) :
+			base(theName, theContainer, theQ) {	}
+
+		protected override void innerloop(object o) {
+			MEETRecvPacket msg = (MEETRecvPacket) o;
+			m_parent.WriteLog(LogLevel.DEBUG, String.Format("Received packet type {0} from {1} at {2}:",
+				msg.MTypeString, msg.Conn.IpepRemote, msg.RecvTime));
+			m_parent.WriteLog(LogLevel.DEBUG, Encoding.UTF8.GetString(msg.Br.ReadBytes(1024)));
+			Interlocked.Increment(ref m_count);
+		}
+	}
+}
diff --git a/csharp/MEETLib/MEETLib.csproj b/csharp/MEETLib/MEETLib.csproj
new file mode 100644
index 0000000..866ba85
--- /dev/null
+++ b/csharp/MEETLib/MEETLib.csproj
@@ -0,0 +1,209 @@
+<VisualStudioProject>
+    <CSHARP
+        ProjectType = "Local"
+        ProductVersion = "7.10.3077"
+        SchemaVersion = "2.0"
+        ProjectGuid = "{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}"
+    >
+        <Build>
+            <Settings
+                ApplicationIcon = ""
+                AssemblyKeyContainerName = ""
+                AssemblyName = "MEETLib"
+                AssemblyOriginatorKeyFile = ""
+                DefaultClientScript = "JScript"
+                DefaultHTMLPageLayout = "Grid"
+                DefaultTargetSchema = "IE50"
+                DelaySign = "false"
+                OutputType = "Library"
+                PreBuildEvent = ""
+                PostBuildEvent = ""
+                RootNamespace = "MEETLib"
+                RunPostBuildEvent = "OnBuildSuccess"
+                StartupObject = ""
+            >
+                <Config
+                    Name = "Debug"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "DEBUG;TRACE"
+                    DocumentationFile = ""
+                    DebugSymbols = "true"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "false"
+                    OutputPath = "bin\Debug\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+                <Config
+                    Name = "Release"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "TRACE"
+                    DocumentationFile = ""
+                    DebugSymbols = "false"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "true"
+                    OutputPath = "bin\Release\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+            </Settings>
+            <References>
+                <Reference
+                    Name = "System"
+                    AssemblyName = "System"
+                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+                />
+                <Reference
+                    Name = "System.Data"
+                    AssemblyName = "System.Data"
+                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+                />
+                <Reference
+                    Name = "System.XML"
+                    AssemblyName = "System.Xml"
+                    HintPath = "..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+                />
+            </References>
+        </Build>
+        <Files>
+            <Include>
+                <File
+                    RelPath = "App.config"
+                    BuildAction = "None"
+                />
+                <File
+                    RelPath = "AssemblyInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "IMEETInputQueue.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETChannel.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETClock.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETContainer.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETDataPacket.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETException.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETIFace.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETInDespatch.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETIPEndPoint.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETModule.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETNode.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETPacket.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETPCQueue.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETQModule.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETRecvPacket.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETSockConnection.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETSockListener.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETSockSender.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETTcpSockListener.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETTcpSockSender.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETUdpSockListener.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETUdpSockSender.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+            </Include>
+        </Files>
+    </CSHARP>
+</VisualStudioProject>
+
diff --git a/csharp/MEETLib/MEETLib.csproj.user b/csharp/MEETLib/MEETLib.csproj.user
new file mode 100644
index 0000000..686cccb
--- /dev/null
+++ b/csharp/MEETLib/MEETLib.csproj.user
@@ -0,0 +1,48 @@
+<VisualStudioProject>
+    <CSHARP LastOpenVersion = "7.10.3077" >
+        <Build>
+            <Settings ReferencePath = "" >
+                <Config
+                    Name = "Debug"
+                    EnableASPDebugging = "false"
+                    EnableASPXDebugging = "false"
+                    EnableUnmanagedDebugging = "false"
+                    EnableSQLServerDebugging = "false"
+                    RemoteDebugEnabled = "false"
+                    RemoteDebugMachine = ""
+                    StartAction = "Project"
+                    StartArguments = ""
+                    StartPage = ""
+                    StartProgram = ""
+                    StartURL = ""
+                    StartWorkingDirectory = ""
+                    StartWithIE = "true"
+                />
+                <Config
+                    Name = "Release"
+                    EnableASPDebugging = "false"
+                    EnableASPXDebugging = "false"
+                    EnableUnmanagedDebugging = "false"
+                    EnableSQLServerDebugging = "false"
+                    RemoteDebugEnabled = "false"
+                    RemoteDebugMachine = ""
+                    StartAction = "Project"
+                    StartArguments = ""
+                    StartPage = ""
+                    StartProgram = ""
+                    StartURL = ""
+                    StartWorkingDirectory = ""
+                    StartWithIE = "true"
+                />
+            </Settings>
+        </Build>
+        <OtherProjectSettings
+            CopyProjectDestinationFolder = ""
+            CopyProjectUncPath = ""
+            CopyProjectOption = "0"
+            ProjectView = "ProjectFiles"
+            ProjectTrust = "0"
+        />
+    </CSHARP>
+</VisualStudioProject>
+
diff --git a/csharp/MEETLib/MEETModule.cs b/csharp/MEETLib/MEETModule.cs
new file mode 100644
index 0000000..ba610b8
--- /dev/null
+++ b/csharp/MEETLib/MEETModule.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Threading;
+
+namespace MEETLib
+{
+
+	/// <summary>
+	///  Status of this module
+	/// </summary>
+	public enum ModStatus {NEW, RUNNING, STOPPED}
+
+	/// <summary>
+	/// a generic MEET subsystem: can start, stop, get status.
+	/// TODO: reuse after stop?
+	/// </summary>
+	public abstract class MEETModule {
+
+		public virtual string ClassName {get {return "MEETModule";}}
+		protected bool m_done = false;
+
+
+		protected ModStatus m_status = ModStatus.NEW;
+		public virtual ModStatus Status { get {return m_status;} }
+
+		protected string m_name = "GenericContainer";
+		public virtual string Name { get { return m_name; } }
+
+		protected MEETContainer m_parent = null;
+		public virtual MEETContainer Parent { get { return m_parent; } }
+
+		protected Exception m_errorSrc = null;
+		public virtual Exception ErrorSrc { get { return m_errorSrc; } }
+
+		protected Thread m_thread = null;
+
+
+		public MEETModule(string theName, MEETContainer theContainer) {
+			m_name = theName;
+			if (!theContainer.AddModule(this)) {
+				// leave m_parent as null
+				return;
+			}
+
+			m_parent = theContainer;
+			m_status = ModStatus.NEW;
+
+			try {
+				m_thread = new Thread(new ThreadStart(run));
+				m_thread.Name = m_name;
+			}
+			catch (Exception ex) {
+				m_status = ModStatus.STOPPED;
+				m_errorSrc = ex;
+				m_parent.WriteLog(LogLevel.ERROR, String.Format("{0} {1}: {2}",
+					m_name, m_status, m_errorSrc.ToString()));
+				return;
+			}
+		}
+
+		public virtual bool Start() {
+			if (m_status != ModStatus.RUNNING) {
+				try {
+					m_thread.Start();
+				} catch (Exception ex) {
+					m_status = ModStatus.STOPPED;
+					m_errorSrc = ex;
+					m_parent.WriteLog(LogLevel.ERROR, String.Format("{0} {1}: {2}",
+						m_name, m_status, m_errorSrc.ToString()));
+					return false;
+				}
+				m_status = ModStatus.RUNNING;
+			}
+			return true;
+		}
+
+		public virtual bool Stop() {
+			if (m_status != ModStatus.STOPPED) {
+				m_done = true;
+				try {
+					shutdown();
+				} catch (Exception ex) {
+					m_errorSrc = ex;
+					m_parent.WriteLog(LogLevel.ERROR, String.Format("{0} {1}: {2}",
+						m_name, m_status, m_errorSrc.ToString()));
+					return false;
+				}
+				m_status = ModStatus.STOPPED;
+			}
+			return true;
+		}
+
+		protected virtual void run() {
+			m_parent.WriteLog(LogLevel.INFO, String.Format("{0} loop running", m_name));
+			while (!m_done) {
+				innerloop();
+			}
+			m_parent.WriteLog(LogLevel.INFO, String.Format("{0} {1}: loop terminated",
+				m_name, m_status));
+
+		}
+
+		/// <summary>
+		/// while (!m_done) {...}
+		/// </summary>
+		protected virtual void innerloop() {}
+
+		/// <summary>
+		/// kill anything that could be blocking, and cleanup if necessary
+		/// </summary>
+		protected virtual void shutdown() {}
+
+
+	}
+}
diff --git a/csharp/MEETLib/MEETNode.cs b/csharp/MEETLib/MEETNode.cs
new file mode 100644
index 0000000..02d1668
--- /dev/null
+++ b/csharp/MEETLib/MEETNode.cs
@@ -0,0 +1,203 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Collections;
+using System.Threading;
+using System.IO;
+
+namespace MEETLib {
+	/// <summary>
+	/// Summary description for MEETNode.
+	/// </summary>
+	public class MEETNode : MEETContainer {
+		public override string ClassName {get {return "MEETNode";}}
+
+		private IList m_log = null;
+		public override IList Log {
+			get { return m_log; }
+			set { m_log = value; }
+		}
+
+		protected Hashtable m_ifaces = null;
+		/// <summary>
+		/// holds the list of network interfaces (indexed by m_IPALocal)
+		/// each of which in turn has a hashtable of SockConnections.
+		/// </summary>
+		public Hashtable IFaces {
+			get { return m_ifaces; }
+		}
+
+		public MEETNode(string theName) : base(theName) {
+			m_log = new ArrayList(1024);
+			m_ifaces = new Hashtable();
+		}
+
+		public override void Shutdown() {
+			WriteLog(LogLevel.INFO, String.Format("{0} shutting down...", m_name));
+			base.Shutdown();
+			foreach (DictionaryEntry de in m_ifaces) {
+				( (MEETIFace)(de.Value)).Shutdown();
+			}
+			WriteLog(LogLevel.INFO, String.Format("{0} shutdown.", m_name));
+
+		}
+
+		public override void WriteLog(LogLevel level, string msg) {
+			m_log.Add(String.Format("{0} {1}: {2}",
+				DateTime.Now.ToString("yyyyMMdd-HH:mm:ss.fff"),
+				level, msg));
+		}
+
+
+		/* private UdpListenerThread m_ultListener = null;
+		private InHandlerThread m_iht = null;
+		// private static EventLog _elLog = null;
+		private String m_hostname = null;
+
+
+		/// <summary>
+		/// master input queue of likely MEET packets
+		/// </summary>
+		public IMEETInputQueue InqMEETEvent {
+			get { return m_inqMEETEvent; }
+			set { m_inqMEETEvent = value; }
+		}
+		private IMEETInputQueue m_inqMEETEvent = null;
+
+		/// <summary>
+		/// master input queue of non-MEET packets
+		/// </summary>
+		public MEETPCQueue InqOtherEvent {
+			get { return m_inqOtherEvent; }
+		}
+		private MEETPCQueue m_inqOtherEvent = null;
+
+		/// <summary>
+		/// master output queue for MEET packets
+		/// </summary>
+		public MEETPCQueue OutqMEETEvent {
+			get { return m_outqMEETEvent; }
+		}
+		private MEETPCQueue m_outqMEETEvent = null;
+
+		/// <summary>
+		/// reserved
+		/// </summary>
+		public MEETPCQueue OutqOtherEvent {
+			get { return m_outqOtherEvent; }
+		}
+		private MEETPCQueue m_outqOtherEvent = null;
+
+		/// <summary>
+		/// Singleton hashtable of (IPEndPoint, MEETModule)
+		/// </summary>
+		public Hashtable htInterfaces {
+			get { return m_htInterfaces; }
+		}
+		private Hashtable m_htInterfaces = null;
+
+		public Hashtable htChannels {
+			get { return m_htChannels; }
+		}
+		private Hashtable m_htChannels = null;
+
+		public IList lstLogEvents {
+			get { return m_lstLogEvents; }
+			set { m_lstLogEvents = value; }
+		}
+		private IList m_lstLogEvents = null;
+
+		public IList lstErrorEvents {
+			get { return m_lstErrorEvents; }
+			set { m_lstErrorEvents = value; }
+		}
+		private IList m_lstErrorEvents = null;
+
+
+		public MEETNode() : base() {
+
+			m_inqOtherEvent = new MEETPCQueue();
+			m_outqMEETEvent = new MEETPCQueue();
+			m_outqOtherEvent = new MEETPCQueue();
+			m_htInterfaces = Hashtable.Synchronized(new Hashtable());
+			m_htChannels = Hashtable.Synchronized(new Hashtable());
+
+			if (m_debug) m_log = Console.Out;
+
+			try {
+				// Get the local computer host name.
+				m_hostname = Dns.GetHostName();
+				m_log.WriteLine("Computer name :{0}", m_hostname);
+				IPHostEntry iphe = Dns.GetHostByName(m_hostname);
+				m_log.WriteLine("Addresses:");
+				foreach (IPAddress ipaddr in iphe.AddressList) {
+					m_log.WriteLine("\t" + ipaddr);
+					m_htInterfaces.Add(ipaddr, new MEETIFace(ipaddr));
+				}
+			} catch (Exception ex) {
+				m_error.WriteLine(String.Format("{0} {1}: {2}",
+					m_className, "Initializing", ex.ToString()));
+			}
+
+			foreach (DictionaryEntry deIF in m_htInterfaces) {
+				try {
+					m_ultListener = new UdpListenerThread(this, (MEETIFace) deIF.Value);
+					m_ultListener.start();
+				} catch (Exception ex) {
+					m_error.WriteLine(String.Format("{0} {1} {2}: {3}",
+						m_className, "starting UDP listener on",
+						deIF.Key, ex.ToString()));
+				}
+			}
+
+			m_iht = new InHandlerThread(this);
+			m_iht.start();
+
+			m_log.WriteLine(String.Format("Hostname = {0}", m_hostname));
+
+			//m_node = new MEETNode();
+			//String cfloc = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
+			//m_log.Add(String.Format("config loc = {0}", cfloc));
+			//m_log.Add(String.Format("cwd = {0}", Directory.GetCurrentDirectory()));
+			//m_hostname = ConfigurationSettings.AppSettings["machineName"];
+
+			/*
+			 string c1 = "shortname";
+						string c2 = "http://www.example.com/namespace/sometype";
+						MEETChannel mc1 = new MEETChannel(c1);
+						m_log.Add(String.Format("hash {0:X}, channel hash {1:X}",
+							c1.GetHashCode(), mc1.GetHashCode()));
+						MEETChannel mc2 = new MEETChannel(c2);
+						m_log.Add(String.Format("hash {0:X}, channel hash {1:X}",
+							c2.GetHashCode(), mc2.GetHashCode()));
+							*/
+
+/*
+		}
+
+		public void Dispose() {
+			m_inqOtherEvent.Dispose();
+			m_outqMEETEvent.Dispose();
+			m_outqOtherEvent.Dispose();
+			m_iht.stop();
+			foreach (DictionaryEntry deIF in htInterfaces) {
+				MEETIFace iface = (MEETIFace)deIF.Value;
+				m_log.WriteLine("stopping iface " + iface.ipaLocal);
+				foreach (DictionaryEntry deIn in iface.htInConns) {
+					MEETIPEndPoint ipep = (MEETIPEndPoint)deIn.Key;
+					MEETModule module = (MEETModule)deIn.Value;
+					m_log.WriteLine("\tstopping " + ipep);
+					module.stop();
+				}
+				foreach (DictionaryEntry deOut in iface.htOutConns) {
+					MEETIPEndPoint ipep = (MEETIPEndPoint)deOut.Key;
+					MEETModule module = (MEETModule)deOut.Value;
+					m_log.WriteLine("\tstopping " + ipep);
+					module.stop();
+				}
+			}
+			htInterfaces.Clear();
+		}
+*/
+	}
+}
diff --git a/csharp/MEETLib/MEETPCQueue.cs b/csharp/MEETLib/MEETPCQueue.cs
new file mode 100644
index 0000000..669b2fb
--- /dev/null
+++ b/csharp/MEETLib/MEETPCQueue.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections;
+using System.Threading;
+
+namespace MEETLib
+{
+	/// <summary>
+	/// Producer/consumer queue.  Dequeue blocks if queue is empty.
+	/// </summary>
+	public class MEETPCQueue :IMEETInputQueue {
+		private Queue m_q = null;
+		private Object m_lock = null;
+		private bool m_done = false;
+		// private bool m_disposed = false;
+
+		/// hard limit on queue size; writes will block if at max.
+		/// 0 => no limit
+		private int m_sizeLimit = 0;
+		public int SizeLimit { get { return m_sizeLimit; } }
+
+		/// <summary>
+		/// timeout for thread waiting on queue, to see if m_done has been set
+		/// </summary>
+		private int m_waitMS = 250;  // 4Hz
+		public int WaitMS { get { return m_waitMS; } }
+
+
+		// largest size reached by queue
+		private int m_peakSize = 0;
+		public int PeakSize { get { return m_peakSize; } }
+
+		public MEETPCQueue() : this(0) {}
+
+	    public MEETPCQueue(int sizeLimit) {
+			m_sizeLimit = sizeLimit;
+			m_q = new Queue();
+			m_lock = m_q.SyncRoot;
+		}
+
+		public void Enqueue(Object obj) {
+			if (!m_done) {
+				Monitor.Enter(m_lock);
+				if (m_sizeLimit != 0) {
+					while (!m_done && (m_sizeLimit == m_q.Count)) {
+						Monitor.Wait(m_lock, m_waitMS);
+					}
+				}
+				m_q.Enqueue(obj);
+				if (m_q.Count > m_peakSize) {
+					m_peakSize = m_q.Count;
+				}
+				Monitor.Pulse(m_lock);
+				Monitor.Exit(m_lock);
+			}
+		}
+
+		public object Dequeue() {
+			object result = null;
+			if (!m_done) {
+				Monitor.Enter(m_lock);
+				while (!m_done && (0 == m_q.Count)) {
+					Monitor.Wait(m_lock, m_waitMS);
+				}
+				if (!m_done) {
+					result = m_q.Dequeue();
+					if (m_sizeLimit != 0) {
+						Monitor.Pulse(m_lock);
+					}
+				}
+				Monitor.Exit(m_lock);
+			}
+			return result;
+		}
+
+		public int Count {
+			get {
+				Monitor.Enter(m_lock);
+				int result = m_q.Count;
+				Monitor.Exit(m_lock);
+				return result;
+			}
+		}
+
+		public void Close() {
+			Monitor.Enter(m_lock);
+			m_done = true;
+			Monitor.PulseAll(m_lock);  // wakey wakey
+			Monitor.Exit(m_lock);
+		}
+
+/*		public void Dispose() {
+			Dispose(true);
+		}
+
+		/// <summary>
+		/// Not sure if all this disposing stuff is necessary,
+		/// but I want to make sure at shutdown that no thread is still
+		/// waiting around to read the queue.
+		/// </summary>
+		/// <param name="disposing"></param>
+		void Dispose(bool disposing) {
+			if (!m_disposed) {
+				Monitor.Enter(m_lock);
+				m_done = true;
+				Monitor.PulseAll(m_lock);  // wakey wakey
+				if (disposing) {
+					GC.SuppressFinalize(this);  // once is enough...
+				}
+				m_disposed = true;
+				Monitor.Exit(m_lock);
+			}
+		}
+
+		~MEETPCQueue() { Dispose(false); }
+		*/
+
+
+	}
+}
diff --git a/csharp/MEETLib/MEETPacket.cs b/csharp/MEETLib/MEETPacket.cs
new file mode 100644
index 0000000..8735bbc
--- /dev/null
+++ b/csharp/MEETLib/MEETPacket.cs
@@ -0,0 +1,56 @@
+using System;
+using System.IO;
+
+namespace MEETLib
+{
+
+	/// <summary>
+	/// MEET Basic Type Enumeration
+	/// </summary>
+	public enum MType : ushort {
+		Announce=1,
+		AnnounceReply,
+		Advertise,
+		Unadvertise,
+		Subscribe,
+		Unsubscribe,
+		UserChannel,
+		SysLimit=UserChannel
+	}
+
+
+	/// <summary>
+	/// Basic MEET Packet: nothing but type and a Magic
+	/// </summary>
+	public class MEETPacket
+	{
+		public const ushort MEET_MAGIC = 0xEEEE;
+
+		// unsafe name?
+		private MType m_type = 0;
+		public MType Type { get { return m_type; } }
+
+		/// <summary>
+		///  can't create instance directly.
+		/// </summary>
+		protected MEETPacket(MType type) {
+			m_type = type;
+		}
+
+		public string MTypeString {
+			get {
+				switch (m_type) {
+					case MType.Announce:		return "Announce";
+					case MType.AnnounceReply:	return "AnnounceReply";
+					case MType.Advertise:		return "Advertise";
+					case MType.Unadvertise:		return "Unadvertise";
+					case MType.Subscribe:		return "Subscribe";
+					case MType.Unsubscribe:		return "Unsubscribe";
+					case MType.UserChannel:		return "UserChannel";
+					default:
+						return "User Type " + (ushort)m_type;
+				}
+			}
+		}
+	}
+}
diff --git a/csharp/MEETLib/MEETQModule.cs b/csharp/MEETLib/MEETQModule.cs
new file mode 100644
index 0000000..6a7b829
--- /dev/null
+++ b/csharp/MEETLib/MEETQModule.cs
@@ -0,0 +1,61 @@
+using System;
+
+namespace MEETLib {
+	/// <summary>
+	/// a MEETModule that will be getting its input from a queue, not an external source
+	/// </summary>
+	public abstract class MEETQModule : MEETModule {
+
+		public override string ClassName {get {return "MEETQModule";}}
+
+		protected MEETPCQueue m_inputQ = null;
+
+		/// <summary>
+		/// return an enqueue-only view
+		/// </summary>
+		public IMEETInputQueue InputQ { get { return m_inputQ; } }
+
+		public MEETQModule(string theName, MEETContainer theContainer, MEETPCQueue q) :
+			base(theName, theContainer) {
+			m_inputQ = q;
+		}
+
+		protected virtual void innerloop(object o) {}
+
+		protected override void run() {
+			m_parent.WriteLog(LogLevel.INFO, String.Format("{0} loop running", m_name));
+			while (!m_done) {
+				object o = m_inputQ.Dequeue();
+				// null values are theoretically allowed in the queue;
+				// not bothering to distinguish from a true Count=0
+				// situation.
+				if (null == o) {
+					m_done = true;
+				} else {
+					innerloop(o);
+				}
+			}
+			m_parent.WriteLog(LogLevel.INFO, String.Format("{0} {1}: loop terminated",
+				m_name, m_status));
+		}
+
+		public override bool Stop() {
+			if (m_status != ModStatus.STOPPED) {
+				m_done = true;
+				try {
+					m_inputQ.Close();
+					shutdown();
+				} catch (Exception ex) {
+					m_errorSrc = ex;
+					m_parent.WriteLog(LogLevel.ERROR, String.Format("{0} {1}: {2}",
+						m_name, m_status, m_errorSrc.ToString()));
+					return false;
+				}
+			}
+			m_status = ModStatus.STOPPED;
+			return true;
+		}
+
+
+	}
+}
diff --git a/csharp/MEETLib/MEETRecvPacket.cs b/csharp/MEETLib/MEETRecvPacket.cs
new file mode 100644
index 0000000..f6e70be
--- /dev/null
+++ b/csharp/MEETLib/MEETRecvPacket.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+
+namespace MEETLib {
+	/// <summary>
+	/// extension of MEETPacket for received packets
+	///
+	/// At the moment, sibling of MEETDataPacket, rather than child.  Don't want to
+	/// read the data array more than once.
+	/// </summary>
+	public class MEETRecvPacket : MEETPacket {
+		public const int MAX_DATA_SIZE=1024;
+
+		/// handle to packet data.  Enqueued incoming data will have current position
+		///   four bytes in (magic and type read).
+		private BinaryReader m_br = null;
+		public BinaryReader Br { get { return m_br; } }
+
+		private DateTime m_recvTime = DateTime.UtcNow;
+		public DateTime RecvTime { get { return m_recvTime; } }
+
+		private MEETSockConnection m_conn = null;
+		public MEETSockConnection Conn { get { return m_conn; } }
+
+		public MEETRecvPacket(MType type, BinaryReader br, DateTime dt,
+			MEETSockConnection conn) : base(type) {
+			m_br = br;
+			m_recvTime = dt;
+			m_conn = conn;
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETSockConnection.cs b/csharp/MEETLib/MEETSockConnection.cs
new file mode 100644
index 0000000..dae5386
--- /dev/null
+++ b/csharp/MEETLib/MEETSockConnection.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Net;
+using System.Net.Sockets;
+
+namespace MEETLib {
+	/// <summary>
+	/// IP/Port connection pair
+	/// </summary>
+	public class MEETSockConnection {
+		protected MEETIFace m_ifParent = null;
+		protected MEETIPEndPoint m_ipepLocal = null;
+		public MEETIPEndPoint IpepLocal { get { return m_ipepLocal; } }
+		protected MEETIPEndPoint m_ipepRemote = null;
+		public MEETIPEndPoint IpepRemote { get { return m_ipepRemote; } }
+
+		protected MEETPCQueue m_inQ = null;
+		// TODO: use input and output interfaces to restrict...
+		public MEETPCQueue InQ { get { return m_inQ; } }
+
+		protected MEETPCQueue m_outQ = null;
+		public MEETPCQueue OutQ { get { return m_outQ; } }
+
+
+
+		/// <summary>
+		/// packet receiver thread
+		/// </summary>
+		protected MEETSockListener m_mqmListener = null;
+
+		/// <summary>
+		/// packet sender thread
+		/// </summary>
+		protected MEETSockSender m_mqmSender = null;
+
+		public bool IsStream { get { return m_isStream; } }
+		protected bool m_isStream = false;
+
+		public Socket Sock { get { return m_sock; } }
+		protected Socket m_sock = null;
+
+		public virtual Exception ErrorSrc { get { return m_errorSrc; } }
+		protected Exception m_errorSrc = null;
+
+		public MEETSockConnection(
+			MEETIFace parent,
+			MEETIPEndPoint local,
+			MEETIPEndPoint remote,
+			MEETPCQueue theInQ,
+			MEETPCQueue theOutQ,
+			bool isStream)
+		{
+		m_ifParent = parent;
+			m_ipepLocal = local;
+			m_ipepRemote = remote;
+			m_isStream = isStream;
+			m_inQ = theInQ;
+			m_outQ = theOutQ;
+
+			try {
+				// TODO support for Raw Sockets
+				if (m_isStream) {
+					m_sock = new Socket(AddressFamily.InterNetwork,
+						SocketType.Stream, ProtocolType.Tcp);
+				} else {
+					m_sock = new Socket(AddressFamily.InterNetwork,
+						SocketType.Dgram, ProtocolType.Udp);
+				}
+				m_sock.Bind(m_ipepLocal);
+				m_sock.Connect(m_ipepRemote);
+			} catch (Exception ex) {
+				m_sock = null;
+				m_errorSrc = ex;
+			}
+		}
+
+		public bool StartListener() {
+			if (m_isStream) {
+				m_mqmListener = new MEETTcpSockListener("TcpSockListener", m_ifParent, this, m_inQ);
+
+			} else {
+				m_mqmListener = new MEETUdpSockListener("UdpSockListener", m_ifParent, this, m_inQ);
+			}
+			m_mqmListener.Start();
+			return true;
+		}
+
+		public bool StopListener() {
+			m_mqmListener.Stop();
+			return true;
+		}
+
+		public bool StartSender() {
+			if (m_isStream) {
+				m_mqmSender = new MEETTcpSockSender("TcpSockSender", m_ifParent, this, m_outQ);
+
+			} else {
+				m_mqmSender = new MEETUdpSockSender("UdpSockSender", m_ifParent, this, m_outQ);
+			}
+			m_mqmSender.Start();
+			return true;
+		}
+
+		public bool StopSender() {
+			m_mqmSender.Stop();
+			return true;
+		}
+
+		public bool StartBidirectional() {
+			StartSender();
+			StartListener();
+			return true;
+		}
+
+		public bool StopBidirectional() {
+			StopListener();
+			StopSender();
+			return true;
+		}
+
+		public bool Close() {
+			StopBidirectional();
+			m_sock.Close();
+			return true;
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETSockListener.cs b/csharp/MEETLib/MEETSockListener.cs
new file mode 100644
index 0000000..6fd11db
--- /dev/null
+++ b/csharp/MEETLib/MEETSockListener.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Threading;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using System.Collections;
+
+
+namespace MEETLib {
+	/// <summary>
+	/// Generic Socket listener.  Puts meet packets into target queue
+	/// </summary>
+	public abstract class MEETSockListener : MEETModule {
+		protected MEETSockConnection m_conn = null;
+		protected MEETPCQueue m_recvQ = null;
+		public override string ClassName {get {return "MEETSockListener";}}
+
+
+		/// <summary>
+		/// how many MEET packets have we seen?
+		/// </summary>
+		public int MeetCount { get {return m_meetCount; } }
+		protected static int m_meetCount = 0;
+
+		/// <summary>
+		/// how many non-MEET packets have we seen?
+		/// </summary>
+		public int OtherCount { get {return m_otherCount; } }
+		protected static int m_otherCount = 0;
+
+		// public UdpListenerThread(MEETNode node, MEETIFace iface)
+		//	: this(node, iface, UDPLISTENER_DEFAULT_PORT) {}
+
+		public MEETSockListener(
+			string theName,
+			MEETContainer theContainer,
+			MEETSockConnection conn,
+			MEETPCQueue recvQ
+			) : base(theName, theContainer)
+		{
+			m_conn = conn;
+			m_recvQ = recvQ;
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETSockSender.cs b/csharp/MEETLib/MEETSockSender.cs
new file mode 100644
index 0000000..5aa2bb2
--- /dev/null
+++ b/csharp/MEETLib/MEETSockSender.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Threading;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using System.Collections;
+
+
+namespace MEETLib
+{
+	/// <summary>
+	/// Generic Socket send thread.  Packets to be sent are placed in queue.
+	/// </summary>
+	public abstract class MEETSockSender : MEETQModule
+	{
+
+		protected MEETSockConnection m_conn = null;
+		public override string ClassName {get {return "MEETSockSender";}}
+
+		/// <summary>
+		/// how many MEET packets have we seen?
+		/// </summary>
+		public int MeetCount { get {return m_meetCount; } }
+		protected static int m_meetCount = 0;
+
+		public MEETSockSender(
+			string theName,
+			MEETContainer theContainer,
+			MEETSockConnection conn,
+			MEETPCQueue inputQ
+			) : base(theName, theContainer, inputQ)
+		{
+			m_conn = conn;
+		}
+
+
+	}
+}
diff --git a/csharp/MEETLib/MEETTcpSockListener.cs b/csharp/MEETLib/MEETTcpSockListener.cs
new file mode 100644
index 0000000..b74a762
--- /dev/null
+++ b/csharp/MEETLib/MEETTcpSockListener.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace MEETLib
+{
+	/// <summary>
+	/// Summary description for MEETTcpSockListener.
+	/// </summary>
+	public class MEETTcpSockListener : MEETSockListener	{
+		public override string ClassName {get {return "MEETTcpSockListener";}}
+
+		public MEETTcpSockListener(
+			string theName,
+			MEETContainer theContainer,
+			MEETSockConnection conn,
+			MEETPCQueue meetQ
+			) : base(theName, theContainer, conn, meetQ) {
+
+			//
+			// TODO: Add constructor logic here
+			//
+		}
+	}
+}
diff --git a/csharp/MEETLib/MEETTcpSockSender.cs b/csharp/MEETLib/MEETTcpSockSender.cs
new file mode 100644
index 0000000..5c2fc88
--- /dev/null
+++ b/csharp/MEETLib/MEETTcpSockSender.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Threading;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using System.Collections;
+
+
+namespace MEETLib {
+	/// <summary>
+	/// Generic Socket send thread.  Packets to be sent are placed in queue.
+	/// </summary>
+	public class MEETTcpSockSender : MEETSockSender {
+
+		public override string ClassName {get {return "MEETTcpSockSender";}}
+
+		private byte[] buffer = null;
+		private MemoryStream ms = null;
+		private BinaryWriter bw = null;
+
+
+		public MEETTcpSockSender(
+			string theName,
+			MEETContainer theContainer,
+			MEETSockConnection conn,
+			MEETPCQueue inputQ) : base (theName, theContainer, conn, inputQ)
+		{
+			buffer = new byte[1400];
+			ms = new MemoryStream(buffer);
+			bw = new BinaryWriter(ms);
+			bw.Write(MEETPacket.MEET_MAGIC);
+		}
+
+		protected override void innerloop(object o) {
+			try {
+				MEETDataPacket msg = (MEETDataPacket)o;
+				bw.Seek(2, SeekOrigin.Begin); // reset to just past magic
+				bw.Write((ushort)msg.Type);
+				bw.Write(msg.Data.Length); // int
+				bw.Write(msg.Data);
+				int len = (int) bw.Seek(0,SeekOrigin.Current);
+
+				// blocking call
+				// kill with m_sock.Close()
+				int nBytesSent = m_conn.Sock.Send(buffer, len, SocketFlags.None);
+				if (nBytesSent != len) {
+					m_parent.WriteLog(LogLevel.WARN, String.Format(
+						"{0} Warning: sent {1}, not {2} bytes",
+						ClassName, nBytesSent, len));
+				}
+
+				Interlocked.Increment(ref m_meetCount);
+			} catch (Exception ex) {
+				m_errorSrc = ex;
+				// m_node.AlErrorEvents.Add(m_errorSrc.ToString());
+				m_done = true;
+			}
+		}
+
+		protected override void shutdown() {
+			m_done = true;
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETUdpSockListener.cs b/csharp/MEETLib/MEETUdpSockListener.cs
new file mode 100644
index 0000000..6684599
--- /dev/null
+++ b/csharp/MEETLib/MEETUdpSockListener.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Threading;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using System.Collections;
+using System.Diagnostics;
+
+
+namespace MEETLib {
+	/// <summary>
+	/// Summary description for UdpListenerThread.
+	/// </summary>
+	public class MEETUdpSockListener : MEETSockListener {
+
+		public override string ClassName {get {return "MEETUdpSockListener";}}
+		public const int UDPLISTENER_DEFAULT_PORT = 0xEEEE;
+		public const int UDP_BUF_SIZE = 4096;
+		// protected int m_port = UDPLISTENER_DEFAULT_PORT;
+
+
+		protected byte[] buffer = null;
+		protected byte[] data = null;
+
+
+		// public UdpListenerThread(MEETNode node, MEETIFace iface)
+		//	: this(node, iface, UDPLISTENER_DEFAULT_PORT) {}
+
+		public MEETUdpSockListener(
+			string theName,
+			MEETContainer theContainer,
+			MEETSockConnection conn,
+			MEETPCQueue meetQ
+			) : base(theName, theContainer, conn, meetQ)
+		{
+			buffer = new byte[UDP_BUF_SIZE];
+		}
+
+		protected override void innerloop() {
+			try {
+				// blocking call
+				// kill socket to release
+				int nBytesReceived = m_conn.Sock.Receive(buffer);
+				// don't bother reading length: MEETPacket = UDP Packet
+				data = new byte[nBytesReceived];
+				Array.Copy(buffer, data, nBytesReceived);  // copy to new buffer
+				MemoryStream mf = new MemoryStream(data);
+				BinaryReader br = new BinaryReader(mf);
+				ushort magic = br.ReadUInt16();
+				if (MEETPacket.MEET_MAGIC == magic) {
+					// it's a MEET packet
+					MType type = (MType) br.ReadUInt16();
+					Console.WriteLine("endpoint is {0}", m_conn.IpepRemote);
+					// right now, calling time on every packet receipt
+					// TODO: get time from lo-res clock
+					m_recvQ.Enqueue(
+						new MEETRecvPacket(type, br, DateTime.UtcNow, m_conn));
+					Interlocked.Increment(ref m_meetCount);
+				} else {
+					// m_node.InqOtherEvent.Enqueue(data);
+					Interlocked.Increment(ref m_otherCount);
+				}
+				data = null;  // decrement ref count asap?
+			}
+			catch (Exception ex) {
+				m_errorSrc = ex;
+				m_parent.WriteLog(LogLevel.ERROR, String.Format("Read Error : {0}", m_errorSrc.Message));
+				Console.WriteLine("UDPSockL exception {0}: {1}", m_errorSrc.Message, m_errorSrc.StackTrace);
+				Debug.WriteLine(String.Format("Exception from {0}, st {1}", ex.TargetSite, ex.StackTrace));
+
+				// m_node.AlErrorEvents.Add(m_errorSrc.ToString());
+				m_done = true;
+			}
+		}
+
+		protected override void shutdown() {
+			m_done = true;
+			// m_sock.Close();
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/MEETUdpSockSender.cs b/csharp/MEETLib/MEETUdpSockSender.cs
new file mode 100644
index 0000000..5e4b727
--- /dev/null
+++ b/csharp/MEETLib/MEETUdpSockSender.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Threading;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+using System.Collections;
+
+
+namespace MEETLib {
+	/// <summary>
+	/// Generic Socket send thread.  Packets to be sent are placed in queue.
+	/// </summary>
+	public class MEETUdpSockSender : MEETSockSender {
+
+		public override string ClassName {get {return "MEETUdpSockSender";}}
+
+		private byte[] buffer = null;
+		private MemoryStream ms = null;
+		private BinaryWriter bw = null;
+
+
+		public MEETUdpSockSender(
+			string theName,
+			MEETContainer theContainer,
+			MEETSockConnection conn,
+			MEETPCQueue inputQ) : base (theName, theContainer, conn, inputQ)
+		{
+			buffer = new byte[1400];
+			ms = new MemoryStream(buffer);
+			bw = new BinaryWriter(ms);
+			bw.Write(MEETPacket.MEET_MAGIC);
+		}
+
+		protected override void innerloop(object o) {
+			try {
+				MEETDataPacket msg = (MEETDataPacket)o;
+				bw.Seek(2, SeekOrigin.Begin); // reset to just past magic
+				bw.Write((ushort)msg.Type);
+				bw.Write(msg.Data.Length); // int
+				bw.Write(msg.Data);
+				int len = (int) bw.Seek(0,SeekOrigin.Current);
+
+				// blocking call
+				// kill with m_sock.Close()
+				int nBytesSent = m_conn.Sock.Send(buffer, len, SocketFlags.None);
+				if (nBytesSent != len) {
+					m_parent.WriteLog(LogLevel.WARN, String.Format(
+						"{0} Warning: sent {1}, not {2} bytes",
+						ClassName, nBytesSent, len));
+				}
+
+				Interlocked.Increment(ref m_meetCount);
+			} catch (Exception ex) {
+				m_errorSrc = ex;
+				// m_node.AlErrorEvents.Add(m_errorSrc.ToString());
+				m_done = true;
+			}
+		}
+
+		protected override void shutdown() {
+			m_done = true;
+		}
+
+	}
+}
diff --git a/csharp/MEETLib/bin/Debug/MEETLib.dll b/csharp/MEETLib/bin/Debug/MEETLib.dll
new file mode 100644
index 0000000..48090e8
Binary files /dev/null and b/csharp/MEETLib/bin/Debug/MEETLib.dll differ
diff --git a/csharp/MEETLib/bin/Debug/MEETLib.pdb b/csharp/MEETLib/bin/Debug/MEETLib.pdb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/csharp/MEETLib/bin/Debug/MEETLib.pdb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/csharp/MEETLib/bin/Release/MEETLib.dll b/csharp/MEETLib/bin/Release/MEETLib.dll
new file mode 100644
index 0000000..c66a84b
Binary files /dev/null and b/csharp/MEETLib/bin/Release/MEETLib.dll differ
diff --git a/csharp/MEETLib/obj/Debug/MEETLib.dll b/csharp/MEETLib/obj/Debug/MEETLib.dll
new file mode 100644
index 0000000..48090e8
Binary files /dev/null and b/csharp/MEETLib/obj/Debug/MEETLib.dll differ
diff --git a/csharp/MEETLib/obj/Debug/MEETLib.pdb b/csharp/MEETLib/obj/Debug/MEETLib.pdb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/csharp/MEETLib/obj/Debug/MEETLib.pdb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/csharp/MEETLib/obj/Debug/MEETLib.projdata b/csharp/MEETLib/obj/Debug/MEETLib.projdata
new file mode 100644
index 0000000..d6851c6
Binary files /dev/null and b/csharp/MEETLib/obj/Debug/MEETLib.projdata differ
diff --git a/csharp/MEETLib/obj/Release/MEETLib.dll b/csharp/MEETLib/obj/Release/MEETLib.dll
new file mode 100644
index 0000000..c66a84b
Binary files /dev/null and b/csharp/MEETLib/obj/Release/MEETLib.dll differ
diff --git a/csharp/MEETLib/obj/Release/MEETLib.projdata b/csharp/MEETLib/obj/Release/MEETLib.projdata
new file mode 100644
index 0000000..242ddd9
Binary files /dev/null and b/csharp/MEETLib/obj/Release/MEETLib.projdata differ
diff --git a/csharp/MEETTest/App.ico b/csharp/MEETTest/App.ico
new file mode 100644
index 0000000..3a5525f
Binary files /dev/null and b/csharp/MEETTest/App.ico differ
diff --git a/csharp/MEETTest/AssemblyInfo.cs b/csharp/MEETTest/AssemblyInfo.cs
new file mode 100644
index 0000000..9f89a32
--- /dev/null
+++ b/csharp/MEETTest/AssemblyInfo.cs
@@ -0,0 +1,58 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
diff --git a/csharp/MEETTest/MEETTest.cs b/csharp/MEETTest/MEETTest.cs
new file mode 100644
index 0000000..9200e1f
--- /dev/null
+++ b/csharp/MEETTest/MEETTest.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Threading;
+using System.Collections;
+using System.Diagnostics;
+using MEETLib;
+
+namespace MEETTest {
+	/// <summary>
+	/// MEET exerciser
+	/// </summary>
+	class MEETTest {
+
+		public static MEETPCQueue pcq = null;
+
+		public static TestQModule tqm1 = null;
+		public static TestModule tm2 = null;
+		public static MEETClock mc = null;
+
+		public static Random r = null;
+
+		/// <summary>
+		/// The main entry point for the application.
+		/// </summary>
+		[STAThread]
+		public static void Main(string[] args) {
+			r = new Random();
+			MEETNode mn = new MEETNode("TestContainer");
+			pcq = new MEETPCQueue(5);
+			tqm1 = new TestQModule("tqm1", mn, pcq);
+			tm2 = new TestModule("tm2", mn);
+			mc = new MEETClock("mc", mn);
+			mc.Start();
+			tqm1.Start();
+			Thread.Sleep(500);
+			tm2.Start();
+			Thread.Sleep(2000);
+			tm2.Stop();
+			Thread.Sleep(2000);
+			tqm1.Stop();
+			Thread.Sleep(1000);
+			mn.Shutdown();
+
+			Debug.WriteLine("dumping Log:");
+			IList log = mn.Log;
+			Debug.WriteLine("dumping Log:");
+			foreach (string s in log) {
+				Debug.WriteLine(s);
+			}
+		}
+	}
+
+	class TestModule : MEETModule {
+		public override string ClassName {get {return "TestModule";}}
+		IMEETInputQueue inq = null;
+
+		public TestModule(string myName, MEETContainer theContainer) :
+			base(myName, theContainer) {
+			inq = MEETTest.tqm1.InputQ;
+		}
+
+		protected override void innerloop() {
+			Debug.WriteLine(String.Format("{0}:{1}:{2} enqueueing...", ClassName, m_name, MEETClock.Now));
+			inq.Enqueue(String.Format("{0}:{1}:{2} message.", ClassName, m_name, MEETClock.Now));
+			Thread.Sleep(MEETTest.r.Next(250, 750));
+		}
+
+	}
+
+	class TestQModule : MEETQModule {
+		public override string ClassName {get {return "TestQModule";}}
+
+		public TestQModule(string myName, MEETContainer theContainer, MEETPCQueue theQ) :
+			base(myName, theContainer, theQ) {}
+
+		protected override void innerloop(object o) {
+			System.Console.WriteLine("{0}:{1}:{2} received string {3}...",
+				ClassName, m_name, MEETClock.Now, (string) o);
+			Thread.Sleep(500);
+			System.Console.WriteLine("{0}:{1}:{2} done pseudoprocessing.",
+				ClassName, m_name, MEETClock.Now, (string) o);
+		}
+
+	}
+
+}
diff --git a/csharp/MEETTest/MEETTest.csproj b/csharp/MEETTest/MEETTest.csproj
new file mode 100644
index 0000000..c97ffe9
--- /dev/null
+++ b/csharp/MEETTest/MEETTest.csproj
@@ -0,0 +1,109 @@
+<VisualStudioProject>
+    <CSHARP
+        ProjectType = "Local"
+        ProductVersion = "7.10.3077"
+        SchemaVersion = "2.0"
+        ProjectGuid = "{AE73A884-5D4E-4BB2-B866-47DFF2907845}"
+    >
+        <Build>
+            <Settings
+                ApplicationIcon = "App.ico"
+                AssemblyKeyContainerName = ""
+                AssemblyName = "MEETTest"
+                AssemblyOriginatorKeyFile = ""
+                DefaultClientScript = "JScript"
+                DefaultHTMLPageLayout = "Grid"
+                DefaultTargetSchema = "IE50"
+                DelaySign = "false"
+                OutputType = "Exe"
+                PreBuildEvent = ""
+                PostBuildEvent = ""
+                RootNamespace = "MEETTest"
+                RunPostBuildEvent = "OnBuildSuccess"
+                StartupObject = ""
+            >
+                <Config
+                    Name = "Debug"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "DEBUG;TRACE"
+                    DocumentationFile = "doc.xml"
+                    DebugSymbols = "true"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "false"
+                    OutputPath = "bin\Debug\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+                <Config
+                    Name = "Release"
+                    AllowUnsafeBlocks = "false"
+                    BaseAddress = "285212672"
+                    CheckForOverflowUnderflow = "false"
+                    ConfigurationOverrideFile = ""
+                    DefineConstants = "TRACE"
+                    DocumentationFile = ""
+                    DebugSymbols = "false"
+                    FileAlignment = "4096"
+                    IncrementalBuild = "false"
+                    NoStdLib = "false"
+                    NoWarn = ""
+                    Optimize = "true"
+                    OutputPath = "bin\Release\"
+                    RegisterForComInterop = "false"
+                    RemoveIntegerChecks = "false"
+                    TreatWarningsAsErrors = "false"
+                    WarningLevel = "4"
+                />
+            </Settings>
+            <References>
+                <Reference
+                    Name = "System"
+                    AssemblyName = "System"
+                    HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.dll"
+                />
+                <Reference
+                    Name = "System.Data"
+                    AssemblyName = "System.Data"
+                    HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Data.dll"
+                />
+                <Reference
+                    Name = "System.XML"
+                    AssemblyName = "System.Xml"
+                    HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.XML.dll"
+                />
+                <Reference
+                    Name = "MEETLib"
+                    Project = "{DAAF8010-B0DB-4C88-A7A2-2F9DA1E47362}"
+                    Package = "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}"
+                />
+            </References>
+        </Build>
+        <Files>
+            <Include>
+                <File
+                    RelPath = "App.ico"
+                    BuildAction = "Content"
+                />
+                <File
+                    RelPath = "AssemblyInfo.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "MEETTest.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+            </Include>
+        </Files>
+    </CSHARP>
+</VisualStudioProject>
+
diff --git a/csharp/MEETTest/MEETTest.csproj.user b/csharp/MEETTest/MEETTest.csproj.user
new file mode 100644
index 0000000..686cccb
--- /dev/null
+++ b/csharp/MEETTest/MEETTest.csproj.user
@@ -0,0 +1,48 @@
+<VisualStudioProject>
+    <CSHARP LastOpenVersion = "7.10.3077" >
+        <Build>
+            <Settings ReferencePath = "" >
+                <Config
+                    Name = "Debug"
+                    EnableASPDebugging = "false"
+                    EnableASPXDebugging = "false"
+                    EnableUnmanagedDebugging = "false"
+                    EnableSQLServerDebugging = "false"
+                    RemoteDebugEnabled = "false"
+                    RemoteDebugMachine = ""
+                    StartAction = "Project"
+                    StartArguments = ""
+                    StartPage = ""
+                    StartProgram = ""
+                    StartURL = ""
+                    StartWorkingDirectory = ""
+                    StartWithIE = "true"
+                />
+                <Config
+                    Name = "Release"
+                    EnableASPDebugging = "false"
+                    EnableASPXDebugging = "false"
+                    EnableUnmanagedDebugging = "false"
+                    EnableSQLServerDebugging = "false"
+                    RemoteDebugEnabled = "false"
+                    RemoteDebugMachine = ""
+                    StartAction = "Project"
+                    StartArguments = ""
+                    StartPage = ""
+                    StartProgram = ""
+                    StartURL = ""
+                    StartWorkingDirectory = ""
+                    StartWithIE = "true"
+                />
+            </Settings>
+        </Build>
+        <OtherProjectSettings
+            CopyProjectDestinationFolder = ""
+            CopyProjectUncPath = ""
+            CopyProjectOption = "0"
+            ProjectView = "ProjectFiles"
+            ProjectTrust = "0"
+        />
+    </CSHARP>
+</VisualStudioProject>
+
diff --git a/csharp/MEETTest/bin/Debug/MEETLib.dll b/csharp/MEETTest/bin/Debug/MEETLib.dll
new file mode 100644
index 0000000..48090e8
Binary files /dev/null and b/csharp/MEETTest/bin/Debug/MEETLib.dll differ
diff --git a/csharp/MEETTest/bin/Debug/MEETLib.pdb b/csharp/MEETTest/bin/Debug/MEETLib.pdb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/csharp/MEETTest/bin/Debug/MEETLib.pdb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/csharp/MEETTest/bin/Debug/MEETTest.pdb b/csharp/MEETTest/bin/Debug/MEETTest.pdb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/csharp/MEETTest/bin/Debug/MEETTest.pdb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/csharp/MEETTest/bin/Debug/doc.xml b/csharp/MEETTest/bin/Debug/doc.xml
new file mode 100644
index 0000000..69da3c9
--- /dev/null
+++ b/csharp/MEETTest/bin/Debug/doc.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>MEETTest</name>
+    </assembly>
+    <members>
+        <member name="T:MEETTest.MEETTest">
+            <summary>
+            MEET exerciser
+            </summary>
+        </member>
+        <member name="M:MEETTest.MEETTest.Main(System.String[])">
+            <summary>
+            The main entry point for the application.
+            </summary>
+        </member>
+    </members>
+</doc>
diff --git a/csharp/MEETTest/bin/Release/MEETLib.dll b/csharp/MEETTest/bin/Release/MEETLib.dll
new file mode 100644
index 0000000..c66a84b
Binary files /dev/null and b/csharp/MEETTest/bin/Release/MEETLib.dll differ
diff --git a/csharp/MEETTest/doc.xml b/csharp/MEETTest/doc.xml
new file mode 100644
index 0000000..69da3c9
--- /dev/null
+++ b/csharp/MEETTest/doc.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>MEETTest</name>
+    </assembly>
+    <members>
+        <member name="T:MEETTest.MEETTest">
+            <summary>
+            MEET exerciser
+            </summary>
+        </member>
+        <member name="M:MEETTest.MEETTest.Main(System.String[])">
+            <summary>
+            The main entry point for the application.
+            </summary>
+        </member>
+    </members>
+</doc>
diff --git a/csharp/MEETTest/obj/Debug/MEETTest.pdb b/csharp/MEETTest/obj/Debug/MEETTest.pdb
new file mode 100644
index 0000000..9057eba
--- /dev/null
+++ b/csharp/MEETTest/obj/Debug/MEETTest.pdb
@@ -0,0 +1 @@
+Microsoft C/C++ MSF 7.00
diff --git a/csharp/MEETTest/obj/Debug/MEETTest.projdata b/csharp/MEETTest/obj/Debug/MEETTest.projdata
new file mode 100644
index 0000000..35271c2
Binary files /dev/null and b/csharp/MEETTest/obj/Debug/MEETTest.projdata differ
diff --git a/csharp/MEETTest/obj/Release/MEETTest.projdata b/csharp/MEETTest/obj/Release/MEETTest.projdata
new file mode 100644
index 0000000..531c968
Binary files /dev/null and b/csharp/MEETTest/obj/Release/MEETTest.projdata differ