summaryrefslogtreecommitdiff
path: root/Client/Assembly-CSharp/InnerNet/InnerNetServer.cs
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2020-12-30 20:59:04 +0800
committerchai <chaifix@163.com>2020-12-30 20:59:04 +0800
commite9ea621b93fbb58d9edfca8375918791637bbd52 (patch)
tree19ce3b1c1f2d51eda6878c9d0f2c9edc27f13650 /Client/Assembly-CSharp/InnerNet/InnerNetServer.cs
+init
Diffstat (limited to 'Client/Assembly-CSharp/InnerNet/InnerNetServer.cs')
-rw-r--r--Client/Assembly-CSharp/InnerNet/InnerNetServer.cs592
1 files changed, 592 insertions, 0 deletions
diff --git a/Client/Assembly-CSharp/InnerNet/InnerNetServer.cs b/Client/Assembly-CSharp/InnerNet/InnerNetServer.cs
new file mode 100644
index 0000000..3705318
--- /dev/null
+++ b/Client/Assembly-CSharp/InnerNet/InnerNetServer.cs
@@ -0,0 +1,592 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Threading;
+using Hazel;
+using Hazel.Udp;
+using UnityEngine;
+
+namespace InnerNet
+{
+ public class InnerNetServer : DestroyableSingleton<InnerNetServer>
+ {
+ public const int MaxPlayers = 10;
+
+ public bool Running;
+
+ public const int LocalGameId = 32;
+
+ private const int InvalidHost = -1;
+
+ private int HostId = -1;
+
+ public HashSet<string> ipBans = new HashSet<string>();
+
+ public int Port = 22023;
+
+ [SerializeField]
+ private GameStates GameState;
+
+ private NetworkConnectionListener listener;
+
+ private List<InnerNetServer.Player> Clients = new List<InnerNetServer.Player>();
+
+ protected class Player
+ {
+ private static int IdCount = 1;
+
+ public int Id;
+
+ public Connection Connection;
+
+ public LimboStates LimboState;
+
+ public Player(Connection connection)
+ {
+ this.Id = Interlocked.Increment(ref InnerNetServer.Player.IdCount);
+ this.Connection = connection;
+ }
+ }
+
+ public override void OnDestroy()
+ {
+ this.StopServer();
+ base.OnDestroy();
+ }
+
+ public void StartAsServer()
+ {
+ if (this.listener != null)
+ {
+ this.StopServer();
+ }
+ this.GameState = GameStates.NotStarted;
+ this.listener = new UdpConnectionListener(new IPEndPoint(IPAddress.Any, this.Port), IPMode.IPv4, null);
+ this.listener.NewConnection += this.OnServerConnect;
+ this.listener.Start();
+ this.Running = true;
+ }
+
+ public void StopServer()
+ {
+ this.HostId = -1;
+ this.Running = false;
+ this.GameState = GameStates.Destroyed;
+ if (this.listener != null)
+ {
+ this.listener.Close();
+ this.listener.Dispose();
+ this.listener = null;
+ }
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ this.Clients.Clear();
+ }
+ }
+
+ public static bool IsCompatibleVersion(int version)
+ {
+ return Constants.CompatVersions.Contains(version);
+ }
+
+ private void OnServerConnect(NewConnectionEventArgs evt)
+ {
+ MessageReader handshakeData = evt.HandshakeData;
+ try
+ {
+ if (evt.HandshakeData.Length < 5)
+ {
+ InnerNetServer.SendIncorrectVersion(evt.Connection);
+ return;
+ }
+ if (!InnerNetServer.IsCompatibleVersion(handshakeData.ReadInt32()))
+ {
+ InnerNetServer.SendIncorrectVersion(evt.Connection);
+ return;
+ }
+ }
+ finally
+ {
+ handshakeData.Recycle();
+ }
+ InnerNetServer.Player client = new InnerNetServer.Player(evt.Connection);
+ Debug.Log(string.Format("Client {0} added: {1}", client.Id, evt.Connection.EndPoint));
+ UdpConnection udpConnection = (UdpConnection)evt.Connection;
+ udpConnection.KeepAliveInterval = 1500;
+ udpConnection.DisconnectTimeout = 6000;
+ udpConnection.ResendPingMultiplier = 1.5f;
+ udpConnection.DataReceived += delegate(DataReceivedEventArgs e)
+ {
+ this.OnDataReceived(client, e);
+ };
+ udpConnection.Disconnected += delegate(object o, DisconnectedEventArgs e)
+ {
+ this.ClientDisconnect(client);
+ };
+ }
+
+ private static void SendIncorrectVersion(Connection connection)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(1);
+ messageWriter.Write(5);
+ messageWriter.EndMessage();
+ connection.Send(messageWriter);
+ messageWriter.Recycle();
+ }
+
+ private void Connection_DataSentRaw(byte[] data, int length)
+ {
+ Debug.Log("Server Sent: " + string.Join(" ", (from b in data
+ select b.ToString()).ToArray<string>(), 0, length));
+ }
+
+ private void OnDataReceived(InnerNetServer.Player client, DataReceivedEventArgs evt)
+ {
+ MessageReader message = evt.Message;
+ if (message.Length <= 0)
+ {
+ Debug.Log("Server got 0 bytes");
+ message.Recycle();
+ return;
+ }
+ try
+ {
+ while (message.Position < message.Length)
+ {
+ this.HandleMessage(client, message.ReadMessage(), evt.SendOption);
+ }
+ }
+ catch (Exception arg)
+ {
+ Debug.Log(string.Format("{0}\r\n{1}", string.Join<byte>(" ", message.Buffer), arg));
+ }
+ finally
+ {
+ message.Recycle();
+ }
+ }
+
+ private void HandleMessage(InnerNetServer.Player client, MessageReader reader, SendOption sendOption)
+ {
+ switch (reader.Tag)
+ {
+ case 0:
+ {
+ Debug.Log("Server got host game");
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(0);
+ messageWriter.Write(32);
+ messageWriter.EndMessage();
+ client.Connection.Send(messageWriter);
+ messageWriter.Recycle();
+ return;
+ }
+ case 1:
+ {
+ Debug.Log("Server got join game");
+ if (reader.ReadInt32() == 32)
+ {
+ this.JoinGame(client);
+ return;
+ }
+ MessageWriter messageWriter2 = MessageWriter.Get(SendOption.Reliable);
+ messageWriter2.StartMessage(1);
+ messageWriter2.Write(3);
+ messageWriter2.EndMessage();
+ client.Connection.Send(messageWriter2);
+ messageWriter2.Recycle();
+ return;
+ }
+ case 2:
+ if (reader.ReadInt32() == 32)
+ {
+ this.StartGame(reader, client);
+ return;
+ }
+ break;
+ case 3:
+ if (reader.ReadInt32() == 32)
+ {
+ this.ClientDisconnect(client);
+ return;
+ }
+ break;
+ case 4:
+ case 7:
+ case 9:
+ case 10:
+ break;
+ case 5:
+ if (this.Clients.Contains(client))
+ {
+ if (reader.ReadInt32() == 32)
+ {
+ MessageWriter messageWriter3 = MessageWriter.Get(sendOption);
+ messageWriter3.CopyFrom(reader);
+ this.Broadcast(messageWriter3, client);
+ messageWriter3.Recycle();
+ return;
+ }
+ }
+ else if (this.GameState == GameStates.Started)
+ {
+ client.Connection.Dispose();
+ return;
+ }
+ break;
+ case 6:
+ if (this.Clients.Contains(client))
+ {
+ if (reader.ReadInt32() == 32)
+ {
+ int targetId = reader.ReadPackedInt32();
+ MessageWriter messageWriter4 = MessageWriter.Get(sendOption);
+ messageWriter4.CopyFrom(reader);
+ this.SendTo(messageWriter4, targetId);
+ messageWriter4.Recycle();
+ return;
+ }
+ }
+ else if (this.GameState == GameStates.Started)
+ {
+ Debug.Log("GameDataTo: Server didn't have client");
+ client.Connection.Dispose();
+ return;
+ }
+ break;
+ case 8:
+ if (reader.ReadInt32() == 32)
+ {
+ this.EndGame(reader, client);
+ return;
+ }
+ break;
+ case 11:
+ if (reader.ReadInt32() == 32)
+ {
+ this.KickPlayer(reader.ReadPackedInt32(), reader.ReadBoolean());
+ }
+ break;
+ default:
+ return;
+ }
+ }
+
+ private void KickPlayer(int targetId, bool ban)
+ {
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ InnerNetServer.Player player = null;
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ if (this.Clients[i].Id == targetId)
+ {
+ player = this.Clients[i];
+ break;
+ }
+ }
+ if (player != null)
+ {
+ if (ban)
+ {
+ HashSet<string> obj = this.ipBans;
+ lock (obj)
+ {
+ IPEndPoint endPoint = player.Connection.EndPoint;
+ this.ipBans.Add(endPoint.Address.ToString());
+ }
+ }
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(11);
+ messageWriter.Write(32);
+ messageWriter.WritePacked(targetId);
+ messageWriter.Write(ban);
+ messageWriter.EndMessage();
+ this.Broadcast(messageWriter, null);
+ messageWriter.Recycle();
+ }
+ }
+ }
+
+ protected void JoinGame(InnerNetServer.Player client)
+ {
+ HashSet<string> obj = this.ipBans;
+ lock (obj)
+ {
+ IPEndPoint endPoint = client.Connection.EndPoint;
+ if (this.ipBans.Contains(endPoint.Address.ToString()))
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(1);
+ messageWriter.Write(6);
+ messageWriter.EndMessage();
+ client.Connection.Send(messageWriter);
+ messageWriter.Recycle();
+ return;
+ }
+ }
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ switch (this.GameState)
+ {
+ case GameStates.NotStarted:
+ this.HandleNewGameJoin(client);
+ break;
+ default:
+ {
+ MessageWriter messageWriter2 = MessageWriter.Get(SendOption.Reliable);
+ messageWriter2.StartMessage(1);
+ messageWriter2.Write(2);
+ messageWriter2.EndMessage();
+ client.Connection.Send(messageWriter2);
+ messageWriter2.Recycle();
+ break;
+ }
+ case GameStates.Ended:
+ this.HandleRejoin(client);
+ break;
+ }
+ }
+ }
+
+ private void HandleRejoin(InnerNetServer.Player client)
+ {
+ if (client.Id == this.HostId)
+ {
+ this.GameState = GameStates.NotStarted;
+ this.HandleNewGameJoin(client);
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ InnerNetServer.Player player = this.Clients[i];
+ if (player != client)
+ {
+ try
+ {
+ this.WriteJoinedMessage(player, messageWriter, true);
+ player.Connection.Send(messageWriter);
+ }
+ catch
+ {
+ }
+ }
+ }
+ messageWriter.Recycle();
+ return;
+ }
+ if (this.Clients.Count >= 9)
+ {
+ MessageWriter messageWriter2 = MessageWriter.Get(SendOption.Reliable);
+ messageWriter2.StartMessage(1);
+ messageWriter2.Write(1);
+ messageWriter2.EndMessage();
+ client.Connection.Send(messageWriter2);
+ messageWriter2.Recycle();
+ return;
+ }
+ this.Clients.Add(client);
+ client.LimboState = LimboStates.WaitingForHost;
+ MessageWriter messageWriter3 = MessageWriter.Get(SendOption.Reliable);
+ try
+ {
+ messageWriter3.StartMessage(12);
+ messageWriter3.Write(32);
+ messageWriter3.Write(client.Id);
+ messageWriter3.EndMessage();
+ client.Connection.Send(messageWriter3);
+ this.BroadcastJoinMessage(client, messageWriter3);
+ }
+ catch
+ {
+ }
+ finally
+ {
+ messageWriter3.Recycle();
+ }
+ }
+
+ private void HandleNewGameJoin(InnerNetServer.Player client)
+ {
+ if (this.Clients.Count >= 10)
+ {
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ try
+ {
+ messageWriter.StartMessage(1);
+ messageWriter.Write(1);
+ messageWriter.EndMessage();
+ client.Connection.Send(messageWriter);
+ }
+ catch
+ {
+ }
+ finally
+ {
+ messageWriter.Recycle();
+ }
+ return;
+ }
+ this.Clients.Add(client);
+ client.LimboState = LimboStates.PreSpawn;
+ if (this.HostId == -1)
+ {
+ this.HostId = this.Clients[0].Id;
+ }
+ if (this.HostId == client.Id)
+ {
+ client.LimboState = LimboStates.NotLimbo;
+ }
+ MessageWriter messageWriter2 = MessageWriter.Get(SendOption.Reliable);
+ try
+ {
+ this.WriteJoinedMessage(client, messageWriter2, true);
+ client.Connection.Send(messageWriter2);
+ this.BroadcastJoinMessage(client, messageWriter2);
+ }
+ catch
+ {
+ }
+ finally
+ {
+ messageWriter2.Recycle();
+ }
+ }
+
+ private void EndGame(MessageReader message, InnerNetServer.Player source)
+ {
+ if (source.Id == this.HostId)
+ {
+ this.GameState = GameStates.Ended;
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.CopyFrom(message);
+ this.Broadcast(messageWriter, null);
+ messageWriter.Recycle();
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ this.Clients.Clear();
+ return;
+ }
+ }
+ Debug.LogWarning("Reset request rejected from: " + source.Id);
+ }
+
+ private void StartGame(MessageReader message, InnerNetServer.Player source)
+ {
+ this.GameState = GameStates.Started;
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.CopyFrom(message);
+ this.Broadcast(messageWriter, null);
+ messageWriter.Recycle();
+ }
+
+ private void ClientDisconnect(InnerNetServer.Player client)
+ {
+ Debug.Log("Server DC client " + client.Id);
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ this.Clients.Remove(client);
+ client.Connection.Dispose();
+ if (this.Clients.Count > 0)
+ {
+ this.HostId = this.Clients[0].Id;
+ }
+ }
+ MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
+ messageWriter.StartMessage(4);
+ messageWriter.Write(32);
+ messageWriter.Write(client.Id);
+ messageWriter.Write(this.HostId);
+ messageWriter.Write(0);
+ messageWriter.EndMessage();
+ this.Broadcast(messageWriter, null);
+ messageWriter.Recycle();
+ }
+
+ protected void SendTo(MessageWriter msg, int targetId)
+ {
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ InnerNetServer.Player player = this.Clients[i];
+ if (player.Id == targetId)
+ {
+ try
+ {
+ player.Connection.Send(msg);
+ break;
+ }
+ catch (Exception exception)
+ {
+ Debug.LogException(exception);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ protected void Broadcast(MessageWriter msg, InnerNetServer.Player source)
+ {
+ List<InnerNetServer.Player> clients = this.Clients;
+ lock (clients)
+ {
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ InnerNetServer.Player player = this.Clients[i];
+ if (player != source)
+ {
+ try
+ {
+ player.Connection.Send(msg);
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+ }
+
+ private void BroadcastJoinMessage(InnerNetServer.Player client, MessageWriter msg)
+ {
+ msg.Clear(SendOption.Reliable);
+ msg.StartMessage(1);
+ msg.Write(32);
+ msg.Write(client.Id);
+ msg.Write(this.HostId);
+ msg.EndMessage();
+ this.Broadcast(msg, client);
+ }
+
+ private void WriteJoinedMessage(InnerNetServer.Player client, MessageWriter msg, bool clear)
+ {
+ if (clear)
+ {
+ msg.Clear(SendOption.Reliable);
+ }
+ msg.StartMessage(7);
+ msg.Write(32);
+ msg.Write(client.Id);
+ msg.Write(this.HostId);
+ msg.WritePacked(this.Clients.Count - 1);
+ for (int i = 0; i < this.Clients.Count; i++)
+ {
+ InnerNetServer.Player player = this.Clients[i];
+ if (player != client)
+ {
+ msg.WritePacked(player.Id);
+ }
+ }
+ msg.EndMessage();
+ }
+ }
+}