Merge branch 'master' into dev

This commit is contained in:
tgstation-server
2024-01-10 05:44:39 +00:00
10 changed files with 71 additions and 37 deletions
+1 -1
View File
@@ -16,7 +16,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" Condition="'$(TgsTestNoSdk)' != 'true'" />
<!-- Usage: Dependency mocking for tests -->
<!-- Pinned: Be VERY careful about updating https://github.com/moq/moq/issues/1372 -->
<PackageReference Include="Moq" Version="4.20.69" />
<PackageReference Include="Moq" Version="4.20.70" />
<!-- Usage: MSTest execution -->
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<!-- Usage: MSTest asserts etc... -->
@@ -27,7 +27,7 @@
<!-- Usage: HTTP constants reference -->
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<!-- Usage: Decoding the 'nbf' property of JWTs -->
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.0.3" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.1.2" />
<!-- Usage: Primary JSON library -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<!-- Usage: Data model annotating -->
@@ -11,9 +11,9 @@
<ItemGroup>
<!-- Usage: Connecting to SignalR hubs in API -->
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.1" />
<!-- Usage: Using target JSON serializer for API -->
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.1" />
</ItemGroup>
<ItemGroup>
@@ -518,6 +518,7 @@ namespace Tgstation.Server.Host.Components
}
IBridgeHandler? bridgeHandler = null;
var loggedDelay = false;
for (var i = 0; bridgeHandler == null && i < 30; ++i)
{
// There's a miniscule time period where we could potentially receive a bridge request and not have the registration ready when we launch DD
@@ -525,7 +526,15 @@ namespace Tgstation.Server.Host.Components
Task delayTask = Task.CompletedTask;
lock (bridgeHandlers)
if (!bridgeHandlers.TryGetValue(accessIdentifier, out bridgeHandler))
{
if (!loggedDelay)
{
logger.LogTrace("Received bridge request with unregistered access identifier \"{aid}\". Waiting up to 3 seconds for it to be registered...", accessIdentifier);
loggedDelay = true;
}
delayTask = asyncDelayer.Delay(TimeSpan.FromMilliseconds(100), cancellationToken);
}
await delayTask;
}
@@ -36,7 +36,12 @@ namespace Tgstation.Server.Host.Controllers
/// <summary>
/// If the content of bridge requests and responses should be logged.
/// </summary>
internal static bool LogContent { get; set; }
static bool LogContent => logContentDisableCounter == 0;
/// <summary>
/// Counter which, if not zero, indicates content logging should be disabled.
/// </summary>
static uint logContentDisableCounter;
/// <summary>
/// Static counter for the number of requests processed.
@@ -54,12 +59,14 @@ namespace Tgstation.Server.Host.Controllers
readonly ILogger<BridgeController> logger;
/// <summary>
/// Initializes static members of the <see cref="BridgeController"/> class.
/// Temporarily disable content logging. Must be followed up with a call to <see cref="ReenableContentLogging"/>.
/// </summary>
static BridgeController()
{
LogContent = true;
}
internal static void TemporarilyDisableContentLogging() => Interlocked.Increment(ref logContentDisableCounter);
/// <summary>
/// Reenable content logging. Must be preceeded with a call to <see cref="TemporarilyDisableContentLogging"/>.
/// </summary>
internal static void ReenableContentLogging() => Interlocked.Decrement(ref logContentDisableCounter);
/// <summary>
/// Initializes a new instance of the <see cref="BridgeController"/> class.
@@ -87,16 +94,16 @@ namespace Tgstation.Server.Host.Controllers
[AllowAnonymous]
public async ValueTask<IActionResult> Process([FromQuery] string data, CancellationToken cancellationToken)
{
// Nothing to see here
var remoteIP = Request.HttpContext.Connection.RemoteIpAddress;
if (remoteIP == null || !IPAddress.IsLoopback(remoteIP))
{
logger.LogTrace("Rejecting remote bridge request from {remoteIP}", remoteIP);
return Forbid();
}
using (LogContext.PushProperty(SerilogContextHelper.BridgeRequestIterationContextProperty, Interlocked.Increment(ref requestsProcessed)))
{
// Nothing to see here
var remoteIP = Request.HttpContext.Connection.RemoteIpAddress;
if (remoteIP == null || !IPAddress.IsLoopback(remoteIP))
{
logger.LogTrace("Rejecting remote bridge request from {remoteIP}", remoteIP);
return Forbid();
}
BridgeParameters? request;
try
{
@@ -106,6 +113,9 @@ namespace Tgstation.Server.Host.Controllers
{
if (LogContent)
logger.LogWarning(ex, "Error deserializing bridge request: {badJson}", data);
else
logger.LogWarning(ex, "Error deserializing bridge request!");
return BadRequest();
}
@@ -113,11 +123,16 @@ namespace Tgstation.Server.Host.Controllers
{
if (LogContent)
logger.LogWarning("Error deserializing bridge request: {badJson}", data);
else
logger.LogWarning("Error deserializing bridge request!");
return BadRequest();
}
if (LogContent)
logger.LogTrace("Bridge Request: {json}", data);
else
logger.LogTrace("Bridge Request");
var response = await bridgeDispatcher.ProcessBridgeRequest(request, cancellationToken);
if (response == null)
@@ -76,21 +76,21 @@
<!-- Usage: git interop -->
<PackageReference Include="LibGit2Sharp" Version="0.29.0" />
<!-- Usage: JWT injection into HTTP pipeline -->
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.1" />
<!-- Usage: Support ""legacy"" Newotonsoft.Json in HTTP pipeline. The rest of our codebase uses Newtonsoft. -->
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.1" />
<!-- Usage: Using target JSON serializer for API -->
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.1" />
<!-- Usage: Database ORM -->
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.1" />
<!-- Usage: Automatic migration generation using command line -->
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0">
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<!-- Usage: Sqlite ORM plugin -->
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
<!-- Usage: MSSQL ORM plugin -->
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
<!-- Usage: POSIX support for syscalls, signals, and symlinks -->
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
<!-- Usage: YAML config plugin -->
@@ -98,7 +98,7 @@
<!-- Usage: PostgresSQL ORM plugin -->
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
<!-- Usage: GitHub.com interop -->
<PackageReference Include="Octokit" Version="9.0.0" />
<PackageReference Include="Octokit" Version="9.1.0" />
<!-- Usage: MYSQL/MariaDB ORM plugin -->
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.0-beta.2" />
<!-- Usage: Discord interop -->
@@ -119,8 +119,6 @@
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0" />
<!-- Usage: Windows authentication plugin allowing searching for users by name -->
<PackageReference Include="System.DirectoryServices.AccountManagement" Version="8.0.0" />
<!-- Usage: JWT plugin needed to undo some Microsoft meddling in the HTTP pipeline -->
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
<!-- Usage: Identifying owning user of Windows Process objects -->
<PackageReference Include="System.Management" Version="8.0.0" />
<!-- Usage: Temporary resolution to compatibility issues with EFCore 7 and .NET 8 -->
@@ -6,7 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.1" />
</ItemGroup>
<ItemGroup>
@@ -27,7 +27,7 @@ namespace Tgstation.Server.Tests.Live
&& !((exception is BadHttpRequestException) && logMessage.Contains("Unexpected end of request content.")) // canceled request
&& !logMessage.StartsWith("Error disconnecting connection ")
&& !(logMessage.StartsWith("An exception occurred while iterating over the results of a query for context type") && (exception is OperationCanceledException || exception?.InnerException is OperationCanceledException))
&& !(logMessage.StartsWith("An error occurred using the connection to database ") && (exception is OperationCanceledException || exception?.InnerException is OperationCanceledException))
&& !(logMessage.Contains("An error occurred using the connection to database ") && (exception == null || (exception is OperationCanceledException || exception?.InnerException is OperationCanceledException)))
&& !(logMessage.StartsWith("Error when dispatching 'OnConnectedAsync' on hub") && (exception is OperationCanceledException || exception?.InnerException is OperationCanceledException))
&& !(logMessage.StartsWith("An exception occurred in the database while saving changes for context type") && (exception is OperationCanceledException || exception?.InnerException is OperationCanceledException)))
|| (logLevel == LogLevel.Critical && logMessage != "DropDatabase configuration option set! Dropping any existing database..."))
@@ -893,7 +893,7 @@ namespace Tgstation.Server.Tests.Live.Instance
{
// first check the bridge limits
var bridgeTestsTcs = new TaskCompletionSource();
BridgeController.LogContent = false;
BridgeController.TemporarilyDisableContentLogging();
using (var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
@@ -914,7 +914,7 @@ namespace Tgstation.Server.Tests.Live.Instance
await bridgeTestsTcs.Task.WaitAsync(cancellationToken);
}
BridgeController.LogContent = true;
BridgeController.ReenableContentLogging();
// Time for DD to revert the bridge access identifier change
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
@@ -61,6 +61,16 @@ namespace Tgstation.Server.Tests.Live
static readonly Lazy<ushort> mainDDPort = new(() => FreeTcpPort(odDDPort.Value, odDMPort.Value, compatDMPort.Value, compatDDPort.Value));
static readonly Lazy<ushort> mainDMPort = new(() => FreeTcpPort(odDDPort.Value, odDMPort.Value, compatDMPort.Value, compatDDPort.Value, mainDDPort.Value));
static void InitializePorts()
{
_ = odDMPort.Value;
_ = odDDPort.Value;
_ = compatDMPort.Value;
_ = compatDDPort.Value;
_ = mainDDPort.Value;
_ = mainDMPort.Value;
}
readonly ServerClientFactory clientFactory = new (new ProductHeaderValue(Assembly.GetExecutingAssembly().GetName().Name, Assembly.GetExecutingAssembly().GetName().Version.ToString()));
public static List<System.Diagnostics.Process> GetEngineServerProcessesOnPort(EngineType engineType, ushort? port)
@@ -162,7 +172,8 @@ namespace Tgstation.Server.Tests.Live
}
catch
{
l.Stop();
using (l)
l.Stop();
throw;
}
@@ -172,10 +183,9 @@ namespace Tgstation.Server.Tests.Live
}
finally
{
foreach(var l in listeners)
{
l.Stop();
}
foreach (var l in listeners)
using (l)
l.Stop();
}
Console.WriteLine($"Allocated port: {result}");
@@ -1238,6 +1248,8 @@ namespace Tgstation.Server.Tests.Live
using (var currentProcess = System.Diagnostics.Process.GetCurrentProcess())
Assert.AreEqual(ProcessPriorityClass.Normal, currentProcess.PriorityClass);
InitializePorts();
var maximumTestMinutes = TestingUtils.RunningInGitHubActions ? 90 : 20;
using var hardCancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(maximumTestMinutes));
var hardCancellationToken = hardCancellationTokenSource.Token;