Cleaned up namespaces (still have to do Map Project) and removed references to FFXIV Classic from the code. Removed the Launcher Editor project as it is no longer needed (host file editing is cleaner).

This commit is contained in:
Filip Maj 2019-06-19 00:05:18 -04:00
parent 7587a6e142
commit 0f61c4c0e1
544 changed files with 54548 additions and 55498 deletions

264
Lobby Server/Server.cs Normal file
View file

@ -0,0 +1,264 @@
/*
===========================================================================
Copyright (C) 2015-2019 Project Meteor Dev Team
This file is part of Project Meteor Server.
Project Meteor Server is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Project Meteor Server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Project Meteor Server. If not, see <https:www.gnu.org/licenses/>.
===========================================================================
*/
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Meteor.Common;
namespace Meteor.Lobby
{
class Server
{
public const int FFXIV_LOBBY_PORT = 54994;
public const int BUFFER_SIZE = 0xFFFF;
public const int BACKLOG = 100;
private const int CLEANUP_THREAD_SLEEP_TIME = 60;
private Socket mServerSocket;
private List<ClientConnection> mConnectionList = new List<ClientConnection>();
private PacketProcessor mProcessor;
private Thread cleanupThread;
private bool killCleanupThread = false;
private void SocketCleanup()
{
Program.Log.Info("Cleanup thread started; it will run every {0} seconds.", CLEANUP_THREAD_SLEEP_TIME);
while (!killCleanupThread)
{
int count = 0;
for (int i = mConnectionList.Count - 1; i >= 0; i--)
{
ClientConnection conn = mConnectionList[i];
if (conn.socket.Poll(1, SelectMode.SelectRead) && conn.socket.Available == 0)
{
conn.socket.Disconnect(false);
mConnectionList.Remove(conn);
count++;
}
}
if (count != 0)
Program.Log.Info("{0} connections were cleaned up.", count);
Thread.Sleep(CLEANUP_THREAD_SLEEP_TIME*1000);
}
}
#region Socket Handling
public bool StartServer()
{
//cleanupThread = new Thread(new ThreadStart(socketCleanup));
//cleanupThread.Name = "LobbyThread:Cleanup";
//cleanupThread.Start();
IPEndPoint serverEndPoint = new System.Net.IPEndPoint(IPAddress.Parse(ConfigConstants.OPTIONS_BINDIP), int.Parse(ConfigConstants.OPTIONS_PORT));
try{
mServerSocket = new System.Net.Sockets.Socket(serverEndPoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
}
catch (Exception e)
{
throw new ApplicationException("Could not Create socket, check to make sure not duplicating port", e);
}
try
{
mServerSocket.Bind(serverEndPoint);
mServerSocket.Listen(BACKLOG);
}
catch (Exception e)
{
throw new ApplicationException("Error occured while binding socket, check inner exception", e);
}
try
{
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
}
catch (Exception e)
{
throw new ApplicationException("Error occured starting listeners, check inner exception", e);
}
Console.ForegroundColor = ConsoleColor.White;
Program.Log.Info("Lobby Server has started @ {0}:{1}", (mServerSocket.LocalEndPoint as IPEndPoint).Address, (mServerSocket.LocalEndPoint as IPEndPoint).Port);
Console.ForegroundColor = ConsoleColor.Gray;
mProcessor = new PacketProcessor();
return true;
}
private void AcceptCallback(IAsyncResult result)
{
ClientConnection conn = null;
try
{
System.Net.Sockets.Socket s = (System.Net.Sockets.Socket)result.AsyncState;
conn = new ClientConnection();
conn.socket = s.EndAccept(result);
conn.buffer = new byte[BUFFER_SIZE];
lock (mConnectionList)
{
mConnectionList.Add(conn);
}
//Queue recieving of data from the connection
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
//Queue the accept of the next incomming connection
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
Program.Log.Info("Connection {0}:{1} has connected.", (conn.socket.RemoteEndPoint as IPEndPoint).Address, (conn.socket.RemoteEndPoint as IPEndPoint).Port);
}
catch (SocketException)
{
if (conn.socket != null)
{
conn.socket.Close();
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
}
catch (Exception)
{
if (conn.socket != null)
{
conn.socket.Close();
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
mServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), mServerSocket);
}
}
private void ReceiveCallback(IAsyncResult result)
{
ClientConnection conn = (ClientConnection)result.AsyncState;
try
{
int bytesRead = conn.socket.EndReceive(result);
bytesRead += conn.lastPartialSize;
if (bytesRead > 0)
{
int offset = 0;
//Build packets until can no longer or out of data
while (true)
{
BasePacket basePacket = BuildPacket(ref offset, conn.buffer, bytesRead);
//If can't build packet, break, else process another
if (basePacket == null)
break;
else
mProcessor.ProcessPacket(conn, basePacket);
}
//Not all bytes consumed, transfer leftover to beginning
if (offset < bytesRead)
Array.Copy(conn.buffer, offset, conn.buffer, 0, bytesRead - offset);
Array.Clear(conn.buffer, bytesRead - offset, conn.buffer.Length - (bytesRead - offset));
conn.lastPartialSize = bytesRead - offset;
//Build any queued subpackets into basepackets and send
conn.FlushQueuedSendPackets();
if (offset < bytesRead)
//Need offset since not all bytes consumed
conn.socket.BeginReceive(conn.buffer, bytesRead - offset, conn.buffer.Length - (bytesRead - offset), SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
else
//All bytes consumed, full buffer available
conn.socket.BeginReceive(conn.buffer, 0, conn.buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), conn);
}
else
{
Program.Log.Info("{0} has disconnected.", conn.currentUserId == 0 ? conn.GetAddress() : "User " + conn.currentUserId);
lock (mConnectionList)
{
conn.Disconnect();
mConnectionList.Remove(conn);
}
}
}
catch (SocketException)
{
if (conn.socket != null)
{
Program.Log.Info("{0} has disconnected.", conn.currentUserId == 0 ? conn.GetAddress() : "User " + conn.currentUserId);
lock (mConnectionList)
{
mConnectionList.Remove(conn);
}
}
}
}
/// <summary>
/// Builds a packet from the incoming buffer + offset. If a packet can be built, it is returned else null.
/// </summary>
/// <param name="offset">Current offset in buffer.</param>
/// <param name="buffer">Incoming buffer.</param>
/// <returns>Returns either a BasePacket or null if not enough data.</returns>
public BasePacket BuildPacket(ref int offset, byte[] buffer, int bytesRead)
{
BasePacket newPacket = null;
//Too small to even get length
if (bytesRead <= offset)
return null;
ushort packetSize = BitConverter.ToUInt16(buffer, offset);
//Too small to whole packet
if (bytesRead < offset + packetSize)
return null;
if (buffer.Length < offset + packetSize)
return null;
try
{
newPacket = new BasePacket(buffer, ref offset);
}
catch (OverflowException)
{
return null;
}
return newPacket;
}
#endregion
}
}