mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-04 13:47:04 -04:00
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:
parent
f12ba1502b
commit
22191ce648
591 changed files with 53264 additions and 3362 deletions
77
server/FSO.Server.Protocol/Aries/AriesPacketType.cs
Executable file
77
server/FSO.Server.Protocol/Aries/AriesPacketType.cs
Executable 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
server/FSO.Server.Protocol/Aries/AriesPackets.cs
Executable file
41
server/FSO.Server.Protocol/Aries/AriesPackets.cs
Executable 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
38
server/FSO.Server.Protocol/Aries/AriesProtocol.cs
Executable file
38
server/FSO.Server.Protocol/Aries/AriesProtocol.cs
Executable 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;
|
||||
}
|
||||
}
|
||||
}
|
111
server/FSO.Server.Protocol/Aries/AriesProtocolDecoder.cs
Executable file
111
server/FSO.Server.Protocol/Aries/AriesProtocolDecoder.cs
Executable 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
166
server/FSO.Server.Protocol/Aries/AriesProtocolEncoder.cs
Executable file
166
server/FSO.Server.Protocol/Aries/AriesProtocolEncoder.cs
Executable 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();
|
||||
}
|
||||
}
|
||||
}
|
160
server/FSO.Server.Protocol/Aries/AriesProtocolLogger.cs
Executable file
160
server/FSO.Server.Protocol/Aries/AriesProtocolLogger.cs
Executable 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();
|
||||
}
|
||||
}
|
||||
}
|
14
server/FSO.Server.Protocol/Aries/IAriesPacket.cs
Executable file
14
server/FSO.Server.Protocol/Aries/IAriesPacket.cs
Executable 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();
|
||||
}
|
||||
}
|
21
server/FSO.Server.Protocol/Aries/Packets/AnswerAccepted.cs
Executable file
21
server/FSO.Server.Protocol/Aries/Packets/AnswerAccepted.cs
Executable 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
25
server/FSO.Server.Protocol/Aries/Packets/AnswerChallenge.cs
Executable file
25
server/FSO.Server.Protocol/Aries/Packets/AnswerChallenge.cs
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
31
server/FSO.Server.Protocol/Aries/Packets/RequestChallenge.cs
Executable file
31
server/FSO.Server.Protocol/Aries/Packets/RequestChallenge.cs
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
25
server/FSO.Server.Protocol/Aries/Packets/RequestChallengeResponse.cs
Executable file
25
server/FSO.Server.Protocol/Aries/Packets/RequestChallengeResponse.cs
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
21
server/FSO.Server.Protocol/Aries/Packets/RequestClientSession.cs
Executable file
21
server/FSO.Server.Protocol/Aries/Packets/RequestClientSession.cs
Executable 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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
50
server/FSO.Server.Protocol/Aries/Packets/RequestClientSessionResponse.cs
Executable file
50
server/FSO.Server.Protocol/Aries/Packets/RequestClientSessionResponse.cs
Executable 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);
|
||||
}
|
||||
}
|
||||
}
|
11
server/FSO.Server.Protocol/Authorization/AuthRequest.cs
Executable file
11
server/FSO.Server.Protocol/Authorization/AuthRequest.cs
Executable file
|
@ -0,0 +1,11 @@
|
|||
namespace FSO.Server.Protocol.Authorization
|
||||
{
|
||||
public class AuthRequest
|
||||
{
|
||||
public string Username;
|
||||
public string Password;
|
||||
public string ServiceID;
|
||||
public string Version;
|
||||
public string ClientID;
|
||||
}
|
||||
}
|
11
server/FSO.Server.Protocol/Authorization/AuthResult.cs
Executable file
11
server/FSO.Server.Protocol/Authorization/AuthResult.cs
Executable file
|
@ -0,0 +1,11 @@
|
|||
namespace FSO.Server.Protocol.Authorization
|
||||
{
|
||||
public class AuthResult
|
||||
{
|
||||
public bool Valid;
|
||||
public string Ticket;
|
||||
public string ReasonCode;
|
||||
public string ReasonText;
|
||||
public string ReasonURL;
|
||||
}
|
||||
}
|
9
server/FSO.Server.Protocol/CitySelector/AvatarAppearanceType.cs
Executable file
9
server/FSO.Server.Protocol/CitySelector/AvatarAppearanceType.cs
Executable file
|
@ -0,0 +1,9 @@
|
|||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public enum AvatarAppearanceType
|
||||
{
|
||||
Light = 0,
|
||||
Medium = 1,
|
||||
Dark = 2
|
||||
}
|
||||
}
|
96
server/FSO.Server.Protocol/CitySelector/AvatarData.cs
Executable file
96
server/FSO.Server.Protocol/CitySelector/AvatarData.cs
Executable file
|
@ -0,0 +1,96 @@
|
|||
using FSO.Common.Utils;
|
||||
using System;
|
||||
|
||||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public class AvatarData : IXMLEntity
|
||||
{
|
||||
public uint ID;
|
||||
public string Name;
|
||||
public string ShardName;
|
||||
|
||||
|
||||
|
||||
/** Non standard **/
|
||||
|
||||
/** Appearance **/
|
||||
public AvatarAppearanceType AppearanceType { get; set; }
|
||||
public ulong HeadOutfitID { get; set; }
|
||||
public ulong BodyOutfitID { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
/** Lot **/
|
||||
public uint? LotId { get; set; }
|
||||
public uint? LotLocation { get; set; }
|
||||
public string LotName { get; set; }
|
||||
|
||||
#region IXMLPrinter Members
|
||||
|
||||
public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc)
|
||||
{
|
||||
var result = doc.CreateElement("Avatar-Data");
|
||||
result.AppendTextNode("AvatarID", ID.ToString());
|
||||
result.AppendTextNode("Name", Name);
|
||||
result.AppendTextNode("Shard-Name", ShardName);
|
||||
|
||||
//NEW: Appearance info
|
||||
result.AppendTextNode("Head", HeadOutfitID.ToString());
|
||||
result.AppendTextNode("Body", BodyOutfitID.ToString());
|
||||
result.AppendTextNode("Appearance", AppearanceType.ToString());
|
||||
|
||||
if (LotId.HasValue && LotLocation.HasValue && LotName != null){
|
||||
result.AppendTextNode("LotId", LotId.Value.ToString());
|
||||
result.AppendTextNode("LotName", LotName);
|
||||
result.AppendTextNode("LotLocation", LotLocation.Value.ToString());
|
||||
}
|
||||
|
||||
result.AppendTextNode("Description", Description);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Parse(System.Xml.XmlElement element)
|
||||
{
|
||||
this.ID = uint.Parse(element.ReadTextNode("AvatarID"));
|
||||
this.Name = element.ReadTextNode("Name");
|
||||
this.ShardName = element.ReadTextNode("Shard-Name");
|
||||
|
||||
var headString = element.ReadTextNode("Head");
|
||||
if (headString != null)
|
||||
{
|
||||
this.HeadOutfitID = ulong.Parse(headString);
|
||||
}
|
||||
|
||||
var bodyString = element.ReadTextNode("Body");
|
||||
if (bodyString != null)
|
||||
{
|
||||
this.BodyOutfitID = ulong.Parse(bodyString);
|
||||
}
|
||||
|
||||
var apprString = element.ReadTextNode("Appearance");
|
||||
if (apprString != null)
|
||||
{
|
||||
this.AppearanceType = (AvatarAppearanceType)Enum.Parse(typeof(AvatarAppearanceType), apprString);
|
||||
}
|
||||
|
||||
var lotId = element.ReadTextNode("LotId");
|
||||
if(lotId != null)
|
||||
{
|
||||
this.LotId = uint.Parse(lotId);
|
||||
}
|
||||
|
||||
var lotLocation = element.ReadTextNode("LotLocation");
|
||||
if (lotLocation != null)
|
||||
{
|
||||
this.LotLocation = uint.Parse(lotLocation);
|
||||
}
|
||||
|
||||
LotName = element.ReadTextNode("LotName");
|
||||
|
||||
var descString = element.ReadTextNode("Description");
|
||||
this.Description = descString ?? "";
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
8
server/FSO.Server.Protocol/CitySelector/AvatarGender.cs
Executable file
8
server/FSO.Server.Protocol/CitySelector/AvatarGender.cs
Executable file
|
@ -0,0 +1,8 @@
|
|||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public enum AvatarGender
|
||||
{
|
||||
Male = 1,
|
||||
Female = 2
|
||||
}
|
||||
}
|
8
server/FSO.Server.Protocol/CitySelector/InitialConnectServletRequest.cs
Executable file
8
server/FSO.Server.Protocol/CitySelector/InitialConnectServletRequest.cs
Executable file
|
@ -0,0 +1,8 @@
|
|||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public class InitialConnectServletRequest
|
||||
{
|
||||
public string Ticket;
|
||||
public string Version;
|
||||
}
|
||||
}
|
50
server/FSO.Server.Protocol/CitySelector/InitialConnectServletResult.cs
Executable file
50
server/FSO.Server.Protocol/CitySelector/InitialConnectServletResult.cs
Executable file
|
@ -0,0 +1,50 @@
|
|||
using FSO.Common.Utils;
|
||||
using System;
|
||||
|
||||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public class InitialConnectServletResult : IXMLEntity
|
||||
{
|
||||
public InitialConnectServletResultType Status;
|
||||
public XMLErrorMessage Error;
|
||||
public UserAuthorized UserAuthorized;
|
||||
|
||||
|
||||
|
||||
#region IXMLEntity Members
|
||||
|
||||
public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Parse(System.Xml.XmlElement element)
|
||||
{
|
||||
switch (element.Name)
|
||||
{
|
||||
case "Error-Message":
|
||||
Status = InitialConnectServletResultType.Error;
|
||||
Error = new XMLErrorMessage();
|
||||
Error.Parse(element);
|
||||
break;
|
||||
case "User-Authorized":
|
||||
Status = InitialConnectServletResultType.Authorized;
|
||||
UserAuthorized = new UserAuthorized();
|
||||
UserAuthorized.Parse(element);
|
||||
break;
|
||||
case "Patch-Result":
|
||||
Status = InitialConnectServletResultType.Patch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public enum InitialConnectServletResultType
|
||||
{
|
||||
Authorized,
|
||||
Patch,
|
||||
Error
|
||||
}
|
||||
}
|
8
server/FSO.Server.Protocol/CitySelector/ShardSelectorServletRequest.cs
Executable file
8
server/FSO.Server.Protocol/CitySelector/ShardSelectorServletRequest.cs
Executable file
|
@ -0,0 +1,8 @@
|
|||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public class ShardSelectorServletRequest
|
||||
{
|
||||
public string ShardName;
|
||||
public string AvatarID;
|
||||
}
|
||||
}
|
45
server/FSO.Server.Protocol/CitySelector/ShardSelectorServletResponse.cs
Executable file
45
server/FSO.Server.Protocol/CitySelector/ShardSelectorServletResponse.cs
Executable file
|
@ -0,0 +1,45 @@
|
|||
using FSO.Common.Utils;
|
||||
|
||||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public class ShardSelectorServletResponse : IXMLEntity
|
||||
{
|
||||
public string Address;
|
||||
public string Ticket;
|
||||
public string ConnectionID;
|
||||
public uint PlayerID;
|
||||
public string AvatarID;
|
||||
|
||||
public bool PreAlpha = false;
|
||||
|
||||
#region IXMLPrinter Members
|
||||
|
||||
public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc)
|
||||
{
|
||||
var result = doc.CreateElement("Shard-Selection");
|
||||
result.AppendTextNode("Connection-Address", Address);
|
||||
result.AppendTextNode("Authorization-Ticket", Ticket);
|
||||
result.AppendTextNode("PlayerID", PlayerID.ToString());
|
||||
|
||||
if (PreAlpha == false)
|
||||
{
|
||||
result.AppendTextNode("ConnectionID", ConnectionID);
|
||||
result.AppendTextNode("EntitlementLevel", "");
|
||||
}
|
||||
result.AppendTextNode("AvatarID", AvatarID); //freeso now uses this
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Parse(System.Xml.XmlElement element)
|
||||
{
|
||||
this.Address = element.ReadTextNode("Connection-Address");
|
||||
this.Ticket = element.ReadTextNode("Authorization-Ticket");
|
||||
this.PlayerID = uint.Parse(element.ReadTextNode("PlayerID"));
|
||||
|
||||
this.AvatarID = element.ReadTextNode("AvatarID");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
12
server/FSO.Server.Protocol/CitySelector/ShardStatus.cs
Executable file
12
server/FSO.Server.Protocol/CitySelector/ShardStatus.cs
Executable file
|
@ -0,0 +1,12 @@
|
|||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public enum ShardStatus
|
||||
{
|
||||
Up,
|
||||
Down,
|
||||
Busy,
|
||||
Full,
|
||||
Closed,
|
||||
Frontier
|
||||
}
|
||||
}
|
44
server/FSO.Server.Protocol/CitySelector/ShardStatusItem.cs
Executable file
44
server/FSO.Server.Protocol/CitySelector/ShardStatusItem.cs
Executable file
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using FSO.Common.Utils;
|
||||
|
||||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public class ShardStatusItem : IXMLEntity
|
||||
{
|
||||
public string Name;
|
||||
public int Rank;
|
||||
public string Map;
|
||||
public ShardStatus Status;
|
||||
public int Id;
|
||||
public string PublicHost;
|
||||
public string InternalHost;
|
||||
public string VersionName;
|
||||
public string VersionNumber;
|
||||
public int? UpdateID;
|
||||
|
||||
public ShardStatusItem()
|
||||
{
|
||||
}
|
||||
|
||||
public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc)
|
||||
{
|
||||
var result = doc.CreateElement("Shard-Status");
|
||||
result.AppendTextNode("Location", "public");
|
||||
result.AppendTextNode("Name", Name);
|
||||
result.AppendTextNode("Rank", Rank.ToString());
|
||||
result.AppendTextNode("Map", Map);
|
||||
result.AppendTextNode("Status", Status.ToString());
|
||||
result.AppendTextNode("Id", Id.ToString());
|
||||
return result;
|
||||
}
|
||||
|
||||
public void Parse(System.Xml.XmlElement element)
|
||||
{
|
||||
this.Name = element.ReadTextNode("Name");
|
||||
this.Rank = int.Parse(element.ReadTextNode("Rank"));
|
||||
this.Map = element.ReadTextNode("Map");
|
||||
this.Status = (ShardStatus)Enum.Parse(typeof(ShardStatus), element.ReadTextNode("Status"));
|
||||
this.Id = int.Parse(element.ReadTextNode("Id"));
|
||||
}
|
||||
}
|
||||
}
|
30
server/FSO.Server.Protocol/CitySelector/UserAuthorized.cs
Executable file
30
server/FSO.Server.Protocol/CitySelector/UserAuthorized.cs
Executable file
|
@ -0,0 +1,30 @@
|
|||
using FSO.Common.Utils;
|
||||
|
||||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public class UserAuthorized : IXMLEntity
|
||||
{
|
||||
public string FSOVersion;
|
||||
public string FSOBranch;
|
||||
public string FSOUpdateUrl;
|
||||
public string FSOCDNUrl;
|
||||
|
||||
public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc)
|
||||
{
|
||||
var element = doc.CreateElement("User-Authorized");
|
||||
element.AppendTextNode("FSO-Version", FSOVersion);
|
||||
element.AppendTextNode("FSO-Branch", FSOBranch);
|
||||
element.AppendTextNode("FSO-UpdateUrl", FSOUpdateUrl);
|
||||
element.AppendTextNode("FSO-CDNUrl", FSOCDNUrl);
|
||||
return element;
|
||||
}
|
||||
|
||||
public void Parse(System.Xml.XmlElement element)
|
||||
{
|
||||
this.FSOVersion = element.ReadTextNode("FSO-Version");
|
||||
this.FSOBranch = element.ReadTextNode("FSO-Branch");
|
||||
this.FSOUpdateUrl = element.ReadTextNode("FSO-UpdateUrl");
|
||||
this.FSOCDNUrl = element.ReadTextNode("FSO-CDNUrl");
|
||||
}
|
||||
}
|
||||
}
|
38
server/FSO.Server.Protocol/CitySelector/XMLErrorMessage.cs
Executable file
38
server/FSO.Server.Protocol/CitySelector/XMLErrorMessage.cs
Executable file
|
@ -0,0 +1,38 @@
|
|||
using FSO.Common.Utils;
|
||||
using System;
|
||||
|
||||
namespace FSO.Server.Protocol.CitySelector
|
||||
{
|
||||
public class XMLErrorMessage : IXMLEntity
|
||||
{
|
||||
public String Code;
|
||||
public String Message;
|
||||
|
||||
public XMLErrorMessage(){
|
||||
}
|
||||
|
||||
public XMLErrorMessage(String code, String message)
|
||||
{
|
||||
this.Code = code;
|
||||
this.Message = message;
|
||||
}
|
||||
|
||||
#region IXMLPrinter Members
|
||||
|
||||
public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc)
|
||||
{
|
||||
var element = doc.CreateElement("Error-Message");
|
||||
element.AppendTextNode("Error-Number", Code);
|
||||
element.AppendTextNode("Error", Message);
|
||||
return element;
|
||||
}
|
||||
|
||||
public void Parse(System.Xml.XmlElement element)
|
||||
{
|
||||
this.Code = element.ReadTextNode("Error-Number");
|
||||
this.Message = element.ReadTextNode("Error");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
19
server/FSO.Server.Protocol/Electron/AbstractElectronPacket.cs
Executable file
19
server/FSO.Server.Protocol/Electron/AbstractElectronPacket.cs
Executable file
|
@ -0,0 +1,19 @@
|
|||
using Mina.Core.Buffer;
|
||||
using FSO.Common.Serialization;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron
|
||||
{
|
||||
public abstract class AbstractElectronPacket : IElectronPacket
|
||||
{
|
||||
public static IoBuffer Allocate(int size)
|
||||
{
|
||||
IoBuffer buffer = IoBuffer.Allocate(size);
|
||||
buffer.Order = ByteOrder.BigEndian;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public abstract ElectronPacketType GetPacketType();
|
||||
public abstract void Deserialize(IoBuffer input, ISerializationContext context);
|
||||
public abstract void Serialize(IoBuffer output, ISerializationContext context);
|
||||
}
|
||||
}
|
51
server/FSO.Server.Protocol/Electron/ElectronPacketType.cs
Executable file
51
server/FSO.Server.Protocol/Electron/ElectronPacketType.cs
Executable file
|
@ -0,0 +1,51 @@
|
|||
using System;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron
|
||||
{
|
||||
public enum ElectronPacketType : ushort
|
||||
{
|
||||
CreateASimResponse = 1,
|
||||
PurchaseLotRequest,
|
||||
PurchaseLotResponse,
|
||||
InstantMessage,
|
||||
FindLotRequest,
|
||||
FindLotResponse,
|
||||
FSOVMTickBroadcast,
|
||||
FSOVMDirectToClient,
|
||||
FSOVMCommand,
|
||||
FindAvatarRequest,
|
||||
FindAvatarResponse,
|
||||
ChangeRoommateRequest,
|
||||
KeepAlive,
|
||||
ChangeRoommateResponse,
|
||||
ModerationRequest,
|
||||
FSOVMProtocolMessage,
|
||||
AvatarRetireRequest,
|
||||
MailRequest,
|
||||
MailResponse,
|
||||
NhoodRequest,
|
||||
NhoodResponse,
|
||||
NhoodCandidateList,
|
||||
BulletinRequest,
|
||||
BulletinResponse,
|
||||
GlobalTuningUpdate,
|
||||
Unknown = 0xFFFF
|
||||
}
|
||||
|
||||
public static class ElectronPacketTypeUtils
|
||||
{
|
||||
public static ElectronPacketType FromPacketCode(ushort code)
|
||||
{
|
||||
var result = (ElectronPacketType)code;
|
||||
if (Enum.IsDefined(typeof(ElectronPacketType), result))
|
||||
return result;
|
||||
else
|
||||
return ElectronPacketType.Unknown;
|
||||
}
|
||||
|
||||
public static ushort GetPacketCode(this ElectronPacketType type)
|
||||
{
|
||||
return (ushort)type;
|
||||
}
|
||||
}
|
||||
}
|
60
server/FSO.Server.Protocol/Electron/ElectronPackets.cs
Executable file
60
server/FSO.Server.Protocol/Electron/ElectronPackets.cs
Executable file
|
@ -0,0 +1,60 @@
|
|||
using FSO.Server.Protocol.Electron.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron
|
||||
{
|
||||
public class ElectronPackets
|
||||
{
|
||||
public static Dictionary<ushort, Type> ELECTRON_PACKET_BY_TYPEID;
|
||||
public static Type[] ELECTRON_PACKETS = new Type[] {
|
||||
typeof(CreateASimResponse),
|
||||
typeof(PurchaseLotRequest),
|
||||
typeof(PurchaseLotResponse),
|
||||
typeof(InstantMessage),
|
||||
typeof(FindLotRequest),
|
||||
typeof(FindLotResponse),
|
||||
typeof(FSOVMTickBroadcast),
|
||||
typeof(FSOVMDirectToClient),
|
||||
typeof(FSOVMCommand),
|
||||
typeof(FindAvatarRequest),
|
||||
typeof(FindAvatarResponse),
|
||||
typeof(ChangeRoommateRequest),
|
||||
typeof(KeepAlive),
|
||||
typeof(ChangeRoommateResponse),
|
||||
typeof(ModerationRequest),
|
||||
typeof(FSOVMProtocolMessage),
|
||||
typeof(AvatarRetireRequest),
|
||||
typeof(MailRequest),
|
||||
typeof(MailResponse),
|
||||
typeof(NhoodRequest),
|
||||
typeof(NhoodResponse),
|
||||
typeof(NhoodCandidateList),
|
||||
typeof(BulletinRequest),
|
||||
typeof(BulletinResponse),
|
||||
typeof(GlobalTuningUpdate)
|
||||
};
|
||||
|
||||
static ElectronPackets()
|
||||
{
|
||||
ELECTRON_PACKET_BY_TYPEID = new Dictionary<ushort, Type>();
|
||||
foreach (Type packetType in ELECTRON_PACKETS)
|
||||
{
|
||||
IElectronPacket packet = (IElectronPacket)Activator.CreateInstance(packetType);
|
||||
ELECTRON_PACKET_BY_TYPEID.Add(packet.GetPacketType().GetPacketCode(), packetType);
|
||||
}
|
||||
}
|
||||
|
||||
public static Type GetByPacketCode(ushort code)
|
||||
{
|
||||
if (ELECTRON_PACKET_BY_TYPEID.ContainsKey(code))
|
||||
{
|
||||
return ELECTRON_PACKET_BY_TYPEID[code];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
server/FSO.Server.Protocol/Electron/IElectronPacket.cs
Executable file
9
server/FSO.Server.Protocol/Electron/IElectronPacket.cs
Executable file
|
@ -0,0 +1,9 @@
|
|||
using FSO.Common.Serialization;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron
|
||||
{
|
||||
public interface IElectronPacket : IoBufferDeserializable, IoBufferSerializable
|
||||
{
|
||||
ElectronPacketType GetPacketType();
|
||||
}
|
||||
}
|
33
server/FSO.Server.Protocol/Electron/Model/ChangeRoommateResponseStatus.cs
Executable file
33
server/FSO.Server.Protocol/Electron/Model/ChangeRoommateResponseStatus.cs
Executable file
|
@ -0,0 +1,33 @@
|
|||
namespace FSO.Server.Protocol.Electron.Model
|
||||
{
|
||||
public enum ChangeRoommateResponseStatus : byte
|
||||
{
|
||||
INVITE_SUCCESS = 0,
|
||||
|
||||
//invite codes
|
||||
ROOMIE_ELSEWHERE = 1,
|
||||
TOO_MANY_ROOMMATES = 2,
|
||||
OTHER_INVITE_PENDING = 3,
|
||||
|
||||
//shared
|
||||
YOU_ARE_NOT_OWNER = 4, //everything but move out
|
||||
|
||||
//kick or move out
|
||||
YOU_ARE_NOT_ROOMMATE = 5,
|
||||
LOT_MUST_BE_CLOSED = 6, //move out of lot with 1 roommate
|
||||
|
||||
//invite response
|
||||
LOT_DOESNT_EXIST = 7,
|
||||
NO_INVITE_PENDING = 8,
|
||||
|
||||
ACCEPT_SUCCESS = 9,
|
||||
DECLINE_SUCCESS = 10,
|
||||
KICK_SUCCESS = 11,
|
||||
SELFKICK_SUCCESS = 12,
|
||||
|
||||
ROOMMATE_LEFT = 13,
|
||||
GOT_KICKED = 14,
|
||||
|
||||
UNKNOWN = 255
|
||||
}
|
||||
}
|
11
server/FSO.Server.Protocol/Electron/Model/ChangeRoommateType.cs
Executable file
11
server/FSO.Server.Protocol/Electron/Model/ChangeRoommateType.cs
Executable file
|
@ -0,0 +1,11 @@
|
|||
namespace FSO.Server.Protocol.Electron.Model
|
||||
{
|
||||
public enum ChangeRoommateType : byte
|
||||
{
|
||||
INVITE = 0,
|
||||
KICK = 1,
|
||||
ACCEPT = 2,
|
||||
DECLINE = 3,
|
||||
POLL = 4
|
||||
}
|
||||
}
|
11
server/FSO.Server.Protocol/Electron/Model/FindAvatarResponseStatus.cs
Executable file
11
server/FSO.Server.Protocol/Electron/Model/FindAvatarResponseStatus.cs
Executable file
|
@ -0,0 +1,11 @@
|
|||
namespace FSO.Server.Protocol.Electron.Model
|
||||
{
|
||||
public enum FindAvatarResponseStatus
|
||||
{
|
||||
FOUND,
|
||||
IGNORING_THEM,
|
||||
IGNORING_YOU,
|
||||
NOT_ON_LOT,
|
||||
PRIVACY_ENABLED,
|
||||
}
|
||||
}
|
14
server/FSO.Server.Protocol/Electron/Model/FindLotResponseStatus.cs
Executable file
14
server/FSO.Server.Protocol/Electron/Model/FindLotResponseStatus.cs
Executable file
|
@ -0,0 +1,14 @@
|
|||
namespace FSO.Server.Protocol.Electron.Model
|
||||
{
|
||||
public enum FindLotResponseStatus
|
||||
{
|
||||
FOUND,
|
||||
NO_SUCH_LOT,
|
||||
NOT_OPEN,
|
||||
NOT_PERMITTED_TO_OPEN,
|
||||
CLAIM_FAILED,
|
||||
NO_CAPACITY,
|
||||
NO_ADMIT,
|
||||
UNKNOWN_ERROR
|
||||
}
|
||||
}
|
8
server/FSO.Server.Protocol/Electron/Model/IActionRequest.cs
Executable file
8
server/FSO.Server.Protocol/Electron/Model/IActionRequest.cs
Executable file
|
@ -0,0 +1,8 @@
|
|||
namespace FSO.Server.Protocol.Electron.Model
|
||||
{
|
||||
public interface IActionRequest
|
||||
{
|
||||
object OType { get; }
|
||||
bool NeedsValidation { get; }
|
||||
}
|
||||
}
|
8
server/FSO.Server.Protocol/Electron/Model/IActionResponse.cs
Executable file
8
server/FSO.Server.Protocol/Electron/Model/IActionResponse.cs
Executable file
|
@ -0,0 +1,8 @@
|
|||
namespace FSO.Server.Protocol.Electron.Model
|
||||
{
|
||||
public interface IActionResponse
|
||||
{
|
||||
bool Success { get; }
|
||||
object OCode { get; }
|
||||
}
|
||||
}
|
9
server/FSO.Server.Protocol/Electron/Model/ModerationRequestType.cs
Executable file
9
server/FSO.Server.Protocol/Electron/Model/ModerationRequestType.cs
Executable file
|
@ -0,0 +1,9 @@
|
|||
namespace FSO.Server.Protocol.Electron.Model
|
||||
{
|
||||
public enum ModerationRequestType
|
||||
{
|
||||
IPBAN_USER,
|
||||
BAN_USER,
|
||||
KICK_USER
|
||||
}
|
||||
}
|
23
server/FSO.Server.Protocol/Electron/Packets/AvatarRetireRequest.cs
Executable file
23
server/FSO.Server.Protocol/Electron/Packets/AvatarRetireRequest.cs
Executable file
|
@ -0,0 +1,23 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class AvatarRetireRequest : AbstractElectronPacket
|
||||
{
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.AvatarRetireRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(0);
|
||||
}
|
||||
}
|
||||
}
|
69
server/FSO.Server.Protocol/Electron/Packets/BulletinRequest.cs
Executable file
69
server/FSO.Server.Protocol/Electron/Packets/BulletinRequest.cs
Executable file
|
@ -0,0 +1,69 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class BulletinRequest : AbstractElectronPacket, IActionRequest
|
||||
{
|
||||
public BulletinRequestType Type;
|
||||
public uint TargetNHood; //the bulletin board to use
|
||||
|
||||
//post message
|
||||
public string Title = "";
|
||||
public string Message = "";
|
||||
public uint LotID; //0 if empty - optionally reference a lot in this bulletin post
|
||||
|
||||
//post message, delete message, promote message
|
||||
public uint Value; //bulletin type if post, bulletin ID otherwise.
|
||||
|
||||
public object OType => Type;
|
||||
public bool NeedsValidation => false; //the CAN POST items are one off requests, rather than a state machine.
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<BulletinRequestType>();
|
||||
TargetNHood = input.GetUInt32();
|
||||
|
||||
if (Type == BulletinRequestType.POST_MESSAGE || Type == BulletinRequestType.POST_SYSTEM_MESSAGE)
|
||||
{
|
||||
Title = input.GetPascalString();
|
||||
Message = input.GetPascalString();
|
||||
LotID = input.GetUInt32();
|
||||
}
|
||||
Value = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.BulletinRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
output.PutUInt32(TargetNHood);
|
||||
|
||||
if (Type == BulletinRequestType.POST_MESSAGE || Type == BulletinRequestType.POST_SYSTEM_MESSAGE)
|
||||
{
|
||||
output.PutPascalString(Title);
|
||||
output.PutPascalString(Message);
|
||||
output.PutUInt32(LotID);
|
||||
}
|
||||
output.PutUInt32(Value);
|
||||
}
|
||||
}
|
||||
|
||||
public enum BulletinRequestType : byte
|
||||
{
|
||||
GET_MESSAGES = 0,
|
||||
POST_MESSAGE,
|
||||
PROMOTE_MESSAGE, //mayor/admin only.
|
||||
CAN_POST_MESSAGE,
|
||||
CAN_POST_SYSTEM_MESSAGE,
|
||||
|
||||
//admin
|
||||
POST_SYSTEM_MESSAGE,
|
||||
DELETE_MESSAGE,
|
||||
}
|
||||
}
|
90
server/FSO.Server.Protocol/Electron/Packets/BulletinResponse.cs
Executable file
90
server/FSO.Server.Protocol/Electron/Packets/BulletinResponse.cs
Executable file
|
@ -0,0 +1,90 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Files.Formats.tsodata;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
using Mina.Core.Buffer;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class BulletinResponse : AbstractElectronPacket, IActionResponse
|
||||
{
|
||||
public BulletinResponseType Type;
|
||||
public BulletinItem[] Messages = new BulletinItem[0];
|
||||
public string Message;
|
||||
public uint BanEndDate;
|
||||
|
||||
public bool Success => Type == BulletinResponseType.SUCCESS || Type == BulletinResponseType.SEND_SUCCESS || Type == BulletinResponseType.MESSAGES;
|
||||
public object OCode => Type;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<BulletinResponseType>();
|
||||
var numMessages = input.GetInt32();
|
||||
Messages = new BulletinItem[numMessages];
|
||||
for (int j = 0; j < numMessages; j++)
|
||||
{
|
||||
var length = input.GetInt32();
|
||||
var dat = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
dat[i] = input.Get();
|
||||
}
|
||||
|
||||
using (var str = new MemoryStream(dat))
|
||||
{
|
||||
Messages[j] = new BulletinItem(str);
|
||||
}
|
||||
}
|
||||
Message = input.GetPascalVLCString();
|
||||
BanEndDate = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.BulletinResponse;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
output.PutInt32(Messages.Length);
|
||||
foreach (var msg in Messages)
|
||||
{
|
||||
byte[] dat;
|
||||
using (var str = new MemoryStream())
|
||||
{
|
||||
msg.Save(str);
|
||||
dat = str.ToArray();
|
||||
}
|
||||
output.PutInt32(dat.Length);
|
||||
foreach (var b in dat)
|
||||
output.Put(b);
|
||||
}
|
||||
output.PutPascalVLCString(Message);
|
||||
output.PutUInt32(BanEndDate);
|
||||
}
|
||||
}
|
||||
|
||||
public enum BulletinResponseType
|
||||
{
|
||||
MESSAGES,
|
||||
SEND_SUCCESS, //returns message you sent, with dbid
|
||||
SUCCESS,
|
||||
SEND_FAIL_NON_RESIDENT,
|
||||
SEND_FAIL_BAD_PERMISSION,
|
||||
SEND_FAIL_INVALID_LOT,
|
||||
SEND_FAIL_INVALID_MESSAGE,
|
||||
SEND_FAIL_INVALID_TITLE,
|
||||
SEND_FAIL_GAMEPLAY_BAN,
|
||||
SEND_FAIL_TOO_FREQUENT,
|
||||
SEND_FAIL_JUST_MOVED,
|
||||
FAIL_MESSAGE_DOESNT_EXIST,
|
||||
FAIL_NOT_MAYOR,
|
||||
FAIL_CANT_DELETE,
|
||||
FAIL_ALREADY_PROMOTED,
|
||||
FAIL_BAD_PERMISSION,
|
||||
|
||||
CANCEL = 0xFE,
|
||||
FAIL_UNKNOWN = 0xFF
|
||||
}
|
||||
}
|
32
server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateRequest.cs
Executable file
32
server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateRequest.cs
Executable file
|
@ -0,0 +1,32 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class ChangeRoommateRequest : AbstractElectronPacket
|
||||
{
|
||||
public ChangeRoommateType Type;
|
||||
public uint AvatarId;
|
||||
public uint LotLocation;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<ChangeRoommateType>();
|
||||
AvatarId = input.GetUInt32();
|
||||
LotLocation = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.ChangeRoommateRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
output.PutUInt32(AvatarId);
|
||||
output.PutUInt32(LotLocation);
|
||||
}
|
||||
}
|
||||
}
|
29
server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateResponse.cs
Executable file
29
server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateResponse.cs
Executable file
|
@ -0,0 +1,29 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class ChangeRoommateResponse : AbstractElectronPacket
|
||||
{
|
||||
public ChangeRoommateResponseStatus Type;
|
||||
public uint Extra;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<ChangeRoommateResponseStatus>();
|
||||
Extra = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.ChangeRoommateResponse;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
output.PutUInt32(Extra);
|
||||
}
|
||||
}
|
||||
}
|
47
server/FSO.Server.Protocol/Electron/Packets/CreateASimResponse.cs
Executable file
47
server/FSO.Server.Protocol/Electron/Packets/CreateASimResponse.cs
Executable file
|
@ -0,0 +1,47 @@
|
|||
using Mina.Core.Buffer;
|
||||
using FSO.Common.Serialization;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class CreateASimResponse : AbstractElectronPacket
|
||||
{
|
||||
public CreateASimStatus Status { get; set; }
|
||||
public CreateASimFailureReason Reason { get; set; } = CreateASimFailureReason.NONE;
|
||||
public uint NewAvatarId { get; set; }
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.CreateASimResponse;
|
||||
}
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Status = input.GetEnum<CreateASimStatus>();
|
||||
Reason = input.GetEnum<CreateASimFailureReason>();
|
||||
NewAvatarId = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum<CreateASimStatus>(Status);
|
||||
output.PutEnum<CreateASimFailureReason>(Reason);
|
||||
output.PutUInt32(NewAvatarId);
|
||||
}
|
||||
}
|
||||
|
||||
public enum CreateASimStatus
|
||||
{
|
||||
SUCCESS = 0x01,
|
||||
FAILED = 0x02
|
||||
}
|
||||
|
||||
public enum CreateASimFailureReason
|
||||
{
|
||||
NONE = 0x00,
|
||||
NAME_TAKEN = 0x01,
|
||||
NAME_VALIDATION_ERROR = 0x02,
|
||||
DESC_VALIDATION_ERROR = 0x03,
|
||||
BODY_VALIDATION_ERROR = 0x04,
|
||||
HEAD_VALIDATION_ERROR = 0x05
|
||||
}
|
||||
}
|
28
server/FSO.Server.Protocol/Electron/Packets/FSOVMCommand.cs
Executable file
28
server/FSO.Server.Protocol/Electron/Packets/FSOVMCommand.cs
Executable file
|
@ -0,0 +1,28 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class FSOVMCommand : AbstractElectronPacket
|
||||
{
|
||||
public byte[] Data;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
var dataLen = input.GetInt32(); //TODO: limits? 4MB is probably reasonable.
|
||||
Data = new byte[dataLen];
|
||||
input.Get(Data, 0, dataLen);
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.FSOVMCommand;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutInt32(Data.Length);
|
||||
output.Put(Data, 0, Data.Length);
|
||||
}
|
||||
}
|
||||
}
|
28
server/FSO.Server.Protocol/Electron/Packets/FSOVMDirectToClient.cs
Executable file
28
server/FSO.Server.Protocol/Electron/Packets/FSOVMDirectToClient.cs
Executable file
|
@ -0,0 +1,28 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class FSOVMDirectToClient : AbstractElectronPacket
|
||||
{
|
||||
public byte[] Data;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
var dataLen = input.GetInt32(); //TODO: limits? 4MB is probably reasonable.
|
||||
Data = new byte[dataLen];
|
||||
input.Get(Data, 0, dataLen);
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.FSOVMDirectToClient;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutInt32(Data.Length);
|
||||
output.Put(Data, 0, Data.Length);
|
||||
}
|
||||
}
|
||||
}
|
43
server/FSO.Server.Protocol/Electron/Packets/FSOVMProtocolMessage.cs
Executable file
43
server/FSO.Server.Protocol/Electron/Packets/FSOVMProtocolMessage.cs
Executable file
|
@ -0,0 +1,43 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class FSOVMProtocolMessage : AbstractElectronPacket
|
||||
{
|
||||
public bool UseCst;
|
||||
public string Title;
|
||||
public string Message;
|
||||
|
||||
public FSOVMProtocolMessage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public FSOVMProtocolMessage(bool cst, string title, string body)
|
||||
{
|
||||
UseCst = cst;
|
||||
Title = title;
|
||||
Message = body;
|
||||
}
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
UseCst = input.GetBool();
|
||||
Title = input.GetPascalVLCString();
|
||||
Message = input.GetPascalVLCString();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.FSOVMProtocolMessage;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutBool(UseCst);
|
||||
output.PutPascalVLCString(Title);
|
||||
output.PutPascalVLCString(Message);
|
||||
}
|
||||
}
|
||||
}
|
28
server/FSO.Server.Protocol/Electron/Packets/FSOVMTickBroadcast.cs
Executable file
28
server/FSO.Server.Protocol/Electron/Packets/FSOVMTickBroadcast.cs
Executable file
|
@ -0,0 +1,28 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class FSOVMTickBroadcast : AbstractElectronPacket
|
||||
{
|
||||
public byte[] Data;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
var dataLen = input.GetInt32(); //TODO: limits? 4MB is probably reasonable.
|
||||
Data = new byte[dataLen];
|
||||
input.Get(Data, 0, dataLen);
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.FSOVMTickBroadcast;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutInt32(Data.Length);
|
||||
output.Put(Data, 0, Data.Length);
|
||||
}
|
||||
}
|
||||
}
|
25
server/FSO.Server.Protocol/Electron/Packets/FindAvatarRequest.cs
Executable file
25
server/FSO.Server.Protocol/Electron/Packets/FindAvatarRequest.cs
Executable file
|
@ -0,0 +1,25 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class FindAvatarRequest : AbstractElectronPacket
|
||||
{
|
||||
public uint AvatarId;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
AvatarId = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.FindAvatarRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(AvatarId);
|
||||
}
|
||||
}
|
||||
}
|
32
server/FSO.Server.Protocol/Electron/Packets/FindAvatarResponse.cs
Executable file
32
server/FSO.Server.Protocol/Electron/Packets/FindAvatarResponse.cs
Executable file
|
@ -0,0 +1,32 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class FindAvatarResponse : AbstractElectronPacket
|
||||
{
|
||||
public uint AvatarId;
|
||||
public FindAvatarResponseStatus Status;
|
||||
public uint LotId; //0 if status is not FOUND.
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
AvatarId = input.GetUInt32();
|
||||
Status = input.GetEnum<FindAvatarResponseStatus>();
|
||||
LotId = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.FindAvatarResponse;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(AvatarId);
|
||||
output.PutEnum(Status);
|
||||
output.PutUInt32(LotId);
|
||||
}
|
||||
}
|
||||
}
|
28
server/FSO.Server.Protocol/Electron/Packets/FindLotRequest.cs
Executable file
28
server/FSO.Server.Protocol/Electron/Packets/FindLotRequest.cs
Executable file
|
@ -0,0 +1,28 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class FindLotRequest : AbstractElectronPacket
|
||||
{
|
||||
public uint LotId;
|
||||
public bool OpenIfClosed;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
LotId = input.GetUInt32();
|
||||
OpenIfClosed = input.GetBool();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.FindLotRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(LotId);
|
||||
output.PutBool(OpenIfClosed);
|
||||
}
|
||||
}
|
||||
}
|
38
server/FSO.Server.Protocol/Electron/Packets/FindLotResponse.cs
Executable file
38
server/FSO.Server.Protocol/Electron/Packets/FindLotResponse.cs
Executable file
|
@ -0,0 +1,38 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class FindLotResponse : AbstractElectronPacket
|
||||
{
|
||||
public FindLotResponseStatus Status;
|
||||
public uint LotId;
|
||||
public string LotServerTicket;
|
||||
public string Address;
|
||||
public string User;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Status = input.GetEnum<FindLotResponseStatus>();
|
||||
LotId = input.GetUInt32();
|
||||
LotServerTicket = input.GetPascalVLCString();
|
||||
Address = input.GetPascalVLCString();
|
||||
User = input.GetPascalVLCString();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.FindLotResponse;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Status);
|
||||
output.PutUInt32(LotId);
|
||||
output.PutPascalVLCString(LotServerTicket);
|
||||
output.PutPascalVLCString(Address);
|
||||
output.PutPascalVLCString(User);
|
||||
}
|
||||
}
|
||||
}
|
54
server/FSO.Server.Protocol/Electron/Packets/GlobalTuningUpdate.cs
Executable file
54
server/FSO.Server.Protocol/Electron/Packets/GlobalTuningUpdate.cs
Executable file
|
@ -0,0 +1,54 @@
|
|||
using FSO.Common.Model;
|
||||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class GlobalTuningUpdate : AbstractElectronPacket
|
||||
{
|
||||
public DynamicTuning Tuning;
|
||||
public byte[] ObjectUpgrades;
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
|
||||
var dataLen = input.GetInt32();
|
||||
if (dataLen > 4000000 || dataLen > input.Remaining) throw new Exception("Tuning too long");
|
||||
var data = new byte[dataLen];
|
||||
input.Get(data, 0, dataLen);
|
||||
using (var mem = new MemoryStream(data))
|
||||
{
|
||||
using (var reader = new BinaryReader(mem))
|
||||
{
|
||||
Tuning = new DynamicTuning(reader);
|
||||
}
|
||||
}
|
||||
var upgLen = input.GetInt32();
|
||||
if (upgLen > 10000000 || upgLen > input.Remaining) throw new Exception("Upgrades too long");
|
||||
ObjectUpgrades = new byte[upgLen];
|
||||
input.Get(ObjectUpgrades, 0, upgLen);
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.GlobalTuningUpdate;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
using (var mem = new MemoryStream())
|
||||
{
|
||||
using (var writer = new BinaryWriter(mem))
|
||||
{
|
||||
Tuning.SerializeInto(writer);
|
||||
var result = mem.ToArray();
|
||||
output.PutInt32(result.Length);
|
||||
output.Put(result, 0, result.Length);
|
||||
}
|
||||
}
|
||||
output.PutInt32(ObjectUpgrades.Length);
|
||||
output.Put(ObjectUpgrades, 0, ObjectUpgrades.Length);
|
||||
}
|
||||
}
|
||||
}
|
63
server/FSO.Server.Protocol/Electron/Packets/InstantMessage.cs
Executable file
63
server/FSO.Server.Protocol/Electron/Packets/InstantMessage.cs
Executable file
|
@ -0,0 +1,63 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Common.Enum;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class InstantMessage : AbstractElectronPacket
|
||||
{
|
||||
public UserReferenceType FromType;
|
||||
public uint From;
|
||||
public uint To;
|
||||
public InstantMessageType Type;
|
||||
public string Message;
|
||||
public string AckID;
|
||||
public InstantMessageFailureReason Reason = InstantMessageFailureReason.NONE;
|
||||
public uint Color;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
FromType = input.GetEnum<UserReferenceType>();
|
||||
From = input.GetUInt32();
|
||||
To = input.GetUInt32();
|
||||
Type = input.GetEnum<InstantMessageType>();
|
||||
Message = input.GetPascalVLCString();
|
||||
AckID = input.GetPascalVLCString();
|
||||
Reason = input.GetEnum<InstantMessageFailureReason>();
|
||||
Color = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.InstantMessage;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(FromType);
|
||||
output.PutUInt32(From);
|
||||
output.PutUInt32(To);
|
||||
output.PutEnum(Type);
|
||||
output.PutPascalVLCString(Message);
|
||||
output.PutPascalVLCString(AckID);
|
||||
output.PutEnum(Reason);
|
||||
output.PutUInt32(Color);
|
||||
}
|
||||
}
|
||||
|
||||
public enum InstantMessageType
|
||||
{
|
||||
MESSAGE,
|
||||
SUCCESS_ACK,
|
||||
FAILURE_ACK
|
||||
}
|
||||
|
||||
public enum InstantMessageFailureReason
|
||||
{
|
||||
NONE,
|
||||
THEY_ARE_OFFLINE,
|
||||
THEY_ARE_IGNORING_YOU,
|
||||
YOU_ARE_IGNORING_THEM,
|
||||
MESSAGE_QUEUE_FULL
|
||||
}
|
||||
}
|
23
server/FSO.Server.Protocol/Electron/Packets/KeepAlive.cs
Executable file
23
server/FSO.Server.Protocol/Electron/Packets/KeepAlive.cs
Executable file
|
@ -0,0 +1,23 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class KeepAlive : AbstractElectronPacket
|
||||
{
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.KeepAlive;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
70
server/FSO.Server.Protocol/Electron/Packets/MailRequest.cs
Executable file
70
server/FSO.Server.Protocol/Electron/Packets/MailRequest.cs
Executable file
|
@ -0,0 +1,70 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Files.Formats.tsodata;
|
||||
using Mina.Core.Buffer;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class MailRequest : AbstractElectronPacket
|
||||
{
|
||||
public MailRequestType Type;
|
||||
public long TimestampID;
|
||||
public MessageItem Item;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<MailRequestType>();
|
||||
if (Type == MailRequestType.SEND) {
|
||||
var length = input.GetInt32();
|
||||
var dat = new byte[length];
|
||||
for (int i=0; i<length; i++)
|
||||
{
|
||||
dat[i] = input.Get();
|
||||
}
|
||||
|
||||
using (var str = new MemoryStream(dat))
|
||||
{
|
||||
Item = new MessageItem(str);
|
||||
|
||||
}
|
||||
} else
|
||||
{
|
||||
TimestampID = input.GetInt64();
|
||||
}
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.MailRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
if (Type == MailRequestType.SEND)
|
||||
{
|
||||
byte[] dat;
|
||||
if (Item == null) dat = new byte[0];
|
||||
else
|
||||
{
|
||||
using (var str = new MemoryStream())
|
||||
{
|
||||
Item.Save(str);
|
||||
dat = str.ToArray();
|
||||
}
|
||||
}
|
||||
output.PutInt32(dat.Length);
|
||||
foreach (var b in dat)
|
||||
output.Put(b);
|
||||
} else
|
||||
output.PutInt64(TimestampID);
|
||||
}
|
||||
}
|
||||
|
||||
public enum MailRequestType : byte
|
||||
{
|
||||
POLL_INBOX,
|
||||
SEND,
|
||||
DELETE
|
||||
}
|
||||
}
|
69
server/FSO.Server.Protocol/Electron/Packets/MailResponse.cs
Executable file
69
server/FSO.Server.Protocol/Electron/Packets/MailResponse.cs
Executable file
|
@ -0,0 +1,69 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Files.Formats.tsodata;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class MailResponse : AbstractElectronPacket
|
||||
{
|
||||
public MailResponseType Type;
|
||||
public MessageItem[] Messages = new MessageItem[0];
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<MailResponseType>();
|
||||
var numMessages = input.GetInt32();
|
||||
Messages = new MessageItem[numMessages];
|
||||
for (int j = 0; j < numMessages; j++)
|
||||
{
|
||||
var length = input.GetInt32();
|
||||
var dat = new byte[length];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
dat[i] = input.Get();
|
||||
}
|
||||
|
||||
using (var str = new MemoryStream(dat))
|
||||
{
|
||||
Messages[j] = new MessageItem(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.MailResponse;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
output.PutInt32(Messages.Length);
|
||||
foreach (var msg in Messages)
|
||||
{
|
||||
byte[] dat;
|
||||
using (var str = new MemoryStream())
|
||||
{
|
||||
msg.Save(str);
|
||||
dat = str.ToArray();
|
||||
}
|
||||
output.PutInt32(dat.Length);
|
||||
foreach (var b in dat)
|
||||
output.Put(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum MailResponseType
|
||||
{
|
||||
POLL_RESPONSE,
|
||||
NEW_MAIL,
|
||||
SEND_IGNORING_YOU,
|
||||
SEND_IGNORING_THEM,
|
||||
SEND_THROTTLED,
|
||||
SEND_THROTTLED_DAILY,
|
||||
SEND_FAILED,
|
||||
SEND_SUCCESS //returns the message you sent, with its db id
|
||||
}
|
||||
}
|
29
server/FSO.Server.Protocol/Electron/Packets/ModerationRequest.cs
Executable file
29
server/FSO.Server.Protocol/Electron/Packets/ModerationRequest.cs
Executable file
|
@ -0,0 +1,29 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class ModerationRequest : AbstractElectronPacket
|
||||
{
|
||||
public ModerationRequestType Type;
|
||||
public uint EntityId;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<ModerationRequestType>();
|
||||
EntityId = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.ModerationRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
output.PutUInt32(EntityId);
|
||||
}
|
||||
}
|
||||
}
|
76
server/FSO.Server.Protocol/Electron/Packets/NhoodCandidateList.cs
Executable file
76
server/FSO.Server.Protocol/Electron/Packets/NhoodCandidateList.cs
Executable file
|
@ -0,0 +1,76 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class NhoodCandidateList : AbstractElectronPacket
|
||||
{
|
||||
public bool NominationMode;
|
||||
public List<NhoodCandidate> Candidates;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
NominationMode = input.GetBool();
|
||||
int candCount = input.GetInt32();
|
||||
|
||||
Candidates = new List<NhoodCandidate>();
|
||||
for (int i=0; i<candCount; i++)
|
||||
{
|
||||
var candidate = new NhoodCandidate()
|
||||
{
|
||||
ID = input.GetUInt32(),
|
||||
Name = input.GetPascalVLCString(),
|
||||
Rating = input.GetUInt32()
|
||||
};
|
||||
|
||||
if (!NominationMode)
|
||||
{
|
||||
candidate.LastNhoodName = input.GetPascalVLCString();
|
||||
candidate.LastNhoodID = input.GetUInt32();
|
||||
candidate.TermNumber = input.GetUInt32();
|
||||
candidate.Message = input.GetPascalVLCString();
|
||||
}
|
||||
Candidates.Add(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.NhoodCandidateList;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutBool(NominationMode);
|
||||
output.PutInt32(Candidates.Count);
|
||||
|
||||
foreach (var candidate in Candidates)
|
||||
{
|
||||
output.PutUInt32(candidate.ID);
|
||||
output.PutPascalVLCString(candidate.Name);
|
||||
output.PutUInt32(candidate.Rating);
|
||||
|
||||
if (!NominationMode)
|
||||
{
|
||||
output.PutPascalVLCString(candidate.LastNhoodName);
|
||||
output.PutUInt32(candidate.LastNhoodID);
|
||||
output.PutUInt32(candidate.TermNumber);
|
||||
output.PutPascalVLCString(candidate.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class NhoodCandidate
|
||||
{
|
||||
public uint ID;
|
||||
public string Name;
|
||||
public uint Rating;
|
||||
|
||||
public string LastNhoodName = "";
|
||||
public uint LastNhoodID;
|
||||
public uint TermNumber;
|
||||
public string Message = "";
|
||||
}
|
||||
}
|
71
server/FSO.Server.Protocol/Electron/Packets/NhoodRequest.cs
Executable file
71
server/FSO.Server.Protocol/Electron/Packets/NhoodRequest.cs
Executable file
|
@ -0,0 +1,71 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class NhoodRequest : AbstractElectronPacket, IActionRequest
|
||||
{
|
||||
public NhoodRequestType Type;
|
||||
public uint TargetAvatar; //vote, nominate, rate, delete rate, force mayor, gameplay ban, add candidate, remove candidate
|
||||
public uint TargetNHood; //vote, nominate, add candidate, remove candidate
|
||||
|
||||
public object OType => Type;
|
||||
public bool NeedsValidation =>
|
||||
Type == NhoodRequestType.CAN_NOMINATE || Type == NhoodRequestType.CAN_RATE
|
||||
|| Type == NhoodRequestType.CAN_RUN || Type == NhoodRequestType.CAN_VOTE || Type == NhoodRequestType.CAN_FREE_VOTE;
|
||||
|
||||
public string Message = ""; //bulletin, rate
|
||||
public uint Value; //rate (stars), nomination_run (accept if >0)
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<NhoodRequestType>();
|
||||
TargetAvatar = input.GetUInt32();
|
||||
TargetNHood = input.GetUInt32();
|
||||
|
||||
Message = input.GetPascalString();
|
||||
Value = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.NhoodRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
output.PutUInt32(TargetAvatar);
|
||||
output.PutUInt32(TargetNHood);
|
||||
|
||||
output.PutPascalString(Message);
|
||||
output.PutUInt32(Value);
|
||||
}
|
||||
}
|
||||
|
||||
public enum NhoodRequestType : byte
|
||||
{
|
||||
VOTE = 0,
|
||||
CAN_VOTE,
|
||||
NOMINATE,
|
||||
CAN_NOMINATE,
|
||||
|
||||
RATE,
|
||||
CAN_RATE,
|
||||
NOMINATION_RUN,
|
||||
CAN_RUN,
|
||||
|
||||
CAN_FREE_VOTE,
|
||||
FREE_VOTE,
|
||||
|
||||
//moderator commands
|
||||
DELETE_RATE,
|
||||
FORCE_MAYOR,
|
||||
REMOVE_CANDIDATE,
|
||||
ADD_CANDIDATE,
|
||||
TEST_ELECTION, //nhood id, avatar id = state (over/nomination/election), value = end date in x days
|
||||
PRETEND_DATE, //run the daily nhood task as if it's (value) date. (Epoch value)
|
||||
NHOOD_GAMEPLAY_BAN
|
||||
}
|
||||
}
|
81
server/FSO.Server.Protocol/Electron/Packets/NhoodResponse.cs
Executable file
81
server/FSO.Server.Protocol/Electron/Packets/NhoodResponse.cs
Executable file
|
@ -0,0 +1,81 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Protocol.Electron.Model;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class NhoodResponse : AbstractElectronPacket, IActionResponse
|
||||
{
|
||||
public NhoodResponseCode Code;
|
||||
public uint BanEndDate;
|
||||
public string Message = "";
|
||||
|
||||
public bool Success => Code == NhoodResponseCode.SUCCESS;
|
||||
public object OCode => Code;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Code = input.GetEnum<NhoodResponseCode>();
|
||||
BanEndDate = input.GetUInt32();
|
||||
Message = input.GetPascalVLCString();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.NhoodResponse;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Code);
|
||||
output.PutUInt32(BanEndDate);
|
||||
output.PutPascalVLCString(Message);
|
||||
}
|
||||
}
|
||||
|
||||
public enum NhoodResponseCode : byte
|
||||
{
|
||||
SUCCESS = 0x00,
|
||||
|
||||
//nominate/vote
|
||||
NOT_IN_NHOOD = 0x01,
|
||||
ELECTION_OVER = 0x02,
|
||||
CANDIDATE_NOT_IN_NHOOD = 0x03,
|
||||
CANDIDATE_NOT_NOMINATED = 0x04,
|
||||
ALREADY_VOTED = 0x05,
|
||||
ALREADY_VOTED_SAME_IP = 0x06,
|
||||
BAD_STATE = 0x07,
|
||||
|
||||
//rate
|
||||
NOT_YOUR_MAYOR = 0x08,
|
||||
INVALID_RATING = 0x09,
|
||||
CANT_RATE_AVATAR = 0x0A,
|
||||
|
||||
//accept or decline a nomination
|
||||
NOBODY_NOMINATED_YOU_IDIOT = 0x0B,
|
||||
ALREADY_RUNNING = 0x0C,
|
||||
BAD_COMMENT = 0x0D,
|
||||
|
||||
//moderator actions
|
||||
NOT_MODERATOR = 0x0E,
|
||||
INVALID_AVATAR = 0x0F,
|
||||
INVALID_NHOOD = 0x10,
|
||||
|
||||
//shared
|
||||
NHOOD_GAMEPLAY_BAN = 0x11,
|
||||
CANDIDATE_MOVED_RECENTLY = 0x12,
|
||||
YOU_MOVED_RECENTLY = 0x13,
|
||||
CANDIDATE_NHOOD_GAMEPLAY_BAN = 0x14,
|
||||
MISSING_ENTITY = 0x15, //missing someone
|
||||
|
||||
//free vote
|
||||
NHOOD_NO_ELECTION = 0x16,
|
||||
ALREADY_ENROLLED_FOR_FREE_VOTE = 0x17,
|
||||
FREE_VOTE_ALREADY_ELIGIBLE = 0x18,
|
||||
FREE_VOTE_MOVE_DATE = 0x19,
|
||||
FREE_VOTE_ELECTION_OVER = 0x1A,
|
||||
|
||||
CANCEL = 0xFE,
|
||||
UNKNOWN_ERROR = 0xFF
|
||||
};
|
||||
}
|
37
server/FSO.Server.Protocol/Electron/Packets/PurchaseLotRequest.cs
Executable file
37
server/FSO.Server.Protocol/Electron/Packets/PurchaseLotRequest.cs
Executable file
|
@ -0,0 +1,37 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class PurchaseLotRequest : AbstractElectronPacket
|
||||
{
|
||||
public ushort LotLocation_X;
|
||||
public ushort LotLocation_Y;
|
||||
public string Name;
|
||||
public bool StartFresh;
|
||||
public bool MayorMode;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
LotLocation_X = input.GetUInt16();
|
||||
LotLocation_Y = input.GetUInt16();
|
||||
Name = input.GetPascalString();
|
||||
StartFresh = input.GetBool();
|
||||
MayorMode = input.GetBool();
|
||||
}
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.PurchaseLotRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt16(LotLocation_X);
|
||||
output.PutUInt16(LotLocation_Y);
|
||||
output.PutPascalString(Name);
|
||||
output.PutBool(StartFresh);
|
||||
output.PutBool(MayorMode);
|
||||
}
|
||||
}
|
||||
}
|
60
server/FSO.Server.Protocol/Electron/Packets/PurchaseLotResponse.cs
Executable file
60
server/FSO.Server.Protocol/Electron/Packets/PurchaseLotResponse.cs
Executable file
|
@ -0,0 +1,60 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Electron.Packets
|
||||
{
|
||||
public class PurchaseLotResponse : AbstractElectronPacket
|
||||
{
|
||||
public PurchaseLotStatus Status { get; set; }
|
||||
public PurchaseLotFailureReason Reason { get; set; } = PurchaseLotFailureReason.NONE;
|
||||
public uint NewLotId { get; set; }
|
||||
public int NewFunds { get; set; }
|
||||
|
||||
public override ElectronPacketType GetPacketType()
|
||||
{
|
||||
return ElectronPacketType.PurchaseLotResponse;
|
||||
}
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Status = input.GetEnum<PurchaseLotStatus>();
|
||||
Reason = input.GetEnum<PurchaseLotFailureReason>();
|
||||
NewLotId = input.GetUInt32();
|
||||
NewFunds = input.GetInt32();
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum<PurchaseLotStatus>(Status);
|
||||
output.PutEnum<PurchaseLotFailureReason>(Reason);
|
||||
output.PutUInt32(NewLotId);
|
||||
output.PutInt32(NewFunds);
|
||||
}
|
||||
}
|
||||
|
||||
public enum PurchaseLotStatus
|
||||
{
|
||||
SUCCESS = 0x01,
|
||||
FAILED = 0x02
|
||||
}
|
||||
|
||||
public enum PurchaseLotFailureReason
|
||||
{
|
||||
NONE = 0x00,
|
||||
NAME_TAKEN = 0x01,
|
||||
NAME_VALIDATION_ERROR = 0x02,
|
||||
INSUFFICIENT_FUNDS = 0x03,
|
||||
LOT_TAKEN = 0x04,
|
||||
LOT_NOT_PURCHASABLE = 0x05,
|
||||
IN_LOT_CANT_EVICT = 0x06,
|
||||
NOT_OFFLINE_FOR_MOVE = 0x07,
|
||||
LOCATION_TAKEN = 0x08,
|
||||
NHOOD_RESERVED = 0x09,
|
||||
|
||||
TH_NOT_MAYOR = 0x80,
|
||||
TH_INCORRECT_NHOOD = 0x81,
|
||||
|
||||
|
||||
UNKNOWN = 0xFF
|
||||
}
|
||||
}
|
229
server/FSO.Server.Protocol/FSO.Server.Protocol.csproj
Executable file
229
server/FSO.Server.Protocol/FSO.Server.Protocol.csproj
Executable file
|
@ -0,0 +1,229 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{A08ADE32-27E2-44F4-BC52-11A16C56BAA8}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>FSO.Server.Protocol</RootNamespace>
|
||||
<AssemblyName>FSO.Server.Protocol</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>true</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<UseVSHostingProcess>true</UseVSHostingProcess>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'ServerRelease|AnyCPU'">
|
||||
<OutputPath>bin\ServerRelease\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Common.Logging, Version=3.4.1.0, Culture=neutral, PublicKeyToken=af08829b84f0328e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Common.Logging.3.4.1\lib\net40\Common.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Common.Logging.Core, Version=3.4.1.0, Culture=neutral, PublicKeyToken=af08829b84f0328e, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Common.Logging.Core.3.4.1\lib\net40\Common.Logging.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Mina.NET, Version=2.0.11.0, Culture=neutral, PublicKeyToken=bc4dde96e5154fe5, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Mina.2.0.11\lib\net40\Mina.NET.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Ninject, Version=3.0.0.0, Culture=neutral, PublicKeyToken=c7192dc5380945e7, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Portable.Ninject.3.3.1\lib\net40-client\Ninject.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\NLog.4.5.7\lib\net45\NLog.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Aries\AriesPackets.cs" />
|
||||
<Compile Include="Aries\AriesProtocol.cs" />
|
||||
<Compile Include="Aries\AriesProtocolDecoder.cs" />
|
||||
<Compile Include="Aries\AriesProtocolEncoder.cs" />
|
||||
<Compile Include="Aries\AriesProtocolLogger.cs" />
|
||||
<Compile Include="Aries\AriesPacketType.cs" />
|
||||
<Compile Include="Aries\IAriesPacket.cs" />
|
||||
<Compile Include="Aries\Packets\AnswerAccepted.cs" />
|
||||
<Compile Include="Aries\Packets\AnswerChallenge.cs" />
|
||||
<Compile Include="Aries\Packets\RequestChallenge.cs" />
|
||||
<Compile Include="Aries\Packets\RequestChallengeResponse.cs" />
|
||||
<Compile Include="Aries\Packets\RequestClientSession.cs" />
|
||||
<Compile Include="Aries\Packets\RequestClientSessionResponse.cs" />
|
||||
<Compile Include="Authorization\AuthRequest.cs" />
|
||||
<Compile Include="Authorization\AuthResult.cs" />
|
||||
<Compile Include="CitySelector\AvatarAppearanceType.cs" />
|
||||
<Compile Include="CitySelector\AvatarData.cs" />
|
||||
<Compile Include="CitySelector\AvatarGender.cs" />
|
||||
<Compile Include="CitySelector\InitialConnectServletRequest.cs" />
|
||||
<Compile Include="CitySelector\InitialConnectServletResult.cs" />
|
||||
<Compile Include="CitySelector\ShardSelectorServletRequest.cs" />
|
||||
<Compile Include="CitySelector\ShardSelectorServletResponse.cs" />
|
||||
<Compile Include="CitySelector\ShardStatus.cs" />
|
||||
<Compile Include="CitySelector\ShardStatusItem.cs" />
|
||||
<Compile Include="CitySelector\UserAuthorized.cs" />
|
||||
<Compile Include="CitySelector\XMLErrorMessage.cs" />
|
||||
<Compile Include="Electron\AbstractElectronPacket.cs" />
|
||||
<Compile Include="Electron\ElectronPackets.cs" />
|
||||
<Compile Include="Electron\ElectronPacketType.cs" />
|
||||
<Compile Include="Electron\IElectronPacket.cs" />
|
||||
<Compile Include="Electron\Model\ChangeRoommateResponseStatus.cs" />
|
||||
<Compile Include="Electron\Model\ChangeRoommateType.cs" />
|
||||
<Compile Include="Electron\Model\FindAvatarResponseStatus.cs" />
|
||||
<Compile Include="Electron\Model\FindLotResponseStatus.cs" />
|
||||
<Compile Include="Electron\Model\IActionRequest.cs" />
|
||||
<Compile Include="Electron\Model\IActionResponse.cs" />
|
||||
<Compile Include="Electron\Model\ModerationRequestType.cs" />
|
||||
<Compile Include="Electron\Packets\AvatarRetireRequest.cs" />
|
||||
<Compile Include="Electron\Packets\BulletinRequest.cs" />
|
||||
<Compile Include="Electron\Packets\BulletinResponse.cs" />
|
||||
<Compile Include="Electron\Packets\ChangeRoommateRequest.cs" />
|
||||
<Compile Include="Electron\Packets\ChangeRoommateResponse.cs" />
|
||||
<Compile Include="Electron\Packets\FSOVMProtocolMessage.cs" />
|
||||
<Compile Include="Electron\Packets\GlobalTuningUpdate.cs" />
|
||||
<Compile Include="Electron\Packets\MailRequest.cs" />
|
||||
<Compile Include="Electron\Packets\MailResponse.cs" />
|
||||
<Compile Include="Electron\Packets\ModerationRequest.cs" />
|
||||
<Compile Include="Electron\Packets\FindAvatarResponse.cs" />
|
||||
<Compile Include="Electron\Packets\FindLotResponse.cs" />
|
||||
<Compile Include="Electron\Packets\CreateASimResponse.cs" />
|
||||
<Compile Include="Electron\Packets\FindAvatarRequest.cs" />
|
||||
<Compile Include="Electron\Packets\FSOVMDirectToClient.cs" />
|
||||
<Compile Include="Electron\Packets\FSOVMCommand.cs" />
|
||||
<Compile Include="Electron\Packets\FSOVMTickBroadcast.cs" />
|
||||
<Compile Include="Electron\Packets\InstantMessage.cs" />
|
||||
<Compile Include="Electron\Packets\FindLotRequest.cs" />
|
||||
<Compile Include="Electron\Packets\KeepAlive.cs" />
|
||||
<Compile Include="Electron\Packets\NhoodCandidateList.cs" />
|
||||
<Compile Include="Electron\Packets\NhoodRequest.cs" />
|
||||
<Compile Include="Electron\Packets\NhoodResponse.cs" />
|
||||
<Compile Include="Electron\Packets\PurchaseLotRequest.cs" />
|
||||
<Compile Include="Electron\Packets\PurchaseLotResponse.cs" />
|
||||
<Compile Include="Gluon\AbstractElectronPacket.cs" />
|
||||
<Compile Include="Gluon\GluonPackets.cs" />
|
||||
<Compile Include="Gluon\GluonPacketType.cs" />
|
||||
<Compile Include="Gluon\IGluonPacket.cs" />
|
||||
<Compile Include="Gluon\Model\ChangeType.cs" />
|
||||
<Compile Include="Gluon\Model\ClaimAction.cs" />
|
||||
<Compile Include="Gluon\Model\ClaimType.cs" />
|
||||
<Compile Include="Gluon\Packets\AdvertiseCapacity.cs" />
|
||||
<Compile Include="Gluon\Packets\CityNotify.cs" />
|
||||
<Compile Include="Gluon\Packets\HealthPing.cs" />
|
||||
<Compile Include="Gluon\Packets\HealthPingResponse.cs" />
|
||||
<Compile Include="Gluon\Packets\IGluonCall.cs" />
|
||||
<Compile Include="Gluon\Packets\MatchmakerNotify.cs" />
|
||||
<Compile Include="Gluon\Packets\NotifyLotRoommateChange.cs" />
|
||||
<Compile Include="Gluon\Packets\RequestLotClientTermination.cs" />
|
||||
<Compile Include="Gluon\Packets\RequestTask.cs" />
|
||||
<Compile Include="Gluon\Packets\RequestTaskResponse.cs" />
|
||||
<Compile Include="Gluon\Packets\SendCityMail.cs" />
|
||||
<Compile Include="Gluon\Packets\ShardShutdownCompleteResponse.cs" />
|
||||
<Compile Include="Gluon\Packets\ShardShutdownRequest.cs" />
|
||||
<Compile Include="Gluon\Packets\TransferClaim.cs" />
|
||||
<Compile Include="Gluon\Packets\TransferClaimResponse.cs" />
|
||||
<Compile Include="Gluon\Packets\TuningChanged.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utils\ChallengeResponse.cs" />
|
||||
<Compile Include="Utils\SslClientFilter.cs" />
|
||||
<Compile Include="Utils\CustomCumulativeProtocolDecoder.cs" />
|
||||
<Compile Include="Voltron\AbstractVoltronPacket.cs" />
|
||||
<Compile Include="Voltron\cTSONetMessageParameter.cs" />
|
||||
<Compile Include="Voltron\DataService\AvatarSkills.cs" />
|
||||
<Compile Include="Voltron\DataService\Bookmark.cs" />
|
||||
<Compile Include="Voltron\DataService\Avatar.cs" />
|
||||
<Compile Include="Voltron\DataService\AvatarAppearance.cs" />
|
||||
<Compile Include="Voltron\DataService\cITSOProperty.cs" />
|
||||
<Compile Include="Voltron\DataService\clsid.cs" />
|
||||
<Compile Include="Voltron\DataService\cTSOSerializer.cs" />
|
||||
<Compile Include="Voltron\DataService\cTSOValue.cs" />
|
||||
<Compile Include="Voltron\DataService\Location.cs" />
|
||||
<Compile Include="Voltron\DataService\Lot.cs" />
|
||||
<Compile Include="Voltron\Model\Gender.cs" />
|
||||
<Compile Include="Voltron\Model\RPCRequest.cs" />
|
||||
<Compile Include="Voltron\IVoltronPacket.cs" />
|
||||
<Compile Include="Voltron\Model\MagicNumberEnum.cs" />
|
||||
<Compile Include="Voltron\Model\Sender.cs" />
|
||||
<Compile Include="Voltron\Model\SkinTone.cs" />
|
||||
<Compile Include="Voltron\Packets\AnnouncementMsgPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\ChatMsgPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\ServerByePDU.cs" />
|
||||
<Compile Include="Voltron\Packets\ClientByePDU.cs" />
|
||||
<Compile Include="Voltron\Packets\ClientOnlinePDU.cs" />
|
||||
<Compile Include="Voltron\Packets\DataServiceWrapperPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\DBRequestWrapperPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\FindPlayerPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\FindPlayerResponsePDU.cs" />
|
||||
<Compile Include="Voltron\Packets\HostOnlinePDU.cs" />
|
||||
<Compile Include="Voltron\Packets\OccupantArrivedPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\RSGZWrapperPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\SetIgnoreListPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\SetIgnoreListResponsePDU.cs" />
|
||||
<Compile Include="Voltron\Packets\SetInvinciblePDU.cs" />
|
||||
<Compile Include="Voltron\Packets\TransmitCreateAvatarNotificationPDU.cs" />
|
||||
<Compile Include="Voltron\Packets\VariableVoltronPacket.cs" />
|
||||
<Compile Include="Voltron\VoltronPackets.cs" />
|
||||
<Compile Include="Voltron\VoltronPacketType.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\FSO.Server.Common\FSO.Server.Common.csproj">
|
||||
<Project>{39b61962-fe43-4b64-8e57-8f793737fffe}</Project>
|
||||
<Name>FSO.Server.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\tso.common\FSO.Common.csproj">
|
||||
<Project>{c42962a1-8796-4f47-9dcd-79ed5904d8ca}</Project>
|
||||
<Name>FSO.Common</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\tso.files\FSO.Files.csproj">
|
||||
<Project>{18583453-a970-4ac5-83b1-2d6bfdf94c24}</Project>
|
||||
<Name>FSO.Files</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
36
server/FSO.Server.Protocol/Gluon/AbstractElectronPacket.cs
Executable file
36
server/FSO.Server.Protocol/Gluon/AbstractElectronPacket.cs
Executable file
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Protocol.Gluon.Packets;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon
|
||||
{
|
||||
public abstract class AbstractGluonPacket : IGluonPacket
|
||||
{
|
||||
public static IoBuffer Allocate(int size)
|
||||
{
|
||||
IoBuffer buffer = IoBuffer.Allocate(size);
|
||||
buffer.Order = ByteOrder.BigEndian;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public abstract GluonPacketType GetPacketType();
|
||||
public abstract void Deserialize(IoBuffer input, ISerializationContext context);
|
||||
public abstract void Serialize(IoBuffer output, ISerializationContext context);
|
||||
}
|
||||
|
||||
public abstract class AbstractGluonCallPacket : AbstractGluonPacket, IGluonCall
|
||||
{
|
||||
public Guid CallId { get; set; }
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutPascalString(CallId.ToString());
|
||||
}
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
CallId = Guid.Parse(input.GetPascalString());
|
||||
}
|
||||
}
|
||||
}
|
107
server/FSO.Server.Protocol/Gluon/GluonPacketType.cs
Executable file
107
server/FSO.Server.Protocol/Gluon/GluonPacketType.cs
Executable file
|
@ -0,0 +1,107 @@
|
|||
namespace FSO.Server.Protocol.Gluon
|
||||
{
|
||||
public enum GluonPacketType
|
||||
{
|
||||
AdvertiseCapacity,
|
||||
TransferClaim,
|
||||
TransferClaimResponse,
|
||||
RequestLotClientTermination,
|
||||
ShardShutdownRequest,
|
||||
ShardShutdownCompleteResponse,
|
||||
|
||||
HealthPing,
|
||||
HealthPingResponse,
|
||||
RequestTask,
|
||||
RequestTaskResponse,
|
||||
|
||||
NotifyLotRoommateChange,
|
||||
MatchmakerNotify,
|
||||
CityNotify,
|
||||
|
||||
TuningChanged,
|
||||
CitySendMail,
|
||||
|
||||
Unknown
|
||||
}
|
||||
|
||||
public static class GluonPacketTypeUtils
|
||||
{
|
||||
public static GluonPacketType FromPacketCode(ushort code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case 0x0001:
|
||||
return GluonPacketType.AdvertiseCapacity;
|
||||
case 0x0002:
|
||||
return GluonPacketType.TransferClaim;
|
||||
case 0x0003:
|
||||
return GluonPacketType.TransferClaimResponse;
|
||||
case 0x0004:
|
||||
return GluonPacketType.RequestLotClientTermination;
|
||||
case 0x0005:
|
||||
return GluonPacketType.ShardShutdownRequest;
|
||||
case 0x0006:
|
||||
return GluonPacketType.ShardShutdownCompleteResponse;
|
||||
case 0x0007:
|
||||
return GluonPacketType.HealthPing;
|
||||
case 0x0008:
|
||||
return GluonPacketType.HealthPingResponse;
|
||||
case 0x0009:
|
||||
return GluonPacketType.RequestTask;
|
||||
case 0x0010:
|
||||
return GluonPacketType.RequestTaskResponse;
|
||||
case 0x0011:
|
||||
return GluonPacketType.NotifyLotRoommateChange;
|
||||
case 0x0012:
|
||||
return GluonPacketType.MatchmakerNotify;
|
||||
case 0x0013:
|
||||
return GluonPacketType.CityNotify;
|
||||
case 0x0014:
|
||||
return GluonPacketType.TuningChanged;
|
||||
case 0x0015:
|
||||
return GluonPacketType.CitySendMail;
|
||||
default:
|
||||
return GluonPacketType.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
public static ushort GetPacketCode(this GluonPacketType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GluonPacketType.AdvertiseCapacity:
|
||||
return 0x0001;
|
||||
case GluonPacketType.TransferClaim:
|
||||
return 0x0002;
|
||||
case GluonPacketType.TransferClaimResponse:
|
||||
return 0x0003;
|
||||
case GluonPacketType.RequestLotClientTermination:
|
||||
return 0x0004;
|
||||
case GluonPacketType.ShardShutdownRequest:
|
||||
return 0x0005;
|
||||
case GluonPacketType.ShardShutdownCompleteResponse:
|
||||
return 0x0006;
|
||||
case GluonPacketType.HealthPing:
|
||||
return 0x0007;
|
||||
case GluonPacketType.HealthPingResponse:
|
||||
return 0x0008;
|
||||
case GluonPacketType.RequestTask:
|
||||
return 0x0009;
|
||||
case GluonPacketType.RequestTaskResponse:
|
||||
return 0x0010;
|
||||
case GluonPacketType.NotifyLotRoommateChange:
|
||||
return 0x0011;
|
||||
case GluonPacketType.MatchmakerNotify:
|
||||
return 0x0012;
|
||||
case GluonPacketType.CityNotify:
|
||||
return 0x0013;
|
||||
case GluonPacketType.TuningChanged:
|
||||
return 0x0014;
|
||||
case GluonPacketType.CitySendMail:
|
||||
return 0x0015;
|
||||
}
|
||||
|
||||
return 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
50
server/FSO.Server.Protocol/Gluon/GluonPackets.cs
Executable file
50
server/FSO.Server.Protocol/Gluon/GluonPackets.cs
Executable file
|
@ -0,0 +1,50 @@
|
|||
using FSO.Server.Protocol.Gluon.Packets;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon
|
||||
{
|
||||
public class GluonPackets
|
||||
{
|
||||
public static Dictionary<ushort, Type> GLUON_PACKET_BY_TYPEID;
|
||||
public static Type[] ELECTRON_PACKETS = new Type[] {
|
||||
typeof(AdvertiseCapacity),
|
||||
typeof(TransferClaim),
|
||||
typeof(TransferClaimResponse),
|
||||
typeof(RequestLotClientTermination),
|
||||
typeof(ShardShutdownRequest),
|
||||
typeof(ShardShutdownCompleteResponse),
|
||||
typeof(HealthPing),
|
||||
typeof(HealthPingResponse),
|
||||
typeof(RequestTask),
|
||||
typeof(RequestTaskResponse),
|
||||
typeof(NotifyLotRoommateChange),
|
||||
typeof(MatchmakerNotify),
|
||||
typeof(CityNotify),
|
||||
typeof(TuningChanged),
|
||||
typeof(SendCityMail)
|
||||
};
|
||||
|
||||
static GluonPackets()
|
||||
{
|
||||
GLUON_PACKET_BY_TYPEID = new Dictionary<ushort, Type>();
|
||||
foreach (Type packetType in ELECTRON_PACKETS)
|
||||
{
|
||||
IGluonPacket packet = (IGluonPacket)Activator.CreateInstance(packetType);
|
||||
GLUON_PACKET_BY_TYPEID.Add(packet.GetPacketType().GetPacketCode(), packetType);
|
||||
}
|
||||
}
|
||||
|
||||
public static Type GetByPacketCode(ushort code)
|
||||
{
|
||||
if (GLUON_PACKET_BY_TYPEID.ContainsKey(code))
|
||||
{
|
||||
return GLUON_PACKET_BY_TYPEID[code];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
server/FSO.Server.Protocol/Gluon/IGluonPacket.cs
Executable file
9
server/FSO.Server.Protocol/Gluon/IGluonPacket.cs
Executable file
|
@ -0,0 +1,9 @@
|
|||
using FSO.Common.Serialization;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon
|
||||
{
|
||||
public interface IGluonPacket : IoBufferDeserializable, IoBufferSerializable
|
||||
{
|
||||
GluonPacketType GetPacketType();
|
||||
}
|
||||
}
|
11
server/FSO.Server.Protocol/Gluon/Model/ChangeType.cs
Executable file
11
server/FSO.Server.Protocol/Gluon/Model/ChangeType.cs
Executable file
|
@ -0,0 +1,11 @@
|
|||
namespace FSO.Server.Protocol.Gluon.Model
|
||||
{
|
||||
public enum ChangeType
|
||||
{
|
||||
REMOVE_ROOMMATE,
|
||||
ADD_ROOMMATE,
|
||||
BECOME_OWNER,
|
||||
BECOME_OWNER_WITH_OBJECTS,
|
||||
ROOMIE_INHERIT_OBJECTS_ONLY
|
||||
}
|
||||
}
|
10
server/FSO.Server.Protocol/Gluon/Model/ClaimAction.cs
Executable file
10
server/FSO.Server.Protocol/Gluon/Model/ClaimAction.cs
Executable file
|
@ -0,0 +1,10 @@
|
|||
namespace FSO.Server.Protocol.Gluon.Model
|
||||
{
|
||||
public enum ClaimAction
|
||||
{
|
||||
DEFAULT,
|
||||
|
||||
LOT_HOST,
|
||||
LOT_CLEANUP
|
||||
}
|
||||
}
|
8
server/FSO.Server.Protocol/Gluon/Model/ClaimType.cs
Executable file
8
server/FSO.Server.Protocol/Gluon/Model/ClaimType.cs
Executable file
|
@ -0,0 +1,8 @@
|
|||
namespace FSO.Server.Protocol.Gluon.Model
|
||||
{
|
||||
public enum ClaimType
|
||||
{
|
||||
LOT,
|
||||
AVATAR
|
||||
}
|
||||
}
|
37
server/FSO.Server.Protocol/Gluon/Packets/AdvertiseCapacity.cs
Executable file
37
server/FSO.Server.Protocol/Gluon/Packets/AdvertiseCapacity.cs
Executable file
|
@ -0,0 +1,37 @@
|
|||
using Mina.Core.Buffer;
|
||||
using FSO.Common.Serialization;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class AdvertiseCapacity : AbstractGluonPacket
|
||||
{
|
||||
public short MaxLots;
|
||||
public short CurrentLots;
|
||||
public byte CpuPercentAvg;
|
||||
public long RamUsed;
|
||||
public long RamAvaliable;
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.AdvertiseCapacity;
|
||||
}
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
MaxLots = input.GetInt16();
|
||||
CurrentLots = input.GetInt16();
|
||||
CpuPercentAvg = input.Get();
|
||||
RamUsed = input.GetInt64();
|
||||
RamAvaliable = input.GetInt64();
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutInt16(MaxLots);
|
||||
output.PutInt16(CurrentLots);
|
||||
output.Put(CpuPercentAvg);
|
||||
output.PutInt64(RamUsed);
|
||||
output.PutInt64(RamAvaliable);
|
||||
}
|
||||
}
|
||||
}
|
45
server/FSO.Server.Protocol/Gluon/Packets/CityNotify.cs
Executable file
45
server/FSO.Server.Protocol/Gluon/Packets/CityNotify.cs
Executable file
|
@ -0,0 +1,45 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
// Task -> City notifications.
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class CityNotify : AbstractGluonPacket
|
||||
{
|
||||
public CityNotifyType Mode;
|
||||
public uint Value;
|
||||
public string Message = "";
|
||||
|
||||
public CityNotify() { }
|
||||
|
||||
public CityNotify(CityNotifyType mode)
|
||||
{
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Mode = input.GetEnum<CityNotifyType>();
|
||||
Value = input.GetUInt32();
|
||||
Message = input.GetPascalVLCString();
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.CityNotify;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Mode);
|
||||
output.PutUInt32(Value);
|
||||
output.PutPascalVLCString(Message);
|
||||
}
|
||||
}
|
||||
|
||||
public enum CityNotifyType : byte
|
||||
{
|
||||
NhoodUpdate = 1
|
||||
}
|
||||
}
|
23
server/FSO.Server.Protocol/Gluon/Packets/HealthPing.cs
Executable file
23
server/FSO.Server.Protocol/Gluon/Packets/HealthPing.cs
Executable file
|
@ -0,0 +1,23 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class HealthPing : AbstractGluonCallPacket
|
||||
{
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
base.Deserialize(input, context);
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
base.Serialize(output, context);
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.HealthPing;
|
||||
}
|
||||
}
|
||||
}
|
27
server/FSO.Server.Protocol/Gluon/Packets/HealthPingResponse.cs
Executable file
27
server/FSO.Server.Protocol/Gluon/Packets/HealthPingResponse.cs
Executable file
|
@ -0,0 +1,27 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class HealthPingResponse : AbstractGluonCallPacket
|
||||
{
|
||||
public string PoolHash { get; set; }
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
base.Deserialize(input, context);
|
||||
PoolHash = input.GetPascalString();
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
base.Serialize(output, context);
|
||||
output.PutPascalString(PoolHash);
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.HealthPingResponse;
|
||||
}
|
||||
}
|
||||
}
|
9
server/FSO.Server.Protocol/Gluon/Packets/IGluonCall.cs
Executable file
9
server/FSO.Server.Protocol/Gluon/Packets/IGluonCall.cs
Executable file
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public interface IGluonCall
|
||||
{
|
||||
Guid CallId { get; set; }
|
||||
}
|
||||
}
|
40
server/FSO.Server.Protocol/Gluon/Packets/MatchmakerNotify.cs
Executable file
40
server/FSO.Server.Protocol/Gluon/Packets/MatchmakerNotify.cs
Executable file
|
@ -0,0 +1,40 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
/// <summary>
|
||||
/// Lot -> City server messages used to notify the matchmaker about some change to lot state.
|
||||
/// (currently only when an avatar leaves a lot. this frees up a space for the matchmaker to shove someone else in)
|
||||
/// </summary>
|
||||
public class MatchmakerNotify : AbstractGluonPacket
|
||||
{
|
||||
public MatchmakerNotifyType Mode;
|
||||
public uint LotID;
|
||||
public uint AvatarID;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Mode = input.GetEnum<MatchmakerNotifyType>();
|
||||
LotID = input.GetUInt32();
|
||||
AvatarID = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.MatchmakerNotify;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Mode);
|
||||
output.PutUInt32(LotID);
|
||||
output.PutUInt32(AvatarID);
|
||||
}
|
||||
}
|
||||
|
||||
public enum MatchmakerNotifyType : byte
|
||||
{
|
||||
RemoveAvatar = 1
|
||||
}
|
||||
}
|
39
server/FSO.Server.Protocol/Gluon/Packets/NotifyLotRoommateChange.cs
Executable file
39
server/FSO.Server.Protocol/Gluon/Packets/NotifyLotRoommateChange.cs
Executable file
|
@ -0,0 +1,39 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Protocol.Gluon.Model;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
/// <summary>
|
||||
/// A signal sent from the city server to notify a lot that an avatar's roommate status on that lot has changed.
|
||||
/// May wish to change this to be more generic for further avatar related changes in future.
|
||||
/// </summary>
|
||||
public class NotifyLotRoommateChange : AbstractGluonPacket
|
||||
{
|
||||
public uint AvatarId;
|
||||
public uint ReplaceId;
|
||||
public int LotId;
|
||||
public ChangeType Change;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
AvatarId = input.GetUInt32();
|
||||
ReplaceId = input.GetUInt32();
|
||||
LotId = input.GetInt32();
|
||||
Change = input.GetEnum<ChangeType>();
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.NotifyLotRoommateChange;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(AvatarId);
|
||||
output.PutUInt32(ReplaceId);
|
||||
output.PutInt32(LotId);
|
||||
output.PutEnum(Change);
|
||||
}
|
||||
}
|
||||
}
|
31
server/FSO.Server.Protocol/Gluon/Packets/RequestLotClientTermination.cs
Executable file
31
server/FSO.Server.Protocol/Gluon/Packets/RequestLotClientTermination.cs
Executable file
|
@ -0,0 +1,31 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class RequestLotClientTermination : AbstractGluonPacket
|
||||
{
|
||||
public uint AvatarId;
|
||||
public int LotId;
|
||||
public string FromOwner;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
AvatarId = input.GetUInt32();
|
||||
LotId = input.GetInt32();
|
||||
FromOwner = input.GetPascalString();
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.RequestLotClientTermination;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(AvatarId);
|
||||
output.PutInt32(LotId);
|
||||
output.PutPascalString(FromOwner);
|
||||
}
|
||||
}
|
||||
}
|
34
server/FSO.Server.Protocol/Gluon/Packets/RequestTask.cs
Executable file
34
server/FSO.Server.Protocol/Gluon/Packets/RequestTask.cs
Executable file
|
@ -0,0 +1,34 @@
|
|||
using System.Text;
|
||||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class RequestTask : AbstractGluonCallPacket
|
||||
{
|
||||
public string TaskType { get; set; }
|
||||
public string ParameterJson { get; set; }
|
||||
public int ShardId { get; set; }
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
base.Deserialize(input, context);
|
||||
TaskType = input.GetPascalString();
|
||||
ShardId = input.GetInt32();
|
||||
ParameterJson = input.GetString(Encoding.UTF8);
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
base.Serialize(output, context);
|
||||
output.PutPascalString(TaskType);
|
||||
output.PutInt32(ShardId);
|
||||
output.PutString(ParameterJson, Encoding.UTF8);
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.RequestTask;
|
||||
}
|
||||
}
|
||||
}
|
27
server/FSO.Server.Protocol/Gluon/Packets/RequestTaskResponse.cs
Executable file
27
server/FSO.Server.Protocol/Gluon/Packets/RequestTaskResponse.cs
Executable file
|
@ -0,0 +1,27 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class RequestTaskResponse : AbstractGluonCallPacket
|
||||
{
|
||||
public int TaskId;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
base.Deserialize(input, context);
|
||||
TaskId = input.GetInt32();
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
base.Serialize(output, context);
|
||||
output.PutInt32(TaskId);
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.RequestTaskResponse;
|
||||
}
|
||||
}
|
||||
}
|
58
server/FSO.Server.Protocol/Gluon/Packets/SendCityMail.cs
Executable file
58
server/FSO.Server.Protocol/Gluon/Packets/SendCityMail.cs
Executable file
|
@ -0,0 +1,58 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Files.Formats.tsodata;
|
||||
using Mina.Core.Buffer;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class SendCityMail : AbstractGluonCallPacket
|
||||
{
|
||||
public List<MessageItem> Items { get; set; }
|
||||
|
||||
public SendCityMail() { }
|
||||
|
||||
public SendCityMail(List<MessageItem> items) {
|
||||
Items = items;
|
||||
}
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
base.Deserialize(input, context);
|
||||
var itemCount = input.GetInt32();
|
||||
var dataSize = input.GetInt32();
|
||||
var data = input.GetSlice(dataSize).GetBytes();
|
||||
using (var mem = new MemoryStream(data)) {
|
||||
Items = new List<MessageItem>();
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
{
|
||||
var message = new MessageItem();
|
||||
message.Read(mem);
|
||||
Items.Add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
base.Serialize(output, context);
|
||||
byte[] data = null;
|
||||
using (var mem = new MemoryStream())
|
||||
{
|
||||
foreach (var item in Items)
|
||||
{
|
||||
item.Save(mem);
|
||||
}
|
||||
data = mem.ToArray();
|
||||
}
|
||||
output.PutInt32(Items.Count);
|
||||
output.PutInt32(data.Length);
|
||||
output.Put(data);
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.CitySendMail;
|
||||
}
|
||||
}
|
||||
}
|
25
server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownCompleteResponse.cs
Executable file
25
server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownCompleteResponse.cs
Executable file
|
@ -0,0 +1,25 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class ShardShutdownCompleteResponse : AbstractGluonPacket
|
||||
{
|
||||
public uint ShardId;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
ShardId = input.GetUInt32();
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.ShardShutdownCompleteResponse;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(ShardId);
|
||||
}
|
||||
}
|
||||
}
|
29
server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownRequest.cs
Executable file
29
server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownRequest.cs
Executable file
|
@ -0,0 +1,29 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Common;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class ShardShutdownRequest : AbstractGluonPacket
|
||||
{
|
||||
public uint ShardId;
|
||||
public ShutdownType Type;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
ShardId = input.GetUInt32();
|
||||
Type = input.GetEnum<ShutdownType>();
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.ShardShutdownRequest;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(ShardId);
|
||||
output.PutEnum(Type);
|
||||
}
|
||||
}
|
||||
}
|
41
server/FSO.Server.Protocol/Gluon/Packets/TransferClaim.cs
Executable file
41
server/FSO.Server.Protocol/Gluon/Packets/TransferClaim.cs
Executable file
|
@ -0,0 +1,41 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Server.Protocol.Gluon.Model;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class TransferClaim : AbstractGluonPacket
|
||||
{
|
||||
public ClaimType Type;
|
||||
public ClaimAction Action;
|
||||
public int EntityId;
|
||||
public uint ClaimId;
|
||||
public uint SpecialId; //job lot info
|
||||
public string FromOwner;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Type = input.GetEnum<ClaimType>();
|
||||
Action = input.GetEnum<ClaimAction>();
|
||||
EntityId = input.GetInt32();
|
||||
ClaimId = input.GetUInt32();
|
||||
SpecialId = input.GetUInt32();
|
||||
FromOwner = input.GetPascalString();
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.TransferClaim;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Type);
|
||||
output.PutEnum(Action);
|
||||
output.PutInt32(EntityId);
|
||||
output.PutUInt32(ClaimId);
|
||||
output.PutUInt32(SpecialId);
|
||||
output.PutPascalString(FromOwner);
|
||||
}
|
||||
}
|
||||
}
|
45
server/FSO.Server.Protocol/Gluon/Packets/TransferClaimResponse.cs
Executable file
45
server/FSO.Server.Protocol/Gluon/Packets/TransferClaimResponse.cs
Executable file
|
@ -0,0 +1,45 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Server.Protocol.Gluon.Model;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class TransferClaimResponse : AbstractGluonPacket
|
||||
{
|
||||
public TransferClaimResponseStatus Status;
|
||||
public ClaimType Type;
|
||||
public int EntityId;
|
||||
public uint ClaimId;
|
||||
public string NewOwner;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
Status = input.GetEnum<TransferClaimResponseStatus>();
|
||||
Type = input.GetEnum<ClaimType>();
|
||||
EntityId = input.GetInt32();
|
||||
ClaimId = input.GetUInt32();
|
||||
NewOwner = input.GetPascalString();
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.TransferClaimResponse;
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutEnum(Status);
|
||||
output.PutEnum(Type);
|
||||
output.PutInt32(EntityId);
|
||||
output.PutUInt32(ClaimId);
|
||||
output.PutPascalString(NewOwner);
|
||||
}
|
||||
}
|
||||
|
||||
public enum TransferClaimResponseStatus
|
||||
{
|
||||
ACCEPTED,
|
||||
REJECTED,
|
||||
CLAIM_NOT_FOUND
|
||||
}
|
||||
}
|
27
server/FSO.Server.Protocol/Gluon/Packets/TuningChanged.cs
Executable file
27
server/FSO.Server.Protocol/Gluon/Packets/TuningChanged.cs
Executable file
|
@ -0,0 +1,27 @@
|
|||
using FSO.Common.Serialization;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Gluon.Packets
|
||||
{
|
||||
public class TuningChanged : AbstractGluonCallPacket
|
||||
{
|
||||
public bool UpdateInstantly;
|
||||
|
||||
public override void Deserialize(IoBuffer input, ISerializationContext context)
|
||||
{
|
||||
base.Deserialize(input, context);
|
||||
UpdateInstantly = input.GetBool();
|
||||
}
|
||||
|
||||
public override void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
base.Serialize(output, context);
|
||||
output.PutBool(UpdateInstantly);
|
||||
}
|
||||
|
||||
public override GluonPacketType GetPacketType()
|
||||
{
|
||||
return GluonPacketType.TuningChanged;
|
||||
}
|
||||
}
|
||||
}
|
36
server/FSO.Server.Protocol/Properties/AssemblyInfo.cs
Executable file
36
server/FSO.Server.Protocol/Properties/AssemblyInfo.cs
Executable file
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("FSO.Server.Protocol")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("FSO.Server.Protocol")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a08ade32-27e2-44f4-bc52-11a16c56baa8")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
77
server/FSO.Server.Protocol/Utils/ChallengeResponse.cs
Executable file
77
server/FSO.Server.Protocol/Utils/ChallengeResponse.cs
Executable file
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace FSO.Server.Protocol.Utils
|
||||
{
|
||||
public class ChallengeResponse
|
||||
{
|
||||
private static int _salt_byte_length = 320;
|
||||
private static int _nonce_byte_length = 32;
|
||||
private static RNGCryptoServiceProvider _random_crypt_prov = new RNGCryptoServiceProvider();
|
||||
private static Random _random_gen = new Random();
|
||||
private static int _min_iteration_count = 4000;
|
||||
private static int _max_iteration_count = 5000;
|
||||
private const int _sha_output_length = 20;
|
||||
|
||||
private static byte[] ComputeHMACHash(byte[] data, string secret)
|
||||
{
|
||||
using (var _hmac_sha_1 = new HMACSHA1(data, true))
|
||||
{
|
||||
byte[] _hash_bytes = _hmac_sha_1.ComputeHash(Encoding.UTF8.GetBytes(secret));
|
||||
return _hash_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
public static string AnswerChallenge(string challenge, string secret)
|
||||
{
|
||||
var components = new Dictionary<string, string>();
|
||||
var parts = challenge.Split(',');
|
||||
foreach(var part in parts){
|
||||
var subParts = part.Split(new char[] { '=' }, 2);
|
||||
components.Add(subParts[0], subParts[1]);
|
||||
}
|
||||
|
||||
var iterations = int.Parse(components["i"]);
|
||||
var salt = components["s"];
|
||||
var salted = Hi(secret, Convert.FromBase64String(salt), iterations);
|
||||
|
||||
return Convert.ToBase64String(ComputeHMACHash(salted, secret));
|
||||
}
|
||||
|
||||
public static string GetChallenge()
|
||||
{
|
||||
var numIterations = GetRandomInteger();
|
||||
return "i=" + numIterations + ",s=" + Convert.ToBase64String(GetRandomByteArray(_nonce_byte_length));
|
||||
}
|
||||
|
||||
private static byte[] Hi(string password, byte[] salt, int iteration_count)
|
||||
{
|
||||
Rfc2898DeriveBytes _pdb = new Rfc2898DeriveBytes(password, salt, iteration_count);
|
||||
return _pdb.GetBytes(_sha_output_length);
|
||||
}
|
||||
|
||||
private static int GetRandomInteger()
|
||||
{
|
||||
if (_random_gen == null)
|
||||
_random_gen = new Random();
|
||||
|
||||
int _random_int = _random_gen.Next(_min_iteration_count, _max_iteration_count);
|
||||
|
||||
if (_random_int < 0)
|
||||
_random_int *= -1;
|
||||
|
||||
return _random_int;
|
||||
}
|
||||
|
||||
private static byte[] GetRandomByteArray(int byte_array_length)
|
||||
{
|
||||
byte[] _random_byte_array = new byte[byte_array_length];
|
||||
|
||||
_random_crypt_prov.GetBytes(_random_byte_array);
|
||||
|
||||
return _random_byte_array;
|
||||
}
|
||||
}
|
||||
}
|
160
server/FSO.Server.Protocol/Utils/CustomCumulativeProtocolDecoder.cs
Executable file
160
server/FSO.Server.Protocol/Utils/CustomCumulativeProtocolDecoder.cs
Executable file
|
@ -0,0 +1,160 @@
|
|||
using System;
|
||||
using Mina.Core.Buffer;
|
||||
using Mina.Core.Session;
|
||||
using Mina.Filter.Codec;
|
||||
|
||||
namespace FSO.Server.Protocol.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="IProtocolDecoder"/> that cumulates the content of received buffers to a
|
||||
/// cumulative buffer to help users implement decoders.
|
||||
/// </summary>
|
||||
public abstract class CustomCumulativeProtocolDecoder : ProtocolDecoderAdapter
|
||||
{
|
||||
private readonly AttributeKey BUFFER = new AttributeKey(typeof(CustomCumulativeProtocolDecoder), "buffer");
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
protected CustomCumulativeProtocolDecoder()
|
||||
{ }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Decode(IoSession session, IoBuffer input, IProtocolDecoderOutput output)
|
||||
{
|
||||
if (!session.TransportMetadata.HasFragmentation)
|
||||
{
|
||||
while (input.HasRemaining)
|
||||
{
|
||||
if (!DoDecode(session, input, output))
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Boolean usingSessionBuffer = true;
|
||||
IoBuffer buf = session.GetAttribute<IoBuffer>(BUFFER);
|
||||
|
||||
// If we have a session buffer, append data to that; otherwise
|
||||
// use the buffer read from the network directly.
|
||||
if (buf == null)
|
||||
{
|
||||
buf = input;
|
||||
usingSessionBuffer = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Boolean appended = false;
|
||||
// Make sure that the buffer is auto-expanded.
|
||||
if (buf.AutoExpand)
|
||||
{
|
||||
try
|
||||
{
|
||||
buf.Put(input);
|
||||
appended = true;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// A user called derivation method (e.g. slice()),
|
||||
// which disables auto-expansion of the parent buffer.
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
// A user disabled auto-expansion.
|
||||
}
|
||||
}
|
||||
|
||||
if (appended)
|
||||
{
|
||||
buf.Flip();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reallocate the buffer if append operation failed due to
|
||||
// derivation or disabled auto-expansion.
|
||||
buf.Flip();
|
||||
|
||||
IoBuffer newBuf = IoBuffer.Allocate(buf.Remaining + input.Remaining);
|
||||
newBuf.AutoExpand = true;
|
||||
newBuf.Order = buf.Order;
|
||||
newBuf.Put(buf);
|
||||
newBuf.Put(input);
|
||||
newBuf.Flip();
|
||||
buf = newBuf;
|
||||
|
||||
// Update the session attribute.
|
||||
session.SetAttribute(BUFFER, buf);
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
Int32 oldPos = buf.Position;
|
||||
Boolean decoded = DoDecode(session, buf, output);
|
||||
if (decoded)
|
||||
{
|
||||
if (buf.Position == oldPos)
|
||||
throw new InvalidOperationException("DoDecode() can't return true when buffer is not consumed.");
|
||||
if (!buf.HasRemaining)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if there is any data left that cannot be decoded, we store
|
||||
// it in a buffer in the session and next time this decoder is
|
||||
// invoked the session buffer gets appended to
|
||||
if (buf.HasRemaining)
|
||||
{
|
||||
if (usingSessionBuffer && buf.AutoExpand)
|
||||
{
|
||||
buf.Compact();
|
||||
}
|
||||
else
|
||||
{
|
||||
StoreRemainingInSession(buf, session);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (usingSessionBuffer)
|
||||
{
|
||||
RemoveSessionBuffer(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implement this method to consume the specified cumulative buffer and decode its content into message(s).
|
||||
/// </summary>
|
||||
/// <param name="session"></param>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="output"></param>
|
||||
/// <returns>
|
||||
/// true if and only if there's more to decode in the buffer
|
||||
/// and you want to have DoDecode method invoked again.
|
||||
/// Return false if remaining data is not enough to decode,
|
||||
/// then this method will be invoked again when more data is cumulated.
|
||||
/// </returns>
|
||||
protected abstract Boolean DoDecode(IoSession session, IoBuffer input, IProtocolDecoderOutput output);
|
||||
|
||||
private void RemoveSessionBuffer(IoSession session)
|
||||
{
|
||||
session.RemoveAttribute(BUFFER);
|
||||
}
|
||||
|
||||
private void StoreRemainingInSession(IoBuffer buf, IoSession session)
|
||||
{
|
||||
IoBuffer remainingBuf = IoBuffer.Allocate(buf.Capacity);
|
||||
remainingBuf.AutoExpand = true;
|
||||
|
||||
remainingBuf.Order = buf.Order;
|
||||
remainingBuf.Put(buf);
|
||||
|
||||
session.SetAttribute(BUFFER, remainingBuf);
|
||||
}
|
||||
}
|
||||
}
|
618
server/FSO.Server.Protocol/Utils/SslClientFilter.cs
Executable file
618
server/FSO.Server.Protocol/Utils/SslClientFilter.cs
Executable file
|
@ -0,0 +1,618 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Net.Security;
|
||||
using System.Security.Authentication;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading;
|
||||
using Common.Logging;
|
||||
using Mina.Core.Buffer;
|
||||
using Mina.Core.Filterchain;
|
||||
using Mina.Core.Future;
|
||||
using Mina.Core.Session;
|
||||
using Mina.Core.Write;
|
||||
|
||||
namespace FSO.Server.Protocol.Utils
|
||||
{
|
||||
public class CustomSslFilter : IoFilterAdapter
|
||||
{
|
||||
static readonly ILog log = LogManager.GetLogger(typeof(CustomSslFilter));
|
||||
|
||||
private static readonly AttributeKey NEXT_FILTER = new AttributeKey(typeof(CustomSslFilter), "nextFilter");
|
||||
private static readonly AttributeKey SSL_HANDLER = new AttributeKey(typeof(CustomSslFilter), "handler");
|
||||
|
||||
X509Certificate _serverCertificate = null;
|
||||
SslProtocols _sslProtocol = SslProtocols.Default;
|
||||
|
||||
public CustomSslFilter(String certFile)
|
||||
: this(X509Certificate.CreateFromCertFile(certFile))
|
||||
{ }
|
||||
|
||||
public CustomSslFilter(X509Certificate cert)
|
||||
{
|
||||
_serverCertificate = cert;
|
||||
}
|
||||
|
||||
public SslProtocols SslProtocol
|
||||
{
|
||||
get { return _sslProtocol; }
|
||||
set { _sslProtocol = value; }
|
||||
}
|
||||
|
||||
public X509Certificate Certificate
|
||||
{
|
||||
get { return _serverCertificate; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns <code>true</code> if and only if the specified session is
|
||||
/// encrypted/decrypted over SSL/TLS currently.
|
||||
/// </summary>
|
||||
public Boolean IsSslStarted(IoSession session)
|
||||
{
|
||||
SslHandler handler = session.GetAttribute<SslHandler>(SSL_HANDLER);
|
||||
return handler != null && handler.Authenticated;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnPreAdd(IoFilterChain parent, String name, INextFilter nextFilter)
|
||||
{
|
||||
if (parent.Contains<CustomSslFilter>())
|
||||
throw new InvalidOperationException("Only one SSL filter is permitted in a chain.");
|
||||
|
||||
IoSession session = parent.Session;
|
||||
session.SetAttribute(NEXT_FILTER, nextFilter);
|
||||
// Create a SSL handler and start handshake.
|
||||
SslHandler handler = new SslHandler(this, session);
|
||||
session.SetAttribute(SSL_HANDLER, handler);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnPostAdd(IoFilterChain parent, String name, INextFilter nextFilter)
|
||||
{
|
||||
SslHandler handler = GetSslSessionHandler(parent.Session);
|
||||
handler.Handshake(nextFilter);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnPreRemove(IoFilterChain parent, String name, INextFilter nextFilter)
|
||||
{
|
||||
IoSession session = parent.Session;
|
||||
session.RemoveAttribute(NEXT_FILTER);
|
||||
session.RemoveAttribute(SSL_HANDLER);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void SessionClosed(INextFilter nextFilter, IoSession session)
|
||||
{
|
||||
SslHandler handler = GetSslSessionHandler(session);
|
||||
try
|
||||
{
|
||||
// release resources
|
||||
handler.Destroy();
|
||||
}
|
||||
finally
|
||||
{
|
||||
// notify closed session
|
||||
base.SessionClosed(nextFilter, session);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void MessageReceived(INextFilter nextFilter, IoSession session, Object message)
|
||||
{
|
||||
IoBuffer buf = (IoBuffer)message;
|
||||
SslHandler handler = GetSslSessionHandler(session);
|
||||
// forward read encrypted data to SSL handler
|
||||
handler.MessageReceived(nextFilter, buf);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void MessageSent(INextFilter nextFilter, IoSession session, IWriteRequest writeRequest)
|
||||
{
|
||||
EncryptedWriteRequest encryptedWriteRequest = writeRequest as EncryptedWriteRequest;
|
||||
if (encryptedWriteRequest == null)
|
||||
{
|
||||
// ignore extra buffers used for handshaking
|
||||
}
|
||||
else
|
||||
{
|
||||
base.MessageSent(nextFilter, session, encryptedWriteRequest.InnerRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void ExceptionCaught(INextFilter nextFilter, IoSession session, Exception cause)
|
||||
{
|
||||
base.ExceptionCaught(nextFilter, session, cause);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void FilterWrite(INextFilter nextFilter, IoSession session, IWriteRequest writeRequest)
|
||||
{
|
||||
SslHandler handler = GetSslSessionHandler(session);
|
||||
handler.ScheduleFilterWrite(nextFilter, writeRequest);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void FilterClose(INextFilter nextFilter, IoSession session)
|
||||
{
|
||||
SslHandler handler = session.GetAttribute<SslHandler>(SSL_HANDLER);
|
||||
if (handler == null)
|
||||
{
|
||||
// The connection might already have closed, or
|
||||
// SSL might have not started yet.
|
||||
base.FilterClose(nextFilter, session);
|
||||
return;
|
||||
}
|
||||
|
||||
IWriteFuture future = null;
|
||||
try
|
||||
{
|
||||
future = InitiateClosure(handler, nextFilter, session);
|
||||
future.Complete += (s, e) => base.FilterClose(nextFilter, session);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (future == null)
|
||||
base.FilterClose(nextFilter, session);
|
||||
}
|
||||
}
|
||||
|
||||
private IWriteFuture InitiateClosure(SslHandler handler, INextFilter nextFilter, IoSession session)
|
||||
{
|
||||
IWriteFuture future = DefaultWriteFuture.NewWrittenFuture(session);
|
||||
handler.Destroy();
|
||||
return future;
|
||||
}
|
||||
|
||||
private SslHandler GetSslSessionHandler(IoSession session)
|
||||
{
|
||||
SslHandler handler = session.GetAttribute<SslHandler>(SSL_HANDLER);
|
||||
|
||||
if (handler == null)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
if (handler.SslFilter != this)
|
||||
throw new ArgumentException("Not managed by this filter.");
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
public static void DisplaySecurityLevel(SslStream stream)
|
||||
{
|
||||
log.DebugFormat("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
|
||||
log.DebugFormat("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
|
||||
log.DebugFormat("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
|
||||
log.DebugFormat("Protocol: {0}", stream.SslProtocol);
|
||||
}
|
||||
|
||||
public static void DisplaySecurityServices(SslStream stream)
|
||||
{
|
||||
log.DebugFormat("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);
|
||||
log.DebugFormat("IsSigned: {0}", stream.IsSigned);
|
||||
log.DebugFormat("Is Encrypted: {0}", stream.IsEncrypted);
|
||||
}
|
||||
|
||||
public static void DisplayStreamProperties(SslStream stream)
|
||||
{
|
||||
log.DebugFormat("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);
|
||||
log.DebugFormat("Can timeout: {0}", stream.CanTimeout);
|
||||
}
|
||||
|
||||
public static void DisplayCertificateInformation(SslStream stream)
|
||||
{
|
||||
log.DebugFormat("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);
|
||||
|
||||
X509Certificate localCertificate = stream.LocalCertificate;
|
||||
if (stream.LocalCertificate != null)
|
||||
{
|
||||
log.DebugFormat("Local cert was issued to {0} and is valid from {1} until {2}.",
|
||||
localCertificate.Subject,
|
||||
localCertificate.GetEffectiveDateString(),
|
||||
localCertificate.GetExpirationDateString());
|
||||
}
|
||||
else
|
||||
{
|
||||
log.DebugFormat("Local certificate is null.");
|
||||
}
|
||||
// Display the properties of the client's certificate.
|
||||
X509Certificate remoteCertificate = stream.RemoteCertificate;
|
||||
if (stream.RemoteCertificate != null)
|
||||
{
|
||||
log.DebugFormat("Remote cert was issued to {0} and is valid from {1} until {2}.",
|
||||
remoteCertificate.Subject,
|
||||
remoteCertificate.GetEffectiveDateString(),
|
||||
remoteCertificate.GetExpirationDateString());
|
||||
}
|
||||
else
|
||||
{
|
||||
log.DebugFormat("Remote certificate is null.");
|
||||
}
|
||||
}
|
||||
|
||||
internal class EncryptedWriteRequest : WriteRequestWrapper
|
||||
{
|
||||
private readonly IoBuffer _encryptedMessage;
|
||||
|
||||
public EncryptedWriteRequest(IWriteRequest writeRequest, IoBuffer encryptedMessage)
|
||||
: base(writeRequest)
|
||||
{
|
||||
_encryptedMessage = encryptedMessage;
|
||||
}
|
||||
|
||||
public override Object Message
|
||||
{
|
||||
get { return _encryptedMessage; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SslHandler : IDisposable
|
||||
{
|
||||
static readonly ILog log = LogManager.GetLogger(typeof(CustomSslFilter));
|
||||
|
||||
private readonly CustomSslFilter _sslFilter;
|
||||
private readonly IoSession _session;
|
||||
private readonly IoSessionStream _sessionStream;
|
||||
private readonly SslStream _sslStream;
|
||||
private volatile Boolean _authenticated;
|
||||
private readonly ConcurrentQueue<IoFilterEvent> _preHandshakeEventQueue = new ConcurrentQueue<IoFilterEvent>();
|
||||
private INextFilter _currentNextFilter;
|
||||
private IWriteRequest _currentWriteRequest;
|
||||
|
||||
public SslHandler(CustomSslFilter sslFilter, IoSession session)
|
||||
{
|
||||
_sslFilter = sslFilter;
|
||||
_session = session;
|
||||
_sessionStream = new IoSessionStream(this);
|
||||
_sslStream = new SslStream(_sessionStream, false);
|
||||
}
|
||||
|
||||
public CustomSslFilter SslFilter
|
||||
{
|
||||
get { return _sslFilter; }
|
||||
}
|
||||
|
||||
public Boolean Authenticated
|
||||
{
|
||||
get { return _authenticated; }
|
||||
private set
|
||||
{
|
||||
_authenticated = value;
|
||||
if (value)
|
||||
FlushPreHandshakeEvents();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_sessionStream.Dispose();
|
||||
_sslStream.Dispose();
|
||||
}
|
||||
|
||||
public void Handshake(INextFilter nextFilter)
|
||||
{
|
||||
//lock (_sessionStream)
|
||||
//{
|
||||
_currentNextFilter = nextFilter;
|
||||
_sslStream.BeginAuthenticateAsClient("auth.east.ea.com", null, _sslFilter.SslProtocol, false, AuthenticateCallback, null);
|
||||
//}
|
||||
}
|
||||
|
||||
private void AuthenticateCallback(IAsyncResult ar)
|
||||
{
|
||||
try
|
||||
{
|
||||
_sslStream.EndAuthenticateAsClient(ar);
|
||||
}
|
||||
catch (AuthenticationException e)
|
||||
{
|
||||
_sslFilter.ExceptionCaught(_currentNextFilter, _session, e);
|
||||
return;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_sslFilter.ExceptionCaught(_currentNextFilter, _session, e);
|
||||
return;
|
||||
}
|
||||
|
||||
Authenticated = true;
|
||||
|
||||
if (log.IsDebugEnabled)
|
||||
{
|
||||
// Display the properties and settings for the authenticated stream.
|
||||
CustomSslFilter.DisplaySecurityLevel(_sslStream);
|
||||
CustomSslFilter.DisplaySecurityServices(_sslStream);
|
||||
CustomSslFilter.DisplayCertificateInformation(_sslStream);
|
||||
CustomSslFilter.DisplayStreamProperties(_sslStream);
|
||||
}
|
||||
}
|
||||
|
||||
public void ScheduleFilterWrite(INextFilter nextFilter, IWriteRequest writeRequest)
|
||||
{
|
||||
|
||||
if (!_authenticated)
|
||||
{
|
||||
if (_session.Connected)
|
||||
{
|
||||
// Handshake not complete yet.
|
||||
_preHandshakeEventQueue.Enqueue(new IoFilterEvent(nextFilter, IoEventType.Write, _session, writeRequest));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
IoBuffer buf = (IoBuffer)writeRequest.Message;
|
||||
if (buf.Remaining == 0) { return; }
|
||||
|
||||
//lock (_sessionStream)
|
||||
//{
|
||||
ArraySegment<Byte> array = buf.GetRemaining();
|
||||
_currentNextFilter = nextFilter;
|
||||
_currentWriteRequest = writeRequest;
|
||||
// SSL encrypt
|
||||
_sslStream.Write(array.Array, array.Offset, array.Count);
|
||||
_sslStream.Flush();
|
||||
//}
|
||||
}
|
||||
|
||||
public void MessageReceived(INextFilter nextFilter, IoBuffer buf)
|
||||
{
|
||||
//lock (_sessionStream)
|
||||
//{
|
||||
_currentNextFilter = nextFilter;
|
||||
_sessionStream.Write(buf);
|
||||
if (_authenticated)
|
||||
{
|
||||
IoBuffer readBuffer = ReadBuffer();
|
||||
nextFilter.MessageReceived(_session, readBuffer);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
{
|
||||
_sslStream.Close();
|
||||
IoFilterEvent scheduledWrite;
|
||||
while (_preHandshakeEventQueue.TryDequeue(out scheduledWrite))
|
||||
{ }
|
||||
}
|
||||
|
||||
private void FlushPreHandshakeEvents()
|
||||
{
|
||||
lock (_sessionStream)
|
||||
{
|
||||
IoFilterEvent scheduledWrite;
|
||||
while (_preHandshakeEventQueue.TryDequeue(out scheduledWrite))
|
||||
{
|
||||
_sslFilter.FilterWrite(scheduledWrite.NextFilter, scheduledWrite.Session, (IWriteRequest)scheduledWrite.Parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteBuffer(IoBuffer buf)
|
||||
{
|
||||
IWriteRequest writeRequest;
|
||||
if (_authenticated)
|
||||
writeRequest = new CustomSslFilter.EncryptedWriteRequest(_currentWriteRequest, buf);
|
||||
else
|
||||
writeRequest = new DefaultWriteRequest(buf);
|
||||
_currentNextFilter.FilterWrite(_session, writeRequest);
|
||||
}
|
||||
|
||||
private IoBuffer ReadBuffer()
|
||||
{
|
||||
IoBuffer buf = IoBuffer.Allocate(_sessionStream.Remaining);
|
||||
|
||||
while (true)
|
||||
{
|
||||
ArraySegment<Byte> array = buf.GetRemaining();
|
||||
Int32 bytesRead = _sslStream.Read(array.Array, array.Offset, array.Count);
|
||||
if (bytesRead <= 0)
|
||||
break;
|
||||
buf.Position += bytesRead;
|
||||
|
||||
if (_sessionStream.Remaining == 0)
|
||||
break;
|
||||
else
|
||||
{
|
||||
// We have to grow the target buffer, it's too small.
|
||||
buf.Capacity += _sessionStream.Remaining;
|
||||
buf.Limit = buf.Capacity;
|
||||
}
|
||||
}
|
||||
|
||||
buf.Flip();
|
||||
return buf;
|
||||
}
|
||||
|
||||
class IoSessionStream : System.IO.Stream
|
||||
{
|
||||
readonly Object _syncRoot = new Byte[0];
|
||||
readonly SslHandler _sslHandler;
|
||||
readonly IoBuffer _buf;
|
||||
volatile Boolean _closed;
|
||||
volatile Boolean _released;
|
||||
IOException _exception;
|
||||
|
||||
public IoSessionStream(SslHandler sslHandler)
|
||||
{
|
||||
_sslHandler = sslHandler;
|
||||
_buf = IoBuffer.Allocate(16);
|
||||
_buf.AutoExpand = true;
|
||||
_buf.Limit = 0;
|
||||
}
|
||||
|
||||
public override Int32 ReadByte()
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (!WaitForData())
|
||||
return 0;
|
||||
return _buf.Get() & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
public override Int32 Read(Byte[] buffer, Int32 offset, Int32 count)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (!WaitForData())
|
||||
return 0;
|
||||
|
||||
Int32 readBytes = Math.Min(count, _buf.Remaining);
|
||||
_buf.Get(buffer, offset, readBytes);
|
||||
return readBytes;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
base.Close();
|
||||
|
||||
if (_closed)
|
||||
return;
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_closed = true;
|
||||
ReleaseBuffer();
|
||||
Monitor.PulseAll(_syncRoot);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(Byte[] buffer, Int32 offset, Int32 count)
|
||||
{
|
||||
_sslHandler.WriteBuffer(IoBuffer.Wrap((Byte[])buffer.Clone(), offset, count));
|
||||
}
|
||||
|
||||
public override void WriteByte(Byte value)
|
||||
{
|
||||
IoBuffer buf = IoBuffer.Allocate(1);
|
||||
buf.Put(value);
|
||||
buf.Flip();
|
||||
_sslHandler.WriteBuffer(buf);
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{ }
|
||||
|
||||
public void Write(IoBuffer buf)
|
||||
{
|
||||
if (_closed)
|
||||
return;
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (_buf.HasRemaining)
|
||||
{
|
||||
_buf.Compact().Put(buf).Flip();
|
||||
}
|
||||
else
|
||||
{
|
||||
_buf.Clear().Put(buf).Flip();
|
||||
Monitor.PulseAll(_syncRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean WaitForData()
|
||||
{
|
||||
if (_released)
|
||||
return false;
|
||||
|
||||
lock (_syncRoot)
|
||||
{
|
||||
while (!_released && _buf.Remaining == 0 && _exception == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Monitor.Wait(_syncRoot);
|
||||
}
|
||||
catch (ThreadInterruptedException e)
|
||||
{
|
||||
throw new IOException("Interrupted while waiting for more data", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_exception != null)
|
||||
{
|
||||
ReleaseBuffer();
|
||||
throw _exception;
|
||||
}
|
||||
|
||||
if (_closed && _buf.Remaining == 0)
|
||||
{
|
||||
ReleaseBuffer();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ReleaseBuffer()
|
||||
{
|
||||
if (_released)
|
||||
return;
|
||||
_released = true;
|
||||
}
|
||||
|
||||
public IOException Exception
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_exception == null)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
_exception = value;
|
||||
Monitor.PulseAll(_syncRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Int32 Remaining
|
||||
{
|
||||
get { return _buf.Remaining; }
|
||||
}
|
||||
|
||||
public override Boolean CanRead
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override Boolean CanSeek
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public override Boolean CanWrite
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public override Int64 Length
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override Int64 Position
|
||||
{
|
||||
get { throw new NotSupportedException(); }
|
||||
set { throw new NotSupportedException(); }
|
||||
}
|
||||
|
||||
public override Int64 Seek(Int64 offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(Int64 value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
33
server/FSO.Server.Protocol/Voltron/AbstractVoltronPacket.cs
Executable file
33
server/FSO.Server.Protocol/Voltron/AbstractVoltronPacket.cs
Executable file
|
@ -0,0 +1,33 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Server.Protocol.Voltron.Model;
|
||||
using Mina.Core.Buffer;
|
||||
|
||||
namespace FSO.Server.Protocol.Voltron
|
||||
{
|
||||
public abstract class AbstractVoltronPacket : IVoltronPacket
|
||||
{
|
||||
public static Sender GetSender(IoBuffer buffer)
|
||||
{
|
||||
var ariesID = buffer.GetPascalString();
|
||||
var masterID = buffer.GetPascalString();
|
||||
return new Sender { AriesID = ariesID, MasterAccountID = masterID };
|
||||
}
|
||||
|
||||
public static void PutSender(IoBuffer buffer, Sender sender)
|
||||
{
|
||||
buffer.PutPascalString(sender.AriesID);
|
||||
buffer.PutPascalString(sender.MasterAccountID);
|
||||
}
|
||||
|
||||
public static IoBuffer Allocate(int size)
|
||||
{
|
||||
IoBuffer buffer = IoBuffer.Allocate(size);
|
||||
buffer.Order = ByteOrder.BigEndian;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public abstract VoltronPacketType GetPacketType();
|
||||
public abstract void Serialize(IoBuffer output, ISerializationContext context);
|
||||
public abstract void Deserialize(IoBuffer input, ISerializationContext context);
|
||||
}
|
||||
}
|
20
server/FSO.Server.Protocol/Voltron/DataService/Avatar.cs
Executable file
20
server/FSO.Server.Protocol/Voltron/DataService/Avatar.cs
Executable file
|
@ -0,0 +1,20 @@
|
|||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
public class Avatar
|
||||
{
|
||||
public bool Avatar_IsFounder { get; set; }
|
||||
public string Avatar_Name { get; set; }
|
||||
public string Avatar_Description { get; set; }
|
||||
public bool Avatar_IsParentalControlLocked { get; set; }
|
||||
|
||||
/*public bool Avatar_IsOnline { get; set; }
|
||||
public uint Avatar_LotGridXY { get; set; }
|
||||
public uint Avatar_Age { get; set; }
|
||||
public ushort Avatar_SkillsLockPoints { get; set; }
|
||||
|
||||
public AvatarAppearance Avatar_Appearance { get; set; }
|
||||
public AvatarSkills Avatar_Skills { get; set; }
|
||||
|
||||
public List<Bookmark> Avatar_BookmarksVec { get; set; }*/
|
||||
}
|
||||
}
|
9
server/FSO.Server.Protocol/Voltron/DataService/AvatarAppearance.cs
Executable file
9
server/FSO.Server.Protocol/Voltron/DataService/AvatarAppearance.cs
Executable file
|
@ -0,0 +1,9 @@
|
|||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
public class AvatarAppearance
|
||||
{
|
||||
public ulong AvatarAppearance_BodyOutfitID { get; set; }
|
||||
public byte AvatarAppearance_SkinTone { get; set; }
|
||||
public ulong AvatarAppearance_HeadOutfitID { get; set; }
|
||||
}
|
||||
}
|
18
server/FSO.Server.Protocol/Voltron/DataService/AvatarSkills.cs
Executable file
18
server/FSO.Server.Protocol/Voltron/DataService/AvatarSkills.cs
Executable file
|
@ -0,0 +1,18 @@
|
|||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
public class AvatarSkills
|
||||
{
|
||||
public ushort AvatarSkills_Logic { get; set; }
|
||||
public ushort AvatarSkills_LockLv_Logic { get; set; }
|
||||
public ushort AvatarSkills_Body { get; set; }
|
||||
public ushort AvatarSkills_LockLv_Body { get; set; }
|
||||
public ushort AvatarSkills_LockLv_Mechanical { get; set; }
|
||||
public ushort AvatarSkills_LockLv_Creativity { get; set; }
|
||||
public ushort AvatarSkills_LockLv_Cooking { get; set; }
|
||||
public ushort AvatarSkills_Cooking { get; set; }
|
||||
public ushort AvatarSkills_Charisma { get; set; }
|
||||
public ushort AvatarSkills_LockLv_Charisma { get; set; }
|
||||
public ushort AvatarSkills_Mechanical { get; set; }
|
||||
public ushort AvatarSkills_Creativity { get; set; }
|
||||
}
|
||||
}
|
13
server/FSO.Server.Protocol/Voltron/DataService/Bookmark.cs
Executable file
13
server/FSO.Server.Protocol/Voltron/DataService/Bookmark.cs
Executable file
|
@ -0,0 +1,13 @@
|
|||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
public class Bookmark
|
||||
{
|
||||
public uint Bookmark_TargetID { get; set; }
|
||||
public BookmarkType Bookmark_Type { get; set; }
|
||||
}
|
||||
|
||||
public enum BookmarkType : byte
|
||||
{
|
||||
BOOKMARK = 0x01
|
||||
}
|
||||
}
|
6
server/FSO.Server.Protocol/Voltron/DataService/Location.cs
Executable file
6
server/FSO.Server.Protocol/Voltron/DataService/Location.cs
Executable file
|
@ -0,0 +1,6 @@
|
|||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
public class Location
|
||||
{
|
||||
}
|
||||
}
|
7
server/FSO.Server.Protocol/Voltron/DataService/Lot.cs
Executable file
7
server/FSO.Server.Protocol/Voltron/DataService/Lot.cs
Executable file
|
@ -0,0 +1,7 @@
|
|||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
public class Lot
|
||||
{
|
||||
|
||||
}
|
||||
}
|
41
server/FSO.Server.Protocol/Voltron/DataService/cITSOProperty.cs
Executable file
41
server/FSO.Server.Protocol/Voltron/DataService/cITSOProperty.cs
Executable file
|
@ -0,0 +1,41 @@
|
|||
using System.Collections.Generic;
|
||||
using Mina.Core.Buffer;
|
||||
using FSO.Common.Serialization;
|
||||
|
||||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
public class cITSOProperty : IoBufferSerializable
|
||||
{
|
||||
public uint StructType;
|
||||
public List<cITSOField> StructFields;
|
||||
|
||||
/**cTSOValue<class cRZAutoRefCount<class cITSOProperty> > body:
|
||||
* dword Body clsid (iid=896E3E90 or "GZIID_cITSOProperty"; clsid should be 0x89739A79 for cTSOProperty)
|
||||
* dword Body
|
||||
* dword Struct type (e.g. 0x3B0430BF for AvatarAppearance)
|
||||
* dword Field count
|
||||
* Fields - for each field:
|
||||
* dword Field name (e.g. 0x1D530275 for AvatarAppearance_BodyOutfitID)
|
||||
* dword cTSOValue clsid
|
||||
* cTSOValue body**/
|
||||
|
||||
public void Serialize(IoBuffer output, ISerializationContext context)
|
||||
{
|
||||
output.PutUInt32(0x89739A79);
|
||||
output.PutUInt32(StructType);
|
||||
output.PutUInt32((uint)StructFields.Count);
|
||||
|
||||
foreach(var item in StructFields){
|
||||
output.PutUInt32(item.ID);
|
||||
output.PutUInt32(item.Value.Type);
|
||||
output.PutSerializable(item.Value.Value, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class cITSOField
|
||||
{
|
||||
public uint ID;
|
||||
public cTSOValue Value;
|
||||
}
|
||||
}
|
398
server/FSO.Server.Protocol/Voltron/DataService/cTSOSerializer.cs
Executable file
398
server/FSO.Server.Protocol/Voltron/DataService/cTSOSerializer.cs
Executable file
|
@ -0,0 +1,398 @@
|
|||
using FSO.Common.Serialization;
|
||||
using FSO.Files.Formats.tsodata;
|
||||
using Mina.Core.Buffer;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO: Rewrite this to have much tighter performance
|
||||
/// </summary>
|
||||
public class cTSOSerializer
|
||||
{
|
||||
|
||||
//private static Logger LOG = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public static cTSOSerializer INSTANCE = null;
|
||||
public static cTSOSerializer Get(){
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
public const uint cTSOValue_bool = 0x696D1183;
|
||||
public const uint cTSOValue_uint8 = 0xC976087C;
|
||||
public const uint cTSOValue_uint16 = 0xE9760891;
|
||||
public const uint cTSOValue_uint32 = 0x696D1189;
|
||||
public const uint cTSOValue_uint64 = 0x69D3E3DB;
|
||||
public const uint cTSOValue_sint8 = 0xE976088A;
|
||||
public const uint cTSOValue_sint16 = 0xE9760897;
|
||||
public const uint cTSOValue_sint32 = 0x896D1196;
|
||||
public const uint cTSOValue_sint64 = 0x89D3E3EF;
|
||||
public const uint cTSOValue_string = 0x896D1688;
|
||||
public const uint cTSOValue_property = 0xA96E7E5B;
|
||||
|
||||
private TSODataDefinition Format;
|
||||
private Dictionary<uint, Type> ClassesById = new Dictionary<uint, Type>();
|
||||
private Dictionary<Type, uint> IdByClass = new Dictionary<Type, uint>();
|
||||
|
||||
private Dictionary<uint, Type> cNetMessageParametersById = new Dictionary<uint, Type>();
|
||||
|
||||
|
||||
public cTSOSerializer(TSODataDefinition data){
|
||||
INSTANCE = this;
|
||||
|
||||
this.Format = data;
|
||||
|
||||
//Scan for classes with decorations
|
||||
var assembly = Assembly.GetAssembly(typeof(cTSOSerializer));
|
||||
|
||||
foreach (Type type in assembly.GetTypes())
|
||||
{
|
||||
System.Attribute[] attributes = System.Attribute.GetCustomAttributes(type);
|
||||
|
||||
foreach (Attribute attribute in attributes)
|
||||
{
|
||||
if (attribute is clsid){
|
||||
ClassesById.Add(((clsid)attribute).Value, type);
|
||||
IdByClass.Add(type, ((clsid)attribute).Value);
|
||||
}else if(attribute is cTSONetMessageParameter)
|
||||
{
|
||||
var param = (cTSONetMessageParameter)attribute;
|
||||
object paramValue = param.Value;
|
||||
|
||||
/*if(paramValue is DBRequestType){
|
||||
paramValue = ((DBRequestType)paramValue).GetRequestID();
|
||||
}else if(paramValue is DBResponseType)
|
||||
{
|
||||
paramValue = ((DBResponseType)paramValue).GetResponseID();
|
||||
}*/
|
||||
cNetMessageParametersById.Add((uint)paramValue, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public object Deserialize(uint clsid, IoBuffer buffer)
|
||||
{
|
||||
if (cNetMessageParametersById.ContainsKey(clsid))
|
||||
{
|
||||
var instance = (IoBufferDeserializable)Activator.CreateInstance(cNetMessageParametersById[clsid]);
|
||||
//instance.Deserialize(buffer);
|
||||
return instance;
|
||||
}
|
||||
else if (ClassesById.ContainsKey(clsid))
|
||||
{
|
||||
var instance = (IoBufferDeserializable)Activator.CreateInstance(ClassesById[clsid]);
|
||||
//instance.Deserialize(buffer);
|
||||
return instance;
|
||||
}
|
||||
else if(clsid == cTSOValue_string)
|
||||
{
|
||||
return buffer.GetPascalVLCString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public object Serialize(object obj)
|
||||
{
|
||||
if(obj is IoBufferSerializable)
|
||||
{
|
||||
return (IoBufferSerializable)obj;
|
||||
}
|
||||
return GetValue(obj).Value;
|
||||
}
|
||||
|
||||
public cTSOValue GetValue(object obj){
|
||||
var type = obj.GetType();
|
||||
if (IdByClass.ContainsKey(type))
|
||||
{
|
||||
uint clsid = IdByClass[type];
|
||||
return new cTSOValue() { Type = clsid, Value = obj };
|
||||
}
|
||||
|
||||
throw new Exception("Unknown class " + type);
|
||||
}
|
||||
|
||||
public DerivedStruct GetDerivedStruct(uint id)
|
||||
{
|
||||
return Format.DerivedStructs.FirstOrDefault(x => x.ID == id);
|
||||
}
|
||||
|
||||
public DerivedStruct GetDerivedStruct(string name)
|
||||
{
|
||||
return Format.DerivedStructs.FirstOrDefault(x => x.Name == name);
|
||||
}
|
||||
|
||||
/*public List<DataServiceWrapperPDU> SerializeDerivedUpdate(uint avatarId, string derivedTypeName, uint structId, object instance)
|
||||
{
|
||||
var type = GetDerivedStruct(derivedTypeName);
|
||||
|
||||
var fields = SerializeDerived(derivedTypeName, structId, instance);
|
||||
var result = new List<DataServiceWrapperPDU>();
|
||||
|
||||
foreach(var update in fields){
|
||||
result.Add(new DataServiceWrapperPDU() {
|
||||
SendingAvatarID = avatarId,
|
||||
RequestTypeID = 0x3998426C,
|
||||
Body = update
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}*/
|
||||
|
||||
/*
|
||||
public List<cTSOTopicUpdateMessage> SerializeDerived(string derivedTypeName, uint structId, object instance)
|
||||
{
|
||||
return SerializeDerived(GetDerivedStruct(derivedTypeName).ID, structId, instance);
|
||||
}
|
||||
|
||||
public List<cTSOTopicUpdateMessage> SerializeDerived(uint derivedType, uint structId, object instance){
|
||||
var result = new List<cTSOTopicUpdateMessage>();
|
||||
var type = Format.DerivedStructs.First(x => x.ID == derivedType);
|
||||
var parent = Format.Structs.First(x => x.ID == type.Parent);
|
||||
|
||||
foreach(var field in parent.Fields){
|
||||
var mask = type.FieldMasks.FirstOrDefault(x => x.ID == field.ID);
|
||||
var action = DerivedStructFieldMaskType.KEEP;
|
||||
if (mask != null){
|
||||
action = mask.Type;
|
||||
}
|
||||
|
||||
if(action == DerivedStructFieldMaskType.REMOVE){
|
||||
continue;
|
||||
}
|
||||
|
||||
object value = GetFieldValue(instance, field.Name);
|
||||
if (value == null) { continue; }
|
||||
|
||||
try {
|
||||
var serialized = SerializeField(field, value);
|
||||
serialized.StructType = parent.ID;
|
||||
serialized.StructId = structId;
|
||||
result.Add(serialized);
|
||||
}catch(Exception ex)
|
||||
{
|
||||
LOG.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}*/
|
||||
|
||||
private object GetFieldValue(object obj, string fieldName)
|
||||
{
|
||||
var objectField = obj.GetType().GetProperty(fieldName);
|
||||
if (objectField == null) { return null; }
|
||||
|
||||
var value = objectField.GetValue(obj);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*private cTSOTopicUpdateMessage SerializeField(StructField field, object value){
|
||||
cTSOTopicUpdateMessage result = new cTSOTopicUpdateMessage();
|
||||
result.StructField = field.ID;
|
||||
|
||||
if(field.Classification == StructFieldClassification.List)
|
||||
{
|
||||
IoBuffer resultBytes = AbstractVoltronPacket.Allocate(4);
|
||||
resultBytes.AutoExpand = true;
|
||||
var serializedValues = new List<cTSOValue>();
|
||||
System.Collections.ICollection list = (System.Collections.ICollection)value;
|
||||
|
||||
foreach (var item in list){
|
||||
serializedValues.Add(SerializeValue(field.TypeID, item));
|
||||
}
|
||||
|
||||
var itemType = serializedValues.First().Type;
|
||||
var vectorType = GetVectorClsId(itemType);
|
||||
|
||||
resultBytes.PutUInt32((uint)serializedValues.Count);
|
||||
|
||||
foreach (var serializedValue in serializedValues){
|
||||
//resultBytes.PutSerializable(serializedValue.Value);
|
||||
}
|
||||
|
||||
resultBytes.Flip();
|
||||
|
||||
/*result.cTSOValue = new cTSOValue {
|
||||
Type = 0xA97384A3,//field.TypeID,
|
||||
Value = resultBytes
|
||||
};
|
||||
|
||||
}else if(field.Classification == StructFieldClassification.SingleField)
|
||||
{
|
||||
var serializedValue = SerializeValue(field.TypeID, value);
|
||||
//result.cTSOValue = serializedValue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}*/
|
||||
|
||||
private uint GetVectorClsId(uint clsid)
|
||||
{
|
||||
switch (clsid)
|
||||
{
|
||||
//cTSOValue < unsigned long>
|
||||
case 0x696D1189:
|
||||
//cTSOValueVector < unsigned long>
|
||||
return 0x89738496;
|
||||
//cTSOValue < long >
|
||||
case 0x896D1196:
|
||||
//cTSOValueVector < long >
|
||||
return 0x8973849A;
|
||||
//cTSOValue < unsigned short>
|
||||
case 0xE9760891:
|
||||
//cTSOValueVector < unsigned short>
|
||||
return 0x097608B3;
|
||||
//cTSOValue < short >
|
||||
case 0xE9760897:
|
||||
//cTSOValueVector < short >
|
||||
return 0x097608B6;
|
||||
//cTSOValue<class cRZAutoRefCount<class cITSOProperty> >
|
||||
case 0xA96E7E5B:
|
||||
//cTSOValueVector<class cRZAutoRefCount<class cITSOProperty> >
|
||||
return 0xA97384A3;
|
||||
//cTSOValue <class cRZAutoRefCount<class cIGZString> >
|
||||
default:
|
||||
throw new Exception("Cannot map clsid to vector clsid, " + clsid);
|
||||
}
|
||||
}
|
||||
|
||||
private cTSOValue SerializeValue(uint type, object value)
|
||||
{
|
||||
var result = new cTSOValue();
|
||||
IoBuffer buffer = null;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 0x48BC841E:
|
||||
if (!(value is sbyte) && !(value is Enum))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
result.Type = cTSOValue_sint8;
|
||||
result.Value = new sbyte[] { Convert.ToSByte(value) };
|
||||
break;
|
||||
|
||||
case 0x74336731:
|
||||
if (!(value is ushort))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer = AbstractVoltronPacket.Allocate(2);
|
||||
buffer.PutUInt16((ushort)value);
|
||||
buffer.Flip();
|
||||
|
||||
result.Type = cTSOValue_uint16;
|
||||
result.Value = buffer;
|
||||
break;
|
||||
|
||||
case 0xF192ECA6:
|
||||
if (!(value is short))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer = AbstractVoltronPacket.Allocate(2);
|
||||
buffer.PutInt16((short)value);
|
||||
buffer.Flip();
|
||||
|
||||
result.Type = cTSOValue_sint16;
|
||||
result.Value = buffer;
|
||||
break;
|
||||
|
||||
case 0xE0463A2F:
|
||||
if (!(value is uint))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer = AbstractVoltronPacket.Allocate(4);
|
||||
buffer.PutUInt32((uint)value);
|
||||
buffer.Flip();
|
||||
|
||||
result.Type = cTSOValue_uint32;
|
||||
result.Value = buffer;
|
||||
break;
|
||||
|
||||
case 0xA0587098:
|
||||
if (!(value is int))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer = AbstractVoltronPacket.Allocate(4);
|
||||
buffer.PutInt32((int)value);
|
||||
buffer.Flip();
|
||||
|
||||
result.Type = cTSOValue_sint32;
|
||||
result.Value = buffer;
|
||||
break;
|
||||
|
||||
case 0x385070C9:
|
||||
if (!(value is ulong))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer = AbstractVoltronPacket.Allocate(8);
|
||||
buffer.PutUInt64((ulong)value);
|
||||
buffer.Flip();
|
||||
|
||||
result.Type = cTSOValue_uint64;
|
||||
result.Value = buffer;
|
||||
break;
|
||||
|
||||
case 0x90D315F7:
|
||||
if (!(value is long))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
buffer = AbstractVoltronPacket.Allocate(8);
|
||||
buffer.PutInt64((long)value);
|
||||
buffer.Flip();
|
||||
|
||||
result.Type = cTSOValue_sint64;
|
||||
result.Value = buffer;
|
||||
break;
|
||||
|
||||
default:
|
||||
//It may be a struct
|
||||
var _struct = Format.Structs.FirstOrDefault(x => x.ID == type);
|
||||
if (_struct != null)
|
||||
{
|
||||
var body = new cITSOProperty();
|
||||
body.StructType = _struct.ID;
|
||||
body.StructFields = new List<cITSOField>();
|
||||
|
||||
foreach(var field in _struct.Fields){
|
||||
object fieldValue = GetFieldValue(value, field.Name);
|
||||
if (fieldValue == null) { continue; }
|
||||
|
||||
body.StructFields.Add(new cITSOField {
|
||||
ID = field.ID,
|
||||
Value = SerializeValue(field.TypeID, fieldValue)
|
||||
});
|
||||
}
|
||||
|
||||
result.Type = cTSOValue_property;
|
||||
result.Value = body;
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
8
server/FSO.Server.Protocol/Voltron/DataService/cTSOValue.cs
Executable file
8
server/FSO.Server.Protocol/Voltron/DataService/cTSOValue.cs
Executable file
|
@ -0,0 +1,8 @@
|
|||
namespace FSO.Server.Protocol.Voltron.DataService
|
||||
{
|
||||
public class cTSOValue
|
||||
{
|
||||
public uint Type { get; set; }
|
||||
public object Value { get; set; }
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue