Skip to content

Commit 5737aab

Browse files
committed
Work on server multithreading
1 parent c363a50 commit 5737aab

File tree

2 files changed

+123
-41
lines changed

2 files changed

+123
-41
lines changed

SmartImage.Rdx/Commands/ServerCommand.cs

Lines changed: 122 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@
2222
using Spectre.Console.Rendering;
2323
using System.Threading.Tasks;
2424
using Kantan.Text;
25+
using Flurl.Http;
26+
using System.Text;
27+
using Microsoft.Extensions.Hosting.Internal;
2528

2629
#nullable disable
2730
namespace SmartImage.Rdx.Commands;
2831

29-
using RouteCallbackMap = Dictionary<string, SmartHttpListener.HandleRequestCallback>;
32+
using RouteCallbackMap = Dictionary<string, ServerCommand.HandleRequestCallback2>;
3033

3134
#pragma warning disable IL2026
3235

@@ -37,6 +40,8 @@ public sealed class ServerCommand : AsyncCommand<ServerCommandSettings>, IDispos
3740

3841
private ServerCommandSettings m_scs;
3942

43+
public delegate Task<object> HandleRequestCallback2(HttpListenerContext ctx);
44+
4045
public static readonly JsonSerializerOptions Options2 = new(HttpUtilities.Options)
4146
{
4247
WriteIndented = true,
@@ -52,10 +57,19 @@ public sealed class ServerCommand : AsyncCommand<ServerCommandSettings>, IDispos
5257
};
5358

5459

55-
public SmartHttpListener Listener { get; private set; }
60+
public HttpListener Listener { get; }
61+
62+
private const int ChunkSize = 1024;
63+
5664

5765
public RouteCallbackMap Handlers { get; }
5866

67+
public Encoding Encoding { get; internal set; }
68+
69+
// public delegate Task<string> RequestDataCallback(byte[] buf);
70+
71+
// public delegate Task<string> HandleRequestCallback(HttpListenerRequest buf);
72+
5973
public ServerCommand()
6074
{
6175
Client = new SearchClient(SearchConfig.Default);
@@ -69,69 +83,94 @@ public ServerCommand()
6983
};
7084

7185
m_scs = null;
86+
87+
88+
Listener = new HttpListener()
89+
{
90+
TimeoutManager =
91+
{
92+
// IdleConnection = Timeout.InfiniteTimeSpan,
93+
},
94+
};
95+
96+
97+
// Start();
98+
99+
// Debug.WriteLine("ProtoPad HTTP Server started");
72100
}
73101

74-
private async Task InitConfigAsync([CBN] object c)
102+
103+
public async Task StartAsync(CancellationToken ct = default)
75104
{
76-
//todo
105+
if (!Listener.IsListening) {
106+
Listener.Start();
77107

78-
Client.Config.SearchEngines = m_scs.SearchEngines;
79-
Client.Config.PriorityEngines = m_scs.PriorityEngines;
108+
// Listener.BeginGetContext(HandleRequest, Listener);
80109

81-
Client.Config.ReadCookies = m_scs.ReadCookies;
110+
while (Listener.IsListening) {
111+
var ctx = await Listener.GetContextAsync().ConfigureAwait(false);
82112

83-
Client.Config.FlareSolverr = m_scs.FlareSolverr;
84-
Client.Config.FlareSolverrApiUrl = m_scs.FlareSolverrApiUrl;
113+
Trace.WriteLine($"{ctx}");
85114

86-
await Client.LoadEnginesAsync();
115+
// var res = await HandleRequestAsync(ctx, ct);
87116

88-
}
117+
// var request = ctx.Request;
118+
// var response = ctx.Response;
89119

90-
public override async Task<int> ExecuteAsync(CommandContext context, ServerCommandSettings settings)
91-
{
92-
m_scs = settings;
120+
foreach (var requestHandler in Handlers) {
93121

94-
var uriPrefix = $"http://*:{m_scs.Port}/";
95-
Trace.WriteLine($"{uriPrefix}");
122+
var requestUrl = ctx.Request.Url;
96123

97-
await AnsiConsole.Progress().StartAsync(async ctx =>
98-
{
99-
var task = ctx.AddTask("Starting server");
100-
task.IsIndeterminate = true;
101-
// task.Description = "Initializing config";
102-
await InitConfigAsync(null);
103-
task.Increment(ConsoleFormat.COMPLETE);
104-
});
124+
if (requestUrl != null && !requestUrl.PathAndQuery.Contains(requestHandler.Key)) {
125+
continue;
126+
}
105127

106-
Listener = new SmartHttpListener(Handlers, uriPrefix);
128+
var task = Task.Run(() => requestHandler.Value(ctx), ct);
129+
130+
Trace.WriteLine($"queued {task.Id}");
107131

132+
/*if (handlerObject is byte[] responseBytes) {
133+
//...
134+
}
135+
else if (handlerObject is string sz) {
136+
responseBytes = Encoding.GetBytes(sz);
137+
}
138+
else {
139+
responseBytes = await request.ReadRequestDataAsync(ct: ct);
140+
}*/
108141

109-
AnsiConsole.WriteLine($"Listening on {Listener.Listener.Prefixes.QuickJoin()}");
110142

111-
await Listener.StartAsync();
143+
}
112144

113-
return BaseOSIntegration.EC_OK;
145+
if (ct.IsCancellationRequested) {
146+
break;
147+
}
148+
}
149+
}
114150
}
115151

