diff --git a/apps/sam/csharp/src/I2P.SAM.Client/AssemblyInfo.cs b/apps/sam/csharp/src/I2P.SAM.Client/AssemblyInfo.cs
new file mode 100644
index 000000000..f7d478392
--- /dev/null
+++ b/apps/sam/csharp/src/I2P.SAM.Client/AssemblyInfo.cs
@@ -0,0 +1,32 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following
+// attributes.
+//
+// change them to the information which is associated with the assembly
+// you compile.
+
+[assembly: AssemblyTitle("sam-sharp")]
+[assembly: AssemblyDescription("Mono/.NET SAM client for I2P")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("sam-sharp")]
+[assembly: AssemblyCopyright("Released into the Public Domain")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has following format :
+//
+// Major.Minor.Build.Revision
+//
+// You can specify all values by your own or you can build default build and revision
+// numbers with the '*' character (the default):
+
+[assembly: AssemblyVersion("0.1")]
+
+// The following attributes specify the key for the sign of your assembly. See the
+// .NET Framework documentation for more information about signing.
+// This is not required, if you don't want signing let these attributes like they're.
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
diff --git a/apps/sam/csharp/src/I2P.SAM.Client/SamBridgeMessages.cs b/apps/sam/csharp/src/I2P.SAM.Client/SamBridgeMessages.cs
new file mode 100644
index 000000000..df96c9643
--- /dev/null
+++ b/apps/sam/csharp/src/I2P.SAM.Client/SamBridgeMessages.cs
@@ -0,0 +1,26 @@
+namespace I2P.SAM.Client
+{
+ public struct SamBridgeMessages
+ {
+ public const string NAMING_REPLY_INVALID_KEY = "INVALID_KEY";
+ public const string NAMING_REPLY_KEY_NOT_FOUND = "KEY_NOT_FOUND";
+ public const string NAMING_REPLY_OK = "OK";
+
+ public const string SESSION_STATUS_DUPLICATE_DEST = "DUPLICATE_DEST";
+ public const string SESSION_STATUS_I2P_ERROR = "I2P_ERROR";
+ public const string SESSION_STATUS_INVALID_KEY = "INVALID_KEY";
+ public const string SESSION_STATUS_OK = "OK";
+
+ public const string STREAM_CLOSED_CANT_REACH_PEER = "CANT_REACH_PEER";
+ public const string STREAM_CLOSED_I2P_ERROR = "I2P_ERROR";
+ public const string STREAM_CLOSED_PEER_NOT_FOUND = "PEER_NOT_FOUND";
+ public const string STREAM_CLOSED_TIMEOUT = "CLOSED";
+ public const string STREAM_CLOSED_OK = "OK";
+
+ public const string STREAM_STATUS_CANT_REACH_PEER = "CANT_REACH_PEER";
+ public const string STREAM_STATUS_I2P_ERROR = "I2P_ERROR";
+ public const string STREAM_STATUS_INVALID_KEY = "INVALID_KEY";
+ public const string STREAM_STATUS_TIMEOUT = "TIMEOUT";
+ public const string STREAM_STATUS_OK = "OK";
+ }
+}
diff --git a/apps/sam/csharp/src/I2P.SAM.Client/SamClientEventListener.cs b/apps/sam/csharp/src/I2P.SAM.Client/SamClientEventListener.cs
new file mode 100644
index 000000000..ab6459d33
--- /dev/null
+++ b/apps/sam/csharp/src/I2P.SAM.Client/SamClientEventListener.cs
@@ -0,0 +1,20 @@
+using System.Collections.Specialized;
+
+namespace I2P.SAM.Client
+{
+ ///
+ /// Async event notification interface for SAM clients.
+ ///
+ public interface SamClientEventListener
+ {
+ void HelloReplyReceived(bool ok);
+ void SessionStatusReceived(string result, string destination, string message);
+ void StreamStatusReceived(string result, int id, string message);
+ void StreamConnectedReceived(string remoteDestination, int id);
+ void StreamClosedReceived(string result, int id, string message);
+ void StreamDataReceived(int id, byte[] data, int offset, int length);
+ void NamingReplyReceived(string name, string result, string valueString, string message);
+ void DestReplyReceived(string publicKey, string privateKey);
+ void UnknownMessageReceived(string major, string minor, NameValueCollection parameters);
+ }
+}
\ No newline at end of file
diff --git a/apps/sam/csharp/src/I2P.SAM.Client/SamClientEventListenerImpl.cs b/apps/sam/csharp/src/I2P.SAM.Client/SamClientEventListenerImpl.cs
new file mode 100644
index 000000000..edd304558
--- /dev/null
+++ b/apps/sam/csharp/src/I2P.SAM.Client/SamClientEventListenerImpl.cs
@@ -0,0 +1,20 @@
+using System.Collections.Specialized;
+
+namespace I2P.SAM.Client
+{
+ ///
+ /// Basic noop client event listener.
+ ///
+ public class SamClientEventListenerImpl : SamClientEventListener
+ {
+ public virtual void DestReplyReceived(string publicKey, string privateKey) {}
+ public virtual void HelloReplyReceived(bool ok) {}
+ public virtual void NamingReplyReceived(string name, string result, string valueString, string message) {}
+ public virtual void SessionStatusReceived(string result, string destination, string message) {}
+ public virtual void StreamClosedReceived(string result, int id, string message) {}
+ public virtual void StreamConnectedReceived(string remoteDestination, int id) {}
+ public virtual void StreamDataReceived(int id, byte[] data, int offset, int length) {}
+ public virtual void StreamStatusReceived(string result, int id, string message) {}
+ public virtual void UnknownMessageReceived(string major, string minor, NameValueCollection parameters) {}
+ }
+}
diff --git a/apps/sam/csharp/src/I2P.SAM.Client/SamEventHandler.cs b/apps/sam/csharp/src/I2P.SAM.Client/SamEventHandler.cs
new file mode 100644
index 000000000..0dfaf19c5
--- /dev/null
+++ b/apps/sam/csharp/src/I2P.SAM.Client/SamEventHandler.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Specialized;
+using System.Threading;
+
+namespace I2P.SAM.Client
+{
+ ///
+ /// Simple helper implementation of a SamClientEventListener.
+ ///
+ public class SamEventHandler : SamClientEventListenerImpl
+ {
+ private object _helloLock = new Object();
+ private String _helloOk;
+ private NameValueCollection _namingReplies = new NameValueCollection();
+ private object _namingReplyLock = new Object();
+ private object _sessionCreateLock = new Object();
+ private String _sessionCreateOk;
+
+ public override void HelloReplyReceived(bool ok) {
+ lock (_helloLock) {
+ if (ok)
+ _helloOk = Boolean.TrueString;
+ else
+ _helloOk = Boolean.FalseString;
+
+ Monitor.PulseAll(_helloLock);
+ }
+ }
+
+ public override void NamingReplyReceived(string name, string result, string valueString, string message) {
+ lock (_namingReplyLock) {
+ if (result.Equals(SamBridgeMessages.NAMING_REPLY_OK))
+ _namingReplies.Add(name, valueString);
+ else
+ _namingReplies.Add(name, result);
+
+ Monitor.PulseAll(_namingReplyLock);
+ }
+ }
+
+ public override void SessionStatusReceived(string result, string destination, string message) {
+ lock (_sessionCreateLock) {
+ if (result.Equals(SamBridgeMessages.SESSION_STATUS_OK))
+ _sessionCreateOk = Boolean.TrueString;
+ else
+ _sessionCreateOk = Boolean.FalseString;
+
+ Monitor.PulseAll(_sessionCreateLock);
+ }
+ }
+
+ public override void UnknownMessageReceived(string major, string minor, NameValueCollection parameters) {
+ Console.WriteLine("wrt, [" + major + "] [" + minor + "] [" + parameters + "]");
+ }
+
+ /*
+ * Blocking lookup calls below.
+ */
+
+ ///
+ /// Wait for the connection to be established, returning true if
+ /// everything went ok.
+ ///
+ public bool WaitForHelloReply() {
+ while (true) {
+ lock (_helloLock) {
+ if (_helloOk == null)
+ Monitor.Wait(_helloLock);
+ else
+ return Boolean.Parse(_helloOk);
+ }
+ }
+ }
+
+ ///
+ /// Return the destination found matching the name, or null if
+ /// the key was not able to be retrieved.
+ ///
+ /// The name to be looked for, or "ME".
+ public string WaitForNamingReply(string name) {
+ while (true) {
+ lock (_namingReplyLock) {
+ try {
+ string valueString = _namingReplies[name];
+ _namingReplies.Remove(name);
+
+ if (valueString.Equals(SamBridgeMessages.NAMING_REPLY_INVALID_KEY))
+ return null;
+ else if (valueString.Equals(SamBridgeMessages.NAMING_REPLY_KEY_NOT_FOUND))
+ return null;
+ else
+ return valueString;
+
+ } catch (ArgumentNullException ane) {
+ Monitor.Wait(_namingReplyLock);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Wait for the session to be created, returning true if everything
+ /// went ok.
+ ///
+ public bool WaitForSessionCreateReply() {
+ while (true) {
+ lock (_sessionCreateLock) {
+ if (_sessionCreateOk == null)
+ Monitor.Wait(_sessionCreateLock);
+ else
+ return Boolean.Parse(_sessionCreateOk);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/apps/sam/csharp/src/I2P.SAM.Client/SamReader.cs b/apps/sam/csharp/src/I2P.SAM.Client/SamReader.cs
new file mode 100644
index 000000000..ac99d7d29
--- /dev/null
+++ b/apps/sam/csharp/src/I2P.SAM.Client/SamReader.cs
@@ -0,0 +1,259 @@
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.IO;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+
+namespace I2P.SAM.Client
+{
+ ///
+ /// Read from a socket, producing events for any SAM message read.
+ ///
+ public class SamReader
+ {
+ private bool _isLive;
+ private SamClientEventListener _listener;
+ private NetworkStream _samStream;
+ private StreamReader _streamReader;
+
+ public SamReader(NetworkStream samStream, SamClientEventListener listener) {
+ _samStream = samStream;
+ _listener = listener;
+ }
+
+ public void RunThread() {
+
+ NameValueCollection parameters = new NameValueCollection();
+
+ while (_isLive) {
+
+ string line = null;
+
+ _streamReader = new StreamReader(_samStream);
+
+ try {
+ line = _streamReader.ReadLine();
+ _streamReader.Close();
+ } catch (IOException ioe) {
+ Console.Error.WriteLine("Error reading from SAM: {1}", ioe);
+ } catch (OutOfMemoryException oome) {
+ Console.Error.WriteLine("Out of memory while reading from SAM: {1}", oome);
+ return;
+ }
+
+ if (line == null) {
+ break;
+ }
+
+ string[] tokens = line.Split(new char[1] { ' ' });
+
+ if (tokens.Length < 2) {
+ Console.Error.WriteLine("Invalid SAM line: [" + line + "]");
+ _isLive = false;
+ return;
+ }
+
+ IEnumerator tokensEnumerator = tokens.GetEnumerator();
+ tokensEnumerator.MoveNext();
+ string major = (string) tokensEnumerator.Current;
+ tokensEnumerator.MoveNext();
+ string minor = (string) tokensEnumerator.Current;
+
+ parameters.Clear();
+
+ while (tokensEnumerator.MoveNext()) {
+
+ string pair = (string) tokensEnumerator.Current;
+ int equalsPosition = pair.IndexOf('=');
+
+ if ( (equalsPosition > 0) && (equalsPosition < pair.Length - 1) ) {
+
+ string name = pair.Substring(0, equalsPosition);
+ string valueString = pair.Substring(equalsPosition + 1);
+
+ while ( (valueString[0] == '\"') && (valueString.Length > 0) )
+ valueString = valueString.Substring(1);
+
+ while ( (valueString.Length > 0) && (valueString[valueString.Length - 1] == '\"') )
+ valueString = valueString.Substring(0, valueString.Length - 1);
+
+ parameters.Set(name, valueString);
+ }
+ }
+
+ ProcessEvent(major, minor, parameters);
+ }
+ }
+
+ private void ProcessEvent(string major, string minor, NameValueCollection parameters) {
+
+ switch (major)
+ {
+ case "HELLO" :
+
+ if (minor.Equals("REPLY")) {
+
+ string result = parameters.Get("RESULT");
+
+ if (result.Equals("OK"))
+ _listener.HelloReplyReceived(true);
+ else
+ _listener.HelloReplyReceived(false);
+ } else {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+
+ break;
+
+ case "SESSION" :
+
+ if (minor.Equals("STATUS")) {
+
+ string result = parameters.Get("RESULT");
+ string destination = parameters.Get("DESTINATION");
+ string message = parameters.Get("MESSAGE");
+
+ _listener.SessionStatusReceived(result, destination, message);
+ } else {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+
+ break;
+
+ case "STREAM" :
+
+ ProcessStream(major, minor, parameters);
+ break;
+
+ case "NAMING" :
+
+ if (minor.Equals("REPLY")) {
+
+ string name = parameters.Get("NAME");
+ string result = parameters.Get("RESULT");
+ string valueString = parameters.Get("VALUE");
+ string message = parameters.Get("MESSAGE");
+
+ _listener.NamingReplyReceived(name, result, valueString, message);
+ } else {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+
+ break;
+
+ case "DEST" :
+
+ if (minor.Equals("REPLY")) {
+
+ string pub = parameters.Get("PUB");
+ string priv = parameters.Get("PRIV");
+
+ _listener.DestReplyReceived(pub, priv);
+ } else {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+
+ break;
+
+ default :
+
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ break;
+ }
+ }
+
+ private void ProcessStream(string major, string minor, NameValueCollection parameters) {
+
+ /*
+ * Would use another tidy switch() statement here but the Mono
+ * compiler presently gets variable scopes confused within nested
+ * switch() contexts. Broken with Mono/mcs 1.0.5, 1.1.3, and SVN
+ * head.
+ */
+ if (minor.Equals("STATUS")) {
+
+ string result = parameters.Get("RESULT");
+ string id = parameters.Get("ID");
+ string message = parameters.Get("MESSAGE");
+
+ try {
+ _listener.StreamStatusReceived(result, Int32.Parse(id), message);
+ } catch {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+
+ } else if (minor.Equals("CONNECTED")) {
+
+ string destination = parameters.Get("DESTINATION");
+ string id = parameters.Get("ID");
+
+ try {
+ _listener.StreamConnectedReceived(destination, Int32.Parse(id));
+ } catch {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+
+ } else if (minor.Equals("CLOSED")) {
+
+ string result = parameters.Get("RESULT");
+ string id = parameters.Get("ID");
+ string message = parameters.Get("MESSAGE");
+
+ try {
+ _listener.StreamClosedReceived(result, Int32.Parse(id), message);
+ } catch {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+
+ } else if (minor.Equals("RECEIVED")) {
+
+ string id = parameters.Get("ID");
+ string size = parameters.Get("SIZE");
+
+ if (id != null) {
+ try {
+
+ int idValue = Int32.Parse(id);
+ int sizeValue = Int32.Parse(size);
+ byte[] data = new byte[sizeValue];
+ int bytesRead;
+
+ try {
+ bytesRead = _samStream.Read(data, 0, sizeValue);
+
+ if (bytesRead != sizeValue) {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ return;
+ }
+ } catch {
+ _isLive = false;
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+
+ _listener.StreamDataReceived(idValue, data, 0, sizeValue);
+ } catch (FormatException fe) {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+ } else {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+ } else {
+ _listener.UnknownMessageReceived(major, minor, parameters);
+ }
+ }
+
+ public void StartReading() {
+ _isLive = true;
+ ThreadStart threadStart = new ThreadStart(RunThread);
+ Thread thread = new Thread(threadStart);
+ thread.Name = "SAM Reader";
+ thread.Start();
+ }
+
+ public void StopReading() {
+ _isLive = false;
+ }
+ }
+}
diff --git a/apps/sam/csharp/src/SAM.NET/SAM.NET.Test/AssemblyInfo.cs b/apps/sam/csharp/src/SAM.NET/SAM.NET.Test/AssemblyInfo.cs
deleted file mode 100644
index 9f89a3282..000000000
--- a/apps/sam/csharp/src/SAM.NET/SAM.NET.Test/AssemblyInfo.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-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\. 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/apps/sam/csharp/src/SAM.NET/SAM.NET.Test/SAM.NET.Test.cs b/apps/sam/csharp/src/SAM.NET/SAM.NET.Test/SAM.NET.Test.cs
deleted file mode 100644
index e3805c7b8..000000000
--- a/apps/sam/csharp/src/SAM.NET/SAM.NET.Test/SAM.NET.Test.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System;
-using System.Net;
-using System.Threading;
-using System.Text;
-using System.Collections;
-
-namespace SAM.NET
-{
- class SAMTester
- {
- [STAThread]
- static void Main(string[] args)
- {
- new SAMTester();
- }
- public SAMTester ()
- {
- SAMConnection connection1 = new SAMConnection(IPAddress.Parse("127.0.0.1"),7656);
- SAMSession session1 = new SAMSession(connection1,SAM.NET.SamSocketType.Stream,"alice");
-
- SAMConnection connection2 = new SAMConnection(IPAddress.Parse("127.0.0.1"),7656);
- SAMSession session2 = new SAMSession(connection2,SAM.NET.SamSocketType.Stream,"bob");
-
- SAMStream stream1 = new SAMStream(connection1,session1,233);
- stream1.Connect(session2.getKey());
-
- //Wait till we are connected to destination
- while (!stream1.isConnected)
- Thread.Sleep(1000);
-
- //Send some bytes
- stream1.Write(Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString() + "Hi!!!!!!"));
-
- //Wait till a stream magically appears on the other side
- while (session2.getStreams().Count == 0) Thread.Sleep(1000);
-
- Thread.Sleep(1000);
- foreach (SAMStream stream in session2.getStreams().Values)
- {
- Console.WriteLine("Text received on " + stream.getID() + " at " + DateTime.Now.ToLongTimeString());
- Console.WriteLine(Encoding.ASCII.GetString(stream.ReadToEnd()));
- stream.Close();
- }
-
- stream1.Close();
- connection1.Close();
- connection2.Close();
- }
- }
-}
diff --git a/apps/sam/csharp/src/SAM.NET/SAM.NET/AssemblyInfo.cs b/apps/sam/csharp/src/SAM.NET/SAM.NET/AssemblyInfo.cs
deleted file mode 100644
index 9f89a3282..000000000
--- a/apps/sam/csharp/src/SAM.NET/SAM.NET/AssemblyInfo.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-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\. 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/apps/sam/csharp/src/SAM.NET/SAM.NET/SAM.NET.cs b/apps/sam/csharp/src/SAM.NET/SAM.NET/SAM.NET.cs
deleted file mode 100644
index 96ff4e09b..000000000
--- a/apps/sam/csharp/src/SAM.NET/SAM.NET/SAM.NET.cs
+++ /dev/null
@@ -1,271 +0,0 @@
-using System;
-using System.Net.Sockets;
-using System.Text;
-using System.Net;
-using System.IO;
-using System.Collections;
-using System.Threading;
-
-namespace SAM.NET
-{
- public enum SamSocketType
- {
- Stream,
- Datagram,
- Raw
- }
-
- public class SAMConnection
- {
- private const string propertyMinVersion = "1.0";
- private const string propertyMaxVersion = "1.0";
-
- private Socket _sock;
- private NetworkStream _sockStream;
- private StreamReader _sockStreamIn;
- private StreamWriter _sockStreamOut;
-
- public SAMConnection(IPAddress routerIP, int port)
- {
- _sock = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
- IPEndPoint rEP = new IPEndPoint(routerIP,port);
- _sock.Connect(rEP);
- _sockStream = new NetworkStream(_sock);
- _sockStreamIn = new StreamReader(_sockStream);
- _sockStreamOut = new StreamWriter(_sockStream);
- try
- {
- sendVersion(propertyMinVersion,propertyMinVersion);
- }
- catch (Exception e)
- {
- _sock.Close();
- throw (new Exception("No SAM for you :("));
- }
-
- }
-
- private void sendVersion(string min, string max)
- {
- _sockStreamOut.WriteLine("HELLO VERSION MIN=" + propertyMinVersion + " MAX=" + propertyMaxVersion);
- _sockStreamOut.Flush();
- Hashtable response = SAMUtil.parseKeyValues(_sockStreamIn.ReadLine(),2);
- if (response["RESULT"].ToString() != "OK") throw (new Exception("Version mismatch"));
- }
-
- public StreamWriter getOutputStream()
- {
- return _sockStreamOut;
- }
-
- public StreamReader getInputStream()
- {
- return _sockStreamIn;
- }
-
- public NetworkStream getStream()
- {
- return _sockStream;
- }
-
- public void Close()
- {
- _sock.Close();
- }
- }
-
- /*
- * Creating a SAMSession object will automatically:
- * 1) create a sesion on SAM
- * 1) query for the base64key
- * 2) start a listening thread to catch all stream commands
- */
- public class SAMSession
- {
- private Hashtable _streams;
- private string _sessionKey;
-
- public SAMSession (SAMConnection connection, SamSocketType type, string destination)
- {
- _streams = new Hashtable();
- StreamWriter writer = connection.getOutputStream();
- StreamReader reader = connection.getInputStream();
- writer.WriteLine("SESSION CREATE STYLE=STREAM DESTINATION=" + destination);
- writer.Flush();
- Hashtable response = SAMUtil.parseKeyValues(reader.ReadLine(),2);
- if (response["RESULT"].ToString() != "OK")
- {
- throw (new Exception(response["MESSAGE"].ToString()));
- }
- else
- {
- writer.WriteLine("NAMING LOOKUP NAME=ME");
- writer.Flush();
- response = SAMUtil.parseKeyValues(reader.ReadLine(),2);
- _sessionKey = response["VALUE"].ToString();
- SAMSessionListener listener = new SAMSessionListener(connection,this,_streams);
- new Thread(new ThreadStart(listener.startListening)).Start();
- }
- }
- public void addStream(SAMStream stream)
- {
- _streams.Add(stream.getID(),stream);
- }
- public string getKey()
- {
- return _sessionKey;
- }
- public Hashtable getStreams()
- {
- return _streams;
- }
- }
-
- public class SAMSessionListener
- {
- private Hashtable _streams;
- private SAMConnection _connection;
- private SAMSession _session;
- private bool stayAlive = true;
-
- public SAMSessionListener(SAMConnection connection,SAMSession session, Hashtable streams)
- {
- _streams = streams;
- _connection = connection;
- _session = session;
- }
- public void startListening()
- {
- StreamReader reader = _connection.getInputStream();
- while (stayAlive)
- {
- string response = reader.ReadLine();
- if (response.StartsWith("STREAM STATUS"))
- {
- Hashtable values = SAMUtil.parseKeyValues(response,2);
- SAMStream theStream = (SAMStream)_streams[int.Parse(values["ID"].ToString())];
- if (theStream != null) theStream.ReceivedStatus(values);
- }
- if (response.StartsWith("STREAM CONNECTED"))
- {
- Hashtable values = SAMUtil.parseKeyValues(response,2);
- SAMStream theStream = (SAMStream)_streams[int.Parse(values["ID"].ToString())];
- if (theStream != null) theStream.isConnected = true;
- }
- if (response.StartsWith("STREAM RECEIVED"))
- {
- Hashtable values = SAMUtil.parseKeyValues(response,2);
- int streamID = int.Parse(values["ID"].ToString());
- SAMStream theStream = (SAMStream)_streams[streamID];
- if (theStream == null) new SAMStream(_connection,_session,streamID);
- theStream = (SAMStream)_streams[streamID];
- theStream.ReceivedData(int.Parse(values["SIZE"].ToString()));
- }
- if (response.StartsWith("STREAM CLOSE"))
- {
- Hashtable values = SAMUtil.parseKeyValues(response,2);
- SAMStream theStream = (SAMStream)_streams[int.Parse(values["ID"].ToString())];
- if (theStream != null) theStream.isConnected = false;
- }
- }
- }
- }
-
- public class SAMStream
- {
- private int _ID;
- private byte[] _data;
- private int _position=0;
- private int _size=0;
- private SAMSession _session;
- private SAMConnection _connection;
- public bool isConnected=false;
-
- public SAMStream (SAMConnection connection,SAMSession session, int ID)
- {
- _data = new byte[100000]; //FIXME: change to non-static structure for storing stream data
- _ID = ID;
- _connection = connection;
- _session = session;
- _session.addStream(this);
- }
-
- public void Connect(string destination)
- {
- StreamWriter writer = _connection.getOutputStream();
- writer.WriteLine("STREAM CONNECT ID=" + _ID.ToString() + " DESTINATION=" + destination);
- writer.Flush();
- }
-
- public void ReceivedData(int size) //FIXME: WTF is going on when reading the payload here? All zeros and way too many of them.
- {
- NetworkStream stream = _connection.getStream();
- int bytesRead = stream.Read(_data,_size,size);
- _size = _size + bytes;
- }
-
- public void ReceivedStatus(Hashtable response)
- {
- if (response["RESULT"].ToString() != "OK")
- {
- throw (new Exception(response["RESULT"].ToString()));
- }
- else
- {
- isConnected = true;
- }
- }
-
- public int getID() {return _ID;}
-
- public bool DataAvailable()
- {
- return _position != _size;
- }
-
- public void Write(byte[] buf)
- {
- NetworkStream stream = _connection.getStream();
- int sent = 0;
- while (sent < buf.Length)
- {
- int toSend = Math.Min(buf.Length - sent,32768);
- string header = "STREAM SEND ID=" + _ID.ToString() + " SIZE=" + toSend.ToString() + "\n";
- byte[] headerbytes = Encoding.ASCII.GetBytes(header);
- stream.Write(headerbytes,0,headerbytes.Length);
- stream.Write(buf,sent,toSend);
- sent = sent + toSend;
- }
- }
-
- public byte[] ReadToEnd()
- {
- byte[] ret = new byte[_size - _position];
- Array.Copy(_data,_position,ret,0,_size - _position);
- _position = _size;
- return ret;
- }
-
- public void Close()
- {
- StreamWriter writer = _connection.getOutputStream();
- writer.WriteLine("STREAM CLOSE " + _ID.ToString());
- writer.Flush();
- }
- }
-
- public class SAMUtil
- {
- public static Hashtable parseKeyValues(string str, int startingWord)
- {
- Hashtable hash = new Hashtable();
- string strTruncated = string.Join(" ",str.Split(' '),startingWord,str.Split(' ').Length - startingWord);
- string[] sets = strTruncated.Split('=',' ');
- for (int i=0; i