feat: [SimpleWebTransport] Add ability to specify a custom client port (for reverse proxy scenarios not using port 80/443) (#3648)

* Add ability to specify a client port (for reverse proxy scenarios not using port 80/443)

* Create custom editor for simple web transport to enable customizing client port

* Incorporate James' suggestions

* Clients can specify custom paths too

* Tidy up code, try to make new settings more user friendly (+tooltips)

* Move simplewebtransport editor into new simplewebtransport.editor asmdef

* Remove custom path from client websocket connection

* Update Assets/Mirror/Transports/SimpleWeb/Editor/ClientWebsocketSettingsDrawer.cs

Co-authored-by: MrGadget <9826063+MrGadget1024@users.noreply.github.com>

* var -> explicit type

* Remove editor asmdef

* remove private

---------

Co-authored-by: MrGadget <9826063+MrGadget1024@users.noreply.github.com>
This commit is contained in:
Andrew Allbright 2023-11-20 17:38:18 -05:00 committed by GitHub
parent dbe98740be
commit 2425898def
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 119 additions and 8 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a7a134b4d9eef45239a2d7caf7f52c3e
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,70 @@
using UnityEditor;
using UnityEngine;
namespace Mirror.SimpleWeb.Editor
{
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(ClientWebsocketSettings))]
public class ClientWebsocketSettingsDrawer : PropertyDrawer
{
readonly string websocketPortOptionName = nameof(ClientWebsocketSettings.ClientPortOption);
readonly string customPortName = nameof(ClientWebsocketSettings.CustomClientPort);
readonly GUIContent portOptionLabel = new ("Client Port Option",
"Specify what port the client websocket connection uses (default same as server port)");
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
property.isExpanded = true;
return SumPropertyHeights(property, websocketPortOptionName, customPortName);
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
DrawPortSettings(position, property);
}
void DrawPortSettings(Rect position, SerializedProperty property)
{
SerializedProperty portOptionProp = property.FindPropertyRelative(websocketPortOptionName);
SerializedProperty portProp = property.FindPropertyRelative(customPortName);
float portOptionHeight = EditorGUI.GetPropertyHeight(portOptionProp);
float portHeight = EditorGUI.GetPropertyHeight(portProp);
float spacing = EditorGUIUtility.standardVerticalSpacing;
bool wasEnabled = GUI.enabled;
position.height = portOptionHeight;
EditorGUI.PropertyField(position, portOptionProp, portOptionLabel);
position.y += spacing + portOptionHeight;
position.height = portHeight;
WebsocketPortOption portOption = (WebsocketPortOption)portOptionProp.enumValueIndex;
if (portOption == WebsocketPortOption.MatchWebpageProtocol || portOption == WebsocketPortOption.DefaultSameAsServer)
{
int port = 0;
if (property.serializedObject.targetObject is SimpleWebTransport swt)
if (portOption == WebsocketPortOption.MatchWebpageProtocol)
port = swt.clientUseWss ? 443 : 80;
else
port = swt.port;
GUI.enabled = false;
EditorGUI.IntField(position, new GUIContent("Client Port"), port);
GUI.enabled = wasEnabled;
}
else
EditorGUI.PropertyField(position, portProp);
position.y += spacing + portHeight;
}
float SumPropertyHeights(SerializedProperty property, params string[] propertyNames)
{
float totalHeight = 0;
foreach (var name in propertyNames)
totalHeight += EditorGUI.GetPropertyHeight(property.FindPropertyRelative(name)) + EditorGUIUtility.standardVerticalSpacing;
return totalHeight;
}
}
#endif
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2d0e5b00ac8e45c99e68ad95cf843f80
timeCreated: 1700081340

View File

@ -0,0 +1,17 @@
using System;
namespace Mirror.SimpleWeb
{
[Serializable]
public struct ClientWebsocketSettings
{
public WebsocketPortOption ClientPortOption;
public ushort CustomClientPort;
}
public enum WebsocketPortOption
{
DefaultSameAsServer,
MatchWebpageProtocol,
SpecifyPort
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 20ed869c5ba54a56b750ac9e82be069f
timeCreated: 1700425326

View File

@ -16,9 +16,6 @@ public class SimpleWebTransport : Transport, PortTransport
public ushort port = 7778;
public ushort Port { get => port; set => port=value; }
[Tooltip("Tells the client to use the default port. This is useful when connecting to reverse proxy rather than directly to websocket server")]
public bool ClientUseDefaultPort;
[Tooltip("Protect against allocation attacks by keeping the max message size small. Otherwise an attacker might send multiple fake packets with 2GB headers, causing the server to run out of memory after allocating multiple large packets.")]
public int maxMessageSize = 16 * 1024;
@ -51,8 +48,6 @@ public class SimpleWebTransport : Transport, PortTransport
public bool waitBeforeSend = true;
[Header("Ssl Settings")]
[Tooltip("Sets connect scheme to wss. Useful when client needs to connect using wss when TLS is outside of transport.\nNOTE: if sslEnabled is true clientUseWss is also true")]
public bool clientUseWss;
[Tooltip("Requires wss connections on server, only to be used with SSL cert.json, never with reverse proxy.\nNOTE: if sslEnabled is true clientUseWss is also true")]
public bool sslEnabled;
@ -63,6 +58,11 @@ public class SimpleWebTransport : Transport, PortTransport
[Tooltip("Protocols that SSL certificate is created to support.")]
public SslProtocols sslProtocols = SslProtocols.Tls12;
[Header("Client settings")]
[Tooltip("Sets connect scheme to wss. Useful when client needs to connect using wss when TLS is outside of transport.\nNOTE: if sslEnabled is true clientUseWss is also true")]
public bool clientUseWss;
public ClientWebsocketSettings clientWebsocketSettings;
[Header("Debug")]
[Tooltip("Log functions uses ConditionalAttribute which will effect which log methods are allowed.")]
[FormerlySerializedAs("logLevels")]
@ -126,9 +126,19 @@ public override void ClientConnect(string hostname)
Scheme = GetClientScheme(),
Host = hostname,
};
// https://github.com/MirrorNetworking/Mirror/pull/3477
if (!ClientUseDefaultPort)
builder.Port = Port;
switch (clientWebsocketSettings.ClientPortOption) {
case WebsocketPortOption.SpecifyPort:
builder.Port = clientWebsocketSettings.CustomClientPort;
break;
case WebsocketPortOption.MatchWebpageProtocol:
// not including a port in the builder allows the webpage to drive the port
// https://github.com/MirrorNetworking/Mirror/pull/3477
break;
default: // default case handles ClientWebsocketPortOption.DefaultSameAsServerPort
builder.Port = Port;
break;
}
ClientConnect(builder.Uri);
}