mirror of
https://github.com/microsoft/autogen.git
synced 2025-11-14 17:13:29 +00:00
68 lines
2.0 KiB
C#
68 lines
2.0 KiB
C#
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
|
// FreePortManager.cs
|
||
|
|
|
||
|
|
using System.Diagnostics;
|
||
|
|
|
||
|
|
namespace Microsoft.AutoGen.Core.Grpc.Tests;
|
||
|
|
|
||
|
|
internal sealed class FreePortManager
|
||
|
|
{
|
||
|
|
private HashSet<int> takenPorts = new();
|
||
|
|
private readonly object mutex = new();
|
||
|
|
|
||
|
|
[DebuggerDisplay($"{{{nameof(Port)}}}")]
|
||
|
|
internal sealed class PortTicket(FreePortManager portManager, int port) : IDisposable
|
||
|
|
{
|
||
|
|
private FreePortManager? portManager = portManager;
|
||
|
|
|
||
|
|
public int Port { get; } = port;
|
||
|
|
|
||
|
|
public void Dispose()
|
||
|
|
{
|
||
|
|
FreePortManager? localPortManager = Interlocked.Exchange(ref this.portManager, null);
|
||
|
|
localPortManager?.takenPorts.Remove(this.Port);
|
||
|
|
}
|
||
|
|
|
||
|
|
public override string ToString()
|
||
|
|
{
|
||
|
|
return this.Port.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
public override bool Equals(object? obj)
|
||
|
|
{
|
||
|
|
return obj is PortTicket ticket && ticket.Port == this.Port;
|
||
|
|
}
|
||
|
|
|
||
|
|
public override int GetHashCode()
|
||
|
|
{
|
||
|
|
return this.Port.GetHashCode();
|
||
|
|
}
|
||
|
|
|
||
|
|
public static implicit operator int(PortTicket ticket) => ticket.Port;
|
||
|
|
public static implicit operator string(PortTicket ticket) => ticket.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
public PortTicket GetAvailablePort()
|
||
|
|
{
|
||
|
|
lock (mutex)
|
||
|
|
{
|
||
|
|
int port;
|
||
|
|
do
|
||
|
|
{
|
||
|
|
using var listener = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Loopback, 0);
|
||
|
|
listener.Start();
|
||
|
|
port = ((System.Net.IPEndPoint)listener.LocalEndpoint).Port;
|
||
|
|
listener.Stop();
|
||
|
|
listener.Dispose();
|
||
|
|
Thread.Yield(); // Let the listener actually shut down before we try to use the port
|
||
|
|
} while (takenPorts.Contains(port));
|
||
|
|
|
||
|
|
takenPorts.Add(port);
|
||
|
|
|
||
|
|
Console.WriteLine($"FreePortManager: Yielding port {port}");
|
||
|
|
Debug.WriteLine($"FreePortManager: Yielding port {port}");
|
||
|
|
return new PortTicket(this, port);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|