Files
Articulate-Network/Client.cs
Ryan ece0dffd85 Implementing Packet Framing
Surrounding packets with Int32 6655 to identify packet structure
2021-12-16 16:41:29 +10:00

181 lines
5.3 KiB
C#

using Articulate_Network.Interfaces;
using Articulate_Network.Managers;
using Articulate_Network.Packets;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Articulate_Network
{
public class Client
{
List<IManager> managers = new List<IManager>();
int bufferSize = 16384;
TcpClient tcp;
public Client()
{
InitializeManagers();
tcp = new TcpClient()
{
SendBufferSize = bufferSize,
ReceiveBufferSize = bufferSize
};
}
public async Task<TcpClient> Connect(string ip, int port)
{
return await Task.Run(() =>
{
try
{
tcp.Connect(ip, port);
tcp.SendBufferSize = bufferSize;
tcp.ReceiveBufferSize = bufferSize;
_ = ReceiveData();
return tcp;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return tcp;
}
}
);
}
public async Task<bool> SendPacket(Packet packet)
{
await Task.Run(() =>
{
byte[] buffer = Get<PacketManager>().SerializePacket(packet);
tcp.Client.Send(buffer, buffer.Length, SocketFlags.None);
});
return false;
}
public async Task<bool> ReceiveData()
{
await Task.Run(() =>
{
byte[] buffer = new byte[bufferSize];
int offset = 0;
while (true)
{
int bytesToRead = tcp.Client.Receive(buffer, offset, buffer.Length - offset, SocketFlags.None);
if (offset > 0)
offset = 0;
var ms = new MemoryStream(buffer);
var br = new BinaryReader(ms);
while (ms.Position < ms.Length)
{
if (ms.Position + 4 > ms.Length)
break;
int magic = br.ReadInt32();
if (magic != 6655)
{
//Console.WriteLine("Not the start of a packet.");
continue;
}
int length = (int)br.ReadInt64();
if (ms.Position + length > ms.Length) // Received partial packet data, store partial data and continue
{
ms.Position -= 12;
offset = (int)(ms.Length - ms.Position);
//Console.WriteLine($"Partial data. Offset: {offset}");
buffer = new byte[bufferSize];
ms.Read(buffer, 0, offset);
break;
}
ms.Position += length;
int end = (int)br.ReadInt64();
ms.Position -= 8;
ms.Position -= length;
if (length == end && length > 1) // Valid packet, trigger event
{
var p = Get<PacketManager>().DeserializePacket(ms);
OnDataReceived(new Articulate_Network.Events.DataReceivedEventArgs()
{
Packet = p
});
}
else
{
Console.WriteLine($"Not a valid packet. Length: {length} - End: {end} - Offset: {offset} - Position: {ms.Position}");
}
}
}
});
return false;
}
public void InitializeManagers()
{
var @interface = typeof(IManager);
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var managersFound = assembly.GetTypes().Where(t => @interface.IsAssignableFrom(t) && !t.IsAbstract);
foreach (var m in managersFound)
{
var manager = (IManager)Activator.CreateInstance(m);
manager.Initialize();
managers.Add(manager);
}
}
Console.WriteLine($"Initialized {managers.Count} manager{(managers.Count > 1 ? "s" : "")}");
}
public T Get<T>()
{
return (T)managers.SingleOrDefault(t => typeof(T) == t.GetType());
}
protected virtual void OnDataReceived(Articulate_Network.Events.DataReceivedEventArgs e)
{
EventHandler<Articulate_Network.Events.DataReceivedEventArgs> handler = DataReceived;
if (handler != null)
handler(this, e);
}
public event EventHandler<Articulate_Network.Events.DataReceivedEventArgs> DataReceived;
}
}