Advertisement
ossimc82

ClientSocket.cs

Mar 23rd, 2016
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.74 KB | None | 0 0
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.Sockets;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using GameServer.net.messaging;
  11. using GameServer.net.messaging.incoming;
  12. using GameServer.net.messaging.outgoing;
  13. using ROTF.Model;
  14. using ROTF.Model.IO;
  15.  
  16. namespace GameServer.net
  17. {
  18.     public class ClientSocket
  19.     {
  20.         public Socket Socket { get; }
  21.         public Client Client { get; }
  22.  
  23.         private readonly ConcurrentQueue<byte[]> pendingMessages;
  24.  
  25.         private bool sending;
  26.         private bool disconnecting;
  27.         private readonly object sendLock = new object();
  28.  
  29.         public ClientSocket(Socket skt, Client client)
  30.         {
  31.             pendingMessages = new ConcurrentQueue<byte[]>();
  32.             Socket = skt;
  33.             Client = client;
  34.         }
  35.  
  36.         public void Start()
  37.         {
  38.             receiveMessageLength();
  39.         }
  40.  
  41.         private void receiveMessageLength()
  42.         {
  43.             var buffer = new byte[4];
  44.             disposeSafeSocketOperation(() => Socket.BeginReceive(buffer, 0, 4, SocketFlags.None, receiveMessageId, buffer));
  45.         }
  46.  
  47.         private void receiveMessageId(IAsyncResult ar)
  48.         {
  49.             disposeSafeSocketOperation(() => Socket.EndReceive(ar));
  50.             var buffer = (byte[])ar.AsyncState;
  51.             Array.Resize(ref buffer,
  52.                 IPAddress.NetworkToHostOrder(BitConverter.ToInt32(buffer, 0)));
  53.             disposeSafeSocketOperation(() => Socket.BeginReceive(buffer, 4, 1, SocketFlags.None, receiveMessage, buffer));
  54.         }
  55.  
  56.         private void receiveMessage(IAsyncResult ar)
  57.         {
  58.             disposeSafeSocketOperation(() => Socket.EndReceive(ar));
  59.             var buffer = (byte[])ar.AsyncState;
  60.             disposeSafeSocketOperation(() => Socket.BeginReceive(buffer, 5, buffer.Length - 5, SocketFlags.None, endMessageReceive, buffer));
  61.         }
  62.  
  63.         private void endMessageReceive(IAsyncResult ar)
  64.         {
  65.             disposeSafeSocketOperation(() => Socket.EndReceive(ar));
  66.             var buffer = (byte[])ar.AsyncState;
  67.  
  68.             var b = new byte[buffer.Length-5];
  69.  
  70.             Buffer.BlockCopy(buffer, 5, b, 0, b.Length);
  71.  
  72.             var msg = Singleton<MessageMap>.Instance.Require(buffer[4]) as IncomingMessage;
  73.             msg.ReadFromInput(new DataReader(new MemoryStream(b)));
  74.  
  75.             var handler = Singleton<MessageMap>.Instance.GetHandler(buffer[4]);
  76.             handler.Init(Client);
  77.             handler.Handle(msg);
  78.  
  79.             receiveMessageLength();
  80.         }
  81.  
  82.         public void SendMessage(OutgoingMessage message)
  83.         {
  84.             if (disconnecting) return;
  85.  
  86.             //Structure:
  87.             //
  88.             // Message Length: Int32 (4 bytes) [5 + messageData bytes count]
  89.             // Message Id:     Byte (1 byte)
  90.             // Message Data:   Bytes (x bytes) [RC4 Encrypted]
  91.  
  92.             Task.Factory.StartNew(() =>
  93.             {
  94.                 var msgStrm = new MemoryStream();
  95.                 var msgWtr = new DataWriter(msgStrm);
  96.                 message.WriteToOutput(msgWtr);
  97.  
  98.                 var messageDataBytes = msgStrm.ToArray();
  99.                 var len = 5 + messageDataBytes.Length;
  100.                 var messageBytes = new byte[len];
  101.  
  102.                 unsafe
  103.                 {
  104.                     var bytes = new byte[4];
  105.                     fixed (byte* b = bytes)
  106.                         *(int*)b = IPAddress.HostToNetworkOrder(len);
  107.                    
  108.                     messageBytes[0] = bytes[0];
  109.                     messageBytes[1] = bytes[1];
  110.                     messageBytes[2] = bytes[2];
  111.                     messageBytes[3] = bytes[3];
  112.                 }
  113.  
  114.                 messageBytes[4] = message.MessageId;
  115.  
  116.                 Buffer.BlockCopy(messageDataBytes, 0, messageBytes, 5, len - 5);
  117.                 pendingMessages.Enqueue(messageBytes);
  118.  
  119.                 sendPendingMessages();
  120.             });
  121.         }
  122.  
  123.         private void sendPendingMessages()
  124.         {
  125.             if (pendingMessages.Count == 0)
  126.             {
  127.                 if (disconnecting)
  128.                     Disconnect(disconnecting);
  129.                 return;
  130.             }
  131.  
  132.             lock (sendLock)
  133.             {
  134.                 if (sending)
  135.                     return;
  136.                 sending = true;
  137.             }
  138.  
  139.             byte[] data;
  140.             var res = pendingMessages.TryDequeue(out data);
  141.  
  142.             if (!res) return;
  143.  
  144.             disposeSafeSocketOperation(() => Socket.BeginSend(data, 0, data.Length, SocketFlags.None, sendComplete, data.Length));
  145.         }
  146.  
  147.         private void sendComplete(IAsyncResult ar)
  148.         {
  149.             SocketError result;
  150.             var bytesTransfered = Socket.EndSend(ar, out result);
  151.  
  152.             lock (sendLock)
  153.                 sending = false;
  154.  
  155.             if (bytesTransfered != (int)ar.AsyncState)
  156.                 throw new InvalidDataException($"Not all bytes were sent!\nBytes: {bytesTransfered}\nSent: {ar.AsyncState}");
  157.             sendPendingMessages();
  158.         }
  159.  
  160.         public void Disconnect(bool immediate)
  161.         {
  162.             if (immediate)
  163.             {
  164.                 Socket.Close();
  165.                 Socket.Dispose();
  166.                 return;
  167.             }
  168.  
  169.             disconnecting = true;
  170.         }
  171.  
  172.  
  173.         private void disposeSafeSocketOperation(Action action)
  174.         {
  175.             try
  176.             {
  177.                 if (Socket.Connected)
  178.                     action();
  179.             }
  180.             catch (ObjectDisposedException)
  181.             {
  182.                 Socket.Disconnect(false);
  183.                 Socket.Dispose();
  184.             }
  185.         }
  186.     }
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement