Removed NioTSO client and server

- NioTSO client isn't needed because we're using RayLib
- Added FreeSO's API server to handle most backend operations
This commit is contained in:
Tony Bark 2024-05-01 02:55:43 -04:00
parent f12ba1502b
commit 22191ce648
591 changed files with 53264 additions and 3362 deletions

View file

@ -0,0 +1,77 @@
using System;
namespace FSO.Server.Protocol.Aries
{
public enum AriesPacketType
{
Voltron,
Electron,
Gluon,
RequestClientSession,
RequestClientSessionResponse,
RequestChallenge,
RequestChallengeResponse,
AnswerChallenge,
AnswerAccepted,
Unknown
}
public static class AriesPacketTypeUtils
{
public static AriesPacketType FromPacketCode(uint code)
{
switch (code)
{
case 0:
return AriesPacketType.Voltron;
case 1000:
return AriesPacketType.Electron;
case 1001:
return AriesPacketType.Gluon;
case 1002:
return AriesPacketType.RequestChallenge;
case 1003:
return AriesPacketType.RequestChallengeResponse;
case 1004:
return AriesPacketType.AnswerChallenge;
case 1005:
return AriesPacketType.AnswerAccepted;
case 22:
return AriesPacketType.RequestClientSession;
case 21:
return AriesPacketType.RequestClientSessionResponse;
default:
return AriesPacketType.Unknown;
}
}
public static uint GetPacketCode(this AriesPacketType type)
{
switch (type)
{
case AriesPacketType.Voltron:
return 0;
case AriesPacketType.Electron:
return 1000;
case AriesPacketType.Gluon:
return 1001;
case AriesPacketType.RequestChallenge:
return 1002;
case AriesPacketType.RequestChallengeResponse:
return 1003;
case AriesPacketType.AnswerChallenge:
return 1004;
case AriesPacketType.AnswerAccepted:
return 1005;
case AriesPacketType.RequestClientSession:
return 22;
case AriesPacketType.RequestClientSessionResponse:
return 21;
default:
throw new Exception("Unknown aries packet type " + type.ToString());
}
}
}
}

View file

@ -0,0 +1,41 @@
using FSO.Server.Protocol.Aries.Packets;
using System;
using System.Collections.Generic;
namespace FSO.Server.Protocol.Aries
{
public class AriesPackets
{
public static Dictionary<uint, Type> ARIES_PACKET_BY_TYPEID;
public static Type[] ARIES_PACKETS = new Type[] {
typeof(RequestClientSession),
typeof(RequestClientSessionResponse),
typeof(RequestChallenge),
typeof(RequestChallengeResponse),
typeof(AnswerChallenge),
typeof(AnswerAccepted)
};
static AriesPackets()
{
ARIES_PACKET_BY_TYPEID = new Dictionary<uint, Type>();
foreach (Type packetType in ARIES_PACKETS)
{
IAriesPacket packet = (IAriesPacket)Activator.CreateInstance(packetType);
ARIES_PACKET_BY_TYPEID.Add(packet.GetPacketType().GetPacketCode(), packetType);
}
}
public static Type GetByPacketCode(uint code)
{
if (ARIES_PACKET_BY_TYPEID.ContainsKey(code))
{
return ARIES_PACKET_BY_TYPEID[code];
}
else
{
return null;
}
}
}
}

View file

@ -0,0 +1,38 @@
using Mina.Filter.Codec;
using Ninject;
using Mina.Core.Session;
namespace FSO.Server.Protocol.Aries
{
public class AriesProtocol : IProtocolCodecFactory
{
private IKernel Kernel;
public AriesProtocol(IKernel kernel)
{
this.Kernel = kernel;
}
private IProtocolDecoder _Decoder;
public IProtocolDecoder GetDecoder(IoSession session)
{
if (_Decoder == null)
{
_Decoder = Kernel.Get<AriesProtocolDecoder>();
}
return _Decoder;
}
private IProtocolEncoder _Encoder;
public IProtocolEncoder GetEncoder(IoSession session)
{
if(_Encoder == null)
{
_Encoder = Kernel.Get<AriesProtocolEncoder>();
}
return _Encoder;
}
}
}

View file

@ -0,0 +1,111 @@
using Mina.Filter.Codec;
using System;
using Mina.Core.Buffer;
using Mina.Core.Session;
using FSO.Server.Protocol.Voltron;
using FSO.Server.Protocol.Electron;
using FSO.Common.Serialization;
using FSO.Server.Protocol.Utils;
using FSO.Server.Protocol.Gluon;
namespace FSO.Server.Protocol.Aries
{
public class AriesProtocolDecoder : CustomCumulativeProtocolDecoder
{
//private static Logger LOG = LogManager.GetCurrentClassLogger();
private ISerializationContext Context;
public AriesProtocolDecoder(ISerializationContext context)
{
this.Context = context;
}
protected override bool DoDecode(IoSession session, IoBuffer buffer, IProtocolDecoderOutput output)
{
if(buffer.Remaining < 12){
return false;
}
/**
* We expect aries, voltron or electron packets
*/
var startPosition = buffer.Position;
buffer.Order = ByteOrder.LittleEndian;
uint packetType = buffer.GetUInt32();
uint timestamp = buffer.GetUInt32();
uint payloadSize = buffer.GetUInt32();
if (buffer.Remaining < payloadSize)
{
/** Not all here yet **/
buffer.Position = startPosition;
return false;
}
//LOG.Info("[ARIES] " + packetType + " (" + payloadSize + ")");
if(packetType == AriesPacketType.Voltron.GetPacketCode())
{
DecodeVoltronStylePackets(buffer, ref payloadSize, output, VoltronPackets.GetByPacketCode);
}
else if (packetType == AriesPacketType.Electron.GetPacketCode())
{
DecodeVoltronStylePackets(buffer, ref payloadSize, output, ElectronPackets.GetByPacketCode);
}else if(packetType == AriesPacketType.Gluon.GetPacketCode())
{
DecodeVoltronStylePackets(buffer, ref payloadSize, output, GluonPackets.GetByPacketCode);
}
else
{
//Aries
var packetClass = AriesPackets.GetByPacketCode(packetType);
if (packetClass != null)
{
byte[] data = new byte[(int)payloadSize];
buffer.Get(data, 0, (int)payloadSize);
IAriesPacket packet = (IAriesPacket)Activator.CreateInstance(packetClass);
var io = IoBuffer.Wrap(data);
io.Order = ByteOrder.LittleEndian;
packet.Deserialize(io, Context);
output.Write(packet);
payloadSize = 0;
}
else
{
buffer.Skip((int)payloadSize);
payloadSize = 0;
}
}
return true;
}
private void DecodeVoltronStylePackets(IoBuffer buffer, ref uint payloadSize, IProtocolDecoderOutput output, Func<ushort, Type> typeResolver)
{
while (payloadSize > 0)
{
/** Voltron packet **/
buffer.Order = ByteOrder.BigEndian;
ushort type = buffer.GetUInt16();
uint innerPayloadSize = buffer.GetUInt32() - 6;
byte[] data = new byte[(int)innerPayloadSize];
buffer.Get(data, 0, (int)innerPayloadSize);
var packetClass = typeResolver(type);
if (packetClass != null)
{
IoBufferDeserializable packet = (IoBufferDeserializable)Activator.CreateInstance(packetClass);
packet.Deserialize(IoBuffer.Wrap(data), Context);
output.Write(packet);
}
payloadSize -= innerPayloadSize + 6;
}
}
}
}

View file

@ -0,0 +1,166 @@
using FSO.Common.Serialization;
using FSO.Server.Protocol.Electron;
using FSO.Server.Protocol.Gluon;
using FSO.Server.Protocol.Voltron;
using Mina.Core.Buffer;
using Mina.Core.Session;
using Mina.Filter.Codec;
using System;
namespace FSO.Server.Protocol.Aries
{
public class AriesProtocolEncoder : IProtocolEncoder
{
//private static Logger LOG = LogManager.GetCurrentClassLogger();
private ISerializationContext Context;
public AriesProtocolEncoder(ISerializationContext context)
{
this.Context = context;
}
public void Dispose(IoSession session)
{
}
public void Encode(IoSession session, object message, IProtocolEncoderOutput output)
{
if (message is IVoltronPacket)
{
EncodeVoltron(session, message, output);
}
else if (message is IElectronPacket)
{
EncodeElectron(session, message, output);
}else if(message is IGluonPacket)
{
EncodeGluon(session, message, output);
}
else if (message is IAriesPacket)
{
EncodeAries(session, message, output);
}
else if (message.GetType().IsArray)
{
object[] arr = (object[])message;
bool allVoltron = true;
for (var i = 0; i < arr.Length; i++)
{
if (!(arr[i] is IVoltronPacket))
{
allVoltron = false;
break;
}
}
//TODO: Chunk these into fewer packets
for (var i = 0; i < arr.Length; i++)
{
Encode(session, arr[i], output);
}
}
}
private void EncodeAries(IoSession session, object message, IProtocolEncoderOutput output)
{
IAriesPacket ariesPacket = (IAriesPacket)message;
AriesPacketType ariesPacketType = ariesPacket.GetPacketType();
var payload = IoBuffer.Allocate(128);
payload.Order = ByteOrder.LittleEndian;
payload.AutoExpand = true;
ariesPacket.Serialize(payload, Context);
payload.Flip();
int payloadSize = payload.Remaining;
IoBuffer headers = IoBuffer.Allocate(12);
headers.Order = ByteOrder.LittleEndian;
/**
* Aries header
* uint32 type
* uint32 timestamp
* uint32 payloadSize
*/
uint timestamp = (uint)TimeSpan.FromTicks(DateTime.Now.Ticks - session.CreationTime.Ticks).TotalMilliseconds;
headers.PutUInt32(ariesPacketType.GetPacketCode());
headers.PutUInt32(timestamp);
headers.PutUInt32((uint)payloadSize);
if (payloadSize > 0)
{
headers.AutoExpand = true;
headers.Put(payload);
}
headers.Flip();
output.Write(headers);
//output.Flush();
}
private void EncodeVoltron(IoSession session, object message, IProtocolEncoderOutput output)
{
IVoltronPacket voltronPacket = (IVoltronPacket)message;
VoltronPacketType voltronPacketType = voltronPacket.GetPacketType();
EncodeVoltronStylePackets(session, output, AriesPacketType.Voltron, voltronPacketType.GetPacketCode(), voltronPacket);
}
private void EncodeElectron(IoSession session, object message, IProtocolEncoderOutput output)
{
IElectronPacket packet = (IElectronPacket)message;
ElectronPacketType packetType = packet.GetPacketType();
EncodeVoltronStylePackets(session, output, AriesPacketType.Electron, packetType.GetPacketCode(), packet);
}
private void EncodeGluon(IoSession session, object message, IProtocolEncoderOutput output)
{
IGluonPacket packet = (IGluonPacket)message;
GluonPacketType packetType = packet.GetPacketType();
EncodeVoltronStylePackets(session, output, AriesPacketType.Gluon, packetType.GetPacketCode(), packet);
}
private void EncodeVoltronStylePackets(IoSession session, IProtocolEncoderOutput output, AriesPacketType ariesType, ushort packetType, IoBufferSerializable message)
{
var payload = IoBuffer.Allocate(512);
payload.Order = ByteOrder.BigEndian;
payload.AutoExpand = true;
message.Serialize(payload, Context);
payload.Flip();
int payloadSize = payload.Remaining;
IoBuffer headers = IoBuffer.Allocate(18);
headers.Order = ByteOrder.LittleEndian;
/**
* Aries header
* uint32 type
* uint32 timestamp
* uint32 payloadSize
*/
uint timestamp = (uint)TimeSpan.FromTicks(DateTime.Now.Ticks - session.CreationTime.Ticks).TotalMilliseconds;
headers.PutUInt32(ariesType.GetPacketCode());
headers.PutUInt32(timestamp);
headers.PutUInt32((uint)payloadSize + 6);
/**
* Voltron header
* uint16 type
* uint32 payloadSize
*/
headers.Order = ByteOrder.BigEndian;
headers.PutUInt16(packetType);
headers.PutUInt32((uint)payloadSize + 6);
if (payloadSize > 0)
{
headers.AutoExpand = true;
headers.Put(payload);
}
headers.Flip();
output.Write(headers);
//output.Flush();
}
}
}

View file

