quantum-space-buddies/QuantumUNET/QSBNetworkClient.cs

921 lines
23 KiB
C#
Raw Normal View History

2020-12-04 22:15:41 +00:00
using OWML.Logging;
2020-12-07 21:19:16 +00:00
using QuantumUNET.Messages;
using QuantumUNET.Transport;
2020-12-02 18:40:38 +00:00
using System;
2020-12-02 12:42:26 +00:00
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
using UnityEngine.Networking;
2020-12-04 22:14:53 +00:00
namespace QuantumUNET
2020-12-02 12:42:26 +00:00
{
2020-12-02 18:40:38 +00:00
public class QSBNetworkClient
2020-12-02 12:42:26 +00:00
{
public QSBNetworkClient()
{
m_MsgBuffer = new byte[65535];
m_MsgReader = new NetworkReader(m_MsgBuffer);
AddClient(this);
}
public QSBNetworkClient(QSBNetworkConnection conn)
{
m_MsgBuffer = new byte[65535];
m_MsgReader = new NetworkReader(m_MsgBuffer);
AddClient(this);
SetActive(true);
m_Connection = conn;
m_AsyncConnect = ConnectState.Connected;
conn.SetHandlers(m_MessageHandlers);
RegisterSystemHandlers(false);
}
public static List<QSBNetworkClient> allClients { get; private set; } = new List<QSBNetworkClient>();
2020-12-02 12:42:26 +00:00
public static bool active { get; private set; }
2020-12-02 12:42:26 +00:00
internal void SetHandlers(QSBNetworkConnection conn) => conn.SetHandlers(m_MessageHandlers);
2020-12-02 12:42:26 +00:00
public string serverIp { get; private set; } = "";
2020-12-02 12:42:26 +00:00
public int serverPort { get; private set; }
2020-12-02 12:42:26 +00:00
public QSBNetworkConnection connection => m_Connection;
2020-12-02 12:42:26 +00:00
internal int hostId { get; private set; } = -1;
2020-12-02 12:42:26 +00:00
public Dictionary<short, QSBNetworkMessageDelegate> handlers => m_MessageHandlers.GetHandlers();
2020-12-02 12:42:26 +00:00
public int numChannels => hostTopology.DefaultConfig.ChannelCount;
2020-12-02 12:42:26 +00:00
public HostTopology hostTopology { get; private set; }
2020-12-02 12:42:26 +00:00
public int hostPort
{
2020-12-18 20:28:22 +00:00
get => m_HostPort;
2020-12-02 12:42:26 +00:00
set
{
if (value < 0)
{
throw new ArgumentException("Port must not be a negative number.");
}
if (value > 65535)
{
throw new ArgumentException("Port must not be greater than 65535.");
}
m_HostPort = value;
}
}
public bool isConnected => m_AsyncConnect == ConnectState.Connected;
2020-12-02 12:42:26 +00:00
public Type networkConnectionClass { get; private set; } = typeof(QSBNetworkConnection);
2020-12-02 12:42:26 +00:00
public void SetNetworkConnectionClass<T>() where T : QSBNetworkConnection => networkConnectionClass = typeof(T);
2020-12-02 12:42:26 +00:00
public bool Configure(ConnectionConfig config, int maxConnections)
{
var topology = new HostTopology(config, maxConnections);
2020-12-02 12:42:26 +00:00
return Configure(topology);
}
public bool Configure(HostTopology topology)
{
hostTopology = topology;
2020-12-02 12:42:26 +00:00
return true;
}
public bool ReconnectToNewHost(string serverIp, int serverPort)
{
bool result;
if (!active)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect - NetworkClient must be active");
2020-12-02 12:42:26 +00:00
result = false;
}
else if (m_Connection == null)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect - no old connection exists");
2020-12-02 12:42:26 +00:00
result = false;
}
else
{
2020-12-18 20:20:54 +00:00
Debug.Log(string.Concat(new object[]
2020-12-02 12:42:26 +00:00
{
"NetworkClient Reconnect ",
serverIp,
":",
serverPort
2020-12-18 20:20:54 +00:00
}));
2020-12-02 12:42:26 +00:00
QSBClientScene.HandleClientDisconnect(m_Connection);
QSBClientScene.ClearLocalPlayers();
m_Connection.Disconnect();
m_Connection = null;
hostId = NetworkTransport.AddHost(hostTopology, m_HostPort);
this.serverPort = serverPort;
2020-12-02 12:42:26 +00:00
if (Application.platform == RuntimePlatform.WebGLPlayer)
{
this.serverIp = serverIp;
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Resolved;
}
else if (serverIp.Equals("127.0.0.1") || serverIp.Equals("localhost"))
{
this.serverIp = "127.0.0.1";
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Resolved;
}
else
{
2020-12-18 20:20:54 +00:00
Debug.Log("Async DNS START:" + serverIp);
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Resolving;
Dns.BeginGetHostAddresses(serverIp, new AsyncCallback(GetHostAddressesCallback), this);
}
result = true;
}
return result;
}
public bool ReconnectToNewHost(EndPoint secureTunnelEndPoint)
{
bool result;
if (!active)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect - NetworkClient must be active");
2020-12-02 12:42:26 +00:00
result = false;
}
else if (m_Connection == null)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect - no old connection exists");
2020-12-02 12:42:26 +00:00
result = false;
}
else
{
2020-12-18 20:20:54 +00:00
Debug.Log("NetworkClient Reconnect to remoteSockAddr");
2020-12-02 12:42:26 +00:00
QSBClientScene.HandleClientDisconnect(m_Connection);
QSBClientScene.ClearLocalPlayers();
m_Connection.Disconnect();
m_Connection = null;
hostId = NetworkTransport.AddHost(hostTopology, m_HostPort);
2020-12-02 12:42:26 +00:00
if (secureTunnelEndPoint == null)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect failed: null endpoint passed in");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
result = false;
}
else if (secureTunnelEndPoint.AddressFamily != AddressFamily.InterNetwork && secureTunnelEndPoint.AddressFamily != AddressFamily.InterNetworkV6)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect failed: Endpoint AddressFamily must be either InterNetwork or InterNetworkV6");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
result = false;
}
else
{
var fullName = secureTunnelEndPoint.GetType().FullName;
2020-12-02 12:42:26 +00:00
if (fullName == "System.Net.IPEndPoint")
{
var ipendPoint = (IPEndPoint)secureTunnelEndPoint;
Connect(ipendPoint.Address.ToString(), ipendPoint.Port);
2020-12-02 12:42:26 +00:00
result = (m_AsyncConnect != ConnectState.Failed);
}
else if (fullName != "UnityEngine.XboxOne.XboxOneEndPoint" && fullName != "UnityEngine.PS4.SceEndPoint")
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect failed: invalid Endpoint (not IPEndPoint or XboxOneEndPoint or SceEndPoint)");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
result = false;
}
else
{
m_RemoteEndPoint = secureTunnelEndPoint;
m_AsyncConnect = ConnectState.Connecting;
byte b;
2020-12-02 12:42:26 +00:00
try
{
m_ClientConnectionId = NetworkTransport.ConnectEndPoint(hostId, m_RemoteEndPoint, 0, out b);
2020-12-02 12:42:26 +00:00
}
catch (Exception arg)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect failed: Exception when trying to connect to EndPoint: " + arg);
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
return false;
}
if (m_ClientConnectionId == 0)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Reconnect failed: Unable to connect to EndPoint (" + b + ")");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
result = false;
}
else
{
m_Connection = (QSBNetworkConnection)Activator.CreateInstance(networkConnectionClass);
2020-12-02 12:42:26 +00:00
m_Connection.SetHandlers(m_MessageHandlers);
m_Connection.Initialize(serverIp, hostId, m_ClientConnectionId, hostTopology);
2020-12-02 12:42:26 +00:00
result = true;
}
}
}
}
return result;
}
public void ConnectWithSimulator(string serverIp, int serverPort, int latency, float packetLoss)
{
m_UseSimulator = true;
m_SimulatedLatency = latency;
m_PacketLoss = packetLoss;
Connect(serverIp, serverPort);
}
private static bool IsValidIpV6(string address)
{
foreach (var c in address)
2020-12-02 12:42:26 +00:00
{
if (c != ':' && (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F'))
{
return false;
}
}
return true;
}
public void Connect(string serverIp, int serverPort)
{
PrepareForConnect();
this.serverPort = serverPort;
2020-12-02 12:42:26 +00:00
if (Application.platform == RuntimePlatform.WebGLPlayer)
{
this.serverIp = serverIp;
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Resolved;
}
else if (serverIp.Equals("127.0.0.1") || serverIp.Equals("localhost"))
{
this.serverIp = "127.0.0.1";
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Resolved;
}
else if (serverIp.IndexOf(":") != -1 && IsValidIpV6(serverIp))
{
this.serverIp = serverIp;
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Resolved;
}
else
{
2020-12-04 22:14:53 +00:00
ModConsole.OwmlConsole.WriteLine("Async DNS START:" + serverIp);
2020-12-02 12:42:26 +00:00
m_RequestedServerHost = serverIp;
m_AsyncConnect = ConnectState.Resolving;
Dns.BeginGetHostAddresses(serverIp, new AsyncCallback(GetHostAddressesCallback), this);
}
}
public void Connect(EndPoint secureTunnelEndPoint)
{
2020-12-02 18:40:38 +00:00
//bool usePlatformSpecificProtocols = NetworkTransport.DoesEndPointUsePlatformProtocols(secureTunnelEndPoint);
var usePlatformSpecificProtocols = false;
2020-12-02 12:42:26 +00:00
PrepareForConnect(usePlatformSpecificProtocols);
2020-12-18 20:20:54 +00:00
Debug.Log("Client Connect to remoteSockAddr");
2020-12-02 12:42:26 +00:00
if (secureTunnelEndPoint == null)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Connect failed: null endpoint passed in");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
}
else if (secureTunnelEndPoint.AddressFamily != AddressFamily.InterNetwork && secureTunnelEndPoint.AddressFamily != AddressFamily.InterNetworkV6)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Connect failed: Endpoint AddressFamily must be either InterNetwork or InterNetworkV6");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
}
else
{
var fullName = secureTunnelEndPoint.GetType().FullName;
2020-12-02 12:42:26 +00:00
if (fullName == "System.Net.IPEndPoint")
{
var ipendPoint = (IPEndPoint)secureTunnelEndPoint;
Connect(ipendPoint.Address.ToString(), ipendPoint.Port);
2020-12-02 12:42:26 +00:00
}
else if (fullName != "UnityEngine.XboxOne.XboxOneEndPoint" && fullName != "UnityEngine.PS4.SceEndPoint" && fullName != "UnityEngine.PSVita.SceEndPoint")
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Connect failed: invalid Endpoint (not IPEndPoint or XboxOneEndPoint or SceEndPoint)");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
}
else
{
byte b = 0;
m_RemoteEndPoint = secureTunnelEndPoint;
m_AsyncConnect = ConnectState.Connecting;
try
{
m_ClientConnectionId = NetworkTransport.ConnectEndPoint(hostId, m_RemoteEndPoint, 0, out b);
2020-12-02 12:42:26 +00:00
}
catch (Exception arg)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Connect failed: Exception when trying to connect to EndPoint: " + arg);
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
return;
}
if (m_ClientConnectionId == 0)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("Connect failed: Unable to connect to EndPoint (" + b + ")");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Failed;
}
else
{
m_Connection = (QSBNetworkConnection)Activator.CreateInstance(networkConnectionClass);
2020-12-02 12:42:26 +00:00
m_Connection.SetHandlers(m_MessageHandlers);
m_Connection.Initialize(serverIp, hostId, m_ClientConnectionId, hostTopology);
2020-12-02 12:42:26 +00:00
}
}
}
}
private void PrepareForConnect() => PrepareForConnect(false);
2020-12-02 12:42:26 +00:00
private void PrepareForConnect(bool usePlatformSpecificProtocols)
{
SetActive(true);
RegisterSystemHandlers(false);
if (hostTopology == null)
2020-12-02 12:42:26 +00:00
{
var connectionConfig = new ConnectionConfig();
2020-12-02 12:42:26 +00:00
connectionConfig.AddChannel(QosType.ReliableSequenced);
connectionConfig.AddChannel(QosType.Unreliable);
connectionConfig.UsePlatformSpecificProtocols = usePlatformSpecificProtocols;
hostTopology = new HostTopology(connectionConfig, 8);
2020-12-02 12:42:26 +00:00
}
if (m_UseSimulator)
{
var num = (m_SimulatedLatency / 3) - 1;
2020-12-02 12:42:26 +00:00
if (num < 1)
{
num = 1;
}
var num2 = m_SimulatedLatency * 3;
2020-12-04 22:14:53 +00:00
ModConsole.OwmlConsole.WriteLine(string.Concat(new object[]
2020-12-02 12:42:26 +00:00
{
2020-12-02 18:40:38 +00:00
"AddHost Using Simulator ",
num,
"/",
num2
}));
hostId = NetworkTransport.AddHostWithSimulator(hostTopology, num, num2, m_HostPort);
2020-12-02 12:42:26 +00:00
}
else
{
hostId = NetworkTransport.AddHost(hostTopology, m_HostPort);
2020-12-02 12:42:26 +00:00
}
}
internal static void GetHostAddressesCallback(IAsyncResult ar)
{
try
{
var array = Dns.EndGetHostAddresses(ar);
var networkClient = (QSBNetworkClient)ar.AsyncState;
2020-12-02 12:42:26 +00:00
if (array.Length == 0)
{
2020-12-02 18:40:38 +00:00
Debug.LogError("DNS lookup failed for:" + networkClient.m_RequestedServerHost);
2020-12-02 12:42:26 +00:00
networkClient.m_AsyncConnect = ConnectState.Failed;
}
else
{
networkClient.serverIp = array[0].ToString();
2020-12-02 12:42:26 +00:00
networkClient.m_AsyncConnect = ConnectState.Resolved;
2020-12-02 18:40:38 +00:00
Debug.Log(string.Concat(new string[]
2020-12-02 12:42:26 +00:00
{
2020-12-02 18:40:38 +00:00
"Async DNS Result:",
networkClient.serverIp,
2020-12-02 18:40:38 +00:00
" for ",
networkClient.m_RequestedServerHost,
": ",
networkClient.serverIp
2020-12-02 18:40:38 +00:00
}));
2020-12-02 12:42:26 +00:00
}
}
catch (SocketException ex)
{
var networkClient2 = (QSBNetworkClient)ar.AsyncState;
2020-12-02 18:40:38 +00:00
Debug.LogError("DNS resolution failed: " + ex.GetErrorCode());
Debug.LogError("Exception:" + ex);
2020-12-02 12:42:26 +00:00
networkClient2.m_AsyncConnect = ConnectState.Failed;
}
}
internal void ContinueConnect()
{
if (m_UseSimulator)
{
var num = m_SimulatedLatency / 3;
2020-12-02 12:42:26 +00:00
if (num < 1)
{
num = 1;
}
2020-12-04 22:14:53 +00:00
ModConsole.OwmlConsole.WriteLine(string.Concat(new object[]
2020-12-02 12:42:26 +00:00
{
2020-12-02 18:40:38 +00:00
"Connect Using Simulator ",
m_SimulatedLatency / 3,
"/",
m_SimulatedLatency
}));
var conf = new ConnectionSimulatorConfig(num, m_SimulatedLatency, num, m_SimulatedLatency, m_PacketLoss);
m_ClientConnectionId = NetworkTransport.ConnectWithSimulator(hostId, serverIp, serverPort, 0, out var b, conf);
2020-12-02 12:42:26 +00:00
}
else
{
m_ClientConnectionId = NetworkTransport.Connect(hostId, serverIp, serverPort, 0, out var b);
2020-12-02 12:42:26 +00:00
}
m_Connection = (QSBNetworkConnection)Activator.CreateInstance(networkConnectionClass);
2020-12-02 12:42:26 +00:00
m_Connection.SetHandlers(m_MessageHandlers);
m_Connection.Initialize(serverIp, hostId, m_ClientConnectionId, hostTopology);
2020-12-02 12:42:26 +00:00
}
public virtual void Disconnect()
{
m_AsyncConnect = ConnectState.Disconnected;
QSBClientScene.HandleClientDisconnect(m_Connection);
if (m_Connection != null)
{
m_Connection.Disconnect();
m_Connection.Dispose();
m_Connection = null;
if (hostId != -1)
2020-12-02 12:42:26 +00:00
{
NetworkTransport.RemoveHost(hostId);
hostId = -1;
2020-12-02 12:42:26 +00:00
}
}
}
2020-12-04 09:23:27 +00:00
public bool Send(short msgType, QSBMessageBase msg)
2020-12-02 12:42:26 +00:00
{
bool result;
if (m_Connection != null)
{
if (m_AsyncConnect != ConnectState.Connected)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient Send when not connected to a server");
2020-12-02 12:42:26 +00:00
result = false;
}
else
{
result = m_Connection.Send(msgType, msg);
}
}
else
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient Send with no connection");
2020-12-02 12:42:26 +00:00
result = false;
}
return result;
}
2020-12-04 09:23:27 +00:00
public bool SendWriter(QSBNetworkWriter writer, int channelId)
2020-12-02 12:42:26 +00:00
{
bool result;
if (m_Connection != null)
{
if (m_AsyncConnect != ConnectState.Connected)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient SendWriter when not connected to a server");
2020-12-02 12:42:26 +00:00
result = false;
}
else
{
result = m_Connection.SendWriter(writer, channelId);
}
}
else
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient SendWriter with no connection");
2020-12-02 12:42:26 +00:00
result = false;
}
return result;
}
public bool SendBytes(byte[] data, int numBytes, int channelId)
{
bool result;
if (m_Connection != null)
{
if (m_AsyncConnect != ConnectState.Connected)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient SendBytes when not connected to a server");
2020-12-02 12:42:26 +00:00
result = false;
}
else
{
result = m_Connection.SendBytes(data, numBytes, channelId);
}
}
else
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient SendBytes with no connection");
2020-12-02 12:42:26 +00:00
result = false;
}
return result;
}
2020-12-04 09:23:27 +00:00
public bool SendUnreliable(short msgType, QSBMessageBase msg)
2020-12-02 12:42:26 +00:00
{
bool result;
if (m_Connection != null)
{
if (m_AsyncConnect != ConnectState.Connected)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient SendUnreliable when not connected to a server");
2020-12-02 12:42:26 +00:00
result = false;
}
else
{
result = m_Connection.SendUnreliable(msgType, msg);
}
}
else
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient SendUnreliable with no connection");
2020-12-02 12:42:26 +00:00
result = false;
}
return result;
}
2020-12-04 09:23:27 +00:00
public bool SendByChannel(short msgType, QSBMessageBase msg, int channelId)
2020-12-02 12:42:26 +00:00
{
bool result;
if (m_Connection != null)
{
if (m_AsyncConnect != ConnectState.Connected)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient SendByChannel when not connected to a server");
2020-12-02 12:42:26 +00:00
result = false;
}
else
{
result = m_Connection.SendByChannel(msgType, msg, channelId);
}
}
else
{
2020-12-18 20:20:54 +00:00
Debug.LogError("NetworkClient SendByChannel with no connection");
2020-12-02 12:42:26 +00:00
result = false;
}
return result;
}
public void SetMaxDelay(float seconds)
{
if (m_Connection == null)
{
2020-12-18 20:20:54 +00:00
Debug.LogWarning("SetMaxDelay failed, not connected.");
2020-12-02 12:42:26 +00:00
}
else
{
m_Connection.SetMaxDelay(seconds);
}
}
public void Shutdown()
{
2020-12-18 20:20:54 +00:00
Debug.Log("Shutting down client " + hostId);
if (hostId != -1)
2020-12-02 12:42:26 +00:00
{
NetworkTransport.RemoveHost(hostId);
hostId = -1;
2020-12-02 12:42:26 +00:00
}
RemoveClient(this);
if (allClients.Count == 0)
2020-12-02 12:42:26 +00:00
{
SetActive(false);
}
}
internal virtual void Update()
{
if (hostId != -1)
2020-12-02 12:42:26 +00:00
{
switch (m_AsyncConnect)
{
case ConnectState.None:
case ConnectState.Resolving:
case ConnectState.Disconnected:
return;
case ConnectState.Resolved:
m_AsyncConnect = ConnectState.Connecting;
ContinueConnect();
return;
case ConnectState.Failed:
GenerateConnectError(11);
m_AsyncConnect = ConnectState.Disconnected;
return;
}
if (m_Connection != null)
{
if ((int)Time.time != m_StatResetTime)
{
m_Connection.ResetStats();
m_StatResetTime = (int)Time.time;
}
}
var num = 0;
2020-12-02 12:42:26 +00:00
byte b;
for (; ; )
{
var networkEventType = NetworkTransport.ReceiveFromHost(hostId, out var num2, out var channelId, m_MsgBuffer, (ushort)m_MsgBuffer.Length, out var numBytes, out b);
2020-12-02 12:42:26 +00:00
if (m_Connection != null)
{
m_Connection.LastError = (NetworkError)b;
}
switch (networkEventType)
{
case NetworkEventType.DataEvent:
if (b != 0)
{
goto Block_11;
}
m_MsgReader.SeekZero();
m_Connection.TransportReceive(m_MsgBuffer, numBytes, channelId);
break;
2020-12-03 08:28:05 +00:00
2020-12-02 12:42:26 +00:00
case NetworkEventType.ConnectEvent:
2020-12-18 20:20:54 +00:00
Debug.Log("Client connected");
2020-12-02 12:42:26 +00:00
if (b != 0)
{
goto Block_10;
}
m_AsyncConnect = ConnectState.Connected;
m_Connection.InvokeHandlerNoData(32);
break;
2020-12-03 08:28:05 +00:00
2020-12-02 12:42:26 +00:00
case NetworkEventType.DisconnectEvent:
2020-12-18 20:20:54 +00:00
Debug.Log("Client disconnected");
2020-12-02 12:42:26 +00:00
m_AsyncConnect = ConnectState.Disconnected;
if (b != 0)
{
if (b != 6)
{
GenerateDisconnectError(b);
2020-12-02 12:42:26 +00:00
}
}
QSBClientScene.HandleClientDisconnect(m_Connection);
if (m_Connection != null)
{
m_Connection.InvokeHandlerNoData(33);
}
break;
2020-12-03 08:28:05 +00:00
2020-12-02 12:42:26 +00:00
case NetworkEventType.Nothing:
break;
2020-12-03 08:28:05 +00:00
2020-12-02 12:42:26 +00:00
default:
2020-12-18 20:20:54 +00:00
Debug.LogError("Unknown network message type received: " + networkEventType);
2020-12-02 12:42:26 +00:00
break;
}
if (++num >= 500)
{
goto Block_17;
}
if (hostId == -1)
2020-12-02 12:42:26 +00:00
{
goto Block_19;
}
if (networkEventType == NetworkEventType.Nothing)
{
goto IL_2C6;
}
}
Block_10:
GenerateConnectError(b);
2020-12-02 12:42:26 +00:00
return;
Block_11:
GenerateDataError(b);
2020-12-02 12:42:26 +00:00
return;
Block_17:
2020-12-18 20:20:54 +00:00
Debug.Log("MaxEventsPerFrame hit (" + 500 + ")");
2020-12-02 12:42:26 +00:00
Block_19:
IL_2C6:
if (m_Connection != null && m_AsyncConnect == ConnectState.Connected)
{
m_Connection.FlushChannels();
}
}
}
private void GenerateConnectError(int error)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("UNet Client Error Connect Error: " + error);
2020-12-02 12:42:26 +00:00
GenerateError(error);
}
private void GenerateDataError(int error)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("UNet Client Data Error: " + (NetworkError)error);
2020-12-02 12:42:26 +00:00
GenerateError(error);
}
private void GenerateDisconnectError(int error)
{
2020-12-18 20:20:54 +00:00
Debug.LogError("UNet Client Disconnect Error: " + (NetworkError)error);
2020-12-02 12:42:26 +00:00
GenerateError(error);
}
private void GenerateError(int error)
{
var handler = m_MessageHandlers.GetHandler(34);
2020-12-02 12:42:26 +00:00
if (handler == null)
{
handler = m_MessageHandlers.GetHandler(34);
}
if (handler != null)
{
var errorMessage = new QSBErrorMessage
{
errorCode = error
};
var buffer = new byte[200];
var writer = new QSBNetworkWriter(buffer);
2020-12-02 12:42:26 +00:00
errorMessage.Serialize(writer);
var reader = new QSBNetworkReader(buffer);
2020-12-02 12:42:26 +00:00
handler(new QSBNetworkMessage
{
2020-12-03 11:56:32 +00:00
MsgType = 34,
Reader = reader,
Connection = m_Connection,
ChannelId = 0
2020-12-02 12:42:26 +00:00
});
}
}
public void GetStatsOut(out int numMsgs, out int numBufferedMsgs, out int numBytes, out int lastBufferedPerSecond)
{
numMsgs = 0;
numBufferedMsgs = 0;
numBytes = 0;
lastBufferedPerSecond = 0;
if (m_Connection != null)
{
m_Connection.GetStatsOut(out numMsgs, out numBufferedMsgs, out numBytes, out lastBufferedPerSecond);
}
}
public void GetStatsIn(out int numMsgs, out int numBytes)
{
numMsgs = 0;
numBytes = 0;
if (m_Connection != null)
{
m_Connection.GetStatsIn(out numMsgs, out numBytes);
}
}
public Dictionary<short, QSBNetworkConnection.PacketStat> GetConnectionStats()
{
Dictionary<short, QSBNetworkConnection.PacketStat> result;
if (m_Connection == null)
{
result = null;
}
else
{
result = m_Connection.PacketStats;
}
return result;
}
public void ResetConnectionStats()
{
if (m_Connection != null)
{
m_Connection.ResetStats();
}
}
public int GetRTT()
{
int result;
if (hostId == -1)
2020-12-02 12:42:26 +00:00
{
result = 0;
}
else
{
result = NetworkTransport.GetCurrentRTT(hostId, m_ClientConnectionId, out var b);
2020-12-02 12:42:26 +00:00
}
return result;
}
internal void RegisterSystemHandlers(bool localClient)
{
QSBClientScene.RegisterSystemHandlers(this, localClient);
RegisterHandlerSafe(14, new QSBNetworkMessageDelegate(OnCRC));
2020-12-02 12:42:26 +00:00
}
private void OnCRC(QSBNetworkMessage netMsg)
{
2020-12-02 18:40:38 +00:00
netMsg.ReadMessage<QSBCRCMessage>(s_CRCMessage);
QSBNetworkCRC.Validate(s_CRCMessage.scripts, numChannels);
2020-12-02 12:42:26 +00:00
}
public void RegisterHandler(short msgType, QSBNetworkMessageDelegate handler) => m_MessageHandlers.RegisterHandler(msgType, handler);
2020-12-02 12:42:26 +00:00
public void RegisterHandlerSafe(short msgType, QSBNetworkMessageDelegate handler) => m_MessageHandlers.RegisterHandlerSafe(msgType, handler);
2020-12-02 12:42:26 +00:00
public void UnregisterHandler(short msgType) => m_MessageHandlers.UnregisterHandler(msgType);
2020-12-02 12:42:26 +00:00
public static Dictionary<short, QSBNetworkConnection.PacketStat> GetTotalConnectionStats()
{
var dictionary = new Dictionary<short, QSBNetworkConnection.PacketStat>();
for (var i = 0; i < allClients.Count; i++)
2020-12-02 12:42:26 +00:00
{
var networkClient = allClients[i];
var connectionStats = networkClient.GetConnectionStats();
foreach (var key in connectionStats.Keys)
2020-12-02 12:42:26 +00:00
{
if (dictionary.ContainsKey(key))
{
var packetStat = dictionary[key];
2020-12-02 12:42:26 +00:00
packetStat.count += connectionStats[key].count;
packetStat.bytes += connectionStats[key].bytes;
dictionary[key] = packetStat;
}
else
{
dictionary[key] = new QSBNetworkConnection.PacketStat(connectionStats[key]);
}
}
}
return dictionary;
}
internal static void AddClient(QSBNetworkClient client) => allClients.Add(client);
2020-12-02 12:42:26 +00:00
internal static bool RemoveClient(QSBNetworkClient client) => allClients.Remove(client);
2020-12-02 12:42:26 +00:00
internal static void UpdateClients()
{
for (var i = 0; i < allClients.Count; i++)
2020-12-02 12:42:26 +00:00
{
if (allClients[i] != null)
2020-12-02 12:42:26 +00:00
{
allClients[i].Update();
2020-12-02 12:42:26 +00:00
}
else
{
allClients.RemoveAt(i);
2020-12-02 12:42:26 +00:00
}
}
}
public static void ShutdownAll()
{
while (allClients.Count != 0)
2020-12-02 12:42:26 +00:00
{
allClients[0].Shutdown();
2020-12-02 12:42:26 +00:00
}
allClients = new List<QSBNetworkClient>();
active = false;
2020-12-02 12:42:26 +00:00
QSBClientScene.Shutdown();
}
internal static void SetActive(bool state)
{
if (!active && state)
2020-12-02 12:42:26 +00:00
{
NetworkTransport.Init();
}
active = state;
2020-12-02 12:42:26 +00:00
}
private const int k_MaxEventsPerFrame = 500;
private int m_HostPort;
private bool m_UseSimulator;
private int m_SimulatedLatency;
private float m_PacketLoss;
private int m_ClientConnectionId = -1;
private int m_StatResetTime;
private EndPoint m_RemoteEndPoint;
2020-12-18 20:32:16 +00:00
private static readonly QSBCRCMessage s_CRCMessage = new QSBCRCMessage();
2020-12-02 12:42:26 +00:00
2020-12-18 20:32:16 +00:00
private readonly QSBNetworkMessageHandlers m_MessageHandlers = new QSBNetworkMessageHandlers();
2020-12-02 12:42:26 +00:00
protected QSBNetworkConnection m_Connection;
2020-12-18 20:32:16 +00:00
private readonly byte[] m_MsgBuffer;
2020-12-02 12:42:26 +00:00
2020-12-18 20:32:16 +00:00
private readonly NetworkReader m_MsgReader;
2020-12-02 12:42:26 +00:00
protected ConnectState m_AsyncConnect = ConnectState.None;
private string m_RequestedServerHost = "";
protected enum ConnectState
{
None,
Resolving,
Resolved,
Connecting,
Connected,
Disconnected,
Failed
}
}
2020-12-03 08:28:05 +00:00
}