deterministic mirror ports derived from server MAC + upstream port
mirror = (upstream_port ^ (mac[0]<<8 | mac[5])); clamped to >=1024. Same server+upstream always yields the same local port so the user knows where to connect without checking the UI each time. Falls back to OS-assigned port if the deterministic one is already in use.
This commit is contained in:
@@ -88,15 +88,48 @@ sealed class SessionManager : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute a deterministic mirror port from the server MAC and the
|
||||
/// upstream port. XOR the upstream port with (mac[0]<<8 | mac[5]),
|
||||
/// then ensure the result is outside the privileged range.
|
||||
/// </summary>
|
||||
static ushort ComputeMirrorPort(byte[] serverMac, ushort upstreamPort)
|
||||
{
|
||||
var k = (ushort)((serverMac[0] << 8) | serverMac[5]);
|
||||
var port = (ushort)(upstreamPort ^ k);
|
||||
if (port < 1024)
|
||||
port += 1024;
|
||||
return port;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start a local TCP listener for the given upstream. Returns the mirror
|
||||
/// port, or 0 on failure.
|
||||
/// </summary>
|
||||
public int StartListener(UpstreamEntry upstream)
|
||||
{
|
||||
var listener = new TcpListener(IPAddress.Loopback, 0);
|
||||
if (_serverMac == null)
|
||||
return 0;
|
||||
|
||||
var preferred = ComputeMirrorPort(_serverMac, upstream.Port);
|
||||
|
||||
// Try the deterministic port first; fall back to OS assignment.
|
||||
TcpListener listener;
|
||||
int port;
|
||||
try
|
||||
{
|
||||
listener = new TcpListener(IPAddress.Loopback, preferred);
|
||||
listener.Start();
|
||||
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||
port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||
}
|
||||
catch
|
||||
{
|
||||
listener = new TcpListener(IPAddress.Loopback, 0);
|
||||
listener.Start();
|
||||
port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||
Log?.Invoke($"port {preferred} in use, fell back to {port}");
|
||||
}
|
||||
|
||||
var state = new ListenerState(listener, upstream);
|
||||
_listeners[port] = state;
|
||||
_ = AcceptLoop(state);
|
||||
|
||||
Reference in New Issue
Block a user