2005-01-23 smeghead
* Port the java SAM client library to mono/C# and released into the public domain. The 0.1 version of this port is available in CVS as i2p/apps/sam/csharp/src/I2P.SAM.Client. The other nonfunctional C# library has been removed.
This commit is contained in:
32
apps/sam/csharp/src/I2P.SAM.Client/AssemblyInfo.cs
Normal file
32
apps/sam/csharp/src/I2P.SAM.Client/AssemblyInfo.cs
Normal file
@ -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("")]
|
26
apps/sam/csharp/src/I2P.SAM.Client/SamBridgeMessages.cs
Normal file
26
apps/sam/csharp/src/I2P.SAM.Client/SamBridgeMessages.cs
Normal file
@ -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";
|
||||
}
|
||||
}
|
20
apps/sam/csharp/src/I2P.SAM.Client/SamClientEventListener.cs
Normal file
20
apps/sam/csharp/src/I2P.SAM.Client/SamClientEventListener.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace I2P.SAM.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Async event notification interface for SAM clients.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace I2P.SAM.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Basic noop client event listener.
|
||||
/// </summary>
|
||||
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) {}
|
||||
}
|
||||
}
|
116
apps/sam/csharp/src/I2P.SAM.Client/SamEventHandler.cs
Normal file
116
apps/sam/csharp/src/I2P.SAM.Client/SamEventHandler.cs
Normal file
@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Threading;
|
||||
|
||||
namespace I2P.SAM.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple helper implementation of a SamClientEventListener.
|
||||
/// </summary>
|
||||
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.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Wait for the connection to be established, returning true if
|
||||
/// everything went ok.
|
||||
/// </summary>
|
||||
public bool WaitForHelloReply() {
|
||||
while (true) {
|
||||
lock (_helloLock) {
|
||||
if (_helloOk == null)
|
||||
Monitor.Wait(_helloLock);
|
||||
else
|
||||
return Boolean.Parse(_helloOk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the destination found matching the name, or <c>null</c> if
|
||||
/// the key was not able to be retrieved.
|
||||
/// </summary>
|
||||
/// <param name="name">The name to be looked for, or "ME".</param>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wait for the session to be created, returning true if everything
|
||||
/// went ok.
|
||||
/// </summary>
|
||||
public bool WaitForSessionCreateReply() {
|
||||
while (true) {
|
||||
lock (_sessionCreateLock) {
|
||||
if (_sessionCreateOk == null)
|
||||
Monitor.Wait(_sessionCreateLock);
|
||||
else
|
||||
return Boolean.Parse(_sessionCreateOk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
259
apps/sam/csharp/src/I2P.SAM.Client/SamReader.cs
Normal file
259
apps/sam/csharp/src/I2P.SAM.Client/SamReader.cs
Normal file
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Read from a socket, producing events for any SAM message read.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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\<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("")]
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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\<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("")]
|
@ -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<sets.Length; i=i+2)
|
||||
{
|
||||
hash.Add(sets[i],sets[i+1]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,10 @@
|
||||
$Id: history.txt,v 1.130 2005/01/18 19:08:13 jrandom Exp $
|
||||
$Id: history.txt,v 1.131 2005/01/21 20:53:02 jrandom Exp $
|
||||
|
||||
2005-01-23 smeghead
|
||||
* Port the java SAM client library to mono/C# and released into the
|
||||
public domain. The 0.1 version of this port is available in CVS as
|
||||
i2p/apps/sam/csharp/src/I2P.SAM.Client. The other nonfunctional C#
|
||||
library has been removed.
|
||||
|
||||
2005-01-21 Jhor
|
||||
* Updated jbigi build scripts for OSX.
|
||||
|
@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
|
||||
*
|
||||
*/
|
||||
public class RouterVersion {
|
||||
public final static String ID = "$Revision: 1.135 $ $Date: 2005/01/18 19:08:13 $";
|
||||
public final static String ID = "$Revision: 1.136 $ $Date: 2005/01/21 20:53:02 $";
|
||||
public final static String VERSION = "0.4.2.6";
|
||||
public final static long BUILD = 5;
|
||||
public final static long BUILD = 6;
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Router version: " + VERSION);
|
||||
System.out.println("Router ID: " + RouterVersion.ID);
|
||||
|
Reference in New Issue
Block a user