@ -0,0 +1,160 @@
using Mina.Core.Session;
using Mina.Core.Buffer;
using Mina.Core.Filterchain;
using FSO.Server.Common;
using Mina.Core.Write;
using FSO.Server.Protocol.Voltron;
using FSO.Common.Serialization;
namespace FSO.Server.Protocol.Aries
{
public class AriesProtocolLogger : IoFilterAdapter
{
//private static Logger LOG = LogManager.GetCurrentClassLogger();
private IPacketLogger PacketLogger;
private ISerializationContext Context;
public AriesProtocolLogger(IPacketLogger packetLogger, ISerializationContext context)
{
this.PacketLogger = packetLogger;
this.Context = context;
}
public override void MessageSent(INextFilter nextFilter, IoSession session, IWriteRequest writeRequest)
{
IVoltronPacket voltronPacket = writeRequest.OriginalRequest.Message as IVoltronPacket;
if (voltronPacket != null)
{
var voltronBuffer = IoBuffer.Allocate(512);
voltronBuffer.Order = ByteOrder.BigEndian;
voltronBuffer.AutoExpand = true;
voltronPacket.Serialize(voltronBuffer, Context);
voltronBuffer.Flip();
var byteArray = new byte[voltronBuffer.Remaining];
voltronBuffer.Get(byteArray, 0, voltronBuffer.Remaining);
PacketLogger.OnPacket(new Packet
{
Data = byteArray,
Type = PacketType.VOLTRON,
SubType = voltronPacket.GetPacketType().GetPacketCode(),
Direction = PacketDirection.OUTPUT
});
nextFilter.MessageSent(session, writeRequest);
return;
}
IAriesPacket ariesPacket = writeRequest.OriginalRequest.Message as IAriesPacket;
if(ariesPacket != null)
{
IoBuffer ariesBuffer = IoBuffer.Allocate(128);
ariesBuffer.AutoExpand = true;
ariesBuffer.Order = ByteOrder.LittleEndian;
ariesPacket.Serialize(ariesBuffer, Context);
ariesBuffer.Flip();
var byteArray = new byte[ariesBuffer.Remaining];
ariesBuffer.Get(byteArray, 0, ariesBuffer.Remaining);
PacketLogger.OnPacket(new Packet
{
Data = byteArray,
Type = PacketType.ARIES,
SubType = ariesPacket.GetPacketType().GetPacketCode(),
Direction = PacketDirection.OUTPUT
});
nextFilter.MessageSent(session, writeRequest);
return;
}
IoBuffer buffer = writeRequest.Message as IoBuffer;
if (buffer == null)
{
nextFilter.MessageSent(session, writeRequest);
return;
}
TryParseAriesFrame(buffer, PacketDirection.OUTPUT);
nextFilter.MessageSent(session, writeRequest);
}
public override void MessageReceived(INextFilter nextFilter, IoSession session, object message)
{
IoBuffer buffer = message as IoBuffer;
if (buffer == null)
{
nextFilter.MessageReceived(session, message);
return;
}
TryParseAriesFrame(buffer, PacketDirection.INPUT);
nextFilter.MessageReceived(session, message);
}
private void TryParseAriesFrame(IoBuffer buffer, PacketDirection direction)
{
buffer.Rewind();
if(buffer.Remaining < 12)
{
return;
}
buffer.Order = ByteOrder.LittleEndian;
uint packetType = buffer.GetUInt32();
uint timestamp = buffer.GetUInt32();
uint payloadSize = buffer.GetUInt32();
if (buffer.Remaining < payloadSize)
{
buffer.Skip(-12);
return;
}
while (payloadSize > 0)
{
if (packetType == 0)
{
/** Voltron packet **/
buffer.Order = ByteOrder.BigEndian;
ushort voltronType = buffer.GetUInt16();
uint voltronPayloadSize = buffer.GetUInt32() - 6;
byte[] data = new byte[(int)voltronPayloadSize];
buffer.Get(data, 0, (int)voltronPayloadSize);
PacketLogger.OnPacket(new Packet
{
Data = data,
Type = PacketType.VOLTRON,
SubType = voltronType,
Direction = direction
});
payloadSize -= voltronPayloadSize + 6;
}
else
{
byte[] data = new byte[(int)payloadSize];
buffer.Get(data, 0, (int)payloadSize);
PacketLogger.OnPacket(new Packet
{
Data = data,
Type = PacketType.ARIES,
SubType = packetType,
Direction = direction
});
payloadSize = 0;
}
}
buffer.Rewind();
}
}
}

View file

@ -0,0 +1,14 @@
using FSO.Common.Serialization;
namespace FSO.Server.Protocol.Aries
{
public interface IAriesPacket : IoBufferSerializable, IoBufferDeserializable
{
/**
* Get packet type
*
* @return
*/
AriesPacketType GetPacketType();
}
}

View file

@ -0,0 +1,21 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Aries.Packets
{
public class AnswerAccepted : IAriesPacket
{
public void Deserialize(IoBuffer input, ISerializationContext context)
{
}
public AriesPacketType GetPacketType()
{
return AriesPacketType.AnswerAccepted;
}
public void Serialize(IoBuffer output, ISerializationContext context)
{
}
}
}

View file

@ -0,0 +1,25 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Aries.Packets
{
public class AnswerChallenge : IAriesPacket
{
public string Answer;
public void Deserialize(IoBuffer input, ISerializationContext context)
{
Answer = input.GetPascalVLCString();
}
public AriesPacketType GetPacketType()
{
return AriesPacketType.AnswerChallenge;
}
public void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutPascalVLCString(Answer);
}
}
}

View file

@ -0,0 +1,31 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Aries.Packets
{
public class RequestChallenge : IAriesPacket
{
public string CallSign;
public string PublicHost;
public string InternalHost;
public void Deserialize(IoBuffer input, ISerializationContext context)
{
CallSign = input.GetPascalString();
PublicHost = input.GetPascalString();
InternalHost = input.GetPascalString();
}
public AriesPacketType GetPacketType()
{
return AriesPacketType.RequestChallenge;
}
public void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutPascalString(CallSign);
output.PutPascalString(PublicHost);
output.PutPascalString(InternalHost);
}
}
}

View file

@ -0,0 +1,25 @@
using FSO.Common.Serialization;
using Mina.Core.Buffer;
namespace FSO.Server.Protocol.Aries.Packets
{
public class RequestChallengeResponse : IAriesPacket
{
public string Challenge;
public void Deserialize(IoBuffer input, ISerializationContext context)
{
Challenge = input.GetPascalVLCString();
}
public AriesPacketType GetPacketType()
{
return AriesPacketType.RequestChallengeResponse;
}
public void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutPascalVLCString(Challenge);
}
}
}

View file

@ -0,0 +1,21 @@
using Mina.Core.Buffer;
using FSO.Common.Serialization;
namespace FSO.Server.Protocol.Aries.Packets
{
public class RequestClientSession : IAriesPacket
{
public void Deserialize(IoBuffer input, ISerializationContext context)
{
}
public AriesPacketType GetPacketType()
{
return AriesPacketType.RequestClientSession;
}
public void Serialize(IoBuffer output, ISerializationContext context)
{
}
}
}

View file

@ -0,0 +1,50 @@
using System.Text;
using Mina.Core.Buffer;
using FSO.Common.Serialization;
namespace FSO.Server.Protocol.Aries.Packets
{
public class RequestClientSessionResponse : IAriesPacket
{
public string User { get; set; }
public string AriesVersion { get; set; }
public string Email { get; set; }
public string Authserv { get; set; }
public ushort Product { get; set; }
public byte Unknown { get; set; } = 39;
public string ServiceIdent { get; set; }
public ushort Unknown2 { get; set; } = 4; //1 if re-establishing
public string Password { get; set; }
public void Deserialize(IoBuffer input, ISerializationContext context)
{
this.User = input.GetString(112, Encoding.ASCII);
this.AriesVersion = input.GetString(80, Encoding.ASCII);
this.Email = input.GetString(40, Encoding.ASCII);
this.Authserv = input.GetString(84, Encoding.ASCII);
this.Product = input.GetUInt16();
this.Unknown = input.Get();
this.ServiceIdent = input.GetString(3, Encoding.ASCII);
this.Unknown2 = input.GetUInt16();
this.Password = input.GetString(32, Encoding.ASCII);
}
public AriesPacketType GetPacketType()
{
return AriesPacketType.RequestClientSessionResponse;
}
public void Serialize(IoBuffer output, ISerializationContext context)
{
output.PutString(this.User, 112, Encoding.ASCII);
output.PutString(this.AriesVersion, 80, Encoding.ASCII);
output.PutString(this.Email, 40, Encoding.ASCII);
output.PutString(this.Authserv, 84, Encoding.ASCII);
output.PutUInt16(this.Product);
output.Put(this.Unknown);
output.PutString(this.ServiceIdent, 3, Encoding.ASCII);
output.PutUInt16(this.Unknown2);
output.PutString(this.Password, 32, Encoding.ASCII);
}
}
}