Skip to content

Commit aa56b9c

Browse files
Misc code changes thorough the server stack to resolve memory leaks, and harmonize logger/coe styling.
This commit adjusts a few things as mentioned: - Fixes memory leaks in WatsonWebserver, SVO, and TdfEncoder. - Adjust some logger in async listener methods to be more unified. - Implements KeepAlive support in SVO, as well as a slight adjustment in the GT4 class, and log responses sent to clients as well. - ApacheNet/SVO: Cleans up response logs to not show duplicate URLs.
1 parent 1d04c9c commit aa56b9c

File tree

14 files changed

+150
-52
lines changed

14 files changed

+150
-52
lines changed

Diff for: BackendServices/NetworkLibrary/Extension/StringUtils.cs

+7-11
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public static string GetSubstringByString(this string a, string b, string c)
6666

6767
/// <summary>
6868
/// Transform a string to it's hexadecimal representation.
69-
/// <para>Obtenir un string dans sa représentation hexadecimale.</para>
69+
/// <para>Obtenir un string dans sa représentation hexadecimale.</para>
7070
/// <param name="str">The string to transform.</param>
7171
/// </summary>
7272
/// <returns>A string.</returns>
@@ -101,7 +101,7 @@ public static double Eval(this string expression, string filter = null)
101101

102102
/// <summary>
103103
/// Convert a hex-formatted string to byte array.
104-
/// <para>Convertir une représentation hexadécimal en tableau de bytes.</para>
104+
/// <para>Convertir une représentation hexadécimal en tableau de bytes.</para>
105105
/// </summary>
106106
/// <param name="hex">A string looking like "300D06092A864886F70D0101050500".</param>
107107
/// <returns>A byte array.</returns>
@@ -128,28 +128,24 @@ public static byte[] HexStringToByteArray(this string hex)
128128
/// </summary>
129129
/// <param name="report">The Ghidra report as a string</param>
130130
/// <returns>Byte array constructed from the report</returns>
131-
public static byte[] GhidraStrReportToBytes(string report, int sizeOf = -1)
131+
public static byte[] GhidraStrReportToBytes(string report, int sizeOfOutput = -1)
132132
{
133133
string[] lines = report.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
134-
byte[] byteArray = new byte[sizeOf == -1 ? lines.Length : sizeOf];
134+
byte[] byteArray = new byte[sizeOfOutput <= -1 ? lines.Length : sizeOfOutput];
135135

136136
foreach (string line in lines)
137137
{
138138
Match match = Regex.Match(line, @"\b([0-9a-fA-F]+)\s+([0-9a-fA-F]{2})\s+.*?\[(\d+)\]");
139139
if (match.Success)
140-
{
141-
string byteHex = match.Groups[2].Value;
142-
int index = int.Parse(match.Groups[3].Value);
143-
byteArray[index] = Convert.ToByte(byteHex, 16);
144-
}
140+
byteArray[int.Parse(match.Groups[3].Value)] = Convert.ToByte(match.Groups[2].Value, 16);
145141
}
146142

147143
return byteArray;
148144
}
149145

150146
/// <summary>
151147
/// Verify is the string is in base64 format.
152-
/// <para>Vérifie si un string est en format base64.</para>
148+
/// <para>Vérifie si un string est en format base64.</para>
153149
/// </summary>
154150
/// <param name="base64String">The base64 string.</param>
155151
/// <returns>A tuple boolean, byte array.</returns>
@@ -193,7 +189,7 @@ public static Stream ToStream(this string str, Encoding encoding = null)
193189

194190
/// <summary>
195191
/// Adds an element to a double string array.
196-
/// <para>Ajoute un élément à une liste double de strings.</para>
192+
/// <para>Ajoute un élément à une liste double de strings.</para>
197193
/// </summary>
198194
/// <param name="original">The original double array.</param>
199195
/// <param name="bytesToRead">The new array to add.</param>

Diff for: BackendServices/WatsonWebserver/CavemanTcp/CavemanTcpServer.cs

+11-3
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,7 @@ private Task AcceptConnections()
13241324

13251325
if (!_IsListening && (_Clients.Count >= _Settings.MaxConnections))
13261326
{
1327-
Task.Delay(100).Wait();
1327+
Task.Delay(100, _Token).Wait();
13281328
continue;
13291329
}
13301330
else if (!_IsListening)
@@ -1337,7 +1337,7 @@ private Task AcceptConnections()
13371337

13381338
while (TcpClientTasks.Count < MaxConcurrentListeners) //Maximum number of concurrent listeners
13391339
{
1340-
TcpClientTasks.Add(_Listener.AcceptTcpClientAsync().ContinueWith(t =>
1340+
TcpClientTasks.Add(_Listener.AcceptTcpClientAsync(_Token).AsTask().ContinueWith(t =>
13411341
{
13421342
ClientMetadata client = null;
13431343

@@ -1413,10 +1413,18 @@ private Task AcceptConnections()
14131413
}));
14141414
}
14151415

1416-
int RemoveAtIndex = Task.WaitAny(TcpClientTasks.ToArray(), AwaiterTimeoutInMS); //Synchronously Waits up to 500ms for any Task completion
1416+
int RemoveAtIndex = Task.WaitAny(TcpClientTasks.ToArray(), AwaiterTimeoutInMS, _Token); //Synchronously Waits up to 500ms for any Task completion
14171417
if (RemoveAtIndex != -1) //Remove the completed task from the list
14181418
TcpClientTasks.RemoveAt(RemoveAtIndex);
14191419
}
1420+
}
1421+
catch (TaskCanceledException)
1422+
{
1423+
1424+
}
1425+
catch (OperationCanceledException)
1426+
{
1427+
14201428
}
14211429
catch (ObjectDisposedException)
14221430
{

Diff for: BackendServices/WatsonWebserver/CavemanTcp/ClientMetadata.cs

+3-6
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,8 @@ public void Dispose()
118118
{
119119
_SslStream.Close();
120120
}
121-
catch (Exception)
121+
catch
122122
{
123-
124123
}
125124
}
126125

@@ -130,9 +129,8 @@ public void Dispose()
130129
{
131130
_NetworkStream.Close();
132131
}
133-
catch (Exception)
132+
catch
134133
{
135-
136134
}
137135
}
138136

@@ -144,9 +142,8 @@ public void Dispose()
144142
_TcpClient.Dispose();
145143
_TcpClient = null;
146144
}
147-
catch (Exception)
145+
catch
148146
{
149-
150147
}
151148
}
152149
}

Diff for: BackendServices/WatsonWebserver/HttpResponse.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,11 @@ public override MemoryStream Data
104104

105105
#region Private-Members
106106

107+
internal HttpListenerResponse _Response = null;
108+
internal Stream _OutputStream = null;
109+
107110
private HttpRequestBase _Request = null;
108111
private HttpListenerContext _Context = null;
109-
private HttpListenerResponse _Response = null;
110-
private Stream _OutputStream = null;
111112
private bool _HeadersSet = false;
112113
private bool _KeepAliveData = true;
113114

Diff for: BackendServices/WatsonWebserver/Native/HttpResponse.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,11 @@ public override MemoryStream Data
104104

105105
#region Private-Members
106106

107+
internal HttpListenerResponse _Response = null;
108+
internal Stream _OutputStream = null;
109+
107110
private HttpRequestBase _Request = null;
108111
private HttpListenerContext _Context = null;
109-
private HttpListenerResponse _Response = null;
110-
private Stream _OutputStream = null;
111112
private bool _HeadersSet = false;
112113
private bool _KeepAliveData = true;
113114

Diff for: BackendServices/WatsonWebserver/Native/NativeWebserver.cs

+29-1
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,30 @@ private async Task AcceptConnections(CancellationToken token)
743743

744744
if (ctx.Response.ContentLength > 0) Statistics.IncrementSentPayloadBytes(Convert.ToInt64(ctx.Response.ContentLength));
745745
Routes.PostRouting?.Invoke(ctx).ConfigureAwait(false);
746+
747+
if (!listenerCtx.Response.KeepAlive)
748+
{
749+
try
750+
{
751+
ctx.Request.Data?.Close();
752+
}
753+
catch
754+
{
755+
}
756+
}
757+
758+
// Manually dispose the response if previous methods failed to avoids memory leaks.
759+
if (!ctx.Response.ResponseSent)
760+
{
761+
try
762+
{
763+
((HttpResponse)ctx.Response)._OutputStream.Close();
764+
}
765+
catch
766+
{
767+
}
768+
((HttpResponse)ctx.Response)._Response.Close();
769+
}
746770
}
747771
}
748772

@@ -762,7 +786,7 @@ private async Task AcceptConnections(CancellationToken token)
762786
}
763787
}));
764788

765-
int RemoveAtIndex = Task.WaitAny(HttpClientTasks.ToArray(), AwaiterTimeoutInMS); //Synchronously Waits up to 500ms for any Task completion
789+
int RemoveAtIndex = Task.WaitAny(HttpClientTasks.ToArray(), AwaiterTimeoutInMS, token); //Synchronously Waits up to 500ms for any Task completion
766790
if (RemoveAtIndex != -1) //Remove the completed task from the list
767791
HttpClientTasks.RemoveAt(RemoveAtIndex);
768792
}
@@ -772,6 +796,10 @@ private async Task AcceptConnections(CancellationToken token)
772796
catch (TaskCanceledException)
773797
{
774798

799+
}
800+
catch (OperationCanceledException)
801+
{
802+
775803
}
776804
catch (ObjectDisposedException)
777805
{

Diff for: BackendServices/WatsonWebserver/Webserver.cs

+29-1
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,30 @@ private async Task AcceptConnections(CancellationToken token)
744744

745745
if (ctx.Response.ContentLength > 0) Statistics.IncrementSentPayloadBytes(Convert.ToInt64(ctx.Response.ContentLength));
746746
Routes.PostRouting?.Invoke(ctx).ConfigureAwait(false);
747+
748+
if (!listenerCtx.Response.KeepAlive)
749+
{
750+
try
751+
{
752+
ctx.Request.Data?.Close();
753+
}
754+
catch
755+
{
756+
}
757+
}
758+
759+
// Manually dispose the response if previous methods failed to avoids memory leaks.
760+
if (!ctx.Response.ResponseSent)
761+
{
762+
try
763+
{
764+
((HttpResponse)ctx.Response)._OutputStream.Close();
765+
}
766+
catch
767+
{
768+
}
769+
((HttpResponse)ctx.Response)._Response.Close();
770+
}
747771
}
748772
}
749773

@@ -763,7 +787,7 @@ private async Task AcceptConnections(CancellationToken token)
763787
}
764788
}));
765789

766-
int RemoveAtIndex = Task.WaitAny(HttpClientTasks.ToArray(), AwaiterTimeoutInMS); //Synchronously Waits up to 500ms for any Task completion
790+
int RemoveAtIndex = Task.WaitAny(HttpClientTasks.ToArray(), AwaiterTimeoutInMS, token); //Synchronously Waits up to 500ms for any Task completion
767791
if (RemoveAtIndex != -1) //Remove the completed task from the list
768792
HttpClientTasks.RemoveAt(RemoveAtIndex);
769793
}
@@ -773,6 +797,10 @@ private async Task AcceptConnections(CancellationToken token)
773797
catch (TaskCanceledException)
774798
{
775799

800+
}
801+
catch (OperationCanceledException)
802+
{
803+
776804
}
777805
catch (ObjectDisposedException)
778806
{

Diff for: BlazeSDK/Tdf/TdfEncoder.cs

+10-6
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,20 @@ internal TdfEncoder(TdfFactory factory, bool heat1Bug)
2020

2121
public byte[] Encode<T>(T obj) where T : notnull
2222
{
23-
MemoryStream payload = new MemoryStream();
24-
WriteTo(payload, obj);
25-
return payload.ToArray();
23+
using (MemoryStream payload = new MemoryStream())
24+
{
25+
WriteTo(payload, obj);
26+
return payload.ToArray();
27+
}
2628
}
2729

2830
public byte[] Encode(object obj)
2931
{
30-
MemoryStream payload = new MemoryStream();
31-
WriteTo(payload, obj);
32-
return payload.ToArray();
32+
using (MemoryStream payload = new MemoryStream())
33+
{
34+
WriteTo(payload, obj);
35+
return payload.ToArray();
36+
}
3337
}
3438

3539
public void WriteTo<T>(Stream stream, T obj) where T : notnull => WriteTo(stream, (object)obj);

Diff for: BlazeSDK/Tdf/TdfLegacyEncoder.cs

+10-6
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,21 @@ internal TdfLegacyEncoder(TdfFactory factory)
1717

1818
public byte[] Encode<T>(T obj) where T : notnull
1919
{
20-
MemoryStream payload = new MemoryStream();
21-
WriteTo(payload, obj);
22-
return payload.ToArray();
20+
using (MemoryStream payload = new MemoryStream())
21+
{
22+
WriteTo(payload, obj);
23+
return payload.ToArray();
24+
}
2325
}
2426

2527

2628
public byte[] Encode(object obj)
2729
{
28-
MemoryStream payload = new MemoryStream();
29-
WriteTo(payload, obj);
30-
return payload.ToArray();
30+
using (MemoryStream payload = new MemoryStream())
31+
{
32+
WriteTo(payload, obj);
33+
return payload.ToArray();
34+
}
3135
}
3236

3337
public void WriteTo<T>(Stream stream, T obj) where T : notnull => WriteTo(stream, (object)obj);

Diff for: Servers/ApacheNet/ApacheNetProcessor.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -2641,25 +2641,25 @@ private static async Task DefaultRoute(HttpContextBase ctx)
26412641
}
26422642

26432643
if (response.StatusCode < 400)
2644-
LoggerAccessor.LogInfo($"[{loggerprefix}] - {clientip}:{clientport} Requested {fullurl} -> {response.StatusCode}");
2644+
LoggerAccessor.LogInfo($"[{loggerprefix}] - {clientip}:{clientport} -> {response.StatusCode}");
26452645
else
26462646
{
26472647
switch (response.StatusCode)
26482648
{
26492649
case (int)HttpStatusCode.NotFound:
26502650
if (string.IsNullOrEmpty(filePath))
2651-
LoggerAccessor.LogWarn($"[{loggerprefix}] - {clientip}:{clientport} Requested {fullurl} -> {response.StatusCode}");
2651+
LoggerAccessor.LogWarn($"[{loggerprefix}] - {clientip}:{clientport} -> {response.StatusCode}");
26522652
else
26532653
LoggerAccessor.LogWarn($"[{loggerprefix}] - {clientip}:{clientport} Requested a non-existent file: {filePath} -> {response.StatusCode}");
26542654
break;
26552655

26562656
case (int)HttpStatusCode.NotImplemented:
26572657
case (int)HttpStatusCode.RequestedRangeNotSatisfiable:
2658-
LoggerAccessor.LogWarn($"[{loggerprefix}] - {clientip}:{clientport} Requested {fullurl} -> {response.StatusCode}");
2658+
LoggerAccessor.LogWarn($"[{loggerprefix}] - {clientip}:{clientport} -> {response.StatusCode}");
26592659
break;
26602660

26612661
default:
2662-
LoggerAccessor.LogError($"[{loggerprefix}] - {clientip}:{clientport} Requested {fullurl} -> {response.StatusCode}");
2662+
LoggerAccessor.LogError($"[{loggerprefix}] - {clientip}:{clientport} -> {response.StatusCode}");
26632663
break;
26642664
}
26652665
}

Diff for: Servers/MultiSocks/Aries/AbstractAriesServer.cs

+3
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ private void RunLoop()
9292
_ = Task.Run(() => {
9393
if (client != null && client.Client.RemoteEndPoint is IPEndPoint remoteEndPoint)
9494
{
95+
#if DEBUG
96+
LoggerAccessor.LogInfo($"[AbstractAriesServer] - Connection received (Thread " + Thread.CurrentThread.ManagedThreadId.ToString() + ")");
97+
#endif
9598
if (remoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
9699
AddClient(new AriesClient(this, client, secure, CN, WeakChainSignedRSAKey)
97100
{

Diff for: Servers/SVO/Games/PS2/GT4Beta.cs

+2-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class GT4Beta
1010

1111
public static void GT4_XML_SVO(HttpListenerContext context)
1212
{
13-
using (var response = context.Response)
13+
using (var resp = context.Response)
1414
{
1515
try
1616
{
@@ -22,10 +22,8 @@ public static void GT4_XML_SVO(HttpListenerContext context)
2222
{
2323
case "GET":
2424
HttpListenerRequest req = context.Request;
25-
HttpListenerResponse resp = context.Response;
2625
resp.Headers.Set("Content-Type", "text/xml");
2726

28-
2927
byte[] uriStore = Encoding.ASCII.GetBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
3028
"<XML>\r\n\t" +
3129
"<URL_List>\r\n\t\t <SET IPAddress=\"127.0.0.1\" />\r\n\t\t" +
@@ -57,9 +55,6 @@ public static void GT4_XML_SVO(HttpListenerContext context)
5755

5856
resp.ContentLength64 = uriStore.Length;
5957
resp.OutputStream.Write(uriStore);
60-
#if DEBUG
61-
LoggerAccessor.LogInfo($"Start URIStore for GT4 Online Public Beta PS2 SENT!");
62-
#endif
6358
break;
6459
}
6560

@@ -70,7 +65,7 @@ public static void GT4_XML_SVO(HttpListenerContext context)
7065
catch (Exception ex)
7166
{
7267
LoggerAccessor.LogError($"[SVO] - GT4Beta_SVO thrown an assertion - {ex}");
73-
response.StatusCode = (int)HttpStatusCode.InternalServerError;
68+
resp.StatusCode = (int)HttpStatusCode.InternalServerError;
7469
}
7570
}
7671
}

0 commit comments

Comments
 (0)