tgstation-server 6.19.2
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 IOptions< SwarmConfigurationswarmConfigurationOptions
 The IOptions<TOptions> of SwarmConfiguration for the PortAllocator.
 
readonly ILogger< PortAllocatorlogger
 The ILogger 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 value of swarmConfigurationOptions.
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 this.swarmConfigurationOptions = swarmConfigurationOptions ?? 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 IOptions< SwarmConfiguration > swarmConfigurationOptions
The IOptions<TOptions> of 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.swarmConfigurationOptions.

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 .Where(x => x.Instance!.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier)
103 .Select(x => new
104 {
105 Port = x.Port!.Value,
106 x.InstanceId,
107 })
108 .ToListAsync(cancellationToken);
109
110 var dmPorts = await databaseContext
112 .Where(x => x.Instance!.SwarmIdentifer == swarmConfigurationOptions.Value.Identifier)
113 .Select(x => new
114 {
115 ApiValidationPort = x.ApiValidationPort!.Value,
116 x.InstanceId,
117 })
118 .ToListAsync(cancellationToken);
119
120 var exceptions = new List<Exception>();
121 ushort port = 0;
122 try
123 {
124 for (port = basePort; port < ushort.MaxValue; ++port)
125 {
126 if (checkOne && port != basePort)
127 break;
128
130 {
131 logger.LogWarning("Cannot allocate port {port} as it is the TGS API port!", port);
132 continue;
133 }
134
135 var reservedGamePortData = ddPorts.Where(data => data.Port == port).ToList();
136 if (reservedGamePortData.Count > 0)
137 {
138 logger.LogWarning(
139 "Cannot allocate port {port} as it in use by the game server of instance(s): {instanceId}!",
140 port,
141 String.Join(
142 ", ",
143 reservedGamePortData.Select(data => data.InstanceId)));
144 continue;
145 }
146
147 var reservedApiValidationPortData = dmPorts.Where(data => data.ApiValidationPort == port).ToList();
148 if (reservedApiValidationPortData.Count > 0)
149 {
150 logger.LogWarning(
151 "Cannot allocate port {port} as it in use by the API validation server of instance(s): {instanceId}!",
152 port,
153 String.Join(
154 ", ",
155 reservedApiValidationPortData.Select(data => data.InstanceId)));
156 continue;
157 }
158
159 try
160 {
161 SocketExtensions.BindTest(platformIdentifier, port, false, true);
162 SocketExtensions.BindTest(platformIdentifier, port, false, false);
163 }
164 catch (Exception ex)
165 {
166 exceptions.Add(ex);
167 continue;
168 }
169
170 logger.LogInformation("Allocated port {port}", port);
171 return port;
172 }
173
174 logger.LogWarning("Unable to allocate port >= {basePort}!", basePort);
175 return null;
176 }
177 finally
178 {
179 if (port != basePort)
180 {
181 logger.LogDebug(
182 exceptions.Count == 1
183 ? exceptions.First()
184 : new AggregateException(exceptions),
185 "Failed to allocate ports {basePort}-{lastCheckedPort}!",
186 basePort,
187 port - 1);
188 }
189 }
190 }
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.Host.Utils.PortAllocator.logger, Tgstation.Server.Host.Utils.PortAllocator.platformIdentifier, Tgstation.Server.Host.Utils.PortAllocator.serverPortProvider, and Tgstation.Server.Host.Utils.PortAllocator.swarmConfigurationOptions.

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().

◆ swarmConfigurationOptions

readonly IOptions<SwarmConfiguration> Tgstation.Server.Host.Utils.PortAllocator.swarmConfigurationOptions
private

The IOptions<TOptions> of SwarmConfiguration for the PortAllocator.

Definition at line 40 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: