Skip to content

Instantly share code, notes, and snippets.

@GregoryHlavac
Created April 26, 2015 11:43
Show Gist options
  • Save GregoryHlavac/7da1c1c70764671631b8 to your computer and use it in GitHub Desktop.
Save GregoryHlavac/7da1c1c70764671631b8 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Reflection;
using System.IO;
using DOL.GS;
using DOL.Events;
using DOL.GS.PacketHandler;
using DOL.GS.Commands;
using DOL.Database;
using log4net;
using DOL;
namespace Ephemeral.CCData
{
/// <summary>
/// Class which handles the metadata sent from the client logins.
///
/// As well it also supports metadata bans, however due to the extreme measures of this I have
/// not included a command to ban accounts/clients from in-game. This banning procedure requires
/// full database access to manually perform.
/// </summary>
public class CCData_Handler
{
private const int m_Port = 10310;
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly AsyncCallback m_CCAcceptCallback = new AsyncCallback(CCAcceptCallback);
private static FileInfo m_DumpFile = new FileInfo("./logs/CCData.log");
private static Socket m_CCDataSocket = null;
private static readonly DOLEventHandler m_RegionChangeDelegate = new DOLEventHandler(OnPlayerAddedToWorld);
public static string CC_TEMP_KEY = "CC_TEMP_KEY";
[GameServerStartedEvent]
public static void OnServerStart(DOLEvent e, object sender, EventArgs arguments)
{
if(!m_DumpFile.Exists)
{
m_DumpFile.Create();
}
m_CCDataSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_CCDataSocket.Bind(new IPEndPoint(IPAddress.Any, m_Port));
m_CCDataSocket.Listen(100);
m_CCDataSocket.BeginAccept(m_CCAcceptCallback, null);
Log.Info("CC Data Handler Loaded and Initialized.");
GameEventMgr.AddHandler(GamePlayerEvent.AddToWorld, m_RegionChangeDelegate);
}
[GameServerStoppedEvent]
public static void OnServerStop(DOLEvent e, object sender, EventArgs arguments)
{
m_CCDataSocket.Dispose();
m_CCDataSocket.Close();
m_CCDataSocket = null;
GameEventMgr.RemoveHandler(GamePlayerEvent.AddToWorld, m_RegionChangeDelegate);
}
[ScriptLoadedEvent]
public static void OnScriptLoaded(DOLEvent e, object sender, EventArgs args)
{
GameServer.Database.RegisterDataObject(typeof(DBCCData));
GameServer.Database.RegisterDataObject(typeof(DBCCBan));
}
private static void OnPlayerAddedToWorld(DOLEvent e, object sender, EventArgs args)
{
if (!(sender is GamePlayer)) return;
GamePlayer GP = sender as GamePlayer;
IList<DBCCData> acctData = GameServer.Database.SelectObjects<DBCCData>
("(Account ='" + GameServer.Database.Escape(GP.DBCharacter.AccountName) + "')");
if (!(acctData.Count > 0))
{
return;
}
IList<DBCCBan> dBans =
GameServer.Database.SelectObjects<DBCCBan>("(UID ='" + GameServer.Database.Escape(acctData[0].UID) + "')");
GP.TempProperties.setProperty(CC_TEMP_KEY, acctData[0].UID);
if (!(dBans.Count > 0))
{
return;
}
GP.Client.Disconnect();
}
private static void CCAcceptCallback(IAsyncResult ar)
{
Socket sock = null;
try
{
if (m_CCDataSocket == null)
return;
sock = m_CCDataSocket.EndAccept(ar);
sock.SendBufferSize = 16 * 1024;
sock.ReceiveBufferSize = 16 * 1024;
sock.NoDelay = true;
try
{
string IP = sock.Connected ? sock.RemoteEndPoint.ToString() : "NOIP";
byte[] initialBuffer = new byte[4];
sock.Receive(initialBuffer, 4, SocketFlags.None);
ushort dataLength = ConvertToUInt16(initialBuffer[3], initialBuffer[2]);
byte[] data = new byte[dataLength];
sock.Receive(data, dataLength, SocketFlags.None);
XOR(data, initialBuffer[1]);
string dStr = Encoding.Unicode.GetString(data);
AddDBEntry(IP, dStr);
}
catch (SocketException)
{
}
catch (Exception e)
{
if (Log.IsErrorEnabled)
Log.Error("CC Data Error", e);
}
finally
{
if (sock != null)
sock.Close();
}
}
catch
{
if (sock != null) // don't leave the socket open on exception
{
try
{
sock.Close();
}
catch
{
}
}
}
finally
{
if (m_CCDataSocket != null)
{
m_CCDataSocket.BeginAccept(m_CCAcceptCallback, null);
}
}
}
#region Static Stuff
private static void AddDBEntry(string clientIP,string CCDat)
{
DBCCData dData = new DBCCData();
dData.IP = clientIP;
string[] data = CCDat.Split('\n');
foreach(string cStr in data)
{
string[] dat2 = cStr.Split(':');
switch(dat2[0])
{
case "ACC":
dData.Account = dat2[1].Trim();
break;
case "OS":
dData.OS = dat2[1].Trim();
break;
case "UID":
dData.UID = dat2[1].Trim();
break;
case "PATH":
dData.DAoCPath = dat2[2].Trim();
break;
case "CHEATS":
dData.Cheats = dat2[1].Trim();
break;
}
}
dData.Date = DateTime.Now;
GameServer.Database.AddObject(dData);
GameServer.Database.SaveObject(dData);
if (Log.IsInfoEnabled)
Log.Info("Login Meta-Data Received from " + dData.IP + " account " + dData.Account + ".");
return;
}
private static void XOR(byte[] data, byte key)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = (byte)(data[i] ^ key);
}
}
private static ushort ConvertToUInt16(byte v1, byte v2)
{
return (ushort)(v2 | (v1 << 8));
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment