Server now processes session ids and stores the correct logged in user in the clientconnection object. Reserve character now creates a entry in the db.

This commit is contained in:
Filip Maj 2015-08-27 10:19:00 -04:00
parent c1e214175f
commit f996f727dc
7 changed files with 152 additions and 71 deletions

View File

@ -24,7 +24,7 @@ namespace FFXIVClassic_Lobby_Server
public BlockingCollection<BasePacket> sendPacketQueue = new BlockingCollection<BasePacket>(100); public BlockingCollection<BasePacket> sendPacketQueue = new BlockingCollection<BasePacket>(100);
//Instance Stuff //Instance Stuff
public uint currentSession; public uint currentUserId = 0;
public uint currentAccount; public uint currentAccount;
@ -43,6 +43,9 @@ namespace FFXIVClassic_Lobby_Server
public void flushQueuedSendPackets() public void flushQueuedSendPackets()
{ {
if (!socket.Connected)
return;
while (sendPacketQueue.Count > 0) while (sendPacketQueue.Count > 0)
{ {
BasePacket packet = sendPacketQueue.Take(); BasePacket packet = sendPacketQueue.Take();
@ -55,8 +58,6 @@ namespace FFXIVClassic_Lobby_Server
catch(Exception e) catch(Exception e)
{ Debug.WriteLine("Weird case, socket was d/ced: {0}", e); } { Debug.WriteLine("Weird case, socket was d/ced: {0}", e); }
} }
} }
public String getAddress() public String getAddress()

View File

@ -13,22 +13,66 @@ namespace FFXIVClassic_Lobby_Server
class Database class Database
{ {
public static void reserveCharacter(int accountId, int slot, int serverId, String name) public static uint getUserIdFromSession(String sessionId)
{ {
uint id = 0;
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
{ {
try try
{ {
conn.Open(); conn.Open();
MySqlCommand cmd = new MySqlCommand(); MySqlCommand cmd = new MySqlCommand("SELECT * FROM ffxiv_sessions WHERE id = @sessionId AND expiration > NOW()", conn);
cmd.Connection = conn; cmd.Parameters.AddWithValue("@sessionId", sessionId);
cmd.CommandText = "INSERT INTO ffxiv_characters2(accountId, slot, serverId, name, charState) VALUES(@accountId, @slot, @serverId, @name, 0)"; using (MySqlDataReader Reader = cmd.ExecuteReader())
cmd.Prepare(); {
cmd.Parameters.AddWithValue("@accountId", accountId); while (Reader.Read())
cmd.Parameters.AddWithValue("@slot", slot); {
id = Reader.GetUInt32("userId");
}
}
}
catch (MySqlException e)
{ Console.WriteLine(e); }
finally
{
conn.Close();
}
}
return id;
}
public static bool reserveCharacter(uint userId, uint slot, uint serverId, String name)
{
bool alreadyExists = false;
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
{
try
{
conn.Open();
//Check if exists
MySqlCommand cmd = new MySqlCommand("SELECT * FROM ffxiv_characters2 WHERE name=@name AND serverId=@serverId", conn);
cmd.Parameters.AddWithValue("@serverId", serverId); cmd.Parameters.AddWithValue("@serverId", serverId);
cmd.Parameters.AddWithValue("@name", name); cmd.Parameters.AddWithValue("@name", name);
cmd.ExecuteNonQuery(); using (MySqlDataReader Reader = cmd.ExecuteReader())
{
if (Reader.HasRows)
alreadyExists = true;
}
//Reserve
if (!alreadyExists)
{
MySqlCommand cmd2 = new MySqlCommand();
cmd2.Connection = conn;
cmd2.CommandText = "INSERT INTO ffxiv_characters2(userId, slot, serverId, name, state) VALUES(@userId, @slot, @serverId, @name, 0)";
cmd2.Prepare();
cmd2.Parameters.AddWithValue("@userId", userId);
cmd2.Parameters.AddWithValue("@slot", slot);
cmd2.Parameters.AddWithValue("@serverId", serverId);
cmd2.Parameters.AddWithValue("@name", name);
cmd2.ExecuteNonQuery();
}
} }
catch (MySqlException e) catch (MySqlException e)
@ -40,9 +84,11 @@ namespace FFXIVClassic_Lobby_Server
conn.Close(); conn.Close();
} }
} }
return alreadyExists;
} }
public static void makeCharacter(int accountId, String name, Character charaInfo) public static void makeCharacter(uint accountId, String name, Character charaInfo)
{ {
using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD))) using (MySqlConnection conn = new MySqlConnection(String.Format("Server={0}; Port={1}; Database={2}; UID={3}; Password={4}", ConfigConstants.DATABASE_HOST, ConfigConstants.DATABASE_PORT, ConfigConstants.DATABASE_NAME, ConfigConstants.DATABASE_USERNAME, ConfigConstants.DATABASE_PASSWORD)))
{ {
@ -234,5 +280,6 @@ namespace FFXIVClassic_Lobby_Server
return world; return world;
} }
} }
} }
} }

View File

@ -40,6 +40,9 @@
<Reference Include="MySql.Data"> <Reference Include="MySql.Data">
<HintPath>..\packages\MySql.Data.6.9.7\lib\net45\MySql.Data.dll</HintPath> <HintPath>..\packages\MySql.Data.6.9.7\lib\net45\MySql.Data.dll</HintPath>
</Reference> </Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
@ -49,17 +52,18 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Character.cs" /> <Compile Include="dataobjects\Character.cs" />
<Compile Include="ClientConnection.cs" /> <Compile Include="ClientConnection.cs" />
<Compile Include="common\Blowfish.cs" /> <Compile Include="common\Blowfish.cs" />
<Compile Include="common\IniFile.cs" /> <Compile Include="common\IniFile.cs" />
<Compile Include="common\Utils.cs" /> <Compile Include="common\Utils.cs" />
<Compile Include="ConfigConstants.cs" /> <Compile Include="ConfigConstants.cs" />
<Compile Include="Database.cs" /> <Compile Include="Database.cs" />
<Compile Include="dataobjects\World.cs" />
<Compile Include="PacketProcessor.cs" /> <Compile Include="PacketProcessor.cs" />
<Compile Include="packets\BasePacket.cs" /> <Compile Include="packets\BasePacket.cs" />
<Compile Include="packets\CharacterRequestPacket.cs" />
<Compile Include="packets\HardCoded_Packets.cs" /> <Compile Include="packets\HardCoded_Packets.cs" />
<Compile Include="packets\PacketStructs.cs" />
<Compile Include="packets\SubPacket.cs" /> <Compile Include="packets\SubPacket.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

View File

@ -117,19 +117,24 @@ namespace FFXIVClassic_Lobby_Server
private void ProcessSessionAcknowledgement(ClientConnection client, SubPacket packet) private void ProcessSessionAcknowledgement(ClientConnection client, SubPacket packet)
{ {
//String sessionId = Utils.unsafeAsciiBytesToString(packet.data, 0x30); PacketStructs.SessionPacket sessionPacket = PacketStructs.toSessionStruct(packet.data);
//String clientVersion = Utils.unsafeAsciiBytesToString(packet.data, 0x70); String sessionId = sessionPacket.session;
String clientVersion = sessionPacket.version;
Debug.WriteLine("Got acknowledgment for secure session."); Console.WriteLine("Got acknowledgment for secure session.");
// Debug.WriteLine("SESSION_ID: {0}", sessionId); Console.WriteLine("SESSION ID: {0}", sessionId);
// Debug.WriteLine("CLIENT_VERSION: {0}", clientVersion); Console.WriteLine("CLIENT VERSION: {0}", clientVersion);
//Check if got MYSQL Conn uint userId = Database.getUserIdFromSession(sessionId);
client.currentUserId = userId;
if (userId == 0)
{
client.disconnect();
Console.WriteLine("Invalid session, kicking...");
}
//auto query = string_format("SELECT userId FROM ffxiv_sessions WHERE id = '%s' AND expiration > NOW()", sessionId.c_str()); Console.WriteLine("USER ID: {0}", userId);
//Console.WriteLine("UserId {0} logged in.", id);
BasePacket outgoingPacket = new BasePacket("./packets/loginAck.bin"); BasePacket outgoingPacket = new BasePacket("./packets/loginAck.bin");
BasePacket.encryptPacket(client.blowfish, outgoingPacket); BasePacket.encryptPacket(client.blowfish, outgoingPacket);
client.queuePacket(outgoingPacket); client.queuePacket(outgoingPacket);
@ -137,7 +142,7 @@ namespace FFXIVClassic_Lobby_Server
private void ProcessGetCharacters(ClientConnection client, SubPacket packet) private void ProcessGetCharacters(ClientConnection client, SubPacket packet)
{ {
Console.WriteLine("{0} => Get characters", client.getAddress()); Console.WriteLine("{0} => Get characters", client.currentUserId == 0 ? client.getAddress() : "User " + client.currentUserId);
BasePacket outgoingPacket = new BasePacket("./packets/getCharsPacket.bin"); BasePacket outgoingPacket = new BasePacket("./packets/getCharsPacket.bin");
BasePacket.encryptPacket(client.blowfish, outgoingPacket); BasePacket.encryptPacket(client.blowfish, outgoingPacket);
client.queuePacket(outgoingPacket); client.queuePacket(outgoingPacket);
@ -153,7 +158,7 @@ namespace FFXIVClassic_Lobby_Server
binReader.Close(); binReader.Close();
} }
Console.WriteLine("{0} => Select character id {1}", client.getAddress(), characterId); Console.WriteLine("{0} => Select character id {1}", client.currentUserId == 0 ? client.getAddress() : "User " + client.currentUserId, characterId);
String serverIp = "141.117.162.99"; String serverIp = "141.117.162.99";
ushort port = 54992; ushort port = 54992;
@ -180,7 +185,7 @@ namespace FFXIVClassic_Lobby_Server
{ {
packet.debugPrintSubPacket(); packet.debugPrintSubPacket();
CharacterRequestPacket.CharacterRequest charaReq = CharacterRequestPacket.toStruct(packet.data); PacketStructs.CharacterRequestPacket charaReq = PacketStructs.toCharacterRequestStruct(packet.data);
var slot = charaReq.slot; var slot = charaReq.slot;
var code = charaReq.command; var code = charaReq.command;
var name = charaReq.characterName; var name = charaReq.characterName;
@ -189,23 +194,26 @@ namespace FFXIVClassic_Lobby_Server
switch (code) switch (code)
{ {
case 0x01://Reserve case 0x01://Reserve
//Database.reserveCharacter(0, slot, worldId, name); var alreadyTaken = Database.reserveCharacter(client.currentUserId, slot, worldId, name);
if (alreadyTaken)
{ }
//Confirm Reserve //Confirm Reserve
BasePacket confirmReservePacket = new BasePacket("./packets/chara/confirmReserve.bin"); BasePacket confirmReservePacket = new BasePacket("./packets/chara/confirmReserve.bin");
BasePacket.encryptPacket(client.blowfish, confirmReservePacket); BasePacket.encryptPacket(client.blowfish, confirmReservePacket);
client.queuePacket(confirmReservePacket); client.queuePacket(confirmReservePacket);
Console.WriteLine("Reserving character \"{0}\"", charaReq.characterName); Console.WriteLine("User {0} => Reserving character \"{1}\"", client.currentUserId, charaReq.characterName);
break; break;
case 0x02://Make case 0x02://Make
Character character = Character.EncodedToCharacter(charaReq.characterInfoEncoded); Character character = Character.EncodedToCharacter(charaReq.characterInfoEncoded);
Database.makeCharacter(0, name, character); Database.makeCharacter(client.currentUserId, name, character);
//Confirm //Confirm
BasePacket confirmMakePacket = new BasePacket("./packets/chara/confirmMake.bin"); BasePacket confirmMakePacket = new BasePacket("./packets/chara/confirmMake.bin");
BasePacket.encryptPacket(client.blowfish, confirmMakePacket); BasePacket.encryptPacket(client.blowfish, confirmMakePacket);
client.queuePacket(confirmMakePacket); client.queuePacket(confirmMakePacket);
Console.WriteLine("Character created!"); Console.WriteLine("User {0} => Character created!", client.currentUserId);
break; break;
case 0x03://Rename case 0x03://Rename
break; break;
@ -216,7 +224,7 @@ namespace FFXIVClassic_Lobby_Server
BasePacket deleteConfirmPacket = new BasePacket("./packets/chara/confirmDelete.bin"); BasePacket deleteConfirmPacket = new BasePacket("./packets/chara/confirmDelete.bin");
BasePacket.encryptPacket(client.blowfish, deleteConfirmPacket); BasePacket.encryptPacket(client.blowfish, deleteConfirmPacket);
client.queuePacket(deleteConfirmPacket); client.queuePacket(deleteConfirmPacket);
Console.WriteLine("Character deleted \"{0}\"", charaReq.characterName); Console.WriteLine("User {0} => Character deleted \"{1}\"", client.currentUserId, charaReq.characterName);
break; break;
case 0x06://Rename Retainer case 0x06://Rename Retainer
break; break;

View File

@ -121,7 +121,7 @@ namespace FFXIVClassic_Lobby_Server
} }
else else
{ {
Console.WriteLine("Connection {0}:{1} has disconnected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port); Console.WriteLine("{0} has disconnected.", conn.currentUserId == 0 ? conn.getAddress() : "User " + conn.currentUserId);
conn.socket.Close(); conn.socket.Close();
lock (mConnectionList) lock (mConnectionList)
{ {
@ -133,7 +133,7 @@ namespace FFXIVClassic_Lobby_Server
{ {
if (conn.socket != null) if (conn.socket != null)
{ {
Console.WriteLine("Connection @ {0}:{1} has disconnected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port); Console.WriteLine("Connection @ {0}:{1} has disconnected.", conn.currentUserId == 0 ? conn.getAddress() : "User " + conn.currentUserId);
conn.socket.Close(); conn.socket.Close();
lock (mConnectionList) lock (mConnectionList)
{ {

View File

@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Lobby_Server.packets
{
class CharacterRequestPacket
{
[StructLayout(LayoutKind.Sequential)]
public unsafe struct CharacterRequest
{
public uint sequence;
public uint unknown;
public uint characterId;
public uint unknown2;
public byte slot;
public byte command;
public ushort worldId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public String characterName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x190)]
public String characterInfoEncoded;
}
public static unsafe CharacterRequest toStruct(byte[] bytes)
{
fixed (byte* pdata = &bytes[0])
{
return (CharacterRequest)Marshal.PtrToStructure(new IntPtr(pdata), typeof(CharacterRequest));
}
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace FFXIVClassic_Lobby_Server.packets
{
class PacketStructs
{
[StructLayout(LayoutKind.Explicit)]
public unsafe struct SessionPacket
{
[FieldOffset(0)]
public uint sequence;
[FieldOffset(0x50)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public String version;
[FieldOffset(0x70)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public String session;
}
[StructLayout(LayoutKind.Sequential)]
public unsafe struct CharacterRequestPacket
{
public uint sequence;
public uint unknown;
public uint characterId;
public uint unknown2;
public byte slot;
public byte command;
public ushort worldId;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public String characterName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x190)]
public String characterInfoEncoded;
}
public static unsafe CharacterRequestPacket toCharacterRequestStruct(byte[] bytes)
{
fixed (byte* pdata = &bytes[0])
{
return (CharacterRequestPacket)Marshal.PtrToStructure(new IntPtr(pdata), typeof(CharacterRequestPacket));
}
}
public static unsafe SessionPacket toSessionStruct(byte[] bytes)
{
fixed (byte* pdata = &bytes[0])
{
return (SessionPacket)Marshal.PtrToStructure(new IntPtr(pdata), typeof(SessionPacket));
}
}
}
}