Advertisement
RaWRCoder

Server

Jul 21st, 2014
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.70 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Threading;
  7. using CrystalNetwork.Shared;
  8.  
  9. namespace CrystalNetwork.Server
  10. {
  11.     public class BaseServer
  12.     {
  13.         public static Thread MainThread;
  14.         /// <summary>
  15.         /// Throw exceptions?
  16.         /// </summary>
  17.         public static bool DebugMode = false;
  18.         public string Hostname
  19.         {
  20.             get { return _hostname; }
  21.             set
  22.             {
  23.                 var oldname = _hostname;
  24.                 _hostname = value;
  25.                 OnHostnameChanged(oldname, _hostname);
  26.             }
  27.         }
  28.         public IPAddress Address { get; protected set; }
  29.         public uint MaxClients
  30.         {
  31.             get { return _maxclients; }
  32.             set
  33.             {
  34.                 var oldval = _maxclients;
  35.                 _maxclients = value;
  36.                 OnMaxClientsChanged(oldval, _maxclients);
  37.             }
  38.         }
  39.         public uint ClientsOnline
  40.         {
  41.             get { return _online; }
  42.             set
  43.             {
  44.                 var oldval = _online;
  45.                 _online = value;
  46.                 OnOnlineClientsChanged(oldval, _online);
  47.             }
  48.         }
  49.         public ushort Port { get; protected set; }
  50.         public BaseProtocol Protocol { get; set; }
  51.         public MessageManager Log { get; protected set; }
  52.         protected Socket SocketListen { get; set; }
  53.         protected Thread ThreadListen { get; set; }
  54.         protected Thread ThreadTick { get; set; }
  55.         public bool ShouldRun { get; set; }
  56.         public bool IsRuning
  57.         {
  58.             get { return _isrunning; }
  59.             protected set
  60.             {
  61.                 if (_isrunning != value)
  62.                 {
  63.                     _isrunning = !_isrunning;
  64.                     OnRunningStateChanged();
  65.                 }
  66.             }
  67.         }
  68.         /// <summary>
  69.         /// Number of connecting clients queue
  70.         /// </summary>
  71.         public uint Backlog { get; protected set; }
  72.  
  73.         public List<BaseClientConnection> Clients { get; protected set; }
  74.  
  75.         protected Dictionary<int, ClientAnswerHandler> AnswerHandlers { get; set; }
  76.  
  77.         public event Action EV_LAUNCH;
  78.         public event Action EV_STOP;
  79.         public event Action<string, string> EV_HOSTNAME_CHANGED;
  80.         public event Action<uint, uint> EV_MAXCLIENTS_CHANGED;
  81.         public event Action EV_RUNNINGSTATE_CHANGED;
  82.         public event Action EV_ONLINE_CLIENTS_CHANGED;
  83.  
  84.         protected virtual void OnServerLaunch()
  85.         {
  86.             var handler = EV_LAUNCH;
  87.             if (handler != null) handler();
  88.         }
  89.         protected virtual void OnServerStop()
  90.         {
  91.             var handler = EV_STOP;
  92.             if (handler != null) handler();
  93.         }
  94.         protected virtual void OnHostnameChanged(string prev, string @new)
  95.         {
  96.             var handler = EV_HOSTNAME_CHANGED;
  97.             if (handler != null) handler(prev, @new);
  98.         }
  99.         protected virtual void OnMaxClientsChanged(uint prev, uint @new)
  100.         {
  101.             var handler = EV_MAXCLIENTS_CHANGED;
  102.             if (handler != null) handler(prev, @new);
  103.         }
  104.         protected virtual void OnRunningStateChanged()
  105.         {
  106.             var handler = EV_RUNNINGSTATE_CHANGED;
  107.             if (handler != null) handler();
  108.         }
  109.         protected virtual void OnOnlineClientsChanged(uint oldval, uint online)
  110.         {
  111.             var handler = EV_ONLINE_CLIENTS_CHANGED;
  112.             if (handler != null) handler();
  113.         }
  114.  
  115.  
  116.         private bool _isrunning;
  117.         private bool _initialized;
  118.         private string _hostname = "";
  119.         private uint _maxclients = 32;
  120.         private uint _online = 0;
  121.  
  122.         public BaseServer()
  123.         {
  124.             MainThread = Thread.CurrentThread;
  125.             Log = new MessageManager();
  126.             Hostname = "Basic CrystalNetwork Server";
  127.             ShouldRun = true;
  128.             IsRuning = false;
  129.             Backlog = 64;
  130.             Clients = new List<BaseClientConnection>();
  131.             AnswerHandlers = new Dictionary<int, ClientAnswerHandler>();
  132.  
  133.         }
  134.         /// <summary>
  135.         /// Initializes a server, also starts it, if ShouldRun == true
  136.         /// </summary>
  137.         /// <param name="ip">IP to listen</param>
  138.         /// <param name="port">Port to bind to</param>
  139.         /// <returns>Was an operation successful?</returns>
  140.         public bool Start(IPAddress ip = null, ushort port = 27015)
  141.         {
  142.             Address = ip ?? IPAddress.Any;
  143.             Port = port;
  144.             try
  145.             {
  146.                 SocketListen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  147.                 SocketListen.Bind(new IPEndPoint(Address, port));
  148.             }
  149.             catch (Exception ex)
  150.             {
  151.                 Log.PostFrom(
  152.                     LogMessageType.CriticalError,
  153.                     "Could not bind to {0}:{1} - {2}",
  154.                     "BasicServer.Start",
  155.                     Address.ToString(), Port, ex.Message
  156.                     );
  157.                 if (DebugMode)
  158.                     throw;
  159.                 return false;
  160.             }
  161.             Log.Post(
  162.                 LogMessageType.Info,
  163.                 "Successfully binded to {0}:{1}",
  164.                 Address.ToString(), Port
  165.                 );
  166.  
  167.             _initialized = true;
  168.             if (ShouldRun) Run();
  169.            
  170.             return true;
  171.         }
  172.         /// <summary>
  173.         /// If the server is initialized, starts listening loop
  174.         /// </summary>
  175.         public void Run()
  176.         {
  177.             if (!_initialized)
  178.             {
  179.                 Log.PostFrom(
  180.                     LogMessageType.Error,
  181.                     "Failed to run - server is not initialized by BaseServer.Start()",
  182.                     "BaseServer.Run");
  183.                 return;
  184.             }
  185.             if (IsRuning)
  186.             {
  187.                 Log.PostFrom(
  188.                     LogMessageType.Error,
  189.                     "Failed to run - server is already running",
  190.                     "BaseServer.Run");
  191.                 return;
  192.             }
  193.             ShouldRun = true;
  194.             SocketListen.Listen((int)Backlog);
  195.             ThreadListen = new Thread(AcceptLoop);
  196.             ThreadListen.Start();
  197.             OnServerLaunch();
  198.             ThreadTick = new Thread(ServerTick);
  199.             ThreadTick.Start();
  200.         }
  201.  
  202.         public void ServerTick()
  203.         {
  204.             while (IsRuning || ShouldRun)
  205.             {
  206.                 for (var i = 0; i < Clients.Count; i++)
  207.                 {
  208.                     if (Clients[i] != null && (!Clients[i].IsActive || !Clients[i].ShouldBeActive))
  209.                     {
  210.                         Kick((uint)i);
  211.                     }
  212.                 }
  213.                 Thread.Sleep(1000);
  214.             }
  215.         }
  216.  
  217.         /// <summary>
  218.         /// Main listening loop, accepts clients from SocketListen
  219.         /// </summary>
  220.         public void AcceptLoop()
  221.         {
  222.             if (!_initialized)
  223.             {
  224.                 Log.PostFrom(
  225.                     LogMessageType.Error,
  226.                     "Failed to start accept loop - server is not initialized by BaseServer.Start()",
  227.                     "BaseServer.AcceptLoop");
  228.                 return;
  229.             }
  230.             IsRuning = true;
  231.             Log.Post(LogMessageType.Info, "Listening started!");
  232.             while (ShouldRun)
  233.             {
  234.                 try
  235.                 {
  236.                     var sockNew = SocketListen.Accept();
  237.  
  238.                     var remEP = sockNew.RemoteEndPoint as IPEndPoint;
  239.                     Log.Post(LogMessageType.Info,
  240.                         "New incoming connection from '{0}:{1}'",
  241.                         remEP.Address, remEP.Port);
  242.  
  243.                     if (Protocol != null && Protocol.FuncServerNewConnection != null)
  244.                         Protocol.FuncServerNewConnection(this, sockNew);
  245.                 }
  246.                 catch (Exception ex)
  247.                 {
  248.                     if (ex is ThreadAbortException)
  249.                         return;
  250.                     if (ex is SocketException)
  251.                     {
  252.                         var ec = (ex as SocketException).SocketErrorCode;
  253.                         if (ec == SocketError.Interrupted)
  254.                             break;
  255.                         Log.PostFrom(LogMessageType.Debug,
  256.                             "Socket exception {2} - ({1}) {0}",
  257.                             "BaseServer.AcceptLoop", ex.Message, ex, ec);
  258.  
  259.                         return;
  260.                     }
  261.                     Log.PostFrom(LogMessageType.CriticalError,
  262.                        "Failed to accept new client connection - ({1}) {0}",
  263.                        "BaseServer.AcceptLoop", ex.Message, ex);
  264.                     if (DebugMode)
  265.                         throw;
  266.                 }
  267.  
  268.             }
  269.             IsRuning = false;
  270.         }
  271.         public void ShutDown()
  272.         {
  273.             if (!IsRuning || ThreadListen == null)
  274.             {
  275.                 Log.PostFrom(
  276.                     LogMessageType.Error,
  277.                     "Failed to shut the server down - server is not running",
  278.                     "BaseServer.ShutDown");
  279.                 return;
  280.             }
  281.             if (!_initialized)
  282.             {
  283.                 Log.PostFrom(
  284.                     LogMessageType.Error,
  285.                     "Failed to shut the server down - server is not initialized by BaseServer.Start()",
  286.                     "BaseServer.ShutDown");
  287.                 return;
  288.             }
  289.             IsRuning = false;
  290.             ShouldRun = false;
  291.  
  292.             SocketListen.Close();
  293.  
  294.             ThreadTick.Abort();
  295.             ThreadTick.Join(500);
  296.             ThreadTick = null;
  297.  
  298.             ThreadListen.Abort();
  299.             ThreadListen.Join(500);
  300.             ThreadListen = null;
  301.  
  302.             for (uint i = 0; i < Clients.Count; i++)
  303.             {
  304.                 if (Clients[(int)i] != null)
  305.                     Kick(i);
  306.             }
  307.             Clients.Clear();
  308.  
  309.             Log.Post(LogMessageType.Info, "Server has been stopped!");
  310.             OnServerStop();
  311.         }
  312.         public bool ReStart()
  313.         {
  314.             ShutDown();
  315.             ShouldRun = true;
  316.             return Start(Address, Port);
  317.         }
  318.  
  319.         public void OnClientDisconnected(uint clid)
  320.         {
  321.             Log.PostFrom(LogMessageType.Debug,
  322.                 "client [{0}] - stoping client...",
  323.                 "BaseServer.OnClientDisconnected()", clid);
  324.             Clients[(int)clid].Stop();
  325.             Clients[(int)clid] = null;
  326.             ClientsOnline--;
  327.             Log.PostInfo("Client [{0}] disconnected.", clid);
  328.         }
  329.  
  330.         public void Kick(uint clid)
  331.         {
  332.             Log.PostFrom(LogMessageType.Debug,
  333.                 "client [{0}] - kicking client...",
  334.                 "BaseServer.Kick()", clid);
  335.             Clients[(int)clid].Stop();
  336.             Clients[(int)clid] = null;
  337.             ClientsOnline--;
  338.             Log.PostInfo("Kicked client [{0}].", clid);
  339.         }
  340.  
  341.         public bool UnregisterAnswerHandler(int key)
  342.         {
  343.             if (key == 0)
  344.                 return true;
  345.             if (AnswerHandlers.ContainsKey(key))
  346.             {
  347.                 AnswerHandlers.Remove(key);
  348.                 return true;
  349.             }
  350.             return false;
  351.         }
  352.         public bool RegisterAnswerHandler(int key, DProcessRequestResultsServer h)
  353.         {
  354.             if (key == 0 || h == null)
  355.                 return true;
  356.  
  357.             if (AnswerHandlers.Count > 256)
  358.             {
  359.                 var lst = (from cah in AnswerHandlers where cah.Value.IsExpired select cah.Key).ToList();
  360.                 foreach (var i in lst)
  361.                 {
  362.                     AnswerHandlers.Remove(i);
  363.                 }
  364.             }
  365.             ClientAnswerHandler proc;
  366.             if (AnswerHandlers.TryGetValue(key, out proc))
  367.             {
  368.                 if (proc.IsExpired)
  369.                 {
  370.                     Log.Post(LogMessageType.Error,
  371.                         "Registration of packet({1}) failed - previous request has not been yet answered",
  372.                         key);
  373.                     return false;
  374.                 }
  375.                 proc.Expires = DateTime.Now.AddSeconds(5);
  376.                 proc.Func = h;
  377.             }
  378.             else
  379.             {
  380.                 var nh = new ClientAnswerHandler
  381.                 {
  382.                     Expires = DateTime.Now.AddSeconds(5),
  383.                     Func = h
  384.                 };
  385.                 AnswerHandlers.Add(key, nh);
  386.             }
  387.             return true;
  388.         }
  389.  
  390.         public SocketError SendPacket(uint clid, DataPacket p, DProcessRequestResultsServer handler = null)
  391.         {
  392.             if (clid < Clients.Count || Clients[(int)clid] == null )
  393.             {
  394.                 Log.Post(LogMessageType.Error, "Cannot send packet to client[{0}] - client id is invalid!", clid);
  395.                 return SocketError.SocketError;
  396.             }
  397.             if (Protocol == null)
  398.             {
  399.                 Log.Post(LogMessageType.CriticalError, "Cannot send packet to client[{0}] - no protocol specified!", clid);
  400.                 return SocketError.SocketError;
  401.             }
  402.             if (p.DataLength > Protocol.MaxPacketLength)
  403.             {
  404.                 Log.Post(LogMessageType.CriticalError,
  405.                     "Cannot send packet to client[{0}] - packet is too big ({1} vs {2} bytes allowed by protocol)",
  406.                     clid, p.DataLength, Protocol.MaxPacketLength);
  407.                 return SocketError.SocketError;
  408.             }
  409.  
  410.             var client = Clients[(int) clid];
  411.             if (!client.ShouldBeActive || !client.IsActive || client.Socket == null)
  412.             {
  413.                 Log.Post(LogMessageType.Error,
  414.                     "Failed to send packet to client[{0}] - client is now disconnecting",
  415.                     clid);
  416.                 client.ShouldBeActive = false;
  417.                 return SocketError.SocketError;
  418.             }
  419.  
  420.             if (!RegisterAnswerHandler(p.Key, handler))
  421.                 return SocketError.SocketError;
  422.  
  423.             SocketError err;
  424.             client.Socket.Send(p.GetBytes(), 0, DataPacket.HeaderLength, SocketFlags.None, out err);
  425.             if (err != SocketError.Success)
  426.             {
  427.                 Log.Post(LogMessageType.Error,
  428.                     "Failed to send packet to client[{0}] - SocketError.{1}",
  429.                     clid, err);
  430.             }
  431.             return err;
  432.         }
  433.     }
  434. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement