diff --git a/NebulaNetwork/Client.cs b/NebulaNetwork/Client.cs index c9e0b1e29..e627699d7 100644 --- a/NebulaNetwork/Client.cs +++ b/NebulaNetwork/Client.cs @@ -40,6 +40,7 @@ public class Client : IClient AccessTools.FieldRefAccess("_fragmentsBuffer"); private readonly string serverPassword; + private readonly string serverProtocol; private WebSocket clientSocket; @@ -49,15 +50,19 @@ public class Client : IClient private NebulaConnection serverConnection; private bool websocketAuthenticationFailure; - public Client(string url, int port, string password = "") - : this(new IPEndPoint(Dns.GetHostEntry(url).AddressList[0], port), password) + public Client(string url, int port, string protocol, string password = "") + : this(new IPEndPoint(Dns.GetHostEntry(url).AddressList[0], port), protocol, password) { } - public Client(IPEndPoint endpoint, string password = "") + public Client(IPEndPoint endpoint, string protocol = "", string password = "") { ServerEndpoint = endpoint; serverPassword = password; + if (protocol != "") + { + serverProtocol = protocol; + } } public IPEndPoint ServerEndpoint { get; set; } @@ -80,7 +85,7 @@ public void Start() PacketProcessor.SimulateLatency = true; #endif - clientSocket = new WebSocket($"ws://{ServerEndpoint}/socket"); + clientSocket = new WebSocket($"{serverProtocol}://{ServerEndpoint}/socket"); clientSocket.Log.Level = LogLevel.Debug; clientSocket.Log.Output = Log.SocketOutput; clientSocket.OnOpen += ClientSocket_OnOpen; @@ -112,8 +117,8 @@ public void Start() if (Config.Options.RememberLastIP) { - // We've successfully connected, set connection as last ip, cutting out "ws://" and "/socket" - Config.Options.LastIP = ServerEndpoint.ToString(); + // We've successfully connected, set connection as last ip, cutting out "ws://"(but not others, like wss) and "/socket" + Config.Options.LastIP = serverProtocol == "ws" ? ServerEndpoint.ToString() : $"{serverProtocol}://{ServerEndpoint.ToString()}"; Config.SaveOptions(); } @@ -264,6 +269,16 @@ private void ClientSocket_OnOpen(object sender, EventArgs e) private void ClientSocket_OnClose(object sender, CloseEventArgs e) { + // Unity's TLS bug workaround, see https://github.com/sta/websocket-sharp/issues/219 + var sslProtocolHack = (System.Security.Authentication.SslProtocols)(0xC00 | 0x300 | 0xC0); + // TlsHandshakeFailure: 1015 + if (e.Code == 1015 && clientSocket.SslConfiguration.EnabledSslProtocols != sslProtocolHack) + { + clientSocket.SslConfiguration.EnabledSslProtocols = sslProtocolHack; + clientSocket.Connect(); + return; + } + serverConnection = null; UnityDispatchQueue.RunOnMainThread(() => diff --git a/NebulaPatcher/Patches/Dynamic/UIMainMenu_Patch.cs b/NebulaPatcher/Patches/Dynamic/UIMainMenu_Patch.cs index 491efbfed..fa24b8a50 100644 --- a/NebulaPatcher/Patches/Dynamic/UIMainMenu_Patch.cs +++ b/NebulaPatcher/Patches/Dynamic/UIMainMenu_Patch.cs @@ -273,6 +273,22 @@ public static void JoinGame(string ip, string password = "") // Remove whitespaces from connection string var s = ip; + // Parse protocol if set + var protocol = "ws"; + var firstColonPos = s.IndexOf("://"); + if (firstColonPos > 0) + { + var candidate = s.Substring(0, firstColonPos); + switch (candidate) + { + case "wss": + case "ws": + protocol = candidate; + s = s.Substring(firstColonPos + 3); + break; + } + } + // Taken from .net IPEndPoint IPEndPoint result = null; var addressLength = s.Length; // If there's no port then send the entire string to the address parser @@ -330,10 +346,10 @@ public static void JoinGame(string ip, string password = "") p = p == 0 ? Config.Options.HostPort : p; - UIRoot.instance.StartCoroutine(TryConnectToServer(s, p, isIP, password)); + UIRoot.instance.StartCoroutine(TryConnectToServer(s, protocol, p, isIP, password)); } - private static IEnumerator TryConnectToServer(string ip, int port, bool isIP, string password) + private static IEnumerator TryConnectToServer(string ip, string protocol, int port, bool isIP, string password) { InGamePopup.ShowInfo("Connecting".Translate(), "Connecting to server...".Translate(), null); multiplayerMenu.gameObject.SetActive(false); @@ -341,7 +357,7 @@ private static IEnumerator TryConnectToServer(string ip, int port, bool isIP, st // We need to wait here to have time to display the Connecting popup since the game freezes during the connection. yield return new WaitForSeconds(0.5f); - if (!ConnectToServer(ip, port, isIP, password)) + if (!ConnectToServer(ip, protocol, port, isIP, password)) { InGamePopup.FadeOut(); //re-enabling the menu again after failed connect attempt @@ -360,13 +376,13 @@ private static void OnJoinGameBackButtonClick() UIRoot.instance.OpenMainMenuUI(); } - private static bool ConnectToServer(string connectionString, int serverPort, bool isIP, string password) + private static bool ConnectToServer(string connectionString, string protocol, int serverPort, bool isIP, string password) { try { if (isIP) { - Multiplayer.JoinGame(new Client(new IPEndPoint(IPAddress.Parse(connectionString), serverPort), password)); + Multiplayer.JoinGame(new Client(new IPEndPoint(IPAddress.Parse(connectionString), serverPort), protocol, password)); return true; } @@ -375,7 +391,7 @@ private static bool ConnectToServer(string connectionString, int serverPort, boo { return false; } - Multiplayer.JoinGame(new Client(connectionString, serverPort, password)); + Multiplayer.JoinGame(new Client(connectionString, serverPort, protocol, password)); return true; } catch (Exception e)