tgstation-server 5.12.7
The /tg/station 13 server suite
Loading...
Searching...
No Matches
PortAllocator.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Threading;
5using System.Threading.Tasks;
6
7using Microsoft.EntityFrameworkCore;
8using Microsoft.Extensions.Logging;
9using Microsoft.Extensions.Options;
10
15
17{
20 {
25
30
34 readonly ILogger<PortAllocator> logger;
35
40
51 IOptions<SwarmConfiguration> swarmConfigurationOptions,
52 ILogger<PortAllocator> logger)
53 {
54 this.serverPortProvider = serverPortProvider ?? throw new ArgumentNullException(nameof(serverPortProvider));
55 this.databaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
56 swarmConfiguration = swarmConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(swarmConfigurationOptions));
57 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
58 }
59
61 public async Task<ushort?> GetAvailablePort(ushort basePort, bool checkOne, CancellationToken cancellationToken)
62 {
63 logger.LogTrace("Port allocation >= {basePort} requested...", basePort);
64
65 var ddPorts = await databaseContext
67 .AsQueryable()
68 .Where(x => x.Instance.SwarmIdentifer == swarmConfiguration.Identifier)
69 .Select(x => x.Port)
70 .ToListAsync(cancellationToken);
71
72 var dmPorts = await databaseContext
74 .AsQueryable()
75 .Where(x => x.Instance.SwarmIdentifer == swarmConfiguration.Identifier)
76 .Select(x => x.ApiValidationPort)
77 .ToListAsync(cancellationToken);
78
79 var exceptions = new List<Exception>();
80 ushort port = 0;
81 try
82 {
83 for (port = basePort; port < ushort.MaxValue; ++port)
84 {
85 if (checkOne && port != basePort)
86 break;
87
89 || ddPorts.Contains(port)
90 || dmPorts.Contains(port))
91 continue;
92
93 try
94 {
95 SocketExtensions.BindTest(port, false);
96 }
97 catch (Exception ex)
98 {
99 exceptions.Add(ex);
100 continue;
101 }
102
103 logger.LogInformation("Allocated port {port}", port);
104 return port;
105 }
106
107 logger.LogWarning("Unable to allocate port >= {basePort}!", basePort);
108 return null;
109 }
110 finally
111 {
112 if (port != basePort)
113 {
114 logger.LogDebug(
115 exceptions.Count == 1
116 ? exceptions.First()
117 : new AggregateException(exceptions),
118 "Failed to allocate ports {basePort}-{lastCheckedPort}!",
119 basePort,
120 port - 1);
121 }
122 }
123 }
124 }
125}
string? Identifier
The server's identifier.
Definition: SwarmServer.cs:21
Configuration for the server swarm system.
Extension methods for the Socket class.
static void BindTest(ushort port, bool includeIPv6)
Attempt to exclusively bind to a given port .
readonly ILogger< PortAllocator > logger
The ILogger for the PortAllocator.
async Task< ushort?> GetAvailablePort(ushort basePort, bool checkOne, CancellationToken cancellationToken)
Gets a port not currently in use by TGS. A Task<TResult> resulting in the first available port on suc...
readonly SwarmConfiguration swarmConfiguration
The SwarmConfiguration for the PortAllocator.
readonly IServerPortProvider serverPortProvider
The IServerPortProvider for the PortAllocator.
readonly IDatabaseContext databaseContext
The IDatabaseContext for the PortAllocator.
PortAllocator(IServerPortProvider serverPortProvider, IDatabaseContext databaseContext, IOptions< SwarmConfiguration > swarmConfigurationOptions, ILogger< PortAllocator > logger)
Initializes a new instance of the PortAllocator class.
Provides access to the server's HttpApiPort.
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.
Gets unassigned ports for use by TGS.