Skip to content

Instantly share code, notes, and snippets.

@NVentimiglia
Last active July 6, 2016 01:59
Show Gist options
  • Save NVentimiglia/2534ab5dac563565887ee2e9b9ebd3dc to your computer and use it in GitHub Desktop.
Save NVentimiglia/2534ab5dac563565887ee2e9b9ebd3dc to your computer and use it in GitHub Desktop.
LiteNetUdp
using System;
using SignalMQ.Data;
using System.Threading.Tasks;
using LiteNetLib;
using LiteNetLib.Utils;
namespace SignalMQ.Transports.Udp
{
/// <summary>
/// A tcp connection
/// </summary>
public class NetUdpClientTransport : ClientTransport, INetEventListener
{
private NetClient _netClient;
private NetPeer _peer;
private Action<SignalCallback> openCallback;
private string endpoint;
private string key;
private int port;
private bool closing;
public int Ping = 0;
public NetUdpClientTransport(string endpoint, int port, string key = "SignalMQ")
{
this.endpoint = endpoint;
this.port = port;
this.key = key;
}
public override void Open(Action<SignalCallback> callback = null)
{
try
{
if (State != ClientState.Closed)
{
RaiseError(SignalException.AlreadyConnected);
if (callback != null)
{
callback(new SignalCallback { Exception = SignalException.AlreadyConnected.Message });
}
return;
}
if (_netClient != null)
{
Close();
}
openCallback = callback;
State = ClientState.Opening;
_netClient = new NetClient(this, key);
_netClient.Start();
_netClient.Connect(endpoint, port);
_netClient.UpdateTime = 15;
Task.Factory.StartNew(ReceiveAsync, TaskCreationOptions.LongRunning);
}
catch (Exception ex)
{
RaiseError(ex);
Close();
if (openCallback != null)
{
openCallback(new SignalCallback { Exception = ex.Message });
openCallback = null;
}
}
}
protected override void OnOpened()
{
if (openCallback != null)
{
openCallback(new SignalCallback { Success = true });
openCallback = null;
}
}
public override void Send(Signal signal)
{
try
{
if (_peer == null || closing || State == ClientState.Closed)
{
return;
}
_peer.Send(signal.Data, 0, signal.Size, SendOptions.Unreliable);
}
catch (Exception ex)
{
RaiseError(ex);
Close();
}
}
//
public override void Close()
{
closing = true;
if (closing)
return;
if (_netClient != null && State == ClientState.Opened)
{
var signal = new Signal(Signal.SignalSize.SIZE_HEADER, Signal.ROUTE_SERVER, UtilitySignals.CloseSignal);
Send(signal);
}
if (_netClient != null)
{
_netClient.Stop();
_netClient = null;
}
if (State == ClientState.Closed)
{
return;
}
State = ClientState.Closed;
if (openCallback != null)
{
openCallback(new SignalCallback { Exception = SignalException.ConnectionAborted.Message });
openCallback = null;
}
}
public async Task ReceiveAsync()
{
try
{
while (_netClient != null)
{
_netClient.PollEvents();
// await Task.Yield();
}
}
catch (Exception ex)
{
RaiseError(ex);
Close();
}
}
void HandleMessage(byte[] buffer)
{
try
{
if (buffer == null || buffer.Length == 0)
return;
var signal = new Signal(buffer);
if (ProcessSignal(signal))
RaiseData(signal);
}
catch (Exception ex)
{
RaiseError(ex);
if (openCallback != null)
{
openCallback(new SignalCallback { Exception = ex.Message });
openCallback = null;
}
Close();
}
}
public void OnPeerConnected(NetPeer peer)
{
_peer = peer;
}
public void OnPeerDisconnected(NetPeer peer, string additionalInfo)
{
//_peer = null;
}
public void OnNetworkError(NetEndPoint endPoint, string error)
{
RaiseError(new Exception(error));
}
public void OnNetworkReceive(NetPeer peer, NetDataReader reader)
{
HandleMessage(reader.Data);
}
public void OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader)
{
HandleMessage(reader.Data);
}
public void OnNetworkLatencyUpdate(NetPeer peer, int latency)
{
Ping = latency;
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using LiteNetLib;
using SignalMQ.Data;
namespace SignalMQ.Transports.Udp
{
/// <summary>
/// </summary>
public class NetUdpConnection : ServerConnection
{
public static Task Empty = Task.FromResult(string.Empty);
public override bool IsOpen
{
get { return host != null && !hasTermination && host.IsOpen && peer != null; }
}
private NetPeer peer;
private NetUdpServerTransport host;
private bool hasTermination;
public NetUdpConnection(NetUdpServerTransport host, NetPeer peer)
{
this.peer = peer;
this.host = host;
}
public override async Task Send(Signal signal)
{
if (!IsOpen)
{
await Empty;
}
try
{
peer.Send(signal.Data, 0, signal.Size, SendOptions.Unreliable);
}
catch (Exception ex)
{
OnError(this, new Exception("Error while sending", ex));
Close();
}
}
public void HandleClose()
{
hasTermination = true;
Close();
}
public void HandleError(string error)
{
OnError(this, new Exception(error));
}
internal void HandleReceive(byte[] data)
{
var signal = new Signal(data);
if (ProcessSignal(signal))
OnData(this, signal);
}
public override async void Close()
{
if (IsOpen)
{
using (var signal = new Signal(Signal.SignalSize.SIZE_HEADER, Signal.ROUTE_SERVER, UtilitySignals.CloseSignal))
{
await Send(signal);
}
}
hasTermination = true;
if (peer != null)
{
peer = null;
OnClose(this);
}
host = null;
OnOpen = null;
OnClose = null;
OnData = null;
OnLog = null;
OnError = null;
}
}
}
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SignalMQ.Data;
using LiteNetLib;
using LiteNetLib.Utils;
namespace SignalMQ.Transports.Udp
{
public class NetUdpServerTransport : ServerTransport, INetEventListener
{
static Task Empty = Task.FromResult(string.Empty);
public NetServer Server;
public Dictionary<NetPeer, NetUdpConnection> Peers;
int maxClients;
private int port;
string key;
public override bool IsOpen { get { return Server != null && Server.IsRunning; } }
public NetUdpServerTransport(int port, int maxClients = 1000, string key = "SignalMQ")
{
this.maxClients = maxClients;
this.key = key;
this.port = port;
}
public override IEnumerable<ServerConnection> Connections()
{
return Peers.Values;
}
public override Task Send(Signal signal)
{
Server.SendToClients(signal.Data, 0, signal.Size, (SendOptions)signal.Option);
return Empty;
}
public override void Open()
{
if (IsOpen)
return;
try
{
Peers = new Dictionary<NetPeer, NetUdpConnection>();
Server = new NetServer(this, maxClients, key);
Server.Start(port);
Task.Factory.StartNew(ReceiveAsync, TaskCreationOptions.LongRunning);
Console.WriteLine("SignalMQ.UdpServerTransport Running");
}
catch (Exception ex)
{
RaiseError(ex);
Close();
}
}
public async void ReceiveAsync()
{
try
{
while (IsOpen)
{
Server.PollEvents();
// await Task.Yield();
}
}
catch (Exception e)
{
RaiseError(e);
}
finally
{
Close();
}
}
public override void Close()
{
if (!IsOpen)
return;
if (Peers != null)
{
foreach (var connection in Peers)
{
connection.Value.Close();
}
Peers = null;
}
if (Server != null)
{
Server.Stop();
Server = null;
}
}
public async void OnPeerConnected(NetPeer peer)
{
var proxy = new NetUdpConnection(this, peer);
BindConnection(proxy);
Peers.Add(peer, proxy);
await proxy.Init();
}
public void OnPeerDisconnected(NetPeer peer, string additionalInfo)
{
if (Peers.ContainsKey(peer))
{
Peers[peer].HandleClose();
Peers.Remove(peer);
}
}
public void OnNetworkError(NetEndPoint endPoint, string error)
{
var peer = Server.GetPeers().FirstOrDefault(o => o.EndPoint == endPoint);
if (peer != null)
{
NetUdpConnection match;
Peers.TryGetValue(peer, out match);
if (match != null)
{
match.HandleError(error);
}
else
{
RaiseError(new Exception(error));
}
}
}
public void OnNetworkReceive(NetPeer peer, NetDataReader reader)
{
NetUdpConnection match;
Peers.TryGetValue(peer, out match);
if (match != null)
{
match.HandleReceive(reader.Data);
}
}
public void OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader)
{
}
public void OnNetworkLatencyUpdate(NetPeer peer, int latency)
{
NetUdpConnection match;
Peers.TryGetValue(peer, out match);
if (match != null)
{
// match.Session["Latency"] = latency;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment