More work on the world server.

This commit is contained in:
Filip Maj 2016-08-23 16:57:24 -04:00
parent e24a6f99cb
commit a1ca960543
7 changed files with 248 additions and 15 deletions

View File

@ -72,26 +72,38 @@ namespace FFXIVClassic.Common
offset += header.subpacketSize;
}
public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data)
public SubPacket(ushort opcode, uint sourceId, uint targetId, byte[] data) : this(true, opcode, sourceId, targetId, data) { }
public SubPacket(bool isGameMessage, ushort opcode, uint sourceId, uint targetId, byte[] data)
{
header = new SubPacketHeader();
if (isGameMessage)
{
gameMessage = new GameMessageHeader();
gameMessage.opcode = opcode;
header.sourceId = sourceId;
header.targetId = targetId;
gameMessage.timestamp = Utils.UnixTimeStampUTC();
header.type = 0x03;
header.unknown1 = 0x00;
gameMessage.unknown4 = 0x14;
gameMessage.unknown5 = 0x00;
gameMessage.unknown6 = 0x00;
}
header.sourceId = sourceId;
header.targetId = targetId;
if (isGameMessage)
header.type = 0x03;
else
header.type = opcode;
header.unknown1 = 0x00;
this.data = data;
header.subpacketSize = (ushort) (SUBPACKET_SIZE + GAMEMESSAGE_SIZE + data.Length);
header.subpacketSize = (ushort) (SUBPACKET_SIZE + data.Length);
if (isGameMessage)
header.subpacketSize += GAMEMESSAGE_SIZE;
}
public SubPacket(SubPacket original, uint newTargetId)

View File

@ -5,6 +5,7 @@ using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using FFXIVClassic.Common;
namespace FFXIVClassic_World_Server.DataObjects
{
@ -12,6 +13,7 @@ namespace FFXIVClassic_World_Server.DataObjects
{
public readonly string zoneServerIp;
public readonly int zoneServerPort;
public readonly int[] ownedZoneIds;
public bool isConnected = false;
public Socket zoneServerConnection;
@ -36,5 +38,21 @@ namespace FFXIVClassic_World_Server.DataObjects
catch (Exception e)
{ Program.Log.Error("Failed to connect"); return; }
}
public void SendPacket(SubPacket subpacket)
{
if (isConnected)
{
byte[] packetBytes = subpacket.GetBytes();
try
{
zoneServerConnection.Send(packetBytes);
}
catch (Exception e)
{ Program.Log.Error("Weird case, socket was d/ced: {0}", e); }
}
}
}
}

View File

@ -49,6 +49,10 @@
<HintPath>..\packages\NLog.4.3.5\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="RabbitMQ.Client, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89e7d7c5feba84ce, processorArchitecture=MSIL">
<HintPath>..\packages\RabbitMQ.Client.4.0.0\lib\net451\RabbitMQ.Client.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />

View File

@ -0,0 +1,133 @@
using FFXIVClassic.Common;
using FFXIVClassic_World_Server.Packets.Send.Login;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FFXIVClassic_World_Server
{
class PacketProcessor
{
/*
Session Creation:
Get 0x1 from server
Send 0x7
Send 0x2
Zone Change:
Send 0x7
Get 0x8 - Wait??
Send 0x2
*/
Server mServer;
List<ClientConnection> mConnections;
public PacketProcessor(Server server)
{
mServer = server;
}
public void ProcessPacket(ClientConnection client, BasePacket packet)
{
//if (packet.header.isCompressed == 0x01)
// BasePacket.DecryptPacket(client.blowfish, ref packet);
List<SubPacket> subPackets = packet.GetSubpackets();
foreach (SubPacket subpacket in subPackets)
{
//Initial Connect Packet, Create session
if (subpacket.header.type == 0x01)
{
packet.DebugPrintPacket();
byte[] reply1Data = {
0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFD, 0xFF, 0xFF,
0xE5, 0x6E, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x0
};
byte[] reply2Data = {
0x01, 0x00, 0x00, 0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x38, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2B, 0x5F, 0x26,
0x66, 0x00, 0x00, 0x00, 0xC8, 0xD6, 0xAF, 0x2B, 0x38, 0x2B, 0x5F, 0x26, 0xB8, 0x8D, 0xF0, 0x2B,
0xC8, 0xFD, 0x85, 0xFE, 0xA8, 0x7C, 0x5B, 0x09, 0x38, 0x2B, 0x5F, 0x26, 0xC8, 0xD6, 0xAF, 0x2B,
0xB8, 0x8D, 0xF0, 0x2B, 0x88, 0xAF, 0x5E, 0x26
};
BasePacket reply1 = new BasePacket(reply1Data);
BasePacket reply2 = new BasePacket(reply2Data);
//Write Timestamp into Reply1
using (MemoryStream mem = new MemoryStream(reply1.data))
{
using (BinaryWriter binReader = new BinaryWriter(mem))
{
binReader.BaseStream.Seek(0x14, SeekOrigin.Begin);
binReader.Write((UInt32)Utils.UnixTimeStampUTC());
}
}
//Read in Actor Id that owns this connection
uint actorID = 0;
using (MemoryStream mem = new MemoryStream(packet.data))
{
using (BinaryReader binReader = new BinaryReader(mem))
{
try
{
byte[] readIn = new byte[12];
binReader.BaseStream.Seek(0x14, SeekOrigin.Begin);
binReader.Read(readIn, 0, 12);
actorID = UInt32.Parse(Encoding.ASCII.GetString(readIn));
}
catch (Exception)
{ }
}
}
mServer.AddSession(actorID);
if (packet.header.connectionType == BasePacket.TYPE_ZONE)
Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "zone", actorID, client.GetAddress());
else if (packet.header.connectionType == BasePacket.TYPE_CHAT)
Program.Log.Info("Got {0} connection for ActorID {1} @ {2}.", "chat", actorID, client.GetAddress());
break;
}
//Ping from World Server
else if (subpacket.header.type == 0x07)
{
SubPacket init = Login0x7ResponsePacket.BuildPacket(0x50);
client.QueuePacket(BasePacket.CreatePacket(init, true, false));
}
//Zoning Related
else if (subpacket.header.type == 0x08)
{
//Response, client's current [actorID][time]
//BasePacket init = Login0x7ResponsePacket.BuildPacket(BitConverter.ToUInt32(packet.data, 0x10), Utils.UnixTimeStampUTC(), 0x07);
//client.QueuePacket(init);
packet.DebugPrintPacket();
}
//Game Message
else if (subpacket.header.type == 0x03)
{
//Send to the correct zone server
uint targetSession = subpacket.header.targetId;
if (mServer.GetSession(targetSession).routing1 != null)
mServer.GetSession(targetSession).routing1.SendPacket(subpacket);
if (mServer.GetSession(targetSession).routing2 != null)
mServer.GetSession(targetSession).routing2.SendPacket(subpacket);
}
else
packet.DebugPrintPacket();
}
}
}
}

View File

@ -0,0 +1,31 @@
using FFXIVClassic.Common;
using System;
using System.IO;
namespace FFXIVClassic_World_Server.Packets.Send.Login
{
class Login0x7ResponsePacket
{
public static SubPacket BuildPacket(uint actorID)
{
byte[] data = new byte[0x18];
using (MemoryStream mem = new MemoryStream(data))
{
using (BinaryWriter binWriter = new BinaryWriter(mem))
{
try
{
binWriter.Write((UInt32)actorID);
binWriter.Write((UInt32)type);
}
catch (Exception)
{
}
}
}
return BasePacket.CreatePacket(data, false, false);
}
}
}

View File

@ -21,7 +21,8 @@ namespace FFXIVClassic_World_Server
WorldManager worldManager;
private List<ClientConnection> mConnectionList = new List<ClientConnection>();
private Dictionary<uint, Session> mSessionList = new Dictionary<uint, Session>();
private Dictionary<uint, Session> mZoneSessionList = new Dictionary<uint, Session>();
private Dictionary<uint, Session> mChatSessionList = new Dictionary<uint, Session>();
public Server()
{
@ -122,6 +123,35 @@ namespace FFXIVClassic_World_Server
}
}
public void AddSession(uint id)
{
throw new NotImplementedException();
}
public void RemoveSession(uint id)
{
if (mChatSessionList.ContainsKey(id)) {
mChatSessionList[id].clientSocket.Disconnect();
mConnectionList.Remove(mChatSessionList[id].clientSocket);
mChatSessionList.Remove(id);
}
if (mZoneSessionList.ContainsKey(id))
{
mZoneSessionList[id].clientSocket.Disconnect();
mConnectionList.Remove(mZoneSessionList[id].clientSocket);
mZoneSessionList.Remove(id);
}
}
public Session GetSession(uint targetSession)
{
if (mZoneSessionList.ContainsKey(targetSession))
return mZoneSessionList[targetSession];
else
return null;
}
/// <summary>
/// Receive Callback. Reads in incoming data, converting them to base packets. Base packets are sent to be parsed. If not enough data at the end to build a basepacket, move to the beginning and prepend.
/// </summary>
@ -242,5 +272,10 @@ namespace FFXIVClassic_World_Server
#endregion
public WorldManager GetWorldManager()
{
return worldManager;
}
}
}

View File

@ -88,10 +88,10 @@ namespace FFXIVClassic_World_Server
public void DoZoneServerChange(Session session, uint zoneEntrance)
{
/*
->Tell old server to save session info and remove
->Tell old server to save session info and remove session. Start zone packets.
->Update the position to zoneEntrance
->Update routing
->Tell new server to load session info and add
->Tell new server to load session info and add session. Send end zone packets.
*/
}