116152

117-
private async Task<object> HandleRequestAsync(HttpListenerRequest request, HttpListenerResponse response)
153+
private async Task<object> HandleRequestAsync(HttpListenerContext ctx)
118154
{
119155
// AnsiConsole.Clear();
120156

157+
var request = ctx.Request;
158+
var response = ctx.Response;
159+
121160
object ok;
122161
var remEndpoint = request.RemoteEndPoint;
123162

124163
AnsiConsole.WriteLine($"Received request {remEndpoint}");
125-
164+
126165
// Trace.WriteLine($"Request endpoint: {remEndpoint}");
127166

128167
var redirHdr = request.Headers["Redirect"];
129168
var srvResponse = new SearchServerResponse();
130169

131170
try {
132-
SearchQuery query = await GetQuery(request);
171+
SearchQuery query = await GetQueryFromRequestAsync(request);
133172

134-
if (query == SearchQuery.Null) {
173+
if (query == null || query == SearchQuery.Null) {
135174
srvResponse.Message = R1.Err_Query;
136175
}
137176
else {
@@ -214,7 +253,7 @@ await AnsiConsole.Live(layout).StartAsync(async ctx =>
214253
finally {
215254

216255
var responseStr = JsonSerializer.Serialize(srvResponse, Options2);
217-
var responseBytes = Listener.Encoding.GetBytes(responseStr);
256+
var responseBytes = Encoding.GetBytes(responseStr);
218257
var writeOk = await response.WriteResponseDataAsync(responseBytes);
219258

220259
ok = writeOk;
@@ -231,7 +270,53 @@ await AnsiConsole.Live(layout).StartAsync(async ctx =>
231270
return ok;
232271
}
233272

234-
private static async Task<SearchQuery> GetQuery(HttpListenerRequest request)
273+
274+
private async Task InitConfigAsync([CBN] object c)
275+
{
276+
//todo
277+
278+
Client.Config.SearchEngines = m_scs.SearchEngines;
279+
Client.Config.PriorityEngines = m_scs.PriorityEngines;
280+
281+
Client.Config.ReadCookies = m_scs.ReadCookies;
282+
283+
Client.Config.FlareSolverr = m_scs.FlareSolverr;
284+
Client.Config.FlareSolverrApiUrl = m_scs.FlareSolverrApiUrl;
285+
286+
287+
await Client.LoadEnginesAsync();
288+
289+
}
290+
291+
public override async Task<int> ExecuteAsync(CommandContext context, ServerCommandSettings settings)
292+
{
293+
m_scs = settings;
294+
295+
var uriPrefix = $"http://*:{m_scs.Port}/";
296+
Trace.WriteLine($"{uriPrefix}");
297+
Listener.Prefixes.Add(uriPrefix);
298+
Encoding = HttpUtilities.DefaultEncoding;
299+
300+
await AnsiConsole.Progress().StartAsync(async ctx =>
301+
{
302+
var task = ctx.AddTask("Starting server");
303+
task.IsIndeterminate = true;
304+
305+
// task.Description = "Initializing config";
306+
await InitConfigAsync(null);
307+
task.Increment(ConsoleFormat.COMPLETE);
308+
});
309+
310+
311+
AnsiConsole.WriteLine($"Listening on {Listener.Prefixes.QuickJoin()}");
312+
313+
await StartAsync();
314+
315+
return BaseOSIntegration.EC_OK;
316+
}
317+
318+
319+
private static async Task<SearchQuery> GetQueryFromRequestAsync(HttpListenerRequest request)
235320
{
236321
var contentType = request.Headers["Content-Type"] ?? MediaTypeNames.Text.Plain;
237322

@@ -260,8 +345,9 @@ private static async Task<SearchQuery> GetQuery(HttpListenerRequest request)
260345

261346
if (file == null) {
262347
// srvResponse.Message = R1.Err_Content;
263-
264348
return null;
349+
350+
// sqInput = null;
265351
}
266352
else {
267353
string filename = file.FileName;
@@ -281,16 +367,11 @@ private static async Task<SearchQuery> GetQuery(HttpListenerRequest request)
281367
return query;
282368
}
283369

284-
public Task StartAsync(CancellationToken ct = default)
285-
{
286-
return Listener.StartAsync(ct);
287-
}
288-
289370
public void Dispose()
290371
{
291372
Debug.WriteLine($"Disposing {nameof(ServerCommand)}");
292373
Client?.Dispose();
293-
Listener?.Dispose();
374+
Listener?.Close();
294375
Handlers.Clear();
295376
}
296377

SmartImage.Rdx/SmartImage.Rdx.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<AssemblyName>SmartImage</AssemblyName>
1515
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
1616
<Configurations>Debug;Release;Test;UnitTest</Configurations>
17+
<!-- <PublishAot>true</PublishAot> -->
1718
</PropertyGroup>
1819

1920
<PropertyGroup>

0 commit comments

Comments
 (0)