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>
|
/// <summary>
|
||||||
/// Start a local TCP listener for the given upstream. Returns the mirror
|
/// Start a local TCP listener for the given upstream. Returns the mirror
|
||||||
/// port, or 0 on failure.
|
/// port, or 0 on failure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int StartListener(UpstreamEntry upstream)
|
public int StartListener(UpstreamEntry upstream)
|
||||||
{
|
{
|
||||||
var listener = new TcpListener(IPAddress.Loopback, 0);
|
if (_serverMac == null)
|
||||||
listener.Start();
|
return 0;
|
||||||
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
|
||||||
|
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();
|
||||||
|
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);
|
var state = new ListenerState(listener, upstream);
|
||||||
_listeners[port] = state;
|
_listeners[port] = state;
|
||||||
_ = AcceptLoop(state);
|
_ = AcceptLoop(state);
|
||||||
|
|||||||
Reference in New Issue
Block a user