-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DeflateMiddleware: Add deflate compression to game responses (#487)
- Loading branch information
Showing
6 changed files
with
77 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using Bunkum.Core.Database; | ||
using Bunkum.Core.Endpoints.Middlewares; | ||
using Bunkum.Listener.Request; | ||
using Org.BouncyCastle.Utilities.Zlib; | ||
using Refresh.GameServer.Configuration; | ||
using Refresh.GameServer.Endpoints; | ||
|
||
namespace Refresh.GameServer.Middlewares; | ||
|
||
/// <summary> | ||
/// Adds deflate encoding to LBP game server responses if they reach a certain size. | ||
/// The game will eventually corrupt its own memory if we do not do this, | ||
/// since non-deflate requests only get a very small request buffer, and if you send too big of a request, | ||
/// it overruns that buffer and starts corrupting random heap memory. | ||
/// Requests encoded with deflate get a much larger read buffer, so they avoid this problem until much larger buffer sizes. | ||
/// </summary> | ||
public class DeflateMiddleware(GameServerConfig config) : IMiddleware | ||
{ | ||
/// <summary> | ||
/// After this many bytes, start deflating request bodies | ||
/// </summary> | ||
private const int DeflateCutoff = 1024; | ||
|
||
public void HandleRequest(ListenerContext context, Lazy<IDatabaseContext> database, Action next) | ||
{ | ||
next(); | ||
|
||
if (!config.UseDeflateCompression) | ||
return; | ||
|
||
// If this isn't a game request or it's a resource request, don't deflate, since resource requests will be corrupted if deflated | ||
if (!context.Uri.AbsolutePath.StartsWith(GameEndpointAttribute.BaseRoute) || context.Uri.AbsolutePath.StartsWith($"{GameEndpointAttribute.BaseRoute}r/")) | ||
return; | ||
|
||
string? encodings = context.RequestHeaders.Get("Accept-Encoding"); | ||
// If the accepted encodings aren't specified, or they don't contain deflate, or we don't need to use deflate on the data, do nothing. | ||
if (encodings == null || !encodings.Contains("deflate") || context.ResponseStream.Length <= DeflateCutoff) | ||
return; | ||
|
||
// Update the headers marking that we are sending encoded data | ||
context.ResponseHeaders["X-Original-Content-Length"] = context.ResponseStream.Length.ToString(); | ||
context.ResponseHeaders["Vary"] = "Accept-Encoding"; | ||
context.ResponseHeaders["Content-Encoding"] = "deflate"; | ||
|
||
// Create a copy of our uncompressed data | ||
byte[] uncompressed = context.ResponseStream.ToArray(); | ||
|
||
// Reset the response stream position and length to 0, so we can start writing to it again | ||
context.ResponseStream.Position = 0; | ||
context.ResponseStream.SetLength(0); | ||
|
||
// Compress our source data into the response stream | ||
using ZOutputStreamLeaveOpen zlibStream = new(context.ResponseStream, 6); | ||
zlibStream.Write(uncompressed); | ||
zlibStream.Finish(); | ||
zlibStream.Close(); | ||
|
||
// Seek back to the start | ||
context.ResponseStream.Position = 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters