using System; using System.Diagnostics; using System.Threading; using System.Net.Sockets; using Launcher.Code.Tools; using Launcher.Properties; using Launcher.XAML; namespace Launcher.Code { public sealed class HackClient { public delegate void HackClientPass(HackClient pClient); public delegate void PassPacket(Packet pPacket, HackClient pClient); private LockFreeQueue mSendSegments = new LockFreeQueue(); private int mSending = 0; bool Disconnected = false; private short Key = 0; public event HackClientPass OnDisconnect; public event PassPacket OnPacketReceived; public Socket mSock; private byte[] pBuffer; private string usrname; private string password; public HackClient(string pIP, ushort port, string usrname, string password) { this.usrname = usrname; this.password = password; mSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); mSock.BeginConnect(pIP, port, new AsyncCallback(OnConnected), mSock); } private void OnConnected(IAsyncResult ar) { try { mSock.EndConnect(ar); } catch { MessageWindow.ShowErrorMessage(Resources.Message_ServerMaintenance); return; } if (!mSock.Connected) { Trace.WriteLine("Socket disconnected."); Disconnect(); return; } mSock.BeginReceive(pBuffer = new byte[4], 0, 4, SocketFlags.None, new AsyncCallback(OnKey), mSock); } private void OnKey(IAsyncResult ar) { try { if (!mSock.Connected) { Trace.WriteLine("Socket disconnected."); Disconnect(); return; } int len = mSock.EndReceive(ar); if (len != 4) { Trace.WriteLine("Invalid rev len"); Disconnect(); return; } Packet KeyPacket = new Packet(pBuffer, 0, pBuffer.Length); ushort opcode = 0xffff; KeyPacket.ReadUShort(out opcode); if (opcode != 0) { Trace.WriteLine("False op code."); Disconnect(); return; } KeyPacket.ReadShort(out Key); BeginReceive(); } catch(Exception e) { Trace.Write(e.ToString()); Disconnect(); } } private void BeginReceive() { if (!mSock.Connected) { Trace.WriteLine("Socket disconnected."); Disconnect(); return; } mSock.BeginReceive(pBuffer = new byte[4], 0, 4, SocketFlags.None, new AsyncCallback(OnHeader), mSock); } private void OnHeader(IAsyncResult ar) { try { if (!mSock.Connected) { Trace.WriteLine("Socket disconnected."); Disconnect(); return; } int len = mSock.EndReceive(ar); if (len <= 0) { Trace.WriteLine("No bytes transfered."); Disconnect(); return; } if (!CheckPacket(pBuffer)) { Trace.WriteLine("Invalid packet."); Disconnect(); return; } int packLen = getPacketLength(pBuffer); mSock.BeginReceive(pBuffer = new byte[packLen], 0, packLen, SocketFlags.None, new AsyncCallback(OnData), mSock); } catch(Exception e) { Trace.WriteLine(e.ToString()); Disconnect(); } } public void Disconnect() { if (Disconnected) return; if (OnDisconnect != null) OnDisconnect.Invoke(this); Disconnected = true; try { mSock.Shutdown(SocketShutdown.Both); } catch { } } public void SendPacket(Packet pPacket) { if (!mSock.Connected) { Trace.WriteLine("Socket disconnected."); Disconnect(); return; } byte[] toSend = new byte[pPacket.Length + 4]; Buffer.BlockCopy(GetHeader(pPacket.Length), 0, toSend, 0, 4); Buffer.BlockCopy(pPacket.ToArray(), 0, toSend, 4, pPacket.Length); mSendSegments.Enqueue(new ByteArraySegment(toSend)); if (Interlocked.CompareExchange(ref mSending, 1, 0) == 0) BeginSend(); } private void BeginSend() { SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.Completed += (s, a) => EndSend(a); ByteArraySegment segment = mSendSegments.Next; args.SetBuffer(segment.Buffer, segment.Start, segment.Length); try { if (!mSock.SendAsync(args)) EndSend(args); } catch (ObjectDisposedException) { Trace.Write("ObjectDisposedException => DC"); Disconnect(); } } private void EndSend(SocketAsyncEventArgs pArguments) { if (!mSock.Connected) { Trace.WriteLine("Socket disconnected."); Disconnect(); return; } if (pArguments.BytesTransferred <= 0) { Trace.WriteLine("No bytes transfered => DC"); Disconnect(); return; } if (mSendSegments.Next.Advance(pArguments.BytesTransferred)) mSendSegments.Dequeue(); if (mSendSegments.Next != null) BeginSend(); else mSending = 0; } private void OnData(IAsyncResult ar) { try { if (!mSock.Connected) return; int len = mSock.EndReceive(ar); if (len <= 0) { Trace.WriteLine("No bytes transfered."); Disconnect(); return; } Packet pack = new Packet(pBuffer, 0, pBuffer.Length); if (OnPacketReceived != null) OnPacketReceived.Invoke(pack, this); BeginReceive(); } catch(Exception e) { Trace.WriteLine(e.ToString()); Disconnect(); } } private bool CheckPacket(byte[] packet) { int a = packet[0] ^ FileSecurityClient.Version[2]; int b = Key % 0x100; int c = packet[1] ^ FileSecurityClient.Version[3]; int d = 0; return (a == b && c == d); } public static int getPacketLength(byte[] packetHeader) { if (packetHeader.Length < 4) { return -1; } return (((int)(packetHeader[0] ^ packetHeader[2])) | (((int)(packetHeader[1] ^ packetHeader[3]) << 8) & 0xFF00)); } public byte[] GetHeader(int size) { byte[] header = new byte[4]; int a = FileSecurityClient.Version[3] * 0x100 + FileSecurityClient.Version[2]; a = a ^ (Key); int b = a ^ size; header[0] = Convert.ToByte(a % 0x100); header[1] = Convert.ToByte(a / 0x100); header[2] = Convert.ToByte(b % 0x100); header[3] = Convert.ToByte(b / 0x100); return header; } } }