blob: c9365c6db11b7ff75b4bd72d83b3723a27bfbbb3 [file] [log] [blame]
Jake Farrell27274222011-11-10 20:32:44 +00001(*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *)
19
20 unit Thrift.Server;
21
Jens Geyer9f7f11e2016-04-14 21:37:11 +020022{$I Thrift.Defines.inc}
Jens Geyer26ef7432013-09-23 22:01:20 +020023{$I-} // prevent annoying errors with default log delegate and no console
24
Jake Farrell27274222011-11-10 20:32:44 +000025interface
26
27uses
Jens Geyer9f7f11e2016-04-14 21:37:11 +020028 {$IFDEF OLD_UNIT_NAMES}
29 Windows, SysUtils,
Nick4f5229e2016-04-14 16:43:22 +030030 {$ELSE}
Jens Geyer9f7f11e2016-04-14 21:37:11 +020031 Winapi.Windows, System.SysUtils,
32 {$ENDIF}
Jake Farrell27274222011-11-10 20:32:44 +000033 Thrift,
34 Thrift.Protocol,
35 Thrift.Transport;
36
37type
Jens Geyer01640402013-09-25 21:12:21 +020038 IServerEvents = interface
39 ['{9E2A99C5-EE85-40B2-9A52-2D1722B18176}']
40 // Called before the server begins.
41 procedure PreServe;
42 // Called when the server transport is ready to accept requests
43 procedure PreAccept;
44 // Called when a new client has connected and the server is about to being processing.
45 function CreateProcessingContext( const input, output : IProtocol) : IProcessorEvents;
46 end;
47
48
Jake Farrell27274222011-11-10 20:32:44 +000049 IServer = interface
Jens Geyer01640402013-09-25 21:12:21 +020050 ['{ADC46F2D-8199-4D1C-96D2-87FD54351723}']
Jake Farrell27274222011-11-10 20:32:44 +000051 procedure Serve;
52 procedure Stop;
Jens Geyer01640402013-09-25 21:12:21 +020053
54 function GetServerEvents : IServerEvents;
55 procedure SetServerEvents( const value : IServerEvents);
56
57 property ServerEvents : IServerEvents read GetServerEvents write SetServerEvents;
Jake Farrell27274222011-11-10 20:32:44 +000058 end;
59
60 TServerImpl = class abstract( TInterfacedObject, IServer )
61 public
62 type
Roger Meier333bbf32012-01-08 21:51:08 +000063 TLogDelegate = reference to procedure( const str: string);
Jens Geyer2646bd62019-11-09 23:24:52 +010064 protected
Jake Farrell27274222011-11-10 20:32:44 +000065 FProcessor : IProcessor;
66 FServerTransport : IServerTransport;
67 FInputTransportFactory : ITransportFactory;
68 FOutputTransportFactory : ITransportFactory;
69 FInputProtocolFactory : IProtocolFactory;
70 FOutputProtocolFactory : IProtocolFactory;
71 FLogDelegate : TLogDelegate;
Jens Geyer01640402013-09-25 21:12:21 +020072 FServerEvents : IServerEvents;
Jake Farrell27274222011-11-10 20:32:44 +000073
Roger Meier333bbf32012-01-08 21:51:08 +000074 class procedure DefaultLogDelegate( const str: string);
Jake Farrell27274222011-11-10 20:32:44 +000075
Jens Geyer01640402013-09-25 21:12:21 +020076 function GetServerEvents : IServerEvents;
77 procedure SetServerEvents( const value : IServerEvents);
78
Jake Farrell27274222011-11-10 20:32:44 +000079 procedure Serve; virtual; abstract;
80 procedure Stop; virtual; abstract;
81 public
82 constructor Create(
Jens Geyerfad7fd32019-11-09 23:24:52 +010083 const aProcessor :IProcessor;
84 const aServerTransport: IServerTransport;
85 const aInputTransportFactory : ITransportFactory;
86 const aOutputTransportFactory : ITransportFactory;
87 const aInputProtocolFactory : IProtocolFactory;
88 const aOutputProtocolFactory : IProtocolFactory;
89 const aLogDelegate : TLogDelegate
Jake Farrell27274222011-11-10 20:32:44 +000090 ); overload;
91
Jens Geyer01640402013-09-25 21:12:21 +020092 constructor Create(
Jens Geyerfad7fd32019-11-09 23:24:52 +010093 const aProcessor :IProcessor;
94 const aServerTransport: IServerTransport
Jens Geyerd5436f52014-10-03 19:50:38 +020095 ); overload;
Jake Farrell27274222011-11-10 20:32:44 +000096
97 constructor Create(
Jens Geyerfad7fd32019-11-09 23:24:52 +010098 const aProcessor :IProcessor;
99 const aServerTransport: IServerTransport;
100 const aLogDelegate: TLogDelegate
Jake Farrell27274222011-11-10 20:32:44 +0000101 ); overload;
102
103 constructor Create(
Jens Geyerfad7fd32019-11-09 23:24:52 +0100104 const aProcessor :IProcessor;
105 const aServerTransport: IServerTransport;
106 const aTransportFactory : ITransportFactory
Jake Farrell27274222011-11-10 20:32:44 +0000107 ); overload;
108
109 constructor Create(
Jens Geyerfad7fd32019-11-09 23:24:52 +0100110 const aProcessor :IProcessor;
111 const aServerTransport: IServerTransport;
112 const aTransportFactory : ITransportFactory;
113 const aProtocolFactory : IProtocolFactory
Jake Farrell27274222011-11-10 20:32:44 +0000114 ); overload;
115 end;
116
Jens Geyerfad7fd32019-11-09 23:24:52 +0100117
Jake Farrell27274222011-11-10 20:32:44 +0000118 TSimpleServer = class( TServerImpl)
Jens Geyer2646bd62019-11-09 23:24:52 +0100119 private
Jake Farrell27274222011-11-10 20:32:44 +0000120 FStop : Boolean;
121 public
Jens Geyerfad7fd32019-11-09 23:24:52 +0100122 constructor Create(
123 const aProcessor: IProcessor;
124 const aServerTransport: IServerTransport
125 ); overload;
126
127 constructor Create(
128 const aProcessor: IProcessor;
129 const aServerTransport: IServerTransport;
130 const ALogDel: TServerImpl.TLogDelegate
131 ); overload;
132
133 constructor Create(
134 const aProcessor: IProcessor;
135 const aServerTransport: IServerTransport;
136 const aTransportFactory: ITransportFactory
137 ); overload;
138
139 constructor Create(
140 const aProcessor: IProcessor;
141 const aServerTransport: IServerTransport;
142 const aTransportFactory: ITransportFactory;
143 const aProtocolFactory: IProtocolFactory
144 ); overload;
Jake Farrell27274222011-11-10 20:32:44 +0000145
146 procedure Serve; override;
147 procedure Stop; override;
148 end;
149
150
151implementation
152
153{ TServerImpl }
154
Jens Geyerfad7fd32019-11-09 23:24:52 +0100155constructor TServerImpl.Create( const aProcessor: IProcessor;
156 const aServerTransport: IServerTransport;
157 const aLogDelegate: TLogDelegate);
Jake Farrell27274222011-11-10 20:32:44 +0000158var
159 InputFactory, OutputFactory : IProtocolFactory;
160 InputTransFactory, OutputTransFactory : ITransportFactory;
161
162begin
163 InputFactory := TBinaryProtocolImpl.TFactory.Create;
164 OutputFactory := TBinaryProtocolImpl.TFactory.Create;
165 InputTransFactory := TTransportFactoryImpl.Create;
166 OutputTransFactory := TTransportFactoryImpl.Create;
167
Jens Geyer01640402013-09-25 21:12:21 +0200168 //no inherited;
Jake Farrell27274222011-11-10 20:32:44 +0000169 Create(
Jens Geyerfad7fd32019-11-09 23:24:52 +0100170 aProcessor,
171 aServerTransport,
Jake Farrell27274222011-11-10 20:32:44 +0000172 InputTransFactory,
173 OutputTransFactory,
174 InputFactory,
175 OutputFactory,
176 ALogDelegate
177 );
178end;
179
Jens Geyerfad7fd32019-11-09 23:24:52 +0100180constructor TServerImpl.Create(const aProcessor: IProcessor;
181 const aServerTransport: IServerTransport);
Jake Farrell27274222011-11-10 20:32:44 +0000182var
183 InputFactory, OutputFactory : IProtocolFactory;
184 InputTransFactory, OutputTransFactory : ITransportFactory;
185
186begin
187 InputFactory := TBinaryProtocolImpl.TFactory.Create;
188 OutputFactory := TBinaryProtocolImpl.TFactory.Create;
189 InputTransFactory := TTransportFactoryImpl.Create;
190 OutputTransFactory := TTransportFactoryImpl.Create;
191
Jens Geyerd5436f52014-10-03 19:50:38 +0200192 //no inherited;
Jake Farrell27274222011-11-10 20:32:44 +0000193 Create(
Jens Geyerfad7fd32019-11-09 23:24:52 +0100194 aProcessor,
195 aServerTransport,
Jake Farrell27274222011-11-10 20:32:44 +0000196 InputTransFactory,
197 OutputTransFactory,
198 InputFactory,
199 OutputFactory,
200 DefaultLogDelegate
201 );
202end;
203
Jens Geyerfad7fd32019-11-09 23:24:52 +0100204constructor TServerImpl.Create(const aProcessor: IProcessor;
205 const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory);
Jake Farrell27274222011-11-10 20:32:44 +0000206var
207 InputProtocolFactory : IProtocolFactory;
208 OutputProtocolFactory : IProtocolFactory;
209begin
210 InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
211 OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
212
Jens Geyerd5436f52014-10-03 19:50:38 +0200213 //no inherited;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100214 Create( aProcessor, aServerTransport, aTransportFactory, aTransportFactory,
Jake Farrell27274222011-11-10 20:32:44 +0000215 InputProtocolFactory, OutputProtocolFactory, DefaultLogDelegate);
216end;
217
Jens Geyerfad7fd32019-11-09 23:24:52 +0100218constructor TServerImpl.Create(const aProcessor: IProcessor;
219 const aServerTransport: IServerTransport;
220 const aInputTransportFactory, aOutputTransportFactory: ITransportFactory;
221 const aInputProtocolFactory, aOutputProtocolFactory: IProtocolFactory;
222 const aLogDelegate : TLogDelegate);
Jake Farrell27274222011-11-10 20:32:44 +0000223begin
Jens Geyer718f6ee2013-09-06 21:02:34 +0200224 inherited Create;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100225 FProcessor := aProcessor;
226 FServerTransport := aServerTransport;
227 FInputTransportFactory := aInputTransportFactory;
228 FOutputTransportFactory := aOutputTransportFactory;
229 FInputProtocolFactory := aInputProtocolFactory;
230 FOutputProtocolFactory := aOutputProtocolFactory;
231 FLogDelegate := aLogDelegate;
Jake Farrell27274222011-11-10 20:32:44 +0000232end;
233
Roger Meier333bbf32012-01-08 21:51:08 +0000234class procedure TServerImpl.DefaultLogDelegate( const str: string);
Jake Farrell27274222011-11-10 20:32:44 +0000235begin
Jens Geyer26ef7432013-09-23 22:01:20 +0200236 try
237 Writeln( str);
238 if IoResult <> 0 then OutputDebugString(PChar(str));
239 except
240 OutputDebugString(PChar(str));
241 end;
Jake Farrell27274222011-11-10 20:32:44 +0000242end;
243
Jens Geyerfad7fd32019-11-09 23:24:52 +0100244constructor TServerImpl.Create( const aProcessor: IProcessor;
245 const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory;
246 const aProtocolFactory: IProtocolFactory);
Jake Farrell806d2982011-10-26 02:33:31 +0000247begin
Jens Geyer01640402013-09-25 21:12:21 +0200248 //no inherited;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100249 Create( aProcessor, aServerTransport,
250 aTransportFactory, aTransportFactory,
251 aProtocolFactory, aProtocolFactory,
Jake Farrell806d2982011-10-26 02:33:31 +0000252 DefaultLogDelegate);
253end;
254
Jens Geyer01640402013-09-25 21:12:21 +0200255
256function TServerImpl.GetServerEvents : IServerEvents;
257begin
258 result := FServerEvents;
259end;
260
261
262procedure TServerImpl.SetServerEvents( const value : IServerEvents);
263begin
264 // if you need more than one, provide a specialized IServerEvents implementation
265 FServerEvents := value;
266end;
267
268
Jake Farrell806d2982011-10-26 02:33:31 +0000269{ TSimpleServer }
Jake Farrell27274222011-11-10 20:32:44 +0000270
Jens Geyerfad7fd32019-11-09 23:24:52 +0100271constructor TSimpleServer.Create( const aProcessor: IProcessor;
272 const aServerTransport: IServerTransport);
Jake Farrell27274222011-11-10 20:32:44 +0000273var
274 InputProtocolFactory : IProtocolFactory;
275 OutputProtocolFactory : IProtocolFactory;
276 InputTransportFactory : ITransportFactory;
277 OutputTransportFactory : ITransportFactory;
278begin
279 InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
280 OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
281 InputTransportFactory := TTransportFactoryImpl.Create;
282 OutputTransportFactory := TTransportFactoryImpl.Create;
283
Jens Geyerfad7fd32019-11-09 23:24:52 +0100284 inherited Create( aProcessor, aServerTransport, InputTransportFactory,
Jake Farrell27274222011-11-10 20:32:44 +0000285 OutputTransportFactory, InputProtocolFactory, OutputProtocolFactory, DefaultLogDelegate);
286end;
287
Jens Geyerfad7fd32019-11-09 23:24:52 +0100288constructor TSimpleServer.Create( const aProcessor: IProcessor;
289 const aServerTransport: IServerTransport; const ALogDel: TServerImpl.TLogDelegate);
Jake Farrell27274222011-11-10 20:32:44 +0000290var
291 InputProtocolFactory : IProtocolFactory;
292 OutputProtocolFactory : IProtocolFactory;
293 InputTransportFactory : ITransportFactory;
294 OutputTransportFactory : ITransportFactory;
295begin
296 InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
297 OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
298 InputTransportFactory := TTransportFactoryImpl.Create;
299 OutputTransportFactory := TTransportFactoryImpl.Create;
300
Jens Geyerfad7fd32019-11-09 23:24:52 +0100301 inherited Create( aProcessor, aServerTransport, InputTransportFactory,
Jake Farrell27274222011-11-10 20:32:44 +0000302 OutputTransportFactory, InputProtocolFactory, OutputProtocolFactory, ALogDel);
303end;
304
Jens Geyerfad7fd32019-11-09 23:24:52 +0100305constructor TSimpleServer.Create( const aProcessor: IProcessor;
306 const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory);
Jake Farrell27274222011-11-10 20:32:44 +0000307begin
Jens Geyerfad7fd32019-11-09 23:24:52 +0100308 inherited Create( aProcessor, aServerTransport, aTransportFactory,
309 aTransportFactory, TBinaryProtocolImpl.TFactory.Create, TBinaryProtocolImpl.TFactory.Create, DefaultLogDelegate);
Jake Farrell27274222011-11-10 20:32:44 +0000310end;
311
Jens Geyerfad7fd32019-11-09 23:24:52 +0100312constructor TSimpleServer.Create( const aProcessor: IProcessor;
313 const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory;
314 const aProtocolFactory: IProtocolFactory);
Jake Farrell27274222011-11-10 20:32:44 +0000315begin
Jens Geyerfad7fd32019-11-09 23:24:52 +0100316 inherited Create( aProcessor, aServerTransport, aTransportFactory,
317 aTransportFactory, aProtocolFactory, aProtocolFactory, DefaultLogDelegate);
Jake Farrell27274222011-11-10 20:32:44 +0000318end;
319
320procedure TSimpleServer.Serve;
321var
322 client : ITransport;
323 InputTransport : ITransport;
324 OutputTransport : ITransport;
325 InputProtocol : IProtocol;
326 OutputProtocol : IProtocol;
Jens Geyer01640402013-09-25 21:12:21 +0200327 context : IProcessorEvents;
Jake Farrell27274222011-11-10 20:32:44 +0000328begin
329 try
330 FServerTransport.Listen;
331 except
332 on E: Exception do
333 begin
334 FLogDelegate( E.ToString);
335 end;
336 end;
337
Jens Geyer01640402013-09-25 21:12:21 +0200338 if FServerEvents <> nil
339 then FServerEvents.PreServe;
340
Jake Farrell27274222011-11-10 20:32:44 +0000341 client := nil;
Jake Farrell27274222011-11-10 20:32:44 +0000342 while (not FStop) do
343 begin
344 try
Jens Geyer06045cf2013-03-27 20:26:25 +0200345 // clean up any old instances before waiting for clients
346 InputTransport := nil;
347 OutputTransport := nil;
348 InputProtocol := nil;
349 OutputProtocol := nil;
350
Jens Geyer3e8d9272014-09-14 20:10:40 +0200351 // close any old connections before before waiting for new clients
352 if client <> nil then try
353 try
354 client.Close;
355 finally
356 client := nil;
357 end;
358 except
359 // catch all, we can't do much about it at this point
360 end;
361
Jens Geyer01640402013-09-25 21:12:21 +0200362 client := FServerTransport.Accept( procedure
363 begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200364 if FServerEvents <> nil
Jens Geyer01640402013-09-25 21:12:21 +0200365 then FServerEvents.PreAccept;
Jens Geyerd5436f52014-10-03 19:50:38 +0200366 end);
367
368 if client = nil then begin
369 if FStop
370 then Abort // silent exception
Jens Geyere0e32402016-04-20 21:50:48 +0200371 else raise TTransportExceptionUnknown.Create('ServerTransport.Accept() may not return NULL');
Jens Geyerd5436f52014-10-03 19:50:38 +0200372 end;
373
Jake Farrell27274222011-11-10 20:32:44 +0000374 FLogDelegate( 'Client Connected!');
Jens Geyer06045cf2013-03-27 20:26:25 +0200375
Jake Farrell27274222011-11-10 20:32:44 +0000376 InputTransport := FInputTransportFactory.GetTransport( client );
377 OutputTransport := FOutputTransportFactory.GetTransport( client );
378 InputProtocol := FInputProtocolFactory.GetProtocol( InputTransport );
379 OutputProtocol := FOutputProtocolFactory.GetProtocol( OutputTransport );
Jens Geyer01640402013-09-25 21:12:21 +0200380
381 if FServerEvents <> nil
382 then context := FServerEvents.CreateProcessingContext( InputProtocol, OutputProtocol)
383 else context := nil;
384
385 while not FStop do begin
386 if context <> nil
387 then context.Processing( client);
388 if not FProcessor.Process( InputProtocol, OutputProtocol, context)
389 then Break;
Jake Farrell27274222011-11-10 20:32:44 +0000390 end;
Jens Geyer06045cf2013-03-27 20:26:25 +0200391
Jake Farrell27274222011-11-10 20:32:44 +0000392 except
393 on E: TTransportException do
394 begin
Roger Meier79655fb2012-10-20 20:59:41 +0000395 if FStop
396 then FLogDelegate('TSimpleServer was shutting down, caught ' + E.ToString)
397 else FLogDelegate( E.ToString);
Jake Farrell27274222011-11-10 20:32:44 +0000398 end;
399 on E: Exception do
400 begin
Roger Meier79655fb2012-10-20 20:59:41 +0000401 FLogDelegate( E.ToString);
Jake Farrell27274222011-11-10 20:32:44 +0000402 end;
403 end;
Jens Geyer01640402013-09-25 21:12:21 +0200404
405 if context <> nil
406 then begin
407 context.CleanupContext;
408 context := nil;
409 end;
410
Jake Farrell27274222011-11-10 20:32:44 +0000411 if InputTransport <> nil then
412 begin
413 InputTransport.Close;
414 end;
415 if OutputTransport <> nil then
416 begin
417 OutputTransport.Close;
418 end;
419 end;
420
421 if FStop then
422 begin
423 try
424 FServerTransport.Close;
425 except
426 on E: TTransportException do
427 begin
428 FLogDelegate('TServerTranport failed on close: ' + E.Message);
429 end;
430 end;
431 FStop := False;
432 end;
433end;
434
435procedure TSimpleServer.Stop;
436begin
437 FStop := True;
438 FServerTransport.Close;
439end;
440
441end.