using System; using System.Net.Sockets; using System.Threading; using Launcher.Code.Tools; namespace Launcher.Code { public sealed class NormalProxy { private Socket inSocket; private Socket outSocket; private const int MAXBUFFER = 16000; byte[] OutBuffer = new byte[MAXBUFFER]; byte[] InBuffer = new byte[MAXBUFFER]; public bool Connected = true; private LockFreeQueue mInSendSegments = new LockFreeQueue(); private int mInSending = 0; private LockFreeQueue mOutSendSegments = new LockFreeQueue(); private int mOutSending = 0; private string mToIP = ""; public NormalProxy(Socket sock, ushort toPort, string toIP) { try { inSocket = sock; mToIP = toIP; outSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); outSocket.BeginConnect(toIP, toPort, new AsyncCallback(OnOutconnect), outSocket); } catch { } } private void OnOutconnect(IAsyncResult ar) { try { outSocket.EndConnect(ar); } catch { Disconnect(); return; } try { outSocket.BeginReceive(OutBuffer, 0, MAXBUFFER, SocketFlags.None, new AsyncCallback(OnOutPacket), outSocket); SendToOut(System.Text.Encoding.ASCII.GetBytes(DataProvider.FSClient.GUID)); inSocket.BeginReceive(InBuffer, 0, MAXBUFFER, SocketFlags.None, new AsyncCallback(OnInPacket), inSocket); } catch { } } private void SendToIn(byte[] data) { try { if (!Connected) return; mInSendSegments.Enqueue(new ByteArraySegment(data)); if (Interlocked.CompareExchange(ref mInSending, 1, 0) == 0) BeginInSend(); } catch { } } private void SendToOut(byte[] data) { try { if (!Connected) return; mOutSendSegments.Enqueue(new ByteArraySegment(data)); if (Interlocked.CompareExchange(ref mOutSending, 1, 0) == 0) BeginOutSend(); } catch { } } private void BeginOutSend() { SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.Completed += (s, a) => EndOutSend(a); ByteArraySegment segment = mOutSendSegments.Next; args.SetBuffer(segment.Buffer, segment.Start, segment.Length); try { if (!outSocket.SendAsync(args)) EndOutSend(args); } catch (ObjectDisposedException) { } } private void EndOutSend(SocketAsyncEventArgs pArguments) { if (!Connected) return; if (pArguments.BytesTransferred <= 0) { Disconnect(); return; } if (mOutSendSegments.Next.Advance(pArguments.BytesTransferred)) mOutSendSegments.Dequeue(); if (mOutSendSegments.Next != null) BeginOutSend(); else mOutSending = 0; } private void BeginInSend() { SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.Completed += (s, a) => EndInSend(a); ByteArraySegment segment = mInSendSegments.Next; args.SetBuffer(segment.Buffer, segment.Start, segment.Length); try { if (!inSocket.SendAsync(args)) EndInSend(args); } catch (ObjectDisposedException) { } } private void EndInSend(SocketAsyncEventArgs pArguments) { if (!Connected) return; if (pArguments.BytesTransferred <= 0) { Disconnect(); return; } if (mInSendSegments.Next.Advance(pArguments.BytesTransferred)) mInSendSegments.Dequeue(); if (mInSendSegments.Next != null) BeginInSend(); else mInSending = 0; } private void Disconnect() { try { inSocket.Shutdown(SocketShutdown.Both); } catch {} try { outSocket.Shutdown(SocketShutdown.Both); } catch { } } private void OnOutPacket(IAsyncResult ar) { if (!Connected) return; int len = 0; try { len = outSocket.EndReceive(ar); } catch { Disconnect(); return; } if (len <= 0 || !Connected) { Disconnect(); return; } byte[] toSend = new byte[len]; Buffer.BlockCopy(OutBuffer, 0, toSend, 0, len); SendToIn(toSend); outSocket.BeginReceive(OutBuffer, 0, MAXBUFFER, SocketFlags.None, new AsyncCallback(OnOutPacket), outSocket); } private void OnInPacket(IAsyncResult ar) { int len = 0; try { len = inSocket.EndReceive(ar); } catch { Disconnect(); return; } if (len <= 0 || !Connected) { Disconnect(); return; } byte[] toSend = new byte[len]; Buffer.BlockCopy(InBuffer, 0, toSend, 0, len); SendToOut(toSend); inSocket.BeginReceive(InBuffer, 0, MAXBUFFER, SocketFlags.None, new AsyncCallback(OnInPacket), inSocket); } } }