forked from I2P_Developers/i2p.i2p
* C#-ification of sam-sharp: interface greatly simplified using delegates
and events; SamBaseEventHandler provides basic implementation and helper
methods but is now optional.
* NAnt buildfile and README added for sam-sharp.
160 lines
5.2 KiB
C#
160 lines
5.2 KiB
C#
using System;
|
|
using System.Collections.Specialized;
|
|
using System.Threading;
|
|
|
|
namespace I2P.SAM.Client
|
|
{
|
|
/// <summary>
|
|
/// Optional base class providing basic SAM event handling and helper
|
|
/// methods.
|
|
/// </summary>
|
|
public class SamBaseEventHandler
|
|
{
|
|
private object _helloLock = new Object();
|
|
private string _helloOk;
|
|
private NameValueCollection _namingReplies = new NameValueCollection();
|
|
private object _namingReplyLock = new Object();
|
|
private SamReader _samReader;
|
|
private object _sessionCreateLock = new Object();
|
|
private string _sessionCreateOk;
|
|
|
|
/// <summary>
|
|
/// Creates a new <c>SamBaseEventHandler</c> instance and registers
|
|
/// overridable handler methods for all events generated by the given
|
|
/// <see cref="SamReader">SamReader</see>.
|
|
/// </summary>
|
|
public SamBaseEventHandler(SamReader samReader) {
|
|
_samReader = samReader;
|
|
_samReader.DestReplyReceived += new DestReplyReceivedHandler(OnDestReplyReceived);
|
|
_samReader.HelloReplyReceived += new HelloReplyReceivedHandler(OnHelloReplyReceived);
|
|
_samReader.NamingReplyReceived += new NamingReplyReceivedHandler(OnNamingReplyReceived);
|
|
_samReader.SessionStatusReceived += new SessionStatusReceivedHandler(OnSessionStatusReceived);
|
|
_samReader.StreamClosedReceived += new StreamClosedReceivedHandler(OnStreamClosedReceived);
|
|
_samReader.StreamConnectedReceived += new StreamConnectedReceivedHandler(OnStreamConnectedReceived);
|
|
_samReader.StreamDataReceived += new StreamDataReceivedHandler(OnStreamDataReceived);
|
|
_samReader.StreamStatusReceived += new StreamStatusReceivedHandler(OnStreamStatusReceived);
|
|
_samReader.UnknownMessageReceived += new UnknownMessageReceivedHandler(OnUnknownMessageReceived);
|
|
}
|
|
|
|
public virtual void OnDestReplyReceived(string publicKey, string privateKey) {
|
|
}
|
|
|
|
public virtual void OnHelloReplyReceived(bool ok) {
|
|
lock (_helloLock) {
|
|
if (ok)
|
|
_helloOk = Boolean.TrueString;
|
|
else
|
|
_helloOk = Boolean.FalseString;
|
|
|
|
Monitor.PulseAll(_helloLock);
|
|
}
|
|
}
|
|
|
|
public virtual void OnNamingReplyReceived(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 virtual void OnSessionStatusReceived(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 virtual void OnStreamClosedReceived(string result, int id, string message) {
|
|
}
|
|
|
|
public virtual void OnStreamConnectedReceived(string remoteDestination, int id) {
|
|
}
|
|
|
|
public virtual void OnStreamDataReceived(int id, byte[] data, int offset, int length) {
|
|
}
|
|
|
|
public virtual void OnStreamStatusReceived(string result, int id, string message) {
|
|
}
|
|
|
|
public virtual void OnUnknownMessageReceived(string major, string minor, NameValueCollection parameters) {
|
|
Console.WriteLine("wrt, [" + major + "] [" + minor + "] [" + parameters + "]");
|
|
}
|
|
|
|
// Helper methods below.
|
|
|
|
/// <summary>
|
|
/// Waits for a SAM connection to be established.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method blocks until the connection is established.
|
|
/// </remarks>
|
|
/// <returns><c>true</c> if the handshake was successful.</returns>
|
|
public virtual bool WaitForHelloReply() {
|
|
while (true) {
|
|
lock (_helloLock) {
|
|
if (_helloOk == null)
|
|
Monitor.Wait(_helloLock);
|
|
else
|
|
return Boolean.Parse(_helloOk);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Waits for a SAM naming reply message.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method blocks until all naming replies are received.
|
|
/// </remarks>
|
|
/// <param name="name">The name to be looked for, or <c>ME</c>.</param>
|
|
/// <returns>The matching destination for <c>name</c>, or <c>null</c> if
|
|
/// the key was not able to be retrieved.</returns>
|
|
public virtual 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>
|
|
/// Waits for a SAM session to be created.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This method blocks until a SAM session is created.
|
|
/// </remarks>
|
|
/// <returns><c>true</c> if the SAM session was created successfully.
|
|
// </returns>
|
|
public virtual bool WaitForSessionCreateReply() {
|
|
while (true) {
|
|
lock (_sessionCreateLock) {
|
|
if (_sessionCreateOk == null)
|
|
Monitor.Wait(_sessionCreateLock);
|
|
else
|
|
return Boolean.Parse(_sessionCreateOk);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |