Advertisement
maxkhl

Host.cs

Aug 10th, 2015
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 12.83 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Lidgren.Network;
  9. using OutpostOmega.Network;
  10. using OutpostOmega.Data;
  11. using OutpostOmega.Game;
  12.  
  13. namespace OutpostOmega.Server.Network
  14. {
  15.     /// <summary>
  16.     /// Host class that manages all the connections
  17.     /// </summary>
  18.     public class Host : IDisposable
  19.     {
  20.         /// <summary>
  21.         /// Lidgren Server object. Contains all the technical network stuff
  22.         /// </summary>
  23.         public NetServer netServer { get; set; }
  24.  
  25.         /// <summary>
  26.         /// Blocks all new connections if true.
  27.         /// </summary>
  28.         public bool Locked { get; private set; }
  29.  
  30.         /// <summary>
  31.         /// Reason for locking the server
  32.         /// </summary>
  33.         public string Lockreason { get; private set; }
  34.  
  35.         /// <summary>
  36.         /// Port, this server is listening on
  37.         /// </summary>
  38.         public int Port
  39.         {
  40.             get
  41.             {
  42.                 return netServer.Port;
  43.             }
  44.         }
  45.  
  46.         /// <summary>
  47.         /// Name of this host instance
  48.         /// </summary>
  49.         public string Hostname { get; set; }
  50.  
  51.         /// <summary>
  52.         /// Handles all the ingame Networking
  53.         /// </summary>
  54.         public NetworkHandler networkHandler { get; set; }
  55.  
  56.         /// <summary>
  57.         /// All Clients that are currently active
  58.         /// </summary>
  59.         public ObservableCollection<Client> ConnectedClients;
  60.  
  61.         /// <summary>
  62.         /// All known Clients
  63.         /// </summary>
  64.         public List<Client> Clients;
  65.  
  66.         /// <summary>
  67.         /// Assigned world
  68.         /// </summary>
  69.         public World World { get; protected set; }
  70.  
  71.         public Host(string Hostname, World World)
  72.         {
  73.             if (SynchronizationContext.Current == null)
  74.                 SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
  75.  
  76.             // set peer
  77.             NetPeerConfiguration config = new NetPeerConfiguration("pspace_network")
  78.             {
  79.                 MaximumConnections = HostSettings.Default.MaxConnections,
  80.                 Port = HostSettings.Default.Port,
  81.                 ConnectionTimeout = HostSettings.Default.Timeout,
  82.                 //SimulatedLoss = 0.1f,
  83.                 //SimulatedMinimumLatency = 0.2f,
  84.                 //SimulatedRandomLatency = 0.5f
  85.             };
  86.             config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);
  87.  
  88.             netServer = new NetServer(config);
  89.             this.Hostname = Hostname;
  90.  
  91.             this.World = World;
  92.  
  93.             this.networkHandler = new NetworkHandler(World);
  94.  
  95.             ConnectedClients = new ObservableCollection<Client>();
  96.             Clients = new List<Client>();
  97.  
  98.             Main.Message("Host initialized and ready to start");
  99.         }
  100.  
  101.         /// <summary>
  102.         /// Starts the server and listener
  103.         /// </summary>
  104.         /// <returns>True if server got started. Careful! The Startup could still fail!</returns>
  105.         public bool Start()
  106.         {
  107.             if (netServer.Status == NetPeerStatus.NotRunning)
  108.             {
  109.                 try
  110.                 {
  111.                     netServer.Start();
  112.                 }
  113.                 catch(Exception e)
  114.                 {
  115.                     if (e.GetType() == typeof(System.Net.Sockets.SocketException))
  116.                         Main.Message("Socket already bound. Check if you got another server running on the same port.", System.Drawing.Color.Red);
  117.                     else
  118.                         Main.Message("Could not start server: " + e.Message, System.Drawing.Color.Red);
  119.                     return false;
  120.                 }
  121.                 Main.Message("Server started with following configuration");
  122.                 Main.Message("MaxConnections: " + netServer.Configuration.MaximumConnections.ToString());
  123.                 Main.Message("ConnectionTimeout: " + netServer.Configuration.ConnectionTimeout.ToString());
  124.  
  125.                 _serverThread = new Thread(Listener);
  126.                 _serverThread.Name = "MainListener";
  127.                 _serverThread.Priority = ThreadPriority.Lowest;
  128.                 _serverThread.Start();
  129.                
  130.                 //netServer.RegisterReceivedCallback(new SendOrPostCallback(ProcessMessage));
  131.  
  132.                 return true;
  133.             }
  134.             else
  135.             {
  136.                 return false;
  137.             }
  138.         }
  139.  
  140.         /// <summary>
  141.         /// Looks for a active client assigned to the given connection
  142.         /// </summary>
  143.         /// <returns>Null or found Client</returns>
  144.         private Client GetClient(NetConnection connection)
  145.         {
  146.             return (from client in ConnectedClients
  147.                     where client.Connection == connection
  148.                     select client).SingleOrDefault();
  149.         }
  150.  
  151.         private Thread _serverThread;
  152.         private bool _serverThreadAlive = true;
  153.  
  154.         /// <summary>
  155.         /// Processes a incoming Message
  156.         /// </summary>
  157.         private void Listener()
  158.         {
  159.             while (netServer.Status != NetPeerStatus.NotRunning && !Disposing) // Loop as long as the netserver is running
  160.             {
  161.                 netServer.MessageReceivedEvent.WaitOne(500);
  162.  
  163.                 NetIncomingMessage im;
  164.                 while ((im = netServer.ReadMessage()) != null)
  165.                 {
  166.                     //NetIncomingMessage im = netServer.ReadMessage();
  167.  
  168.                     // Get general information about sender
  169.                     var client = GetClient(im.SenderConnection);
  170.  
  171.                     string adress = "Unknown";
  172.                     if (im.SenderConnection != null)
  173.                         adress = im.SenderConnection.RemoteEndPoint.Address.ToString();
  174.  
  175.                     switch (im.MessageType)
  176.                     {
  177.                         // The big Message Block. Contains System-Messages that will be posted to the output-box
  178.                         case NetIncomingMessageType.DebugMessage:
  179.                         case NetIncomingMessageType.ErrorMessage:
  180.                         case NetIncomingMessageType.WarningMessage:
  181.                         case NetIncomingMessageType.VerboseDebugMessage:
  182.  
  183.                             if (client != null)
  184.                                 Main.Message(im.MessageType.ToString() + " from " + client.Mind.Username + " (" + adress + "): " + im.ReadString());
  185.                             else if (im.SenderConnection != null)
  186.                                 Main.Message(im.MessageType.ToString() + " from " + adress + " (no client): " + im.ReadString());
  187.                             else
  188.                                 Main.Message(im.ReadString());
  189.  
  190.                             break;
  191.                         // Connection Approval
  192.                         case NetIncomingMessageType.ConnectionApproval:
  193.  
  194.                             if (Locked)
  195.                             {
  196.                                 im.SenderConnection.Deny("Server is locked currently. Reason: " + Lockreason);
  197.                                 Main.Message("Blocked connection due to active server lock");
  198.                             }
  199.                             else
  200.                             {
  201.                                 var Username = im.ReadString();
  202.  
  203.                                 var User = (from clnt in Clients
  204.                                             where
  205.                                              clnt.Mind.Username == Username
  206.                                             select clnt).SingleOrDefault();
  207.  
  208.                                 if (User != null)
  209.                                 {
  210.                                     if (User.Online) // Same user already online
  211.                                     {
  212.                                         im.SenderConnection.Deny("User with the same name already online");
  213.                                         Main.Message(adress + ": Rejected. Username '" + Username + "' already in use.");
  214.                                     }
  215.                                     else // User known but not online. Here should some kind of authentication happen but for now we'll just assign him to that user
  216.                                     {
  217.                                         im.SenderConnection.Approve();
  218.                                         User.Online = true;
  219.                                         User.Connection = im.SenderConnection;
  220.                                         User.Host = this;
  221.                                     }
  222.                                 }
  223.                                 else // Totaly new user
  224.                                 {
  225.                                     im.SenderConnection.Approve();
  226.                                     User = new Client(Username, this, im.SenderConnection);
  227.                                 }
  228.                             }
  229.                             break;
  230.                         // Connections and Disconnections
  231.                         case NetIncomingMessageType.StatusChanged:
  232.                             NetConnectionStatus status = (NetConnectionStatus)im.ReadByte();
  233.                             string Reason = im.ReadString();
  234.                             switch (status)
  235.                             {
  236.                                 case NetConnectionStatus.RespondedAwaitingApproval:
  237.                                     Main.Message("Incomming connection from " + adress);
  238.                                     break;
  239.                                 case NetConnectionStatus.Disconnected:
  240.                                     if (client != null)
  241.                                     {
  242.                                         client.Online = false;
  243.                                         Main.Message(client.Mind.Username + " (" + adress + ") disconnected. Reason: " + Reason);
  244.                                     }
  245.                                     break;
  246.                                 case NetConnectionStatus.RespondedConnect:
  247.                                 case NetConnectionStatus.Connected:
  248.  
  249.                                     break;
  250.                                 case NetConnectionStatus.Disconnecting:
  251.                                     if (client != null)
  252.                                     {
  253.                                         client.Online = false;
  254.                                     }
  255.                                     break;
  256.                                 default:
  257.                                     Main.Message("Unknown statusmessage '" + status.ToString() + "' (" + Reason + ")");
  258.                                     break;
  259.                             }
  260.                             break;
  261.                         // This is the interesting stuff!
  262.                         case NetIncomingMessageType.Data:
  263.                             if (client != null)
  264.                             {
  265.                                 System.Threading.ThreadPool.QueueUserWorkItem(
  266.                                     new System.Threading.WaitCallback(client.ProcessPackage), im);
  267.                             }
  268.                             else
  269.                                 Main.Message("Error! Unadressed Data-Package from " + im.SenderConnection.RemoteEndPoint.Address.ToString());
  270.                             break;
  271.                         default:
  272.                             string pmsg = im.ReadString();
  273.                             Main.Message("Unknown messagetype '" + im.MessageType.ToString() + "' (" + pmsg + ")");
  274.                             break;
  275.                     }
  276.                 }
  277.             }
  278.         }
  279.  
  280.         /// <summary>
  281.         /// Server-Shutdown
  282.         /// </summary>
  283.         public void Shutdown()
  284.         {
  285.             Main.Message("Shutting down Server");
  286.  
  287.             // Disconnect the clients gently
  288.             for (int i = 0; i < ConnectedClients.Count; i++ )
  289.                 ConnectedClients[i].Disconnect("Server is shutting down");
  290.             ConnectedClients.Clear();
  291.  
  292.             // Now kill everything
  293.             netServer.Shutdown("Server offline");
  294.  
  295.             // Wait for the Server-shutdown
  296.             while (netServer.Status != NetPeerStatus.NotRunning)
  297.                 Thread.Sleep(100);
  298.         }
  299.  
  300.         public void Lock(string Reason)
  301.         {
  302.             Lockreason = Reason;
  303.             Locked = true;
  304.             Main.Message("Server locked with reason '" + Lockreason + "'");
  305.         }
  306.         public void Unlock()
  307.         {
  308.             Locked = false;
  309.             Main.Message("Server unlocked");
  310.         }
  311.  
  312.         public bool Disposing = false;
  313.         public void Dispose()
  314.         {
  315.             Disposing = true;
  316.             Shutdown();
  317.         }
  318.     }
  319. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement