blob: 13c5762cf65fb8d3e2f2143d3a87599f66c46963 [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);
Jake Farrell27274222011-11-10 20:32:44 +000064 protected
65 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(
Roger Meier333bbf32012-01-08 21:51:08 +000083 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(
Roger Meier333bbf32012-01-08 21:51:08 +000093 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(
Roger Meier333bbf32012-01-08 21:51:08 +000098 const AProcessor :IProcessor;
99 const AServerTransport: IServerTransport;
100 const ALogDelegate: TLogDelegate
Jake Farrell27274222011-11-10 20:32:44 +0000101 ); overload;
102
103 constructor Create(
Roger Meier333bbf32012-01-08 21:51:08 +0000104 const AProcessor :IProcessor;
105 const AServerTransport: IServerTransport;
106 const ATransportFactory : ITransportFactory
Jake Farrell27274222011-11-10 20:32:44 +0000107 ); overload;
108
109 constructor Create(
Roger Meier333bbf32012-01-08 21:51:08 +0000110 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
117 TSimpleServer = class( TServerImpl)
118 private
119 FStop : Boolean;
120 public
Roger Meier333bbf32012-01-08 21:51:08 +0000121 constructor Create( const AProcessor: IProcessor; const AServerTransport: IServerTransport); overload;
122 constructor Create( const AProcessor: IProcessor; const AServerTransport: IServerTransport;
Jake Farrell27274222011-11-10 20:32:44 +0000123 ALogDel: TServerImpl.TLogDelegate); overload;
Roger Meier333bbf32012-01-08 21:51:08 +0000124 constructor Create( const AProcessor: IProcessor; const AServerTransport: IServerTransport;
125 const ATransportFactory: ITransportFactory); overload;
126 constructor Create( const AProcessor: IProcessor; const AServerTransport: IServerTransport;
127 const ATransportFactory: ITransportFactory; const AProtocolFactory: IProtocolFactory); overload;
Jake Farrell27274222011-11-10 20:32:44 +0000128
129 procedure Serve; override;
130 procedure Stop; override;
131 end;
132
133
134implementation
135
136{ TServerImpl }
137
Roger Meier333bbf32012-01-08 21:51:08 +0000138constructor TServerImpl.Create( const AProcessor: IProcessor;
139 const AServerTransport: IServerTransport; const ALogDelegate: TLogDelegate);
Jake Farrell27274222011-11-10 20:32:44 +0000140var
141 InputFactory, OutputFactory : IProtocolFactory;
142 InputTransFactory, OutputTransFactory : ITransportFactory;
143
144begin
145 InputFactory := TBinaryProtocolImpl.TFactory.Create;
146 OutputFactory := TBinaryProtocolImpl.TFactory.Create;
147 InputTransFactory := TTransportFactoryImpl.Create;
148 OutputTransFactory := TTransportFactoryImpl.Create;
149
Jens Geyer01640402013-09-25 21:12:21 +0200150 //no inherited;
Jake Farrell27274222011-11-10 20:32:44 +0000151 Create(
152 AProcessor,
153 AServerTransport,
154 InputTransFactory,
155 OutputTransFactory,
156 InputFactory,
157 OutputFactory,
158 ALogDelegate
159 );
160end;
161
Roger Meier333bbf32012-01-08 21:51:08 +0000162constructor TServerImpl.Create(const AProcessor: IProcessor;
163 const AServerTransport: IServerTransport);
Jake Farrell27274222011-11-10 20:32:44 +0000164var
165 InputFactory, OutputFactory : IProtocolFactory;
166 InputTransFactory, OutputTransFactory : ITransportFactory;
167
168begin
169 InputFactory := TBinaryProtocolImpl.TFactory.Create;
170 OutputFactory := TBinaryProtocolImpl.TFactory.Create;
171 InputTransFactory := TTransportFactoryImpl.Create;
172 OutputTransFactory := TTransportFactoryImpl.Create;
173
Jens Geyerd5436f52014-10-03 19:50:38 +0200174 //no inherited;
Jake Farrell27274222011-11-10 20:32:44 +0000175 Create(
176 AProcessor,
177 AServerTransport,
178 InputTransFactory,
179 OutputTransFactory,
180 InputFactory,
181 OutputFactory,
182 DefaultLogDelegate
183 );
184end;
185
Roger Meier333bbf32012-01-08 21:51:08 +0000186constructor TServerImpl.Create(const AProcessor: IProcessor;
187 const AServerTransport: IServerTransport; const ATransportFactory: ITransportFactory);
Jake Farrell27274222011-11-10 20:32:44 +0000188var
189 InputProtocolFactory : IProtocolFactory;
190 OutputProtocolFactory : IProtocolFactory;
191begin
192 InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
193 OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
194
Jens Geyerd5436f52014-10-03 19:50:38 +0200195 //no inherited;
Jake Farrell27274222011-11-10 20:32:44 +0000196 Create( AProcessor, AServerTransport, ATransportFactory, ATransportFactory,
197 InputProtocolFactory, OutputProtocolFactory, DefaultLogDelegate);
198end;
199
Roger Meier333bbf32012-01-08 21:51:08 +0000200constructor TServerImpl.Create(const AProcessor: IProcessor;
201 const AServerTransport: IServerTransport;
202 const AInputTransportFactory, AOutputTransportFactory: ITransportFactory;
203 const AInputProtocolFactory, AOutputProtocolFactory: IProtocolFactory;
204 const ALogDelegate : TLogDelegate);
Jake Farrell27274222011-11-10 20:32:44 +0000205begin
Jens Geyer718f6ee2013-09-06 21:02:34 +0200206 inherited Create;
Jake Farrell27274222011-11-10 20:32:44 +0000207 FProcessor := AProcessor;
208 FServerTransport := AServerTransport;
209 FInputTransportFactory := AInputTransportFactory;
210 FOutputTransportFactory := AOutputTransportFactory;
211 FInputProtocolFactory := AInputProtocolFactory;
212 FOutputProtocolFactory := AOutputProtocolFactory;
213 FLogDelegate := ALogDelegate;
214end;
215
Roger Meier333bbf32012-01-08 21:51:08 +0000216class procedure TServerImpl.DefaultLogDelegate( const str: string);
Jake Farrell27274222011-11-10 20:32:44 +0000217begin
Jens Geyer26ef7432013-09-23 22:01:20 +0200218 try
219 Writeln( str);
220 if IoResult <> 0 then OutputDebugString(PChar(str));
221 except
222 OutputDebugString(PChar(str));
223 end;
Jake Farrell27274222011-11-10 20:32:44 +0000224end;
225
Roger Meier333bbf32012-01-08 21:51:08 +0000226constructor TServerImpl.Create( const AProcessor: IProcessor;
227 const AServerTransport: IServerTransport; const ATransportFactory: ITransportFactory;
228 const AProtocolFactory: IProtocolFactory);
Jake Farrell806d2982011-10-26 02:33:31 +0000229begin
Jens Geyer01640402013-09-25 21:12:21 +0200230 //no inherited;
Jake Farrell806d2982011-10-26 02:33:31 +0000231 Create( AProcessor, AServerTransport,
232 ATransportFactory, ATransportFactory,
233 AProtocolFactory, AProtocolFactory,
234 DefaultLogDelegate);
235end;
236
Jens Geyer01640402013-09-25 21:12:21 +0200237
238function TServerImpl.GetServerEvents : IServerEvents;
239begin
240 result := FServerEvents;
241end;
242
243
244procedure TServerImpl.SetServerEvents( const value : IServerEvents);
245begin
246 // if you need more than one, provide a specialized IServerEvents implementation
247 FServerEvents := value;
248end;
249
250
Jake Farrell806d2982011-10-26 02:33:31 +0000251{ TSimpleServer }
Jake Farrell27274222011-11-10 20:32:44 +0000252
Roger Meier333bbf32012-01-08 21:51:08 +0000253constructor TSimpleServer.Create( const AProcessor: IProcessor;
254 const AServerTransport: IServerTransport);
Jake Farrell27274222011-11-10 20:32:44 +0000255var
256 InputProtocolFactory : IProtocolFactory;
257 OutputProtocolFactory : IProtocolFactory;
258 InputTransportFactory : ITransportFactory;
259 OutputTransportFactory : ITransportFactory;
260begin
261 InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
262 OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
263 InputTransportFactory := TTransportFactoryImpl.Create;
264 OutputTransportFactory := TTransportFactoryImpl.Create;
265
266 inherited Create( AProcessor, AServerTransport, InputTransportFactory,
267 OutputTransportFactory, InputProtocolFactory, OutputProtocolFactory, DefaultLogDelegate);
268end;
269
Roger Meier333bbf32012-01-08 21:51:08 +0000270constructor TSimpleServer.Create( const AProcessor: IProcessor;
271 const AServerTransport: IServerTransport; ALogDel: TServerImpl.TLogDelegate);
Jake Farrell27274222011-11-10 20:32:44 +0000272var
273 InputProtocolFactory : IProtocolFactory;
274 OutputProtocolFactory : IProtocolFactory;
275 InputTransportFactory : ITransportFactory;
276 OutputTransportFactory : ITransportFactory;
277begin
278 InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
279 OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create;
280 InputTransportFactory := TTransportFactoryImpl.Create;
281 OutputTransportFactory := TTransportFactoryImpl.Create;
282
283 inherited Create( AProcessor, AServerTransport, InputTransportFactory,
284 OutputTransportFactory, InputProtocolFactory, OutputProtocolFactory, ALogDel);
285end;
286
Roger Meier333bbf32012-01-08 21:51:08 +0000287constructor TSimpleServer.Create( const AProcessor: IProcessor;
288 const AServerTransport: IServerTransport; const ATransportFactory: ITransportFactory);
Jake Farrell27274222011-11-10 20:32:44 +0000289begin
290 inherited Create( AProcessor, AServerTransport, ATransportFactory,
291 ATransportFactory, TBinaryProtocolImpl.TFactory.Create, TBinaryProtocolImpl.TFactory.Create, DefaultLogDelegate);
292end;
293
Roger Meier333bbf32012-01-08 21:51:08 +0000294constructor TSimpleServer.Create( const AProcessor: IProcessor;
295 const AServerTransport: IServerTransport; const ATransportFactory: ITransportFactory;
296 const AProtocolFactory: IProtocolFactory);
Jake Farrell27274222011-11-10 20:32:44 +0000297begin
298 inherited Create( AProcessor, AServerTransport, ATransportFactory,
299 ATransportFactory, AProtocolFactory, AProtocolFactory, DefaultLogDelegate);
300end;
301
302procedure TSimpleServer.Serve;
303var
304 client : ITransport;
305 InputTransport : ITransport;
306 OutputTransport : ITransport;
307 InputProtocol : IProtocol;
308 OutputProtocol : IProtocol;
Jens Geyer01640402013-09-25 21:12:21 +0200309 context : IProcessorEvents;
Jake Farrell27274222011-11-10 20:32:44 +0000310begin
311 try
312 FServerTransport.Listen;
313 except
314 on E: Exception do
315 begin
316 FLogDelegate( E.ToString);
317 end;
318 end;
319
Jens Geyer01640402013-09-25 21:12:21 +0200320 if FServerEvents <> nil
321 then FServerEvents.PreServe;
322
Jake Farrell27274222011-11-10 20:32:44 +0000323 client := nil;
Jake Farrell27274222011-11-10 20:32:44 +0000324 while (not FStop) do
325 begin
326 try
Jens Geyer06045cf2013-03-27 20:26:25 +0200327 // clean up any old instances before waiting for clients
328 InputTransport := nil;
329 OutputTransport := nil;
330 InputProtocol := nil;
331 OutputProtocol := nil;
332
Jens Geyer3e8d9272014-09-14 20:10:40 +0200333 // close any old connections before before waiting for new clients
334 if client <> nil then try
335 try
336 client.Close;
337 finally
338 client := nil;
339 end;
340 except
341 // catch all, we can't do much about it at this point
342 end;
343
Jens Geyer01640402013-09-25 21:12:21 +0200344 client := FServerTransport.Accept( procedure
345 begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200346 if FServerEvents <> nil
Jens Geyer01640402013-09-25 21:12:21 +0200347 then FServerEvents.PreAccept;
Jens Geyerd5436f52014-10-03 19:50:38 +0200348 end);
349
350 if client = nil then begin
351 if FStop
352 then Abort // silent exception
Jens Geyere0e32402016-04-20 21:50:48 +0200353 else raise TTransportExceptionUnknown.Create('ServerTransport.Accept() may not return NULL');
Jens Geyerd5436f52014-10-03 19:50:38 +0200354 end;
355
Jake Farrell27274222011-11-10 20:32:44 +0000356 FLogDelegate( 'Client Connected!');
Jens Geyer06045cf2013-03-27 20:26:25 +0200357
Jake Farrell27274222011-11-10 20:32:44 +0000358 InputTransport := FInputTransportFactory.GetTransport( client );
359 OutputTransport := FOutputTransportFactory.GetTransport( client );
360 InputProtocol := FInputProtocolFactory.GetProtocol( InputTransport );
361 OutputProtocol := FOutputProtocolFactory.GetProtocol( OutputTransport );
Jens Geyer01640402013-09-25 21:12:21 +0200362
363 if FServerEvents <> nil
364 then context := FServerEvents.CreateProcessingContext( InputProtocol, OutputProtocol)
365 else context := nil;
366
367 while not FStop do begin
368 if context <> nil
369 then context.Processing( client);
370 if not FProcessor.Process( InputProtocol, OutputProtocol, context)
371 then Break;
Jake Farrell27274222011-11-10 20:32:44 +0000372 end;
Jens Geyer06045cf2013-03-27 20:26:25 +0200373
Jake Farrell27274222011-11-10 20:32:44 +0000374 except
375 on E: TTransportException do
376 begin
Roger Meier79655fb2012-10-20 20:59:41 +0000377 if FStop
378 then FLogDelegate('TSimpleServer was shutting down, caught ' + E.ToString)
379 else FLogDelegate( E.ToString);
Jake Farrell27274222011-11-10 20:32:44 +0000380 end;
381 on E: Exception do
382 begin
Roger Meier79655fb2012-10-20 20:59:41 +0000383 FLogDelegate( E.ToString);
Jake Farrell27274222011-11-10 20:32:44 +0000384 end;
385 end;
Jens Geyer01640402013-09-25 21:12:21 +0200386
387 if context <> nil
388 then begin
389 context.CleanupContext;
390 context := nil;
391 end;
392
Jake Farrell27274222011-11-10 20:32:44 +0000393 if InputTransport <> nil then
394 begin
395 InputTransport.Close;
396 end;
397 if OutputTransport <> nil then
398 begin
399 OutputTransport.Close;
400 end;
401 end;
402
403 if FStop then
404 begin
405 try
406 FServerTransport.Close;
407 except
408 on E: TTransportException do
409 begin
410 FLogDelegate('TServerTranport failed on close: ' + E.Message);
411 end;
412 end;
413 FStop := False;
414 end;
415end;
416
417procedure TSimpleServer.Stop;
418begin
419 FStop := True;
420 FServerTransport.Close;
421end;
422
423end.