Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preventing Leakage of the RemotingSession #65

Merged
merged 4 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
330 changes: 165 additions & 165 deletions CoreRemoting/Channels/Tcp/TcpClientChannel.cs
Original file line number Diff line number Diff line change
@@ -1,165 +1,165 @@
using System;
using System.Collections.Generic;
using WatsonTcp;

namespace CoreRemoting.Channels.Tcp;

/// <summary>
/// Client side TCP channel implementation.
/// </summary>
public class TcpClientChannel : IClientChannel, IRawMessageTransport
{
private WatsonTcpClient _tcpClient;
private Dictionary<string, object> _handshakeMetadata;

/// <summary>
/// Event: Fires when a message is received from server.
/// </summary>
public event Action<byte[]> ReceiveMessage;

/// <summary>
/// Event: Fires when an error is occurred.
/// </summary>
public event Action<string, Exception> ErrorOccured;

/// <inheritdoc />
public event Action Disconnected;

/// <summary>
/// Initializes the channel.
/// </summary>
/// <param name="client">CoreRemoting client</param>
public void Init(IRemotingClient client)
{
_tcpClient = new WatsonTcpClient(client.Config.ServerHostName, client.Config.ServerPort);
_tcpClient.Settings.NoDelay = true;

_handshakeMetadata =
new Dictionary<string, object>
{
{ "MessageEncryption", client.MessageEncryption }
};

if (client.MessageEncryption)
_handshakeMetadata.Add("ShakeHands", Convert.ToBase64String(client.PublicKey));
}

/// <summary>
/// Establish a connection with the server.
/// </summary>
public void Connect()
{
if (_tcpClient == null)
throw new InvalidOperationException("Channel is not initialized.");

if (_tcpClient.Connected)
return;

_tcpClient.Events.ExceptionEncountered += OnError;
_tcpClient.Events.MessageReceived += OnMessage;
_tcpClient.Events.ServerDisconnected += OnDisconnected;
_tcpClient.Connect();
}
private void OnDisconnected(object o, DisconnectionEventArgs disconnectionEventArgs)
{
Disconnected?.Invoke();
}

/// <summary>
/// Event procedure: Called when a error occurs on the TCP client layer.
/// </summary>
/// <param name="sender">Event sender</param>
/// <param name="e">Event arguments</param>
private void OnError(object sender, ExceptionEventArgs e)
{
LastException = new NetworkException(e.Exception.Message, e.Exception);

ErrorOccured?.Invoke(e.Exception.Message, e.Exception);
}

/// <summary>
/// Event procedure: Called when a message from server is received.
/// </summary>
/// <param name="sender">Sender of the event</param>
/// <param name="e">Event arguments containing the message content</param>
private void OnMessage(object sender, MessageReceivedEventArgs e)
{
if (e.Metadata != null && e.Metadata.ContainsKey("ServerAcceptConnection"))
{
if (!_tcpClient.Send(new byte[1] { 0x0 }, _handshakeMetadata) && !_tcpClient.Connected)
_tcpClient = null;
}
else
{
ReceiveMessage?.Invoke(e.Data);
}
}

/// <summary>
/// Closes the connection.
/// </summary>
public void Disconnect()
{
if (_tcpClient == null)
return;

_tcpClient.Events.MessageReceived -= OnMessage;
_tcpClient.Events.ExceptionEncountered -= OnError;

if (_tcpClient.Connected)
{
try
{
_tcpClient.Disconnect();
}
catch
{
// ignored
}
}

_tcpClient.Dispose();
_tcpClient = null;
}

/// <summary>
/// Gets whether the connection is established or not.
/// </summary>
public bool IsConnected => _tcpClient?.Connected ?? false;

/// <summary>
/// Gets the raw message transport component for this connection.
/// </summary>
public IRawMessageTransport RawMessageTransport => this;

/// <summary>
/// Sends a message to the server.
/// </summary>
/// <param name="rawMessage">Raw message data</param>
public bool SendMessage(byte[] rawMessage)
{
if (_tcpClient != null)
{
if (_tcpClient.Send(rawMessage))
return true;
if (!_tcpClient.Connected)
_tcpClient = null;
return false;
}
else
throw new NetworkException("Channel disconnected");
}

/// <summary>
/// Gets or sets the last exception.
/// </summary>
public NetworkException LastException { get; set; }

/// <summary>
/// Disconnect and free manages resources.
/// </summary>
public void Dispose()
{
Disconnect();
}
}
using System;
using System.Collections.Generic;
using WatsonTcp;
namespace CoreRemoting.Channels.Tcp;
/// <summary>
/// Client side TCP channel implementation.
/// </summary>
public class TcpClientChannel : IClientChannel, IRawMessageTransport
{
private WatsonTcpClient _tcpClient;
private Dictionary<string, object> _handshakeMetadata;
/// <summary>
/// Event: Fires when a message is received from server.
/// </summary>
public event Action<byte[]> ReceiveMessage;
/// <summary>
/// Event: Fires when an error is occurred.
/// </summary>
public event Action<string, Exception> ErrorOccured;
/// <inheritdoc />
public event Action Disconnected;
/// <summary>
/// Initializes the channel.
/// </summary>
/// <param name="client">CoreRemoting client</param>
public void Init(IRemotingClient client)
{
_tcpClient = new WatsonTcpClient(client.Config.ServerHostName, client.Config.ServerPort);
_tcpClient.Settings.NoDelay = true;
_handshakeMetadata =
new Dictionary<string, object>
{
{ "MessageEncryption", client.MessageEncryption }
};
if (client.MessageEncryption)
_handshakeMetadata.Add("ShakeHands", Convert.ToBase64String(client.PublicKey));
}
/// <summary>
/// Establish a connection with the server.
/// </summary>
public void Connect()
{
if (_tcpClient == null)
throw new InvalidOperationException("Channel is not initialized.");
if (_tcpClient.Connected)
return;
_tcpClient.Events.ExceptionEncountered += OnError;
_tcpClient.Events.MessageReceived += OnMessage;
_tcpClient.Events.ServerDisconnected += OnDisconnected;
_tcpClient.Connect();
}
private void OnDisconnected(object o, DisconnectionEventArgs disconnectionEventArgs)
{
Disconnected?.Invoke();
}
/// <summary>
/// Event procedure: Called when a error occurs on the TCP client layer.
/// </summary>
/// <param name="sender">Event sender</param>
/// <param name="e">Event arguments</param>
private void OnError(object sender, ExceptionEventArgs e)
{
LastException = new NetworkException(e.Exception.Message, e.Exception);
ErrorOccured?.Invoke(e.Exception.Message, e.Exception);
}
/// <summary>
/// Event procedure: Called when a message from server is received.
/// </summary>
/// <param name="sender">Sender of the event</param>
/// <param name="e">Event arguments containing the message content</param>
private void OnMessage(object sender, MessageReceivedEventArgs e)
{
if (e.Metadata != null && e.Metadata.ContainsKey("ServerAcceptConnection"))
{
if (!_tcpClient.SendAsync(new byte[1] { 0x0 }, _handshakeMetadata).Result && !_tcpClient.Connected)
_tcpClient = null;
}
else
{
ReceiveMessage?.Invoke(e.Data);
}
}
/// <summary>
/// Closes the connection.
/// </summary>
public void Disconnect()
{
if (_tcpClient == null)
return;
_tcpClient.Events.MessageReceived -= OnMessage;
_tcpClient.Events.ExceptionEncountered -= OnError;
if (_tcpClient.Connected)
{
try
{
_tcpClient.Disconnect();
}
catch
{
// ignored
}
}
_tcpClient.Dispose();
_tcpClient = null;
}
/// <summary>
/// Gets whether the connection is established or not.
/// </summary>
public bool IsConnected => _tcpClient?.Connected ?? false;
/// <summary>
/// Gets the raw message transport component for this connection.
/// </summary>
public IRawMessageTransport RawMessageTransport => this;
/// <summary>
/// Sends a message to the server.
/// </summary>
/// <param name="rawMessage">Raw message data</param>
public bool SendMessage(byte[] rawMessage)
{
if (_tcpClient != null)
{
if (_tcpClient.SendAsync(rawMessage).Result)
return true;
if (!_tcpClient.Connected)
_tcpClient = null;
return false;
}
else
throw new NetworkException("Channel disconnected");
}
/// <summary>
/// Gets or sets the last exception.
/// </summary>
public NetworkException LastException { get; set; }
/// <summary>
/// Disconnect and free manages resources.
/// </summary>
public void Dispose()
{
Disconnect();
}
}
Loading
Loading