blob: 5dfb14ef0f9fa1259726b80b1a4534dad5e8635f [file] [log] [blame]
Jens Geyerd5436f52014-10-03 19:50:38 +02001(*
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 *)
Jens Geyerd5436f52014-10-03 19:50:38 +020019unit Thrift.Transport;
20
Jens Geyer9f7f11e2016-04-14 21:37:11 +020021{$I Thrift.Defines.inc}
22{$SCOPEDENUMS ON}
23
Jens Geyerd5436f52014-10-03 19:50:38 +020024interface
25
26uses
27 Classes,
28 SysUtils,
29 Math,
Jens Geyerd5436f52014-10-03 19:50:38 +020030 Generics.Collections,
Jens Geyer9f7f11e2016-04-14 21:37:11 +020031 {$IFDEF OLD_UNIT_NAMES}
32 ActiveX, msxml, WinSock, Sockets,
Nick4f5229e2016-04-14 16:43:22 +030033 {$ELSE}
Jens Geyer9f7f11e2016-04-14 21:37:11 +020034 Winapi.ActiveX, Winapi.msxml, Winapi.WinSock,
35 {$IFDEF OLD_SOCKETS}
Jens Geyerbea9bbe2016-04-20 00:02:40 +020036 Web.Win.Sockets,
37 {$ELSE}
38 Thrift.Socket,
Jens Geyer9f7f11e2016-04-14 21:37:11 +020039 {$ENDIF}
40 {$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +020041 Thrift.Collections,
42 Thrift.Utils,
Nick4f5229e2016-04-14 16:43:22 +030043 Thrift.Stream;
Jens Geyerd5436f52014-10-03 19:50:38 +020044
45type
46 ITransport = interface
47 ['{A4A9FC37-D620-44DC-AD21-662D16364CE4}']
48 function GetIsOpen: Boolean;
49 property IsOpen: Boolean read GetIsOpen;
50 function Peek: Boolean;
51 procedure Open;
52 procedure Close;
53 function Read(var buf: TBytes; off: Integer; len: Integer): Integer;
54 function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer;
55 procedure Write( const buf: TBytes); overload;
56 procedure Write( const buf: TBytes; off: Integer; len: Integer); overload;
57 procedure Flush;
58 end;
59
60 TTransportImpl = class( TInterfacedObject, ITransport)
61 protected
62 function GetIsOpen: Boolean; virtual; abstract;
63 property IsOpen: Boolean read GetIsOpen;
64 function Peek: Boolean; virtual;
65 procedure Open(); virtual; abstract;
66 procedure Close(); virtual; abstract;
67 function Read(var buf: TBytes; off: Integer; len: Integer): Integer; virtual; abstract;
68 function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; virtual;
69 procedure Write( const buf: TBytes); overload; virtual;
70 procedure Write( const buf: TBytes; off: Integer; len: Integer); overload; virtual; abstract;
71 procedure Flush; virtual;
72 end;
73
74 TTransportException = class( Exception )
75 public
76 type
77 TExceptionType = (
78 Unknown,
79 NotOpen,
80 AlreadyOpen,
81 TimedOut,
Jens Geyerbea9bbe2016-04-20 00:02:40 +020082 EndOfFile,
83 BadArgs,
84 Interrupted
Jens Geyerd5436f52014-10-03 19:50:38 +020085 );
86 private
Jens Geyere0e32402016-04-20 21:50:48 +020087 function GetType: TExceptionType;
88 protected
89 constructor HiddenCreate(const Msg: string);
Jens Geyerd5436f52014-10-03 19:50:38 +020090 public
Jens Geyere0e32402016-04-20 21:50:48 +020091 class function Create( AType: TExceptionType): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
92 class function Create( const msg: string): TTransportException; reintroduce; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
93 class function Create( AType: TExceptionType; const msg: string): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
94 property Type_: TExceptionType read GetType;
Jens Geyerd5436f52014-10-03 19:50:38 +020095 end;
96
Jens Geyere0e32402016-04-20 21:50:48 +020097 // Needed to remove deprecation warning
98 TTransportExceptionSpecialized = class abstract (TTransportException)
99 public
100 constructor Create(const Msg: string);
101 end;
102
103 TTransportExceptionUnknown = class (TTransportExceptionSpecialized);
104 TTransportExceptionNotOpen = class (TTransportExceptionSpecialized);
105 TTransportExceptionAlreadyOpen = class (TTransportExceptionSpecialized);
106 TTransportExceptionTimedOut = class (TTransportExceptionSpecialized);
107 TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized);
108 TTransportExceptionBadArgs = class (TTransportExceptionSpecialized);
109 TTransportExceptionInterrupted = class (TTransportExceptionSpecialized);
110
Jens Geyerd5436f52014-10-03 19:50:38 +0200111 IHTTPClient = interface( ITransport )
112 ['{0F5DB8AB-710D-4338-AAC9-46B5734C5057}']
113 procedure SetConnectionTimeout(const Value: Integer);
114 function GetConnectionTimeout: Integer;
115 procedure SetReadTimeout(const Value: Integer);
116 function GetReadTimeout: Integer;
117 function GetCustomHeaders: IThriftDictionary<string,string>;
118 procedure SendRequest;
119 property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
120 property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
121 property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
122 end;
123
124 THTTPClientImpl = class( TTransportImpl, IHTTPClient)
125 private
126 FUri : string;
127 FInputStream : IThriftStream;
128 FOutputStream : IThriftStream;
129 FConnectionTimeout : Integer;
130 FReadTimeout : Integer;
131 FCustomHeaders : IThriftDictionary<string,string>;
132
133 function CreateRequest: IXMLHTTPRequest;
134 protected
135 function GetIsOpen: Boolean; override;
136 procedure Open(); override;
137 procedure Close(); override;
138 function Read( var buf: TBytes; off: Integer; len: Integer): Integer; override;
139 procedure Write( const buf: TBytes; off: Integer; len: Integer); override;
140 procedure Flush; override;
141
142 procedure SetConnectionTimeout(const Value: Integer);
143 function GetConnectionTimeout: Integer;
144 procedure SetReadTimeout(const Value: Integer);
145 function GetReadTimeout: Integer;
146 function GetCustomHeaders: IThriftDictionary<string,string>;
147 procedure SendRequest;
148 property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
149 property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
150 property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
151 public
152 constructor Create( const AUri: string);
153 destructor Destroy; override;
154 end;
155
156 IServerTransport = interface
157 ['{C43B87ED-69EA-47C4-B77C-15E288252900}']
158 procedure Listen;
159 procedure Close;
160 function Accept( const fnAccepting: TProc): ITransport;
161 end;
162
163 TServerTransportImpl = class( TInterfacedObject, IServerTransport)
164 protected
165 procedure Listen; virtual; abstract;
166 procedure Close; virtual; abstract;
167 function Accept( const fnAccepting: TProc): ITransport; virtual; abstract;
168 end;
169
170 ITransportFactory = interface
171 ['{DD809446-000F-49E1-9BFF-E0D0DC76A9D7}']
172 function GetTransport( const ATrans: ITransport): ITransport;
173 end;
174
175 TTransportFactoryImpl = class( TInterfacedObject, ITransportFactory)
176 function GetTransport( const ATrans: ITransport): ITransport; virtual;
177 end;
178
179 TTcpSocketStreamImpl = class( TThriftStreamImpl )
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200180{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200181 private type
182 TWaitForData = ( wfd_HaveData, wfd_Timeout, wfd_Error);
183 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200184 FTcpClient : TCustomIpClient;
Jens Geyerd5436f52014-10-03 19:50:38 +0200185 FTimeout : Integer;
186 function Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
187 TimeOut: Integer; var wsaError : Integer): Integer;
188 function WaitForData( TimeOut : Integer; pBuf : Pointer; DesiredBytes: Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +0200189 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200190{$ELSE}
191 FTcpClient: TSocket;
192 protected const
193 SLEEP_TIME = 200;
194{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200195 protected
196 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); override;
197 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; override;
198 procedure Open; override;
199 procedure Close; override;
200 procedure Flush; override;
201
202 function IsOpen: Boolean; override;
203 function ToArray: TBytes; override;
204 public
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200205{$IFDEF OLD_SOCKETS}
206 constructor Create( const ATcpClient: TCustomIpClient; const aTimeout : Integer = 0);
207{$ELSE}
208 constructor Create( const ATcpClient: TSocket; const aTimeout : Longword = 0);
209{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200210 end;
211
212 IStreamTransport = interface( ITransport )
213 ['{A8479B47-2A3E-4421-A9A0-D5A9EDCC634A}']
214 function GetInputStream: IThriftStream;
215 function GetOutputStream: IThriftStream;
216 property InputStream : IThriftStream read GetInputStream;
217 property OutputStream : IThriftStream read GetOutputStream;
218 end;
219
220 TStreamTransportImpl = class( TTransportImpl, IStreamTransport)
221 protected
222 FInputStream : IThriftStream;
223 FOutputStream : IThriftStream;
224 protected
225 function GetIsOpen: Boolean; override;
226
227 function GetInputStream: IThriftStream;
228 function GetOutputStream: IThriftStream;
229 public
230 property InputStream : IThriftStream read GetInputStream;
231 property OutputStream : IThriftStream read GetOutputStream;
232
233 procedure Open; override;
234 procedure Close; override;
235 procedure Flush; override;
236 function Read(var buf: TBytes; off: Integer; len: Integer): Integer; override;
237 procedure Write( const buf: TBytes; off: Integer; len: Integer); override;
238 constructor Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream);
239 destructor Destroy; override;
240 end;
241
242 TBufferedStreamImpl = class( TThriftStreamImpl)
243 private
244 FStream : IThriftStream;
245 FBufSize : Integer;
246 FReadBuffer : TMemoryStream;
247 FWriteBuffer : TMemoryStream;
248 protected
249 procedure Write( const buffer: TBytes; offset: Integer; count: Integer); override;
250 function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; override;
251 procedure Open; override;
252 procedure Close; override;
253 procedure Flush; override;
254 function IsOpen: Boolean; override;
255 function ToArray: TBytes; override;
256 public
257 constructor Create( const AStream: IThriftStream; ABufSize: Integer);
258 destructor Destroy; override;
259 end;
260
261 TServerSocketImpl = class( TServerTransportImpl)
262 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200263{$IFDEF OLD_SOCKETS}
264 FServer : TTcpServer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200265 FPort : Integer;
266 FClientTimeout : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200267{$ELSE}
268 FServer: TServerSocket;
269{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200270 FUseBufferedSocket : Boolean;
271 FOwnsServer : Boolean;
272 protected
273 function Accept( const fnAccepting: TProc) : ITransport; override;
274 public
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200275{$IFDEF OLD_SOCKETS}
276 constructor Create( const AServer: TTcpServer; AClientTimeout: Integer = 0); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +0200277 constructor Create( APort: Integer; AClientTimeout: Integer = 0; AUseBufferedSockets: Boolean = FALSE); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200278{$ELSE}
279 constructor Create( const AServer: TServerSocket; AClientTimeout: Longword = 0); overload;
280 constructor Create( APort: Integer; AClientTimeout: Longword = 0; AUseBufferedSockets: Boolean = FALSE); overload;
281{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200282 destructor Destroy; override;
283 procedure Listen; override;
284 procedure Close; override;
285 end;
286
287 TBufferedTransportImpl = class( TTransportImpl )
288 private
289 FInputBuffer : IThriftStream;
290 FOutputBuffer : IThriftStream;
291 FTransport : IStreamTransport;
292 FBufSize : Integer;
293
294 procedure InitBuffers;
295 function GetUnderlyingTransport: ITransport;
296 protected
297 function GetIsOpen: Boolean; override;
298 procedure Flush; override;
299 public
300 procedure Open(); override;
301 procedure Close(); override;
302 function Read(var buf: TBytes; off: Integer; len: Integer): Integer; override;
303 procedure Write( const buf: TBytes; off: Integer; len: Integer); override;
304 constructor Create( const ATransport : IStreamTransport ); overload;
305 constructor Create( const ATransport : IStreamTransport; ABufSize: Integer); overload;
306 property UnderlyingTransport: ITransport read GetUnderlyingTransport;
307 property IsOpen: Boolean read GetIsOpen;
308 end;
309
310 TSocketImpl = class(TStreamTransportImpl)
311 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200312{$IFDEF OLD_SOCKETS}
313 FClient : TCustomIpClient;
314{$ELSE}
315 FClient: TSocket;
316{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200317 FOwnsClient : Boolean;
318 FHost : string;
319 FPort : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200320{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200321 FTimeout : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200322{$ELSE}
323 FTimeout : Longword;
324{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200325
326 procedure InitSocket;
327 protected
328 function GetIsOpen: Boolean; override;
329 public
330 procedure Open; override;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200331{$IFDEF OLD_SOCKETS}
332 constructor Create( const AClient : TCustomIpClient; aOwnsClient : Boolean; ATimeout: Integer = 0); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +0200333 constructor Create( const AHost: string; APort: Integer; ATimeout: Integer = 0); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200334{$ELSE}
335 constructor Create(const AClient: TSocket; aOwnsClient: Boolean); overload;
336 constructor Create( const AHost: string; APort: Integer; ATimeout: Longword = 0); overload;
337{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200338 destructor Destroy; override;
339 procedure Close; override;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200340{$IFDEF OLD_SOCKETS}
341 property TcpClient: TCustomIpClient read FClient;
342{$ELSE}
343 property TcpClient: TSocket read FClient;
344{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200345 property Host : string read FHost;
346 property Port: Integer read FPort;
347 end;
348
349 TFramedTransportImpl = class( TTransportImpl)
350 private const
351 FHeaderSize : Integer = 4;
352 private class var
353 FHeader_Dummy : array of Byte;
354 protected
355 FTransport : ITransport;
356 FWriteBuffer : TMemoryStream;
357 FReadBuffer : TMemoryStream;
358
359 procedure InitWriteBuffer;
360 procedure ReadFrame;
361 public
362 type
363 TFactory = class( TTransportFactoryImpl )
364 public
365 function GetTransport( const ATrans: ITransport): ITransport; override;
366 end;
367
Jens Geyere0e32402016-04-20 21:50:48 +0200368 {$IFDEF HAVE_CLASS_CTOR}
Jens Geyerd5436f52014-10-03 19:50:38 +0200369 class constructor Create;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200370 {$ENDIF}
Jens Geyere0e32402016-04-20 21:50:48 +0200371
Jens Geyerd5436f52014-10-03 19:50:38 +0200372 constructor Create; overload;
373 constructor Create( const ATrans: ITransport); overload;
374 destructor Destroy; override;
375
376 procedure Open(); override;
377 function GetIsOpen: Boolean; override;
378
379 procedure Close(); override;
380 function Read(var buf: TBytes; off: Integer; len: Integer): Integer; override;
381 procedure Write( const buf: TBytes; off: Integer; len: Integer); override;
382 procedure Flush; override;
383 end;
384
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200385{$IFNDEF HAVE_CLASS_CTOR}
Jens Geyerd5436f52014-10-03 19:50:38 +0200386procedure TFramedTransportImpl_Initialize;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200387{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200388
389const
390 DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms
391
392
393implementation
394
395{ TTransportImpl }
396
397procedure TTransportImpl.Flush;
398begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200399 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200400end;
401
402function TTransportImpl.Peek: Boolean;
403begin
404 Result := IsOpen;
405end;
406
407function TTransportImpl.ReadAll( var buf: TBytes; off, len: Integer): Integer;
408var
409 got : Integer;
410 ret : Integer;
411begin
412 got := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200413 while got < len do begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200414 ret := Read( buf, off + got, len - got);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200415 if ret > 0
Jens Geyere0e32402016-04-20 21:50:48 +0200416 then Inc( got, ret)
417 else raise TTransportExceptionNotOpen.Create( 'Cannot read, Remote side has closed' );
Jens Geyerd5436f52014-10-03 19:50:38 +0200418 end;
419 Result := got;
420end;
421
422procedure TTransportImpl.Write( const buf: TBytes);
423begin
424 Self.Write( buf, 0, Length(buf) );
425end;
426
427{ THTTPClientImpl }
428
429procedure THTTPClientImpl.Close;
430begin
431 FInputStream := nil;
432 FOutputStream := nil;
433end;
434
435constructor THTTPClientImpl.Create(const AUri: string);
436begin
437 inherited Create;
438 FUri := AUri;
439 FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
440 FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
441end;
442
443function THTTPClientImpl.CreateRequest: IXMLHTTPRequest;
444var
445 pair : TPair<string,string>;
446begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200447 {$IF CompilerVersion >= 21.0}
Jens Geyerd5436f52014-10-03 19:50:38 +0200448 Result := CoXMLHTTP.Create;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200449 {$ELSE}
Jens Geyerd5436f52014-10-03 19:50:38 +0200450 Result := CoXMLHTTPRequest.Create;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200451 {$IFEND}
Jens Geyerd5436f52014-10-03 19:50:38 +0200452
453 Result.open('POST', FUri, False, '', '');
454 Result.setRequestHeader( 'Content-Type', 'application/x-thrift');
455 Result.setRequestHeader( 'Accept', 'application/x-thrift');
456 Result.setRequestHeader( 'User-Agent', 'Delphi/IHTTPClient');
457
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200458 for pair in FCustomHeaders do begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200459 Result.setRequestHeader( pair.Key, pair.Value );
460 end;
461end;
462
463destructor THTTPClientImpl.Destroy;
464begin
465 Close;
466 inherited;
467end;
468
469procedure THTTPClientImpl.Flush;
470begin
471 try
472 SendRequest;
473 finally
474 FOutputStream := nil;
475 FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
476 end;
477end;
478
479function THTTPClientImpl.GetConnectionTimeout: Integer;
480begin
481 Result := FConnectionTimeout;
482end;
483
484function THTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
485begin
486 Result := FCustomHeaders;
487end;
488
489function THTTPClientImpl.GetIsOpen: Boolean;
490begin
491 Result := True;
492end;
493
494function THTTPClientImpl.GetReadTimeout: Integer;
495begin
496 Result := FReadTimeout;
497end;
498
499procedure THTTPClientImpl.Open;
500begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200501 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200502end;
503
504function THTTPClientImpl.Read( var buf: TBytes; off, len: Integer): Integer;
505begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100506 if FInputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200507 raise TTransportExceptionNotOpen.Create('No request has been sent');
Jens Geyerd5436f52014-10-03 19:50:38 +0200508 end;
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100509
Jens Geyerd5436f52014-10-03 19:50:38 +0200510 try
511 Result := FInputStream.Read( buf, off, len )
512 except
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100513 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200514 do raise TTransportExceptionUnknown.Create(E.Message);
Jens Geyerd5436f52014-10-03 19:50:38 +0200515 end;
516end;
517
518procedure THTTPClientImpl.SendRequest;
519var
520 xmlhttp : IXMLHTTPRequest;
521 ms : TMemoryStream;
522 a : TBytes;
523 len : Integer;
524begin
525 xmlhttp := CreateRequest;
526
527 ms := TMemoryStream.Create;
528 try
529 a := FOutputStream.ToArray;
530 len := Length(a);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200531 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200532 ms.WriteBuffer( Pointer(@a[0])^, len);
533 end;
534 ms.Position := 0;
535 xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference )));
536 FInputStream := nil;
537 FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream);
538 finally
539 ms.Free;
540 end;
541end;
542
543procedure THTTPClientImpl.SetConnectionTimeout(const Value: Integer);
544begin
545 FConnectionTimeout := Value;
546end;
547
548procedure THTTPClientImpl.SetReadTimeout(const Value: Integer);
549begin
550 FReadTimeout := Value
551end;
552
553procedure THTTPClientImpl.Write( const buf: TBytes; off, len: Integer);
554begin
555 FOutputStream.Write( buf, off, len);
556end;
557
558{ TTransportException }
559
Jens Geyere0e32402016-04-20 21:50:48 +0200560function TTransportException.GetType: TExceptionType;
561begin
562 if Self is TTransportExceptionNotOpen then Result := TExceptionType.NotOpen
563 else if Self is TTransportExceptionAlreadyOpen then Result := TExceptionType.AlreadyOpen
564 else if Self is TTransportExceptionTimedOut then Result := TExceptionType.TimedOut
565 else if Self is TTransportExceptionEndOfFile then Result := TExceptionType.EndOfFile
566 else if Self is TTransportExceptionBadArgs then Result := TExceptionType.BadArgs
567 else if Self is TTransportExceptionInterrupted then Result := TExceptionType.Interrupted
568 else Result := TExceptionType.Unknown;
569end;
570
571constructor TTransportException.HiddenCreate(const Msg: string);
572begin
573 inherited Create(Msg);
574end;
575
576class function TTransportException.Create(AType: TExceptionType): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200577begin
578 //no inherited;
Jens Geyere0e32402016-04-20 21:50:48 +0200579{$WARN SYMBOL_DEPRECATED OFF}
580 Result := Create(AType, '')
581{$WARN SYMBOL_DEPRECATED DEFAULT}
Jens Geyerd5436f52014-10-03 19:50:38 +0200582end;
583
Jens Geyere0e32402016-04-20 21:50:48 +0200584class function TTransportException.Create(AType: TExceptionType;
585 const msg: string): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200586begin
Jens Geyere0e32402016-04-20 21:50:48 +0200587 case AType of
588 TExceptionType.NotOpen: Result := TTransportExceptionNotOpen.Create(msg);
589 TExceptionType.AlreadyOpen: Result := TTransportExceptionAlreadyOpen.Create(msg);
590 TExceptionType.TimedOut: Result := TTransportExceptionTimedOut.Create(msg);
591 TExceptionType.EndOfFile: Result := TTransportExceptionEndOfFile.Create(msg);
592 TExceptionType.BadArgs: Result := TTransportExceptionBadArgs.Create(msg);
593 TExceptionType.Interrupted: Result := TTransportExceptionInterrupted.Create(msg);
594 else
595 Result := TTransportExceptionUnknown.Create(msg);
596 end;
Jens Geyerd5436f52014-10-03 19:50:38 +0200597end;
598
Jens Geyere0e32402016-04-20 21:50:48 +0200599class function TTransportException.Create(const msg: string): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200600begin
Jens Geyere0e32402016-04-20 21:50:48 +0200601 Result := TTransportExceptionUnknown.Create(Msg);
602end;
603
604{ TTransportExceptionSpecialized }
605
606constructor TTransportExceptionSpecialized.Create(const Msg: string);
607begin
608 inherited HiddenCreate(Msg);
Jens Geyerd5436f52014-10-03 19:50:38 +0200609end;
610
611{ TTransportFactoryImpl }
612
613function TTransportFactoryImpl.GetTransport( const ATrans: ITransport): ITransport;
614begin
615 Result := ATrans;
616end;
617
618{ TServerSocket }
619
Jens Geyer23d67462015-12-19 11:44:57 +0100620{$IFDEF OLD_SOCKETS}
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200621constructor TServerSocketImpl.Create( const AServer: TTcpServer; AClientTimeout: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200622begin
623 inherited Create;
624 FServer := AServer;
625 FClientTimeout := AClientTimeout;
626end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200627{$ELSE}
628constructor TServerSocketImpl.Create( const AServer: TServerSocket; AClientTimeout: Longword);
Jens Geyerd5436f52014-10-03 19:50:38 +0200629begin
630 inherited Create;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200631 FServer := AServer;
632 FServer.RecvTimeout := AClientTimeout;
633 FServer.SendTimeout := AClientTimeout;
634end;
635{$ENDIF}
636
637{$IFDEF OLD_SOCKETS}
638constructor TServerSocketImpl.Create(APort, AClientTimeout: Integer; AUseBufferedSockets: Boolean);
639{$ELSE}
640constructor TServerSocketImpl.Create(APort: Integer; AClientTimeout: Longword; AUseBufferedSockets: Boolean);
641{$ENDIF}
642begin
643 inherited Create;
644{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200645 FPort := APort;
646 FClientTimeout := AClientTimeout;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200647 FServer := TTcpServer.Create( nil );
Jens Geyerd5436f52014-10-03 19:50:38 +0200648 FServer.BlockMode := bmBlocking;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200649 {$IF CompilerVersion >= 21.0}
Jens Geyerd5436f52014-10-03 19:50:38 +0200650 FServer.LocalPort := AnsiString( IntToStr( FPort));
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200651 {$ELSE}
Jens Geyerd5436f52014-10-03 19:50:38 +0200652 FServer.LocalPort := IntToStr( FPort);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200653 {$IFEND}
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200654{$ELSE}
655 FServer := TServerSocket.Create(APort, AClientTimeout, AClientTimeout);
656{$ENDIF}
657 FUseBufferedSocket := AUseBufferedSockets;
658 FOwnsServer := True;
Jens Geyerd5436f52014-10-03 19:50:38 +0200659end;
660
661destructor TServerSocketImpl.Destroy;
662begin
663 if FOwnsServer then begin
664 FServer.Free;
665 FServer := nil;
666 end;
667 inherited;
668end;
669
670function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport;
671var
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200672{$IFDEF OLD_SOCKETS}
673 client : TCustomIpClient;
674{$ELSE}
675 client: TSocket;
676{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200677 trans : IStreamTransport;
678begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100679 if FServer = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200680 raise TTransportExceptionNotOpen.Create('No underlying server socket.');
Jens Geyerd5436f52014-10-03 19:50:38 +0200681 end;
682
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200683{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200684 client := nil;
685 try
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200686 client := TCustomIpClient.Create(nil);
Jens Geyerd5436f52014-10-03 19:50:38 +0200687
688 if Assigned(fnAccepting)
689 then fnAccepting();
690
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100691 if not FServer.Accept( client) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200692 client.Free;
693 Result := nil;
694 Exit;
695 end;
696
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100697 if client = nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200698 Result := nil;
699 Exit;
700 end;
701
702 trans := TSocketImpl.Create( client, TRUE, FClientTimeout);
703 client := nil; // trans owns it now
704
705 if FUseBufferedSocket
706 then result := TBufferedTransportImpl.Create( trans)
707 else result := trans;
708
709 except
710 on E: Exception do begin
711 client.Free;
Jens Geyere0e32402016-04-20 21:50:48 +0200712 raise TTransportExceptionUnknown.Create(E.ToString);
Jens Geyerd5436f52014-10-03 19:50:38 +0200713 end;
714 end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200715{$ELSE}
716 if Assigned(fnAccepting) then
717 fnAccepting();
718
719 client := FServer.Accept;
720 try
721 trans := TSocketImpl.Create(client, True);
722 client := nil;
723
724 if FUseBufferedSocket then
725 Result := TBufferedTransportImpl.Create(trans)
726 else
727 Result := trans;
728 except
729 client.Free;
730 raise;
731 end;
732{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200733end;
734
735procedure TServerSocketImpl.Listen;
736begin
737 if FServer <> nil then
738 begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200739{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200740 try
741 FServer.Active := True;
742 except
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200743 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200744 do raise TTransportExceptionUnknown.Create('Could not accept on listening socket: ' + E.Message);
Jens Geyerd5436f52014-10-03 19:50:38 +0200745 end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200746{$ELSE}
747 FServer.Listen;
748{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200749 end;
750end;
751
752procedure TServerSocketImpl.Close;
753begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200754 if FServer <> nil then
755{$IFDEF OLD_SOCKETS}
756 try
757 FServer.Active := False;
758 except
759 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200760 do raise TTransportExceptionUnknown.Create('Error on closing socket : ' + E.Message);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200761 end;
762{$ELSE}
763 FServer.Close;
764{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200765end;
766
767{ TSocket }
768
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200769{$IFDEF OLD_SOCKETS}
770constructor TSocketImpl.Create( const AClient : TCustomIpClient; aOwnsClient : Boolean; ATimeout: Integer = 0);
Jens Geyerd5436f52014-10-03 19:50:38 +0200771var stream : IThriftStream;
772begin
773 FClient := AClient;
774 FTimeout := ATimeout;
775 FOwnsClient := aOwnsClient;
776 stream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
777 inherited Create( stream, stream);
778end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200779{$ELSE}
780constructor TSocketImpl.Create(const AClient: TSocket; aOwnsClient: Boolean);
781var stream : IThriftStream;
782begin
783 FClient := AClient;
784 FTimeout := AClient.RecvTimeout;
785 FOwnsClient := aOwnsClient;
786 stream := TTcpSocketStreamImpl.Create(FClient, FTimeout);
787 inherited Create(stream, stream);
788end;
789{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200790
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200791{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200792constructor TSocketImpl.Create(const AHost: string; APort, ATimeout: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200793{$ELSE}
794constructor TSocketImpl.Create(const AHost: string; APort: Integer; ATimeout: Longword);
795{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200796begin
797 inherited Create(nil,nil);
798 FHost := AHost;
799 FPort := APort;
800 FTimeout := ATimeout;
801 InitSocket;
802end;
803
804destructor TSocketImpl.Destroy;
805begin
806 if FOwnsClient
807 then FreeAndNil( FClient);
808 inherited;
809end;
810
811procedure TSocketImpl.Close;
812begin
813 inherited Close;
814 if FOwnsClient
815 then FreeAndNil( FClient);
816end;
817
818function TSocketImpl.GetIsOpen: Boolean;
819begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200820{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200821 Result := (FClient <> nil) and FClient.Connected;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200822{$ELSE}
823 Result := (FClient <> nil) and FClient.IsOpen
824{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200825end;
826
827procedure TSocketImpl.InitSocket;
828var
829 stream : IThriftStream;
830begin
831 if FOwnsClient
832 then FreeAndNil( FClient)
833 else FClient := nil;
834
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200835{$IFDEF OLD_SOCKETS}
836 FClient := TTcpClient.Create( nil);
837{$ELSE}
838 FClient := TSocket.Create(FHost, FPort);
839{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200840 FOwnsClient := True;
841
842 stream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
843 FInputStream := stream;
844 FOutputStream := stream;
845end;
846
847procedure TSocketImpl.Open;
848begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100849 if IsOpen then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200850 raise TTransportExceptionAlreadyOpen.Create('Socket already connected');
Jens Geyerd5436f52014-10-03 19:50:38 +0200851 end;
852
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100853 if FHost = '' then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200854 raise TTransportExceptionNotOpen.Create('Cannot open null host');
Jens Geyerd5436f52014-10-03 19:50:38 +0200855 end;
856
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100857 if Port <= 0 then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200858 raise TTransportExceptionNotOpen.Create('Cannot open without port');
Jens Geyerd5436f52014-10-03 19:50:38 +0200859 end;
860
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100861 if FClient = nil
862 then InitSocket;
Jens Geyerd5436f52014-10-03 19:50:38 +0200863
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200864{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200865 FClient.RemoteHost := TSocketHost( Host);
866 FClient.RemotePort := TSocketPort( IntToStr( Port));
867 FClient.Connect;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200868{$ELSE}
869 FClient.Open;
870{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200871
872 FInputStream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
873 FOutputStream := FInputStream;
874end;
875
876{ TBufferedStream }
877
878procedure TBufferedStreamImpl.Close;
879begin
880 Flush;
881 FStream := nil;
882
883 FReadBuffer.Free;
884 FReadBuffer := nil;
885
886 FWriteBuffer.Free;
887 FWriteBuffer := nil;
888end;
889
890constructor TBufferedStreamImpl.Create( const AStream: IThriftStream; ABufSize: Integer);
891begin
892 inherited Create;
893 FStream := AStream;
894 FBufSize := ABufSize;
895 FReadBuffer := TMemoryStream.Create;
896 FWriteBuffer := TMemoryStream.Create;
897end;
898
899destructor TBufferedStreamImpl.Destroy;
900begin
901 Close;
902 inherited;
903end;
904
905procedure TBufferedStreamImpl.Flush;
906var
907 buf : TBytes;
908 len : Integer;
909begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200910 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200911 len := FWriteBuffer.Size;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200912 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200913 SetLength( buf, len );
914 FWriteBuffer.Position := 0;
915 FWriteBuffer.Read( Pointer(@buf[0])^, len );
916 FStream.Write( buf, 0, len );
917 end;
918 FWriteBuffer.Clear;
919 end;
920end;
921
922function TBufferedStreamImpl.IsOpen: Boolean;
923begin
924 Result := (FWriteBuffer <> nil)
925 and (FReadBuffer <> nil)
926 and (FStream <> nil);
927end;
928
929procedure TBufferedStreamImpl.Open;
930begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200931 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200932end;
933
934function TBufferedStreamImpl.Read( var buffer: TBytes; offset: Integer; count: Integer): Integer;
935var
936 nRead : Integer;
937 tempbuf : TBytes;
938begin
939 inherited;
940 Result := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200941
942 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200943 while count > 0 do begin
944
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200945 if FReadBuffer.Position >= FReadBuffer.Size then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200946 FReadBuffer.Clear;
947 SetLength( tempbuf, FBufSize);
948 nRead := FStream.Read( tempbuf, 0, FBufSize );
949 if nRead = 0 then Break; // avoid infinite loop
950
951 FReadBuffer.WriteBuffer( Pointer(@tempbuf[0])^, nRead );
952 FReadBuffer.Position := 0;
953 end;
954
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200955 if FReadBuffer.Position < FReadBuffer.Size then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200956 nRead := Min( FReadBuffer.Size - FReadBuffer.Position, count);
957 Inc( Result, FReadBuffer.Read( Pointer(@buffer[offset])^, nRead));
958 Dec( count, nRead);
959 Inc( offset, nRead);
960 end;
961 end;
962 end;
963end;
964
965function TBufferedStreamImpl.ToArray: TBytes;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200966var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200967begin
968 len := 0;
969
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200970 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200971 len := FReadBuffer.Size;
972 end;
973
974 SetLength( Result, len);
975
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200976 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200977 FReadBuffer.Position := 0;
978 FReadBuffer.Read( Pointer(@Result[0])^, len );
979 end;
980end;
981
982procedure TBufferedStreamImpl.Write( const buffer: TBytes; offset: Integer; count: Integer);
983begin
984 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200985 if count > 0 then begin
986 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200987 FWriteBuffer.Write( Pointer(@buffer[offset])^, count );
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200988 if FWriteBuffer.Size > FBufSize then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200989 Flush;
990 end;
991 end;
992 end;
993end;
994
995{ TStreamTransportImpl }
996
997procedure TStreamTransportImpl.Close;
998begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100999 FInputStream := nil;
1000 FOutputStream := nil;
Jens Geyerd5436f52014-10-03 19:50:38 +02001001end;
1002
1003constructor TStreamTransportImpl.Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream);
1004begin
1005 inherited Create;
1006 FInputStream := AInputStream;
1007 FOutputStream := AOutputStream;
1008end;
1009
1010destructor TStreamTransportImpl.Destroy;
1011begin
1012 FInputStream := nil;
1013 FOutputStream := nil;
1014 inherited;
1015end;
1016
1017procedure TStreamTransportImpl.Flush;
1018begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001019 if FOutputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001020 raise TTransportExceptionNotOpen.Create('Cannot flush null outputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001021 end;
1022
1023 FOutputStream.Flush;
1024end;
1025
1026function TStreamTransportImpl.GetInputStream: IThriftStream;
1027begin
1028 Result := FInputStream;
1029end;
1030
1031function TStreamTransportImpl.GetIsOpen: Boolean;
1032begin
1033 Result := True;
1034end;
1035
1036function TStreamTransportImpl.GetOutputStream: IThriftStream;
1037begin
1038 Result := FInputStream;
1039end;
1040
1041procedure TStreamTransportImpl.Open;
1042begin
1043
1044end;
1045
1046function TStreamTransportImpl.Read(var buf: TBytes; off, len: Integer): Integer;
1047begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001048 if FInputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001049 raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001050 end;
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001051
Jens Geyerd5436f52014-10-03 19:50:38 +02001052 Result := FInputStream.Read( buf, off, len );
1053end;
1054
1055procedure TStreamTransportImpl.Write(const buf: TBytes; off, len: Integer);
1056begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001057 if FOutputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001058 raise TTransportExceptionNotOpen.Create('Cannot write to null outputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001059 end;
1060
1061 FOutputStream.Write( buf, off, len );
1062end;
1063
1064{ TBufferedTransportImpl }
1065
1066constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport);
1067begin
1068 //no inherited;
1069 Create( ATransport, 1024 );
1070end;
1071
1072procedure TBufferedTransportImpl.Close;
1073begin
1074 FTransport.Close;
1075end;
1076
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001077constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport; ABufSize: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001078begin
1079 inherited Create;
1080 FTransport := ATransport;
1081 FBufSize := ABufSize;
1082 InitBuffers;
1083end;
1084
1085procedure TBufferedTransportImpl.Flush;
1086begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001087 if FOutputBuffer <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001088 FOutputBuffer.Flush;
1089 end;
1090end;
1091
1092function TBufferedTransportImpl.GetIsOpen: Boolean;
1093begin
1094 Result := FTransport.IsOpen;
1095end;
1096
1097function TBufferedTransportImpl.GetUnderlyingTransport: ITransport;
1098begin
1099 Result := FTransport;
1100end;
1101
1102procedure TBufferedTransportImpl.InitBuffers;
1103begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001104 if FTransport.InputStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001105 FInputBuffer := TBufferedStreamImpl.Create( FTransport.InputStream, FBufSize );
1106 end;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001107 if FTransport.OutputStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001108 FOutputBuffer := TBufferedStreamImpl.Create( FTransport.OutputStream, FBufSize );
1109 end;
1110end;
1111
1112procedure TBufferedTransportImpl.Open;
1113begin
1114 FTransport.Open
1115end;
1116
1117function TBufferedTransportImpl.Read(var buf: TBytes; off, len: Integer): Integer;
1118begin
1119 Result := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001120 if FInputBuffer <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001121 Result := FInputBuffer.Read( buf, off, len );
1122 end;
1123end;
1124
1125procedure TBufferedTransportImpl.Write(const buf: TBytes; off, len: Integer);
1126begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001127 if FOutputBuffer <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001128 FOutputBuffer.Write( buf, off, len );
1129 end;
1130end;
1131
1132{ TFramedTransportImpl }
1133
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001134{$IFDEF HAVE_CLASS_CTOR}
1135class constructor TFramedTransportImpl.Create;
1136begin
1137 SetLength( FHeader_Dummy, FHeaderSize);
1138 FillChar( FHeader_Dummy[0], Length( FHeader_Dummy) * SizeOf( Byte ), 0);
1139end;
1140{$ELSE}
Jens Geyerd5436f52014-10-03 19:50:38 +02001141procedure TFramedTransportImpl_Initialize;
1142begin
1143 SetLength( TFramedTransportImpl.FHeader_Dummy, TFramedTransportImpl.FHeaderSize);
1144 FillChar( TFramedTransportImpl.FHeader_Dummy[0],
1145 Length( TFramedTransportImpl.FHeader_Dummy) * SizeOf( Byte ), 0);
1146end;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001147{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001148
1149constructor TFramedTransportImpl.Create;
1150begin
1151 inherited Create;
1152 InitWriteBuffer;
1153end;
1154
1155procedure TFramedTransportImpl.Close;
1156begin
1157 FTransport.Close;
1158end;
1159
1160constructor TFramedTransportImpl.Create( const ATrans: ITransport);
1161begin
1162 inherited Create;
1163 InitWriteBuffer;
1164 FTransport := ATrans;
1165end;
1166
1167destructor TFramedTransportImpl.Destroy;
1168begin
1169 FWriteBuffer.Free;
1170 FReadBuffer.Free;
1171 inherited;
1172end;
1173
1174procedure TFramedTransportImpl.Flush;
1175var
1176 buf : TBytes;
1177 len : Integer;
1178 data_len : Integer;
1179
1180begin
1181 len := FWriteBuffer.Size;
1182 SetLength( buf, len);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001183 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001184 System.Move( FWriteBuffer.Memory^, buf[0], len );
1185 end;
1186
1187 data_len := len - FHeaderSize;
Jens Geyer30ed90e2016-03-10 20:12:49 +01001188 if (data_len < 0) then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001189 raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: data_len < 0' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001190 end;
1191
1192 InitWriteBuffer;
1193
1194 buf[0] := Byte($FF and (data_len shr 24));
1195 buf[1] := Byte($FF and (data_len shr 16));
1196 buf[2] := Byte($FF and (data_len shr 8));
1197 buf[3] := Byte($FF and data_len);
1198
1199 FTransport.Write( buf, 0, len );
1200 FTransport.Flush;
1201end;
1202
1203function TFramedTransportImpl.GetIsOpen: Boolean;
1204begin
1205 Result := FTransport.IsOpen;
1206end;
1207
1208type
1209 TAccessMemoryStream = class(TMemoryStream)
1210 end;
1211
1212procedure TFramedTransportImpl.InitWriteBuffer;
1213begin
1214 FWriteBuffer.Free;
1215 FWriteBuffer := TMemoryStream.Create;
1216 TAccessMemoryStream(FWriteBuffer).Capacity := 1024;
1217 FWriteBuffer.Write( Pointer(@FHeader_Dummy[0])^, FHeaderSize);
1218end;
1219
1220procedure TFramedTransportImpl.Open;
1221begin
1222 FTransport.Open;
1223end;
1224
1225function TFramedTransportImpl.Read(var buf: TBytes; off, len: Integer): Integer;
1226var
1227 got : Integer;
1228begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001229 if FReadBuffer <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001230 if len > 0
1231 then got := FReadBuffer.Read( Pointer(@buf[off])^, len )
1232 else got := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001233
1234 if got > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001235 Result := got;
1236 Exit;
1237 end;
1238 end;
1239
1240 ReadFrame;
1241 if len > 0
1242 then Result := FReadBuffer.Read( Pointer(@buf[off])^, len)
1243 else Result := 0;
1244end;
1245
1246procedure TFramedTransportImpl.ReadFrame;
1247var
1248 i32rd : TBytes;
1249 size : Integer;
1250 buff : TBytes;
1251begin
1252 SetLength( i32rd, FHeaderSize );
1253 FTransport.ReadAll( i32rd, 0, FHeaderSize);
1254 size :=
1255 ((i32rd[0] and $FF) shl 24) or
1256 ((i32rd[1] and $FF) shl 16) or
1257 ((i32rd[2] and $FF) shl 8) or
1258 (i32rd[3] and $FF);
1259 SetLength( buff, size );
1260 FTransport.ReadAll( buff, 0, size );
1261 FReadBuffer.Free;
1262 FReadBuffer := TMemoryStream.Create;
1263 FReadBuffer.Write( Pointer(@buff[0])^, size );
1264 FReadBuffer.Position := 0;
1265end;
1266
1267procedure TFramedTransportImpl.Write(const buf: TBytes; off, len: Integer);
1268begin
1269 if len > 0
1270 then FWriteBuffer.Write( Pointer(@buf[off])^, len );
1271end;
1272
1273{ TFramedTransport.TFactory }
1274
1275function TFramedTransportImpl.TFactory.GetTransport( const ATrans: ITransport): ITransport;
1276begin
1277 Result := TFramedTransportImpl.Create( ATrans );
1278end;
1279
1280{ TTcpSocketStreamImpl }
1281
1282procedure TTcpSocketStreamImpl.Close;
1283begin
1284 FTcpClient.Close;
1285end;
1286
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001287{$IFDEF OLD_SOCKETS}
1288constructor TTcpSocketStreamImpl.Create( const ATcpClient: TCustomIpClient; const aTimeout : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001289begin
1290 inherited Create;
1291 FTcpClient := ATcpClient;
1292 FTimeout := aTimeout;
1293end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001294{$ELSE}
1295constructor TTcpSocketStreamImpl.Create( const ATcpClient: TSocket; const aTimeout : Longword);
1296begin
1297 inherited Create;
1298 FTcpClient := ATcpClient;
1299 if aTimeout = 0 then
1300 FTcpClient.RecvTimeout := SLEEP_TIME
1301 else
1302 FTcpClient.RecvTimeout := aTimeout;
1303 FTcpClient.SendTimeout := aTimeout;
1304end;
1305{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001306
1307procedure TTcpSocketStreamImpl.Flush;
1308begin
1309
1310end;
1311
1312function TTcpSocketStreamImpl.IsOpen: Boolean;
1313begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001314{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001315 Result := FTcpClient.Active;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001316{$ELSE}
1317 Result := FTcpClient.IsOpen;
1318{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001319end;
1320
1321procedure TTcpSocketStreamImpl.Open;
1322begin
1323 FTcpClient.Open;
1324end;
1325
1326
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001327{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001328function TTcpSocketStreamImpl.Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
1329 TimeOut: Integer; var wsaError : Integer): Integer;
1330var
1331 ReadFds: TFDset;
1332 ReadFdsptr: PFDset;
1333 WriteFds: TFDset;
1334 WriteFdsptr: PFDset;
1335 ExceptFds: TFDset;
1336 ExceptFdsptr: PFDset;
1337 tv: timeval;
1338 Timeptr: PTimeval;
1339 socket : TSocket;
1340begin
1341 if not FTcpClient.Active then begin
1342 wsaError := WSAEINVAL;
1343 Exit( SOCKET_ERROR);
1344 end;
1345
1346 socket := FTcpClient.Handle;
1347
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001348 if Assigned(ReadReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001349 ReadFdsptr := @ReadFds;
1350 FD_ZERO(ReadFds);
1351 FD_SET(socket, ReadFds);
1352 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001353 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001354 ReadFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001355 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001356
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001357 if Assigned(WriteReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001358 WriteFdsptr := @WriteFds;
1359 FD_ZERO(WriteFds);
1360 FD_SET(socket, WriteFds);
1361 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001362 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001363 WriteFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001364 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001365
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001366 if Assigned(ExceptFlag) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001367 ExceptFdsptr := @ExceptFds;
1368 FD_ZERO(ExceptFds);
1369 FD_SET(socket, ExceptFds);
1370 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001371 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001372 ExceptFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001373 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001374
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001375 if TimeOut >= 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001376 tv.tv_sec := TimeOut div 1000;
1377 tv.tv_usec := 1000 * (TimeOut mod 1000);
1378 Timeptr := @tv;
1379 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001380 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001381 Timeptr := nil; // wait forever
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001382 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001383
1384 wsaError := 0;
1385 try
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001386 {$IFDEF MSWINDOWS}
1387 {$IFDEF OLD_UNIT_NAMES}
1388 result := WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1389 {$ELSE}
1390 result := Winapi.WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1391 {$ENDIF}
1392 {$ENDIF}
1393 {$IFDEF LINUX}
1394 result := Libc.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1395 {$ENDIF}
1396
Jens Geyerd5436f52014-10-03 19:50:38 +02001397 if result = SOCKET_ERROR
1398 then wsaError := WSAGetLastError;
1399
1400 except
1401 result := SOCKET_ERROR;
1402 end;
1403
1404 if Assigned(ReadReady) then
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001405 ReadReady^ := FD_ISSET(socket, ReadFds);
1406
Jens Geyerd5436f52014-10-03 19:50:38 +02001407 if Assigned(WriteReady) then
1408 WriteReady^ := FD_ISSET(socket, WriteFds);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001409
Jens Geyerd5436f52014-10-03 19:50:38 +02001410 if Assigned(ExceptFlag) then
1411 ExceptFlag^ := FD_ISSET(socket, ExceptFds);
1412end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001413{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001414
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001415{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001416function TTcpSocketStreamImpl.WaitForData( TimeOut : Integer; pBuf : Pointer;
1417 DesiredBytes : Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001418 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001419var bCanRead, bError : Boolean;
1420 retval : Integer;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001421const
1422 MSG_PEEK = {$IFDEF OLD_UNIT_NAMES} WinSock.MSG_PEEK {$ELSE} Winapi.WinSock.MSG_PEEK {$ENDIF};
Jens Geyerd5436f52014-10-03 19:50:38 +02001423begin
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001424 bytesReady := 0;
1425
Jens Geyerd5436f52014-10-03 19:50:38 +02001426 // The select function returns the total number of socket handles that are ready
1427 // and contained in the fd_set structures, zero if the time limit expired,
1428 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1429 // WSAGetLastError can be used to retrieve a specific error code.
1430 retval := Self.Select( @bCanRead, nil, @bError, TimeOut, wsaError);
1431 if retval = SOCKET_ERROR
1432 then Exit( TWaitForData.wfd_Error);
1433 if (retval = 0) or not bCanRead
1434 then Exit( TWaitForData.wfd_Timeout);
1435
1436 // recv() returns the number of bytes received, or -1 if an error occurred.
1437 // The return value will be 0 when the peer has performed an orderly shutdown.
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001438
1439 retval := recv( FTcpClient.Handle, pBuf^, DesiredBytes, MSG_PEEK);
Jens Geyerd5436f52014-10-03 19:50:38 +02001440 if retval <= 0
1441 then Exit( TWaitForData.wfd_Error);
1442
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001443 // at least we have some data
1444 bytesReady := Min( retval, DesiredBytes);
1445 result := TWaitForData.wfd_HaveData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001446end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001447{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001448
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001449{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001450function TTcpSocketStreamImpl.Read(var buffer: TBytes; offset, count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001451// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001452var wfd : TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001453 wsaError,
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001454 msecs : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001455 nBytes : Integer;
1456 pDest : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001457begin
1458 inherited;
1459
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001460 if FTimeout > 0
1461 then msecs := FTimeout
1462 else msecs := DEFAULT_THRIFT_TIMEOUT;
1463
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001464 result := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +02001465 pDest := Pointer(@buffer[offset]);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001466 while count > 0 do begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001467
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001468 while TRUE do begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001469 wfd := WaitForData( msecs, pDest, count, wsaError, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001470 case wfd of
Jens Geyer65b17462016-03-09 00:07:46 +01001471 TWaitForData.wfd_Error : Exit;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001472 TWaitForData.wfd_HaveData : Break;
1473 TWaitForData.wfd_Timeout : begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001474 if (FTimeout = 0)
1475 then Exit
1476 else begin
Jens Geyere0e32402016-04-20 21:50:48 +02001477 raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001478
1479 end;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001480 end;
1481 else
1482 ASSERT( FALSE);
Jens Geyerd5436f52014-10-03 19:50:38 +02001483 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001484 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001485
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001486 // reduce the timeout once we got data
1487 if FTimeout > 0
1488 then msecs := FTimeout div 10
1489 else msecs := DEFAULT_THRIFT_TIMEOUT div 10;
1490 msecs := Max( msecs, 200);
1491
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001492 ASSERT( nBytes <= count);
1493 nBytes := FTcpClient.ReceiveBuf( pDest^, nBytes);
1494 Inc( pDest, nBytes);
1495 Dec( count, nBytes);
1496 Inc( result, nBytes);
1497 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001498end;
1499
1500function TTcpSocketStreamImpl.ToArray: TBytes;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001501// old sockets version
1502var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001503begin
1504 len := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001505 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001506 len := FTcpClient.BytesReceived;
1507 end;
1508
1509 SetLength( Result, len );
1510
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001511 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001512 FTcpClient.ReceiveBuf( Pointer(@Result[0])^, len);
1513 end;
1514end;
1515
1516procedure TTcpSocketStreamImpl.Write(const buffer: TBytes; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001517// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001518var bCanWrite, bError : Boolean;
1519 retval, wsaError : Integer;
1520begin
1521 inherited;
1522
1523 if not FTcpClient.Active
Jens Geyere0e32402016-04-20 21:50:48 +02001524 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerd5436f52014-10-03 19:50:38 +02001525
1526 // The select function returns the total number of socket handles that are ready
1527 // and contained in the fd_set structures, zero if the time limit expired,
1528 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1529 // WSAGetLastError can be used to retrieve a specific error code.
1530 retval := Self.Select( nil, @bCanWrite, @bError, FTimeOut, wsaError);
1531 if retval = SOCKET_ERROR
Jens Geyere0e32402016-04-20 21:50:48 +02001532 then raise TTransportExceptionUnknown.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001533
Jens Geyerd5436f52014-10-03 19:50:38 +02001534 if (retval = 0)
Jens Geyere0e32402016-04-20 21:50:48 +02001535 then raise TTransportExceptionTimedOut.Create('timed out');
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001536
Jens Geyerd5436f52014-10-03 19:50:38 +02001537 if bError or not bCanWrite
Jens Geyere0e32402016-04-20 21:50:48 +02001538 then raise TTransportExceptionUnknown.Create('unknown error');
Jens Geyerd5436f52014-10-03 19:50:38 +02001539
1540 FTcpClient.SendBuf( Pointer(@buffer[offset])^, count);
1541end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001542
1543{$ELSE}
1544
1545function TTcpSocketStreamImpl.Read(var buffer: TBytes; offset, count: Integer): Integer;
1546// new sockets version
1547var nBytes : Integer;
1548 pDest : PByte;
1549begin
1550 inherited;
1551
1552 result := 0;
1553 pDest := Pointer(@buffer[offset]);
1554 while count > 0 do begin
1555 nBytes := FTcpClient.Read(pDest^, count);
1556 if nBytes = 0 then Exit;
1557 Inc( pDest, nBytes);
1558 Dec( count, nBytes);
1559 Inc( result, nBytes);
1560 end;
1561end;
1562
1563function TTcpSocketStreamImpl.ToArray: TBytes;
1564// new sockets version
1565var len : Integer;
1566begin
1567 len := 0;
1568 try
1569 if FTcpClient.Peek then
1570 repeat
1571 SetLength(Result, Length(Result) + 1024);
1572 len := FTcpClient.Read(Result[Length(Result) - 1024], 1024);
1573 until len < 1024;
1574 except
1575 on TTransportException do begin { don't allow default exceptions } end;
1576 else raise;
1577 end;
1578 if len > 0 then
1579 SetLength(Result, Length(Result) - 1024 + len);
1580end;
1581
1582procedure TTcpSocketStreamImpl.Write(const buffer: TBytes; offset, count: Integer);
1583// new sockets version
1584begin
1585 inherited;
1586
1587 if not FTcpClient.IsOpen
Kyle Johnsone363a342016-04-22 19:11:16 -05001588 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001589
1590 FTcpClient.Write(buffer[offset], count);
1591end;
1592
Jens Geyer23d67462015-12-19 11:44:57 +01001593{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001594
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001595
Jens Geyerd5436f52014-10-03 19:50:38 +02001596{$IF CompilerVersion < 21.0}
1597initialization
1598begin
1599 TFramedTransportImpl_Initialize;
1600end;
1601{$IFEND}
1602
1603
1604end.