@@ -51,13 +51,15 @@ public partial class HttpHandler : ServerHandlerBase
51
51
52
52
public HttpHandler ( )
53
53
{
54
-
54
+ RequestDispatchs = new BeetleX . Dispatchs . DispatchCenter < HttpToken > ( OnRequest , Math . Min ( Environment . ProcessorCount , 16 ) ) ;
55
55
}
56
56
57
- public Task Default ( ReadOnlySpan < byte > url , PipeStream stream , HttpToken token , ISession session )
57
+ private BeetleX . Dispatchs . DispatchCenter < HttpToken > RequestDispatchs ;
58
+
59
+ public Task Default ( PipeStream stream , HttpToken token , ISession session )
58
60
{
59
61
stream . Write ( "<b> beetlex server</b><hr/>" ) ;
60
- stream . Write ( $ " { Encoding . ASCII . GetString ( url ) } not found!") ;
62
+ stream . Write ( "path not found!") ;
61
63
OnCompleted ( stream , session , token ) ;
62
64
return Task . CompletedTask ;
63
65
}
@@ -67,6 +69,8 @@ public override void Connected(IServer server, ConnectedEventArgs e)
67
69
base . Connected ( server , e ) ;
68
70
e . Session . Socket . NoDelay = true ;
69
71
var token = new HttpToken ( ) ;
72
+ token . ThreadDispatcher = RequestDispatchs . Next ( ) ;
73
+ token . Session = e . Session ;
70
74
token . Db = new RawDb ( new ConcurrentRandom ( ) , Npgsql . NpgsqlFactory . Instance ) ;
71
75
e . Session . Tag = token ;
72
76
}
@@ -82,6 +86,14 @@ private int AnalysisUrl(ReadOnlySpan<byte> url)
82
86
83
87
}
84
88
89
+ private void OnRequest ( HttpToken token )
90
+ {
91
+ if ( token . Requests . TryDequeue ( out RequestData result ) )
92
+ {
93
+ OnStartRequest ( result , token . Session , token , token . Session . Stream . ToPipeStream ( ) ) ;
94
+ }
95
+ }
96
+
85
97
public override void SessionReceive ( IServer server , SessionReceiveEventArgs e )
86
98
{
87
99
base . SessionReceive ( server , e ) ;
@@ -96,17 +108,34 @@ public override void SessionReceive(IServer server, SessionReceiveEventArgs e)
96
108
{
97
109
token . Requests . Enqueue ( token . CurrentRequest ) ;
98
110
token . CurrentRequest = null ;
111
+ token . ThreadDispatcher . Enqueue ( token ) ;
99
112
}
100
113
pipeStream . ReadFree ( result . Length ) ;
101
114
}
102
115
else
103
116
{
104
117
if ( token . CurrentRequest == null )
105
118
{
106
- token . CurrentRequest = new RequestData ( ) ;
107
- var buffer = System . Buffers . ArrayPool < byte > . Shared . Rent ( result . Length ) ;
119
+ var request = new RequestData ( ) ;
120
+
121
+ byte [ ] buffer = null ;
122
+ if ( Program . Debug )
123
+ buffer = new byte [ result . Length ] ;
124
+ else
125
+ buffer = System . Buffers . ArrayPool < byte > . Shared . Rent ( result . Length ) ;
108
126
pipeStream . Read ( buffer , 0 , result . Length ) ;
109
- token . CurrentRequest . Data = new ArraySegment < byte > ( buffer , 0 , result . Length ) ;
127
+ request . Data = new ArraySegment < byte > ( buffer , 0 , result . Length ) ;
128
+ AnalysisAction ( request ) ;
129
+ if ( request . Action == ActionType . Plaintext )
130
+ {
131
+ token . CurrentRequest = request ;
132
+ }
133
+ else
134
+ {
135
+ pipeStream . ReadFree ( ( int ) pipeStream . Length ) ;
136
+ OnStartRequest ( request , e . Session , token , pipeStream ) ;
137
+ return ;
138
+ }
110
139
}
111
140
else
112
141
{
@@ -118,41 +147,9 @@ public override void SessionReceive(IServer server, SessionReceiveEventArgs e)
118
147
else
119
148
break ;
120
149
}
121
- if ( pipeStream . Length == 0 && token . CurrentRequest == null )
122
- {
123
- ProcessReqeusts ( token , pipeStream , e . Session ) ;
124
- }
125
- }
126
-
127
- private async Task ProcessReqeusts ( HttpToken token , PipeStream pipeStream , ISession session )
128
- {
129
- PROCESS :
130
- if ( token . EnterProcess ( ) )
131
- {
132
- while ( true )
133
- {
134
- if ( token . Requests . TryDequeue ( out RequestData item ) )
135
- {
136
- using ( item )
137
- {
138
- await OnProcess ( item , pipeStream , token , session ) ;
139
- }
140
- }
141
- else
142
- {
143
- break ;
144
- }
145
- }
146
- session . Stream . Flush ( ) ;
147
- token . CompletedProcess ( ) ;
148
- if ( ! token . Requests . IsEmpty )
149
- {
150
- goto PROCESS ;
151
- }
152
- }
153
150
}
154
151
155
- private Task OnProcess ( RequestData requestData , PipeStream pipeStream , HttpToken token , ISession sessino )
152
+ private void AnalysisAction ( RequestData requestData )
156
153
{
157
154
var line = _line . AsSpan ( ) ;
158
155
int len = requestData . Data . Count ;
@@ -187,77 +184,112 @@ private Task OnProcess(RequestData requestData, PipeStream pipeStream, HttpToken
187
184
}
188
185
}
189
186
}
190
- return OnStartLine ( http , method , url , sessino , token , pipeStream ) ;
191
-
192
- }
193
-
194
-
195
- public virtual Task OnStartLine ( ReadOnlySpan < byte > http , ReadOnlySpan < byte > method , ReadOnlySpan < byte > url , ISession session , HttpToken token , PipeStream stream )
196
- {
197
-
198
187
int queryIndex = AnalysisUrl ( url ) ;
199
188
ReadOnlySpan < byte > baseUrl = default ;
200
189
ReadOnlySpan < byte > queryString = default ;
201
190
if ( queryIndex > 0 )
202
191
{
203
192
baseUrl = url . Slice ( 0 , queryIndex ) ;
204
193
queryString = url . Slice ( queryIndex + 1 , url . Length - queryIndex - 1 ) ;
194
+ requestData . QueryString = Encoding . ASCII . GetString ( queryString ) ;
205
195
}
206
196
else
207
197
{
208
198
baseUrl = url ;
209
199
}
210
- OnWriteHeader ( stream , token ) ;
211
200
if ( baseUrl . Length == _path_Plaintext . Length && baseUrl . StartsWith ( _path_Plaintext ) )
201
+ {
202
+ requestData . Action = ActionType . Plaintext ;
203
+ }
204
+ else if ( baseUrl . Length == _path_Json . Length && baseUrl . StartsWith ( _path_Json ) )
205
+ {
206
+ requestData . Action = ActionType . Json ;
207
+ }
208
+ else if ( baseUrl . Length == _path_Db . Length && baseUrl . StartsWith ( _path_Db ) )
209
+ {
210
+ requestData . Action = ActionType . Db ;
211
+ }
212
+ else if ( baseUrl . Length == _path_Queries . Length && baseUrl . StartsWith ( _path_Queries ) )
213
+ {
214
+ requestData . Action = ActionType . Queries ;
215
+ }
216
+
217
+ else if ( baseUrl . Length == _cached_worlds . Length && baseUrl . StartsWith ( _cached_worlds ) )
218
+ {
219
+ requestData . Action = ActionType . Caching ;
220
+ }
221
+
222
+ else if ( baseUrl . Length == _path_Updates . Length && baseUrl . StartsWith ( _path_Updates ) )
223
+ {
224
+ requestData . Action = ActionType . Updates ;
225
+ }
226
+ else if ( baseUrl . Length == _path_Fortunes . Length && baseUrl . StartsWith ( _path_Fortunes ) )
227
+ {
228
+ requestData . Action = ActionType . Fortunes ;
229
+ }
230
+ else
231
+ {
232
+ requestData . Action = ActionType . Other ;
233
+ }
234
+ }
235
+
236
+ public virtual async Task OnStartRequest ( RequestData data , ISession session , HttpToken token , PipeStream stream )
237
+ {
238
+ OnWriteHeader ( stream , token ) ;
239
+ ActionType type = data . Action ;
240
+ if ( type == ActionType . Plaintext )
212
241
{
213
242
stream . Write ( _headerContentTypeText . Data , 0 , _headerContentTypeText . Length ) ;
214
243
OnWriteContentLength ( stream , token ) ;
215
- return Plaintext ( url , stream , token , session ) ;
244
+ await Plaintext ( stream , token , session ) ;
216
245
}
217
- else if ( baseUrl . Length == _path_Json . Length && baseUrl . StartsWith ( _path_Json ) )
246
+ else if ( type == ActionType . Json )
218
247
{
219
248
stream . Write ( _headerContentTypeJson . Data , 0 , _headerContentTypeJson . Length ) ;
220
249
OnWriteContentLength ( stream , token ) ;
221
- return Json ( stream , token , session ) ;
250
+ await Json ( stream , token , session ) ;
222
251
}
223
- else if ( baseUrl . Length == _path_Db . Length && baseUrl . StartsWith ( _path_Db ) )
252
+ else if ( type == ActionType . Db )
224
253
{
225
254
stream . Write ( _headerContentTypeJson . Data , 0 , _headerContentTypeJson . Length ) ;
226
255
OnWriteContentLength ( stream , token ) ;
227
- return db ( stream , token , session ) ;
256
+ await db ( stream , token , session ) ;
228
257
}
229
- else if ( baseUrl . Length == _path_Queries . Length && baseUrl . StartsWith ( _path_Queries ) )
258
+ else if ( type == ActionType . Queries )
230
259
{
231
260
stream . Write ( _headerContentTypeJson . Data , 0 , _headerContentTypeJson . Length ) ;
232
261
OnWriteContentLength ( stream , token ) ;
233
- return queries ( Encoding . ASCII . GetString ( queryString ) , stream , token , session ) ;
262
+ await queries ( data . QueryString , stream , token , session ) ;
234
263
}
235
264
236
- else if ( baseUrl . Length == _cached_worlds . Length && baseUrl . StartsWith ( _cached_worlds ) )
265
+ else if ( type == ActionType . Caching )
237
266
{
238
267
stream . Write ( _headerContentTypeJson . Data , 0 , _headerContentTypeJson . Length ) ;
239
268
OnWriteContentLength ( stream , token ) ;
240
- return caching ( Encoding . ASCII . GetString ( queryString ) , stream , token , session ) ;
269
+ await caching ( data . QueryString , stream , token , session ) ;
241
270
}
242
271
243
- else if ( baseUrl . Length == _path_Updates . Length && baseUrl . StartsWith ( _path_Updates ) )
272
+ else if ( type == ActionType . Updates )
244
273
{
245
274
stream . Write ( _headerContentTypeJson . Data , 0 , _headerContentTypeJson . Length ) ;
246
275
OnWriteContentLength ( stream , token ) ;
247
- return updates ( Encoding . ASCII . GetString ( queryString ) , stream , token , session ) ;
276
+ await updates ( data . QueryString , stream , token , session ) ;
248
277
}
249
- else if ( baseUrl . Length == _path_Fortunes . Length && baseUrl . StartsWith ( _path_Fortunes ) )
278
+ else if ( type == ActionType . Fortunes )
250
279
{
251
280
stream . Write ( _headerContentTypeHtml . Data , 0 , _headerContentTypeHtml . Length ) ;
252
281
OnWriteContentLength ( stream , token ) ;
253
- return fortunes ( stream , token , session ) ;
282
+ await fortunes ( stream , token , session ) ;
254
283
}
255
284
else
256
285
{
257
286
stream . Write ( _headerContentTypeHtml . Data , 0 , _headerContentTypeHtml . Length ) ;
258
287
OnWriteContentLength ( stream , token ) ;
259
- return Default ( url , stream , token , session ) ;
288
+ await Default ( stream , token , session ) ;
260
289
}
290
+ if ( ! Program . Debug )
291
+ data . Dispose ( ) ;
292
+
261
293
}
262
294
263
295
private void OnWriteHeader ( PipeStream stream , HttpToken token )
@@ -278,9 +310,10 @@ private void OnWriteContentLength(PipeStream stream, HttpToken token)
278
310
279
311
private void OnCompleted ( PipeStream stream , ISession session , HttpToken token )
280
312
{
281
- stream . ReadFree ( ( int ) stream . Length ) ;
282
- token . FullLength ( ( stream . CacheLength - token . ContentPostion ) . ToString ( ) ) ;
283
313
314
+ token . FullLength ( ( stream . CacheLength - token . ContentPostion ) . ToString ( ) ) ;
315
+ if ( token . Requests . IsEmpty )
316
+ session . Stream . Flush ( ) ;
284
317
}
285
318
286
319
}
0 commit comments