tgstation-server 6.17.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
Tgstation.Server.Host.Utils.PortAllocator Class Referencesealed

More...

Inheritance diagram for Tgstation.Server.Host.Utils.PortAllocator:
Inheritance graph
[legend]
Collaboration diagram for Tgstation.Server.Host.Utils.PortAllocator:
Collaboration graph
[legend]

Public Member Functions

 PortAllocator (IServerPortProvider serverPortProvider, IDatabaseContextFactory databaseContextFactory, IPlatformIdentifier platformIdentifier, IOptions< SwarmConfiguration > swarmConfigurationOptions, ILogger< PortAllocator > logger)
 Initializes a new instance of the PortAllocator class.
 
void Dispose ()
 
async ValueTask< ushort?> GetAvailablePort (ushort basePort, bool checkOne, CancellationToken cancellationToken)
 Gets a port not currently in use by TGS.
Parameters
basePortThe port to check first. Will not allocate a port lower than this.
checkOneIf only basePort should be checked and no others.
cancellationTokenThe CancellationToken for the operation.
Returns
A ValueTask<TResult> resulting in the first available port on success, null on failure.

 

Private Member Functions

async ValueTask< ushort?> GetAvailablePort (IDatabaseContext databaseContext, ushort basePort, bool checkOne, CancellationToken cancellationToken)
 Gets a port not currently in use by TGS.
 

Private Attributes

readonly IServerPortProvider serverPortProvider
 The IServerPortProvider for the PortAllocator.
 
readonly IDatabaseContextFactory databaseContextFactory
 The IDatabaseContext for the PortAllocator.
 
readonly IPlatformIdentifier platformIdentifier
 The IPlatformIdentifier for the PortAllocator.
 
readonly ILogger< PortAllocatorlogger
 The ILogger for the PortAllocator.
 
readonly SwarmConfiguration swarmConfiguration
 The SwarmConfiguration for the PortAllocator.
 
readonly SemaphoreSlim allocatorLock
 The SemaphoreSlim used to serialized port requisition requests.
 

Detailed Description

Definition at line 20 of file PortAllocator.cs.

Constructor & Destructor Documentation

◆ PortAllocator()

Tgstation.Server.Host.Utils.PortAllocator.PortAllocator ( IServerPortProvider  serverPortProvider,
IDatabaseContextFactory  databaseContextFactory,
IPlatformIdentifier  platformIdentifier,
IOptions< SwarmConfiguration swarmConfigurationOptions,
ILogger< PortAllocator logger 
)

Initializes a new instance of the PortAllocator class.

Parameters
serverPortProviderThe value of serverPortProvider.
databaseContextFactoryThe value of databaseContextFactory.
platformIdentifierThe value of platformIdentifier.
swarmConfigurationOptionsThe IOptions<TOptions> containing the value of swarmConfiguration.
loggerThe value of logger.

Definition at line 60 of file PortAllocator.cs.

66 {
67 this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
68 this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
69 this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
70 swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
71 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
72
73 allocatorLock = new SemaphoreSlim(1);
74 }
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the PortAllocator.
readonly ILogger< PortAllocator > logger
The ILogger for the PortAllocator.
readonly SwarmConfiguration swarmConfiguration
The SwarmConfiguration for the PortAllocator.
readonly IServerPortProvider serverPortProvider
The IServerPortProvider for the PortAllocator.
readonly SemaphoreSlim allocatorLock
The SemaphoreSlim used to serialized port requisition requests.
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContext for the PortAllocator.

References Tgstation.Server.Host.Utils.PortAllocator.allocatorLock, Tgstation.Server.Host.Utils.PortAllocator.databaseContextFactory, Tgstation.Server.Host.Utils.PortAllocator.logger, Tgstation.Server.Host.Utils.PortAllocator.platformIdentifier, Tgstation.Server.Host.Utils.PortAllocator.serverPortProvider, and Tgstation.Server.Host.Utils.PortAllocator.swarmConfiguration.

Member Function Documentation

◆ Dispose()

void Tgstation.Server.Host.Utils.PortAllocator.Dispose ( )

◆ GetAvailablePort() [1/2]

async ValueTask< ushort?> Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort ( IDatabaseContext  databaseContext,
ushort  basePort,
bool  checkOne,
CancellationToken  cancellationToken 
)
private

Gets a port not currently in use by TGS.

Parameters
databaseContextThe IDatabaseContext to use.
basePortThe port to check first. Will not allocate a port lower than this.
checkOneIf only basePort should be checked and no others.
cancellationTokenThe CancellationToken for the operation.
Returns
A ValueTask<TResult> resulting in the first available port on success, null on failure.

Definition at line 97 of file PortAllocator.cs.

98 {
99 logger.LogTrace("Port allocation >= {basePort} requested...", basePort);
100 var ddPorts = await databaseContext
102 .AsQueryable()
103 .Where(x => x.Instance!.SwarmIdentifer == swarmConfiguration.Identifier)
104 .Select(x => new
105 {
106 Port = x.Port!.Value,
107 x.InstanceId,
108 })
109 .ToListAsync(cancellationToken);
110
111 var dmPorts = await databaseContext
113 .AsQueryable()
114 .Where(x => x.Instance!.SwarmIdentifer == swarmConfiguration.Identifier)
115 .Select(x => new
116 {
117 ApiValidationPort = x.ApiValidationPort!.Value,
118 x.InstanceId,
119 })
120 .ToListAsync(cancellationToken);
121
122 var exceptions = new List<Exception>();
123 ushort port = 0;
124 try
125 {
126 for (port = basePort; port < ushort.MaxValue; ++port)
127 {
128 if (checkOne && port != basePort)
129 break;
130
132 {
133 logger.LogWarning("Cannot allocate port {port} as it is the TGS API port!", port);
134 continue;
135 }
136
137 var reservedGamePortData = ddPorts.Where(data => data.Port == port).ToList();
138 if (reservedGamePortData.Count > 0)
139 {
140 logger.LogWarning(
141 "Cannot allocate port {port} as it in use by the game server of instance(s): {instanceId}!",
142 port,
143 String.Join(
144 ", ",
145 reservedGamePortData.Select(data => data.InstanceId)));
146 continue;
147 }
148
149 var reservedApiValidationPortData = dmPorts.Where(data => data.ApiValidationPort == port).ToList();
150 if (reservedApiValidationPortData.Count > 0)
151 {
152 logger.LogWarning(
153 "Cannot allocate port {port} as it in use by the API validation server of instance(s): {instanceId}!",
154 port,
155 String.Join(
156 ", ",
157 reservedApiValidationPortData.Select(data => data.InstanceId)));
158 continue;
159 }
160
161 try
162 {
163 SocketExtensions.BindTest(platformIdentifier, port, false, true);
164 SocketExtensions.BindTest(platformIdentifier, port, false, false);
165 }
166 catch (Exception ex)
167 {
168 exceptions.Add(ex);
169 continue;
170 }
171
172 logger.LogInformation("Allocated port {port}", port);
173 return port;
174 }
175
176 logger.LogWarning("Unable to allocate port >= {basePort}!", basePort);
177 return null;
178 }
179 finally
180 {
181 if (port != basePort)
182 {
183 logger.LogDebug(
184 exceptions.Count == 1
185 ? exceptions.First()
186 : new AggregateException(exceptions),
187 "Failed to allocate ports {basePort}-{lastCheckedPort}!",
188 basePort,
189 port - 1);
190 }
191 }
192 }
string? Identifier
The server's identifier.
Extension methods for the Socket class.
static void BindTest(IPlatformIdentifier platformIdentifier, ushort port, bool includeIPv6, bool udp)
Attempt to exclusively bind to a given port .
ushort HttpApiPort
The port the server listens on.
IDatabaseCollection< DreamDaemonSettings > DreamDaemonSettings
The Models.DreamDaemonSettings in the IDatabaseContext.
IDatabaseCollection< DreamMakerSettings > DreamMakerSettings
The Models.DreamMakerSettings in the IDatabaseContext.

References Tgstation.Server.Host.Extensions.SocketExtensions.BindTest(), Tgstation.Server.Host.Database.IDatabaseContext.DreamDaemonSettings, Tgstation.Server.Host.Database.IDatabaseContext.DreamMakerSettings, Tgstation.Server.Host.Core.IServerPortProvider.HttpApiPort, Tgstation.Server.Api.Models.Internal.SwarmServer.Identifier, Tgstation.Server.Host.Utils.PortAllocator.logger, Tgstation.Server.Host.Utils.PortAllocator.platformIdentifier, Tgstation.Server.Host.Utils.PortAllocator.serverPortProvider, and Tgstation.Server.Host.Utils.PortAllocator.swarmConfiguration.

Here is the call graph for this function:

◆ GetAvailablePort() [2/2]

async ValueTask< ushort?> Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort ( ushort  basePort,
bool  checkOne,
CancellationToken  cancellationToken 
)

Gets a port not currently in use by TGS.

Parameters
basePortThe port to check first. Will not allocate a port lower than this.
checkOneIf only basePort should be checked and no others.
cancellationTokenThe CancellationToken for the operation.
Returns
A ValueTask<TResult> resulting in the first available port on success, null on failure.

Implements Tgstation.Server.Host.Utils.IPortAllocator.

Definition at line 80 of file PortAllocator.cs.

81 {
82 ushort? result = null;
83 using (await SemaphoreSlimContext.Lock(allocatorLock, cancellationToken))
85 async databaseContext => result = await GetAvailablePort(databaseContext, basePort, checkOne, cancellationToken));
86 return result;
87 }
async ValueTask< ushort?> GetAvailablePort(ushort basePort, bool checkOne, CancellationToken cancellationToken)
Gets a port not currently in use by TGS.A ValueTask<TResult> resulting in the first available port on...
ValueTask UseContext(Func< IDatabaseContext, ValueTask > operation)
Run an operation in the scope of an IDatabaseContext.

References Tgstation.Server.Host.Utils.PortAllocator.allocatorLock, Tgstation.Server.Host.Utils.PortAllocator.databaseContextFactory, Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort(), Tgstation.Server.Host.Utils.SemaphoreSlimContext.Lock(), and Tgstation.Server.Host.Database.IDatabaseContextFactory.UseContext().

Referenced by Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ allocatorLock

readonly SemaphoreSlim Tgstation.Server.Host.Utils.PortAllocator.allocatorLock
private

The SemaphoreSlim used to serialized port requisition requests.

Definition at line 50 of file PortAllocator.cs.

Referenced by Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort(), and Tgstation.Server.Host.Utils.PortAllocator.PortAllocator().

◆ databaseContextFactory

readonly IDatabaseContextFactory Tgstation.Server.Host.Utils.PortAllocator.databaseContextFactory
private

The IDatabaseContext for the PortAllocator.

Definition at line 30 of file PortAllocator.cs.

Referenced by Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort(), and Tgstation.Server.Host.Utils.PortAllocator.PortAllocator().

◆ logger

readonly ILogger<PortAllocator> Tgstation.Server.Host.Utils.PortAllocator.logger
private

◆ platformIdentifier

readonly IPlatformIdentifier Tgstation.Server.Host.Utils.PortAllocator.platformIdentifier
private

The IPlatformIdentifier for the PortAllocator.

Definition at line 35 of file PortAllocator.cs.

Referenced by Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort(), and Tgstation.Server.Host.Utils.PortAllocator.PortAllocator().

◆ serverPortProvider

readonly IServerPortProvider Tgstation.Server.Host.Utils.PortAllocator.serverPortProvider
private

The IServerPortProvider for the PortAllocator.

Definition at line 25 of file PortAllocator.cs.

Referenced by Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort(), and Tgstation.Server.Host.Utils.PortAllocator.PortAllocator().

◆ swarmConfiguration

readonly SwarmConfiguration Tgstation.Server.Host.Utils.PortAllocator.swarmConfiguration
private

The SwarmConfiguration for the PortAllocator.

Definition at line 45 of file PortAllocator.cs.

Referenced by Tgstation.Server.Host.Utils.PortAllocator.GetAvailablePort(), and Tgstation.Server.Host.Utils.PortAllocator.PortAllocator().


The documentation for this class was generated from the following file: