blob: 1f8fdb0b239651b9d3ac31b60d3ca346d10eec7a [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}
Jens Geyer02230912019-04-03 01:12:51 +020032 WinSock, Sockets,
Nick4f5229e2016-04-14 16:43:22 +030033 {$ELSE}
Jens Geyer02230912019-04-03 01:12:51 +020034 Winapi.WinSock,
Jens Geyer9f7f11e2016-04-14 21:37:11 +020035 {$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,
Jens Geyer606f1ef2018-04-09 23:09:41 +020042 Thrift.Exception,
Jens Geyerd5436f52014-10-03 19:50:38 +020043 Thrift.Utils,
Jens Geyer02230912019-04-03 01:12:51 +020044 Thrift.WinHTTP,
Nick4f5229e2016-04-14 16:43:22 +030045 Thrift.Stream;
Jens Geyerd5436f52014-10-03 19:50:38 +020046
47type
48 ITransport = interface
Jens Geyer17c3ad92017-09-05 20:31:27 +020049 ['{DB84961E-8BB3-4532-99E1-A8C7AC2300F7}']
Jens Geyerd5436f52014-10-03 19:50:38 +020050 function GetIsOpen: Boolean;
51 property IsOpen: Boolean read GetIsOpen;
52 function Peek: Boolean;
53 procedure Open;
54 procedure Close;
Jens Geyer17c3ad92017-09-05 20:31:27 +020055 function Read(var buf: TBytes; off: Integer; len: Integer): Integer; overload;
56 function Read(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload;
57 function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; overload;
58 function ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload;
Jens Geyerd5436f52014-10-03 19:50:38 +020059 procedure Write( const buf: TBytes); overload;
60 procedure Write( const buf: TBytes; off: Integer; len: Integer); overload;
Jens Geyer17c3ad92017-09-05 20:31:27 +020061 procedure Write( const pBuf : Pointer; off, len : Integer); overload;
62 procedure Write( const pBuf : Pointer; len : Integer); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +020063 procedure Flush;
64 end;
65
66 TTransportImpl = class( TInterfacedObject, ITransport)
67 protected
68 function GetIsOpen: Boolean; virtual; abstract;
69 property IsOpen: Boolean read GetIsOpen;
70 function Peek: Boolean; virtual;
71 procedure Open(); virtual; abstract;
72 procedure Close(); virtual; abstract;
Jens Geyer17c3ad92017-09-05 20:31:27 +020073 function Read(var buf: TBytes; off: Integer; len: Integer): Integer; overload; inline;
74 function Read(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; virtual; abstract;
75 function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; overload; inline;
76 function ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; virtual;
77 procedure Write( const buf: TBytes); overload; inline;
78 procedure Write( const buf: TBytes; off: Integer; len: Integer); overload; inline;
79 procedure Write( const pBuf : Pointer; len : Integer); overload; inline;
80 procedure Write( const pBuf : Pointer; off, len : Integer); overload; virtual; abstract;
Jens Geyerd5436f52014-10-03 19:50:38 +020081 procedure Flush; virtual;
82 end;
83
Jens Geyer606f1ef2018-04-09 23:09:41 +020084 TTransportException = class( TException)
Jens Geyerd5436f52014-10-03 19:50:38 +020085 public
86 type
87 TExceptionType = (
88 Unknown,
89 NotOpen,
90 AlreadyOpen,
91 TimedOut,
Jens Geyerbea9bbe2016-04-20 00:02:40 +020092 EndOfFile,
93 BadArgs,
94 Interrupted
Jens Geyerd5436f52014-10-03 19:50:38 +020095 );
96 private
Jens Geyere0e32402016-04-20 21:50:48 +020097 function GetType: TExceptionType;
98 protected
99 constructor HiddenCreate(const Msg: string);
Jens Geyerd5436f52014-10-03 19:50:38 +0200100 public
Jens Geyere0e32402016-04-20 21:50:48 +0200101 class function Create( AType: TExceptionType): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
102 class function Create( const msg: string): TTransportException; reintroduce; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
103 class function Create( AType: TExceptionType; const msg: string): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
104 property Type_: TExceptionType read GetType;
Jens Geyerd5436f52014-10-03 19:50:38 +0200105 end;
106
Jens Geyere0e32402016-04-20 21:50:48 +0200107 // Needed to remove deprecation warning
108 TTransportExceptionSpecialized = class abstract (TTransportException)
109 public
110 constructor Create(const Msg: string);
111 end;
112
113 TTransportExceptionUnknown = class (TTransportExceptionSpecialized);
114 TTransportExceptionNotOpen = class (TTransportExceptionSpecialized);
115 TTransportExceptionAlreadyOpen = class (TTransportExceptionSpecialized);
116 TTransportExceptionTimedOut = class (TTransportExceptionSpecialized);
117 TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized);
118 TTransportExceptionBadArgs = class (TTransportExceptionSpecialized);
119 TTransportExceptionInterrupted = class (TTransportExceptionSpecialized);
120
Jens Geyerd5436f52014-10-03 19:50:38 +0200121 IHTTPClient = interface( ITransport )
Jens Geyer20e727e2018-06-22 22:39:57 +0200122 ['{BA142D12-8AE6-4B50-9E33-6B7843B21D73}']
123 procedure SetDnsResolveTimeout(const Value: Integer);
124 function GetDnsResolveTimeout: Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200125 procedure SetConnectionTimeout(const Value: Integer);
126 function GetConnectionTimeout: Integer;
Jens Geyer20e727e2018-06-22 22:39:57 +0200127 procedure SetSendTimeout(const Value: Integer);
128 function GetSendTimeout: Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200129 procedure SetReadTimeout(const Value: Integer);
130 function GetReadTimeout: Integer;
131 function GetCustomHeaders: IThriftDictionary<string,string>;
132 procedure SendRequest;
Jens Geyer20e727e2018-06-22 22:39:57 +0200133
134 property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
Jens Geyerd5436f52014-10-03 19:50:38 +0200135 property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
Jens Geyer20e727e2018-06-22 22:39:57 +0200136 property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
Jens Geyerd5436f52014-10-03 19:50:38 +0200137 property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
138 property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
139 end;
140
Jens Geyerd5436f52014-10-03 19:50:38 +0200141 IServerTransport = interface
142 ['{C43B87ED-69EA-47C4-B77C-15E288252900}']
143 procedure Listen;
144 procedure Close;
145 function Accept( const fnAccepting: TProc): ITransport;
146 end;
147
148 TServerTransportImpl = class( TInterfacedObject, IServerTransport)
149 protected
150 procedure Listen; virtual; abstract;
151 procedure Close; virtual; abstract;
152 function Accept( const fnAccepting: TProc): ITransport; virtual; abstract;
153 end;
154
155 ITransportFactory = interface
156 ['{DD809446-000F-49E1-9BFF-E0D0DC76A9D7}']
157 function GetTransport( const ATrans: ITransport): ITransport;
158 end;
159
160 TTransportFactoryImpl = class( TInterfacedObject, ITransportFactory)
161 function GetTransport( const ATrans: ITransport): ITransport; virtual;
162 end;
163
164 TTcpSocketStreamImpl = class( TThriftStreamImpl )
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200165{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200166 private type
167 TWaitForData = ( wfd_HaveData, wfd_Timeout, wfd_Error);
168 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200169 FTcpClient : TCustomIpClient;
Jens Geyerd5436f52014-10-03 19:50:38 +0200170 FTimeout : Integer;
171 function Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
172 TimeOut: Integer; var wsaError : Integer): Integer;
173 function WaitForData( TimeOut : Integer; pBuf : Pointer; DesiredBytes: Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +0200174 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200175{$ELSE}
176 FTcpClient: TSocket;
177 protected const
178 SLEEP_TIME = 200;
179{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200180 protected
Jens Geyer17c3ad92017-09-05 20:31:27 +0200181 procedure Write( const pBuf : Pointer; offset, count: Integer); override;
182 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200183 procedure Open; override;
184 procedure Close; override;
185 procedure Flush; override;
186
187 function IsOpen: Boolean; override;
188 function ToArray: TBytes; override;
189 public
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200190{$IFDEF OLD_SOCKETS}
191 constructor Create( const ATcpClient: TCustomIpClient; const aTimeout : Integer = 0);
192{$ELSE}
193 constructor Create( const ATcpClient: TSocket; const aTimeout : Longword = 0);
194{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200195 end;
196
197 IStreamTransport = interface( ITransport )
198 ['{A8479B47-2A3E-4421-A9A0-D5A9EDCC634A}']
199 function GetInputStream: IThriftStream;
200 function GetOutputStream: IThriftStream;
201 property InputStream : IThriftStream read GetInputStream;
202 property OutputStream : IThriftStream read GetOutputStream;
203 end;
204
205 TStreamTransportImpl = class( TTransportImpl, IStreamTransport)
206 protected
207 FInputStream : IThriftStream;
208 FOutputStream : IThriftStream;
209 protected
210 function GetIsOpen: Boolean; override;
211
212 function GetInputStream: IThriftStream;
213 function GetOutputStream: IThriftStream;
214 public
215 property InputStream : IThriftStream read GetInputStream;
216 property OutputStream : IThriftStream read GetOutputStream;
217
218 procedure Open; override;
219 procedure Close; override;
220 procedure Flush; override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200221 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
222 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200223 constructor Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream);
224 destructor Destroy; override;
225 end;
226
227 TBufferedStreamImpl = class( TThriftStreamImpl)
228 private
229 FStream : IThriftStream;
230 FBufSize : Integer;
231 FReadBuffer : TMemoryStream;
232 FWriteBuffer : TMemoryStream;
233 protected
Jens Geyer17c3ad92017-09-05 20:31:27 +0200234 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
235 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200236 procedure Open; override;
237 procedure Close; override;
238 procedure Flush; override;
239 function IsOpen: Boolean; override;
240 function ToArray: TBytes; override;
241 public
242 constructor Create( const AStream: IThriftStream; ABufSize: Integer);
243 destructor Destroy; override;
244 end;
245
246 TServerSocketImpl = class( TServerTransportImpl)
247 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200248{$IFDEF OLD_SOCKETS}
249 FServer : TTcpServer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200250 FPort : Integer;
251 FClientTimeout : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200252{$ELSE}
253 FServer: TServerSocket;
254{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200255 FUseBufferedSocket : Boolean;
256 FOwnsServer : Boolean;
257 protected
258 function Accept( const fnAccepting: TProc) : ITransport; override;
259 public
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200260{$IFDEF OLD_SOCKETS}
261 constructor Create( const AServer: TTcpServer; AClientTimeout: Integer = 0); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +0200262 constructor Create( APort: Integer; AClientTimeout: Integer = 0; AUseBufferedSockets: Boolean = FALSE); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200263{$ELSE}
264 constructor Create( const AServer: TServerSocket; AClientTimeout: Longword = 0); overload;
265 constructor Create( APort: Integer; AClientTimeout: Longword = 0; AUseBufferedSockets: Boolean = FALSE); overload;
266{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200267 destructor Destroy; override;
268 procedure Listen; override;
269 procedure Close; override;
270 end;
271
272 TBufferedTransportImpl = class( TTransportImpl )
273 private
274 FInputBuffer : IThriftStream;
275 FOutputBuffer : IThriftStream;
276 FTransport : IStreamTransport;
277 FBufSize : Integer;
278
279 procedure InitBuffers;
280 function GetUnderlyingTransport: ITransport;
281 protected
282 function GetIsOpen: Boolean; override;
283 procedure Flush; override;
284 public
285 procedure Open(); override;
286 procedure Close(); override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200287 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
288 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200289 constructor Create( const ATransport : IStreamTransport ); overload;
290 constructor Create( const ATransport : IStreamTransport; ABufSize: Integer); overload;
291 property UnderlyingTransport: ITransport read GetUnderlyingTransport;
292 property IsOpen: Boolean read GetIsOpen;
293 end;
294
295 TSocketImpl = class(TStreamTransportImpl)
296 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200297{$IFDEF OLD_SOCKETS}
298 FClient : TCustomIpClient;
299{$ELSE}
300 FClient: TSocket;
301{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200302 FOwnsClient : Boolean;
303 FHost : string;
304 FPort : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200305{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200306 FTimeout : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200307{$ELSE}
308 FTimeout : Longword;
309{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200310
311 procedure InitSocket;
312 protected
313 function GetIsOpen: Boolean; override;
314 public
315 procedure Open; override;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200316{$IFDEF OLD_SOCKETS}
317 constructor Create( const AClient : TCustomIpClient; aOwnsClient : Boolean; ATimeout: Integer = 0); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +0200318 constructor Create( const AHost: string; APort: Integer; ATimeout: Integer = 0); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200319{$ELSE}
320 constructor Create(const AClient: TSocket; aOwnsClient: Boolean); overload;
321 constructor Create( const AHost: string; APort: Integer; ATimeout: Longword = 0); overload;
322{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200323 destructor Destroy; override;
324 procedure Close; override;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200325{$IFDEF OLD_SOCKETS}
326 property TcpClient: TCustomIpClient read FClient;
327{$ELSE}
328 property TcpClient: TSocket read FClient;
329{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200330 property Host : string read FHost;
331 property Port: Integer read FPort;
332 end;
333
334 TFramedTransportImpl = class( TTransportImpl)
335 private const
336 FHeaderSize : Integer = 4;
337 private class var
338 FHeader_Dummy : array of Byte;
339 protected
340 FTransport : ITransport;
341 FWriteBuffer : TMemoryStream;
342 FReadBuffer : TMemoryStream;
343
344 procedure InitWriteBuffer;
345 procedure ReadFrame;
346 public
347 type
348 TFactory = class( TTransportFactoryImpl )
349 public
350 function GetTransport( const ATrans: ITransport): ITransport; override;
351 end;
352
Jens Geyere0e32402016-04-20 21:50:48 +0200353 {$IFDEF HAVE_CLASS_CTOR}
Jens Geyerd5436f52014-10-03 19:50:38 +0200354 class constructor Create;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200355 {$ENDIF}
Jens Geyere0e32402016-04-20 21:50:48 +0200356
Jens Geyerd5436f52014-10-03 19:50:38 +0200357 constructor Create; overload;
358 constructor Create( const ATrans: ITransport); overload;
359 destructor Destroy; override;
360
361 procedure Open(); override;
362 function GetIsOpen: Boolean; override;
363
364 procedure Close(); override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200365 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
366 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200367 procedure Flush; override;
368 end;
369
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200370{$IFNDEF HAVE_CLASS_CTOR}
Jens Geyerd5436f52014-10-03 19:50:38 +0200371procedure TFramedTransportImpl_Initialize;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200372{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200373
374const
375 DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms
376
377
378implementation
379
380{ TTransportImpl }
381
382procedure TTransportImpl.Flush;
383begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200384 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200385end;
386
387function TTransportImpl.Peek: Boolean;
388begin
389 Result := IsOpen;
390end;
391
Jens Geyer17c3ad92017-09-05 20:31:27 +0200392function TTransportImpl.Read(var buf: TBytes; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200393begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200394 if Length(buf) > 0
395 then result := Read( @buf[0], Length(buf), off, len)
396 else result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200397end;
398
399function TTransportImpl.ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer;
400begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200401 if Length(buf) > 0
402 then result := ReadAll( @buf[0], Length(buf), off, len)
403 else result := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +0200404end;
405
406procedure TTransportImpl.Write( const buf: TBytes);
407begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200408 if Length(buf) > 0
409 then Write( @buf[0], 0, Length(buf));
Jens Geyer17c3ad92017-09-05 20:31:27 +0200410end;
411
412procedure TTransportImpl.Write( const buf: TBytes; off: Integer; len: Integer);
413begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200414 if Length(buf) > 0
415 then Write( @buf[0], off, len);
Jens Geyer17c3ad92017-09-05 20:31:27 +0200416end;
417
418function TTransportImpl.ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
419var ret : Integer;
420begin
421 result := 0;
422 while result < len do begin
423 ret := Read( pBuf, buflen, off + result, len - result);
424 if ret > 0
425 then Inc( result, ret)
426 else raise TTransportExceptionNotOpen.Create( 'Cannot read, Remote side has closed' );
427 end;
428end;
429
430procedure TTransportImpl.Write( const pBuf : Pointer; len : Integer);
431begin
432 Self.Write( pBuf, 0, len);
Jens Geyerd5436f52014-10-03 19:50:38 +0200433end;
434
Jens Geyerd5436f52014-10-03 19:50:38 +0200435{ TTransportException }
436
Jens Geyere0e32402016-04-20 21:50:48 +0200437function TTransportException.GetType: TExceptionType;
438begin
439 if Self is TTransportExceptionNotOpen then Result := TExceptionType.NotOpen
440 else if Self is TTransportExceptionAlreadyOpen then Result := TExceptionType.AlreadyOpen
441 else if Self is TTransportExceptionTimedOut then Result := TExceptionType.TimedOut
442 else if Self is TTransportExceptionEndOfFile then Result := TExceptionType.EndOfFile
443 else if Self is TTransportExceptionBadArgs then Result := TExceptionType.BadArgs
444 else if Self is TTransportExceptionInterrupted then Result := TExceptionType.Interrupted
445 else Result := TExceptionType.Unknown;
446end;
447
448constructor TTransportException.HiddenCreate(const Msg: string);
449begin
450 inherited Create(Msg);
451end;
452
453class function TTransportException.Create(AType: TExceptionType): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200454begin
455 //no inherited;
Jens Geyere0e32402016-04-20 21:50:48 +0200456{$WARN SYMBOL_DEPRECATED OFF}
457 Result := Create(AType, '')
458{$WARN SYMBOL_DEPRECATED DEFAULT}
Jens Geyerd5436f52014-10-03 19:50:38 +0200459end;
460
Jens Geyere0e32402016-04-20 21:50:48 +0200461class function TTransportException.Create(AType: TExceptionType;
462 const msg: string): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200463begin
Jens Geyere0e32402016-04-20 21:50:48 +0200464 case AType of
465 TExceptionType.NotOpen: Result := TTransportExceptionNotOpen.Create(msg);
466 TExceptionType.AlreadyOpen: Result := TTransportExceptionAlreadyOpen.Create(msg);
467 TExceptionType.TimedOut: Result := TTransportExceptionTimedOut.Create(msg);
468 TExceptionType.EndOfFile: Result := TTransportExceptionEndOfFile.Create(msg);
469 TExceptionType.BadArgs: Result := TTransportExceptionBadArgs.Create(msg);
470 TExceptionType.Interrupted: Result := TTransportExceptionInterrupted.Create(msg);
471 else
472 Result := TTransportExceptionUnknown.Create(msg);
473 end;
Jens Geyerd5436f52014-10-03 19:50:38 +0200474end;
475
Jens Geyere0e32402016-04-20 21:50:48 +0200476class function TTransportException.Create(const msg: string): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200477begin
Jens Geyere0e32402016-04-20 21:50:48 +0200478 Result := TTransportExceptionUnknown.Create(Msg);
479end;
480
481{ TTransportExceptionSpecialized }
482
483constructor TTransportExceptionSpecialized.Create(const Msg: string);
484begin
485 inherited HiddenCreate(Msg);
Jens Geyerd5436f52014-10-03 19:50:38 +0200486end;
487
488{ TTransportFactoryImpl }
489
490function TTransportFactoryImpl.GetTransport( const ATrans: ITransport): ITransport;
491begin
492 Result := ATrans;
493end;
494
495{ TServerSocket }
496
Jens Geyer23d67462015-12-19 11:44:57 +0100497{$IFDEF OLD_SOCKETS}
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200498constructor TServerSocketImpl.Create( const AServer: TTcpServer; AClientTimeout: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200499begin
500 inherited Create;
501 FServer := AServer;
502 FClientTimeout := AClientTimeout;
503end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200504{$ELSE}
505constructor TServerSocketImpl.Create( const AServer: TServerSocket; AClientTimeout: Longword);
Jens Geyerd5436f52014-10-03 19:50:38 +0200506begin
507 inherited Create;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200508 FServer := AServer;
509 FServer.RecvTimeout := AClientTimeout;
510 FServer.SendTimeout := AClientTimeout;
511end;
512{$ENDIF}
513
514{$IFDEF OLD_SOCKETS}
515constructor TServerSocketImpl.Create(APort, AClientTimeout: Integer; AUseBufferedSockets: Boolean);
516{$ELSE}
517constructor TServerSocketImpl.Create(APort: Integer; AClientTimeout: Longword; AUseBufferedSockets: Boolean);
518{$ENDIF}
519begin
520 inherited Create;
521{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200522 FPort := APort;
523 FClientTimeout := AClientTimeout;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200524 FServer := TTcpServer.Create( nil );
Jens Geyerd5436f52014-10-03 19:50:38 +0200525 FServer.BlockMode := bmBlocking;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200526 {$IF CompilerVersion >= 21.0}
Jens Geyerd5436f52014-10-03 19:50:38 +0200527 FServer.LocalPort := AnsiString( IntToStr( FPort));
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200528 {$ELSE}
Jens Geyerd5436f52014-10-03 19:50:38 +0200529 FServer.LocalPort := IntToStr( FPort);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200530 {$IFEND}
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200531{$ELSE}
532 FServer := TServerSocket.Create(APort, AClientTimeout, AClientTimeout);
533{$ENDIF}
534 FUseBufferedSocket := AUseBufferedSockets;
535 FOwnsServer := True;
Jens Geyerd5436f52014-10-03 19:50:38 +0200536end;
537
538destructor TServerSocketImpl.Destroy;
539begin
540 if FOwnsServer then begin
541 FServer.Free;
542 FServer := nil;
543 end;
544 inherited;
545end;
546
547function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport;
548var
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200549{$IFDEF OLD_SOCKETS}
550 client : TCustomIpClient;
551{$ELSE}
552 client: TSocket;
553{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200554 trans : IStreamTransport;
555begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100556 if FServer = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200557 raise TTransportExceptionNotOpen.Create('No underlying server socket.');
Jens Geyerd5436f52014-10-03 19:50:38 +0200558 end;
559
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200560{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200561 client := nil;
562 try
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200563 client := TCustomIpClient.Create(nil);
Jens Geyerd5436f52014-10-03 19:50:38 +0200564
565 if Assigned(fnAccepting)
566 then fnAccepting();
567
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100568 if not FServer.Accept( client) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200569 client.Free;
570 Result := nil;
571 Exit;
572 end;
573
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100574 if client = nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200575 Result := nil;
576 Exit;
577 end;
578
579 trans := TSocketImpl.Create( client, TRUE, FClientTimeout);
580 client := nil; // trans owns it now
581
582 if FUseBufferedSocket
583 then result := TBufferedTransportImpl.Create( trans)
584 else result := trans;
585
586 except
587 on E: Exception do begin
588 client.Free;
Jens Geyere0e32402016-04-20 21:50:48 +0200589 raise TTransportExceptionUnknown.Create(E.ToString);
Jens Geyerd5436f52014-10-03 19:50:38 +0200590 end;
591 end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200592{$ELSE}
593 if Assigned(fnAccepting) then
594 fnAccepting();
595
596 client := FServer.Accept;
597 try
598 trans := TSocketImpl.Create(client, True);
599 client := nil;
600
601 if FUseBufferedSocket then
602 Result := TBufferedTransportImpl.Create(trans)
603 else
604 Result := trans;
605 except
606 client.Free;
607 raise;
608 end;
609{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200610end;
611
612procedure TServerSocketImpl.Listen;
613begin
614 if FServer <> nil then
615 begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200616{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200617 try
618 FServer.Active := True;
619 except
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200620 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200621 do raise TTransportExceptionUnknown.Create('Could not accept on listening socket: ' + E.Message);
Jens Geyerd5436f52014-10-03 19:50:38 +0200622 end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200623{$ELSE}
624 FServer.Listen;
625{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200626 end;
627end;
628
629procedure TServerSocketImpl.Close;
630begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200631 if FServer <> nil then
632{$IFDEF OLD_SOCKETS}
633 try
634 FServer.Active := False;
635 except
636 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200637 do raise TTransportExceptionUnknown.Create('Error on closing socket : ' + E.Message);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200638 end;
639{$ELSE}
640 FServer.Close;
641{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200642end;
643
644{ TSocket }
645
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200646{$IFDEF OLD_SOCKETS}
647constructor TSocketImpl.Create( const AClient : TCustomIpClient; aOwnsClient : Boolean; ATimeout: Integer = 0);
Jens Geyerd5436f52014-10-03 19:50:38 +0200648var stream : IThriftStream;
649begin
650 FClient := AClient;
651 FTimeout := ATimeout;
652 FOwnsClient := aOwnsClient;
653 stream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
654 inherited Create( stream, stream);
655end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200656{$ELSE}
657constructor TSocketImpl.Create(const AClient: TSocket; aOwnsClient: Boolean);
658var stream : IThriftStream;
659begin
660 FClient := AClient;
661 FTimeout := AClient.RecvTimeout;
662 FOwnsClient := aOwnsClient;
663 stream := TTcpSocketStreamImpl.Create(FClient, FTimeout);
664 inherited Create(stream, stream);
665end;
666{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200667
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200668{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200669constructor TSocketImpl.Create(const AHost: string; APort, ATimeout: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200670{$ELSE}
671constructor TSocketImpl.Create(const AHost: string; APort: Integer; ATimeout: Longword);
672{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200673begin
674 inherited Create(nil,nil);
675 FHost := AHost;
676 FPort := APort;
677 FTimeout := ATimeout;
678 InitSocket;
679end;
680
681destructor TSocketImpl.Destroy;
682begin
683 if FOwnsClient
684 then FreeAndNil( FClient);
685 inherited;
686end;
687
688procedure TSocketImpl.Close;
689begin
690 inherited Close;
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200691
692 FInputStream := nil;
693 FOutputStream := nil;
694
Jens Geyerd5436f52014-10-03 19:50:38 +0200695 if FOwnsClient
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200696 then FreeAndNil( FClient)
697 else FClient := nil;
Jens Geyerd5436f52014-10-03 19:50:38 +0200698end;
699
700function TSocketImpl.GetIsOpen: Boolean;
701begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200702{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200703 Result := (FClient <> nil) and FClient.Connected;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200704{$ELSE}
705 Result := (FClient <> nil) and FClient.IsOpen
706{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200707end;
708
709procedure TSocketImpl.InitSocket;
710var
711 stream : IThriftStream;
712begin
713 if FOwnsClient
714 then FreeAndNil( FClient)
715 else FClient := nil;
716
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200717{$IFDEF OLD_SOCKETS}
718 FClient := TTcpClient.Create( nil);
719{$ELSE}
720 FClient := TSocket.Create(FHost, FPort);
721{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200722 FOwnsClient := True;
723
724 stream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
725 FInputStream := stream;
726 FOutputStream := stream;
727end;
728
729procedure TSocketImpl.Open;
730begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100731 if IsOpen then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200732 raise TTransportExceptionAlreadyOpen.Create('Socket already connected');
Jens Geyerd5436f52014-10-03 19:50:38 +0200733 end;
734
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100735 if FHost = '' then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200736 raise TTransportExceptionNotOpen.Create('Cannot open null host');
Jens Geyerd5436f52014-10-03 19:50:38 +0200737 end;
738
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100739 if Port <= 0 then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200740 raise TTransportExceptionNotOpen.Create('Cannot open without port');
Jens Geyerd5436f52014-10-03 19:50:38 +0200741 end;
742
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100743 if FClient = nil
744 then InitSocket;
Jens Geyerd5436f52014-10-03 19:50:38 +0200745
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200746{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200747 FClient.RemoteHost := TSocketHost( Host);
748 FClient.RemotePort := TSocketPort( IntToStr( Port));
749 FClient.Connect;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200750{$ELSE}
751 FClient.Open;
752{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200753
754 FInputStream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
755 FOutputStream := FInputStream;
756end;
757
758{ TBufferedStream }
759
760procedure TBufferedStreamImpl.Close;
761begin
762 Flush;
763 FStream := nil;
764
765 FReadBuffer.Free;
766 FReadBuffer := nil;
767
768 FWriteBuffer.Free;
769 FWriteBuffer := nil;
770end;
771
772constructor TBufferedStreamImpl.Create( const AStream: IThriftStream; ABufSize: Integer);
773begin
774 inherited Create;
775 FStream := AStream;
776 FBufSize := ABufSize;
777 FReadBuffer := TMemoryStream.Create;
778 FWriteBuffer := TMemoryStream.Create;
779end;
780
781destructor TBufferedStreamImpl.Destroy;
782begin
783 Close;
784 inherited;
785end;
786
787procedure TBufferedStreamImpl.Flush;
788var
789 buf : TBytes;
790 len : Integer;
791begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200792 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200793 len := FWriteBuffer.Size;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200794 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200795 SetLength( buf, len );
796 FWriteBuffer.Position := 0;
797 FWriteBuffer.Read( Pointer(@buf[0])^, len );
798 FStream.Write( buf, 0, len );
799 end;
800 FWriteBuffer.Clear;
801 end;
802end;
803
804function TBufferedStreamImpl.IsOpen: Boolean;
805begin
806 Result := (FWriteBuffer <> nil)
807 and (FReadBuffer <> nil)
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200808 and (FStream <> nil)
809 and FStream.IsOpen;
Jens Geyerd5436f52014-10-03 19:50:38 +0200810end;
811
812procedure TBufferedStreamImpl.Open;
813begin
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200814 FStream.Open;
Jens Geyerd5436f52014-10-03 19:50:38 +0200815end;
816
Jens Geyer17c3ad92017-09-05 20:31:27 +0200817function TBufferedStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200818var
819 nRead : Integer;
820 tempbuf : TBytes;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100821 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200822begin
823 inherited;
824 Result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100825
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200826 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200827 while count > 0 do begin
828
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200829 if FReadBuffer.Position >= FReadBuffer.Size then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200830 FReadBuffer.Clear;
831 SetLength( tempbuf, FBufSize);
832 nRead := FStream.Read( tempbuf, 0, FBufSize );
833 if nRead = 0 then Break; // avoid infinite loop
834
835 FReadBuffer.WriteBuffer( Pointer(@tempbuf[0])^, nRead );
836 FReadBuffer.Position := 0;
837 end;
838
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200839 if FReadBuffer.Position < FReadBuffer.Size then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100840 nRead := Min( FReadBuffer.Size - FReadBuffer.Position, count);
841 pTmp := pBuf;
842 Inc( pTmp, offset);
843 Inc( Result, FReadBuffer.Read( pTmp^, nRead));
Jens Geyerd5436f52014-10-03 19:50:38 +0200844 Dec( count, nRead);
845 Inc( offset, nRead);
846 end;
847 end;
848 end;
849end;
850
851function TBufferedStreamImpl.ToArray: TBytes;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200852var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200853begin
854 len := 0;
855
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200856 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200857 len := FReadBuffer.Size;
858 end;
859
860 SetLength( Result, len);
861
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200862 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200863 FReadBuffer.Position := 0;
864 FReadBuffer.Read( Pointer(@Result[0])^, len );
865 end;
866end;
867
Jens Geyer17c3ad92017-09-05 20:31:27 +0200868procedure TBufferedStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +0100869var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200870begin
871 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200872 if count > 0 then begin
873 if IsOpen then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100874 pTmp := pBuf;
875 Inc( pTmp, offset);
876 FWriteBuffer.Write( pTmp^, count );
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200877 if FWriteBuffer.Size > FBufSize then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200878 Flush;
879 end;
880 end;
881 end;
882end;
883
884{ TStreamTransportImpl }
885
Jens Geyerd5436f52014-10-03 19:50:38 +0200886constructor TStreamTransportImpl.Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream);
887begin
888 inherited Create;
889 FInputStream := AInputStream;
890 FOutputStream := AOutputStream;
891end;
892
893destructor TStreamTransportImpl.Destroy;
894begin
895 FInputStream := nil;
896 FOutputStream := nil;
897 inherited;
898end;
899
Jens Geyer20e727e2018-06-22 22:39:57 +0200900procedure TStreamTransportImpl.Close;
901begin
902 FInputStream := nil;
903 FOutputStream := nil;
904end;
905
Jens Geyerd5436f52014-10-03 19:50:38 +0200906procedure TStreamTransportImpl.Flush;
907begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100908 if FOutputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200909 raise TTransportExceptionNotOpen.Create('Cannot flush null outputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +0200910 end;
911
912 FOutputStream.Flush;
913end;
914
915function TStreamTransportImpl.GetInputStream: IThriftStream;
916begin
917 Result := FInputStream;
918end;
919
920function TStreamTransportImpl.GetIsOpen: Boolean;
921begin
922 Result := True;
923end;
924
925function TStreamTransportImpl.GetOutputStream: IThriftStream;
926begin
Jens Geyer02fbe0e2018-03-19 17:35:44 +0100927 Result := FOutputStream;
Jens Geyerd5436f52014-10-03 19:50:38 +0200928end;
929
930procedure TStreamTransportImpl.Open;
931begin
932
933end;
934
Jens Geyer17c3ad92017-09-05 20:31:27 +0200935function TStreamTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200936begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100937 if FInputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200938 raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +0200939 end;
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100940
Jens Geyer17c3ad92017-09-05 20:31:27 +0200941 Result := FInputStream.Read( pBuf,buflen, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +0200942end;
943
Jens Geyer17c3ad92017-09-05 20:31:27 +0200944procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200945begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100946 if FOutputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200947 raise TTransportExceptionNotOpen.Create('Cannot write to null outputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +0200948 end;
949
Jens Geyer17c3ad92017-09-05 20:31:27 +0200950 FOutputStream.Write( pBuf, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +0200951end;
952
953{ TBufferedTransportImpl }
954
955constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport);
956begin
957 //no inherited;
958 Create( ATransport, 1024 );
959end;
960
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200961constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport; ABufSize: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200962begin
963 inherited Create;
964 FTransport := ATransport;
965 FBufSize := ABufSize;
966 InitBuffers;
967end;
968
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200969procedure TBufferedTransportImpl.Close;
970begin
971 FTransport.Close;
972 FInputBuffer := nil;
973 FOutputBuffer := nil;
974end;
975
Jens Geyerd5436f52014-10-03 19:50:38 +0200976procedure TBufferedTransportImpl.Flush;
977begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200978 if FOutputBuffer <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200979 FOutputBuffer.Flush;
980 end;
981end;
982
983function TBufferedTransportImpl.GetIsOpen: Boolean;
984begin
985 Result := FTransport.IsOpen;
986end;
987
988function TBufferedTransportImpl.GetUnderlyingTransport: ITransport;
989begin
990 Result := FTransport;
991end;
992
993procedure TBufferedTransportImpl.InitBuffers;
994begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200995 if FTransport.InputStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200996 FInputBuffer := TBufferedStreamImpl.Create( FTransport.InputStream, FBufSize );
997 end;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200998 if FTransport.OutputStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200999 FOutputBuffer := TBufferedStreamImpl.Create( FTransport.OutputStream, FBufSize );
1000 end;
1001end;
1002
1003procedure TBufferedTransportImpl.Open;
1004begin
Jens Geyera0cf38e2018-04-04 17:31:52 +02001005 FTransport.Open;
Jens Geyer3c0edfa2018-04-02 13:57:55 +02001006 InitBuffers; // we need to get the buffers to match FTransport substreams again
Jens Geyerd5436f52014-10-03 19:50:38 +02001007end;
1008
Jens Geyer17c3ad92017-09-05 20:31:27 +02001009function TBufferedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001010begin
1011 Result := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001012 if FInputBuffer <> nil then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001013 Result := FInputBuffer.Read( pBuf,buflen, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +02001014 end;
1015end;
1016
Jens Geyer17c3ad92017-09-05 20:31:27 +02001017procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001018begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001019 if FOutputBuffer <> nil then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001020 FOutputBuffer.Write( pBuf, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +02001021 end;
1022end;
1023
1024{ TFramedTransportImpl }
1025
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001026{$IFDEF HAVE_CLASS_CTOR}
1027class constructor TFramedTransportImpl.Create;
1028begin
1029 SetLength( FHeader_Dummy, FHeaderSize);
1030 FillChar( FHeader_Dummy[0], Length( FHeader_Dummy) * SizeOf( Byte ), 0);
1031end;
1032{$ELSE}
Jens Geyerd5436f52014-10-03 19:50:38 +02001033procedure TFramedTransportImpl_Initialize;
1034begin
1035 SetLength( TFramedTransportImpl.FHeader_Dummy, TFramedTransportImpl.FHeaderSize);
1036 FillChar( TFramedTransportImpl.FHeader_Dummy[0],
1037 Length( TFramedTransportImpl.FHeader_Dummy) * SizeOf( Byte ), 0);
1038end;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001039{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001040
1041constructor TFramedTransportImpl.Create;
1042begin
1043 inherited Create;
1044 InitWriteBuffer;
1045end;
1046
1047procedure TFramedTransportImpl.Close;
1048begin
1049 FTransport.Close;
1050end;
1051
1052constructor TFramedTransportImpl.Create( const ATrans: ITransport);
1053begin
1054 inherited Create;
1055 InitWriteBuffer;
1056 FTransport := ATrans;
1057end;
1058
1059destructor TFramedTransportImpl.Destroy;
1060begin
1061 FWriteBuffer.Free;
1062 FReadBuffer.Free;
1063 inherited;
1064end;
1065
1066procedure TFramedTransportImpl.Flush;
1067var
1068 buf : TBytes;
1069 len : Integer;
1070 data_len : Integer;
1071
1072begin
1073 len := FWriteBuffer.Size;
1074 SetLength( buf, len);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001075 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001076 System.Move( FWriteBuffer.Memory^, buf[0], len );
1077 end;
1078
1079 data_len := len - FHeaderSize;
Jens Geyer30ed90e2016-03-10 20:12:49 +01001080 if (data_len < 0) then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001081 raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: data_len < 0' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001082 end;
1083
1084 InitWriteBuffer;
1085
1086 buf[0] := Byte($FF and (data_len shr 24));
1087 buf[1] := Byte($FF and (data_len shr 16));
1088 buf[2] := Byte($FF and (data_len shr 8));
1089 buf[3] := Byte($FF and data_len);
1090
1091 FTransport.Write( buf, 0, len );
1092 FTransport.Flush;
1093end;
1094
1095function TFramedTransportImpl.GetIsOpen: Boolean;
1096begin
1097 Result := FTransport.IsOpen;
1098end;
1099
1100type
1101 TAccessMemoryStream = class(TMemoryStream)
1102 end;
1103
1104procedure TFramedTransportImpl.InitWriteBuffer;
1105begin
1106 FWriteBuffer.Free;
1107 FWriteBuffer := TMemoryStream.Create;
1108 TAccessMemoryStream(FWriteBuffer).Capacity := 1024;
1109 FWriteBuffer.Write( Pointer(@FHeader_Dummy[0])^, FHeaderSize);
1110end;
1111
1112procedure TFramedTransportImpl.Open;
1113begin
1114 FTransport.Open;
1115end;
1116
Jens Geyer17c3ad92017-09-05 20:31:27 +02001117function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001118var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001119begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001120 if len > (buflen-off)
1121 then len := buflen-off;
1122
Jens Geyer5089b0a2018-02-01 22:37:18 +01001123 pTmp := pBuf;
1124 Inc( pTmp, off);
1125
Jens Geyer17c3ad92017-09-05 20:31:27 +02001126 if (FReadBuffer <> nil) and (len > 0) then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001127 result := FReadBuffer.Read( pTmp^, len);
Jens Geyer17c3ad92017-09-05 20:31:27 +02001128 if result > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001129 Exit;
1130 end;
1131 end;
1132
1133 ReadFrame;
1134 if len > 0
Jens Geyer5089b0a2018-02-01 22:37:18 +01001135 then Result := FReadBuffer.Read( pTmp^, len)
Jens Geyerd5436f52014-10-03 19:50:38 +02001136 else Result := 0;
1137end;
1138
1139procedure TFramedTransportImpl.ReadFrame;
1140var
1141 i32rd : TBytes;
1142 size : Integer;
1143 buff : TBytes;
1144begin
1145 SetLength( i32rd, FHeaderSize );
1146 FTransport.ReadAll( i32rd, 0, FHeaderSize);
1147 size :=
1148 ((i32rd[0] and $FF) shl 24) or
1149 ((i32rd[1] and $FF) shl 16) or
1150 ((i32rd[2] and $FF) shl 8) or
1151 (i32rd[3] and $FF);
1152 SetLength( buff, size );
1153 FTransport.ReadAll( buff, 0, size );
1154 FReadBuffer.Free;
1155 FReadBuffer := TMemoryStream.Create;
Jens Geyera76e6c72017-09-08 21:03:30 +02001156 if Length(buff) > 0
1157 then FReadBuffer.Write( Pointer(@buff[0])^, size );
Jens Geyerd5436f52014-10-03 19:50:38 +02001158 FReadBuffer.Position := 0;
1159end;
1160
Jens Geyer17c3ad92017-09-05 20:31:27 +02001161procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001162var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001163begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001164 if len > 0 then begin
1165 pTmp := pBuf;
1166 Inc( pTmp, off);
1167
1168 FWriteBuffer.Write( pTmp^, len );
1169 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001170end;
1171
1172{ TFramedTransport.TFactory }
1173
1174function TFramedTransportImpl.TFactory.GetTransport( const ATrans: ITransport): ITransport;
1175begin
1176 Result := TFramedTransportImpl.Create( ATrans );
1177end;
1178
1179{ TTcpSocketStreamImpl }
1180
1181procedure TTcpSocketStreamImpl.Close;
1182begin
1183 FTcpClient.Close;
1184end;
1185
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001186{$IFDEF OLD_SOCKETS}
1187constructor TTcpSocketStreamImpl.Create( const ATcpClient: TCustomIpClient; const aTimeout : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001188begin
1189 inherited Create;
1190 FTcpClient := ATcpClient;
1191 FTimeout := aTimeout;
1192end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001193{$ELSE}
1194constructor TTcpSocketStreamImpl.Create( const ATcpClient: TSocket; const aTimeout : Longword);
1195begin
1196 inherited Create;
1197 FTcpClient := ATcpClient;
1198 if aTimeout = 0 then
1199 FTcpClient.RecvTimeout := SLEEP_TIME
1200 else
1201 FTcpClient.RecvTimeout := aTimeout;
1202 FTcpClient.SendTimeout := aTimeout;
1203end;
1204{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001205
1206procedure TTcpSocketStreamImpl.Flush;
1207begin
1208
1209end;
1210
1211function TTcpSocketStreamImpl.IsOpen: Boolean;
1212begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001213{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001214 Result := FTcpClient.Active;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001215{$ELSE}
1216 Result := FTcpClient.IsOpen;
1217{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001218end;
1219
1220procedure TTcpSocketStreamImpl.Open;
1221begin
1222 FTcpClient.Open;
1223end;
1224
1225
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001226{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001227function TTcpSocketStreamImpl.Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
1228 TimeOut: Integer; var wsaError : Integer): Integer;
1229var
1230 ReadFds: TFDset;
1231 ReadFdsptr: PFDset;
1232 WriteFds: TFDset;
1233 WriteFdsptr: PFDset;
1234 ExceptFds: TFDset;
1235 ExceptFdsptr: PFDset;
1236 tv: timeval;
1237 Timeptr: PTimeval;
1238 socket : TSocket;
1239begin
1240 if not FTcpClient.Active then begin
1241 wsaError := WSAEINVAL;
1242 Exit( SOCKET_ERROR);
1243 end;
1244
1245 socket := FTcpClient.Handle;
1246
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001247 if Assigned(ReadReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001248 ReadFdsptr := @ReadFds;
1249 FD_ZERO(ReadFds);
1250 FD_SET(socket, ReadFds);
1251 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001252 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001253 ReadFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001254 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001255
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001256 if Assigned(WriteReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001257 WriteFdsptr := @WriteFds;
1258 FD_ZERO(WriteFds);
1259 FD_SET(socket, WriteFds);
1260 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001261 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001262 WriteFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001263 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001264
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001265 if Assigned(ExceptFlag) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001266 ExceptFdsptr := @ExceptFds;
1267 FD_ZERO(ExceptFds);
1268 FD_SET(socket, ExceptFds);
1269 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001270 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001271 ExceptFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001272 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001273
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001274 if TimeOut >= 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001275 tv.tv_sec := TimeOut div 1000;
1276 tv.tv_usec := 1000 * (TimeOut mod 1000);
1277 Timeptr := @tv;
1278 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001279 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001280 Timeptr := nil; // wait forever
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001281 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001282
1283 wsaError := 0;
1284 try
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001285 {$IFDEF MSWINDOWS}
1286 {$IFDEF OLD_UNIT_NAMES}
1287 result := WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1288 {$ELSE}
1289 result := Winapi.WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1290 {$ENDIF}
1291 {$ENDIF}
1292 {$IFDEF LINUX}
1293 result := Libc.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1294 {$ENDIF}
1295
Jens Geyerd5436f52014-10-03 19:50:38 +02001296 if result = SOCKET_ERROR
1297 then wsaError := WSAGetLastError;
1298
1299 except
1300 result := SOCKET_ERROR;
1301 end;
1302
1303 if Assigned(ReadReady) then
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001304 ReadReady^ := FD_ISSET(socket, ReadFds);
1305
Jens Geyerd5436f52014-10-03 19:50:38 +02001306 if Assigned(WriteReady) then
1307 WriteReady^ := FD_ISSET(socket, WriteFds);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001308
Jens Geyerd5436f52014-10-03 19:50:38 +02001309 if Assigned(ExceptFlag) then
1310 ExceptFlag^ := FD_ISSET(socket, ExceptFds);
1311end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001312{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001313
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001314{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001315function TTcpSocketStreamImpl.WaitForData( TimeOut : Integer; pBuf : Pointer;
1316 DesiredBytes : Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001317 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001318var bCanRead, bError : Boolean;
1319 retval : Integer;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001320const
1321 MSG_PEEK = {$IFDEF OLD_UNIT_NAMES} WinSock.MSG_PEEK {$ELSE} Winapi.WinSock.MSG_PEEK {$ENDIF};
Jens Geyerd5436f52014-10-03 19:50:38 +02001322begin
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001323 bytesReady := 0;
1324
Jens Geyerd5436f52014-10-03 19:50:38 +02001325 // The select function returns the total number of socket handles that are ready
1326 // and contained in the fd_set structures, zero if the time limit expired,
1327 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1328 // WSAGetLastError can be used to retrieve a specific error code.
1329 retval := Self.Select( @bCanRead, nil, @bError, TimeOut, wsaError);
1330 if retval = SOCKET_ERROR
1331 then Exit( TWaitForData.wfd_Error);
1332 if (retval = 0) or not bCanRead
1333 then Exit( TWaitForData.wfd_Timeout);
1334
1335 // recv() returns the number of bytes received, or -1 if an error occurred.
1336 // The return value will be 0 when the peer has performed an orderly shutdown.
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001337
1338 retval := recv( FTcpClient.Handle, pBuf^, DesiredBytes, MSG_PEEK);
Jens Geyerd5436f52014-10-03 19:50:38 +02001339 if retval <= 0
1340 then Exit( TWaitForData.wfd_Error);
1341
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001342 // at least we have some data
1343 bytesReady := Min( retval, DesiredBytes);
1344 result := TWaitForData.wfd_HaveData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001345end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001346{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001347
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001348{$IFDEF OLD_SOCKETS}
Jens Geyer17c3ad92017-09-05 20:31:27 +02001349function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001350// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001351var wfd : TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001352 wsaError,
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001353 msecs : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001354 nBytes : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001355 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001356begin
1357 inherited;
1358
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001359 if FTimeout > 0
1360 then msecs := FTimeout
1361 else msecs := DEFAULT_THRIFT_TIMEOUT;
1362
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001363 result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001364 pTmp := pBuf;
1365 Inc( pTmp, offset);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001366 while count > 0 do begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001367
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001368 while TRUE do begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001369 wfd := WaitForData( msecs, pTmp, count, wsaError, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001370 case wfd of
Jens Geyer65b17462016-03-09 00:07:46 +01001371 TWaitForData.wfd_Error : Exit;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001372 TWaitForData.wfd_HaveData : Break;
1373 TWaitForData.wfd_Timeout : begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001374 if (FTimeout = 0)
1375 then Exit
1376 else begin
Jens Geyere0e32402016-04-20 21:50:48 +02001377 raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001378
1379 end;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001380 end;
1381 else
1382 ASSERT( FALSE);
Jens Geyerd5436f52014-10-03 19:50:38 +02001383 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001384 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001385
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001386 // reduce the timeout once we got data
1387 if FTimeout > 0
1388 then msecs := FTimeout div 10
1389 else msecs := DEFAULT_THRIFT_TIMEOUT div 10;
1390 msecs := Max( msecs, 200);
1391
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001392 ASSERT( nBytes <= count);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001393 nBytes := FTcpClient.ReceiveBuf( pTmp^, nBytes);
1394 Inc( pTmp, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001395 Dec( count, nBytes);
1396 Inc( result, nBytes);
1397 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001398end;
1399
1400function TTcpSocketStreamImpl.ToArray: TBytes;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001401// old sockets version
1402var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001403begin
1404 len := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001405 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001406 len := FTcpClient.BytesReceived;
1407 end;
1408
1409 SetLength( Result, len );
1410
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001411 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001412 FTcpClient.ReceiveBuf( Pointer(@Result[0])^, len);
1413 end;
1414end;
1415
Jens Geyer17c3ad92017-09-05 20:31:27 +02001416procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001417// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001418var bCanWrite, bError : Boolean;
1419 retval, wsaError : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001420 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001421begin
1422 inherited;
1423
1424 if not FTcpClient.Active
Jens Geyere0e32402016-04-20 21:50:48 +02001425 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerd5436f52014-10-03 19:50:38 +02001426
1427 // The select function returns the total number of socket handles that are ready
1428 // and contained in the fd_set structures, zero if the time limit expired,
1429 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1430 // WSAGetLastError can be used to retrieve a specific error code.
1431 retval := Self.Select( nil, @bCanWrite, @bError, FTimeOut, wsaError);
1432 if retval = SOCKET_ERROR
Jens Geyere0e32402016-04-20 21:50:48 +02001433 then raise TTransportExceptionUnknown.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001434
Jens Geyerd5436f52014-10-03 19:50:38 +02001435 if (retval = 0)
Jens Geyere0e32402016-04-20 21:50:48 +02001436 then raise TTransportExceptionTimedOut.Create('timed out');
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001437
Jens Geyerd5436f52014-10-03 19:50:38 +02001438 if bError or not bCanWrite
Jens Geyere0e32402016-04-20 21:50:48 +02001439 then raise TTransportExceptionUnknown.Create('unknown error');
Jens Geyerd5436f52014-10-03 19:50:38 +02001440
Jens Geyer5089b0a2018-02-01 22:37:18 +01001441 pTmp := pBuf;
1442 Inc( pTmp, offset);
1443 FTcpClient.SendBuf( pTmp^, count);
Jens Geyerd5436f52014-10-03 19:50:38 +02001444end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001445
1446{$ELSE}
1447
Jens Geyer17c3ad92017-09-05 20:31:27 +02001448function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001449// new sockets version
1450var nBytes : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001451 pTmp : PByte;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001452begin
1453 inherited;
1454
1455 result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001456 pTmp := pBuf;
1457 Inc( pTmp, offset);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001458 while count > 0 do begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001459 nBytes := FTcpClient.Read( pTmp^, count);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001460 if nBytes = 0 then Exit;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001461 Inc( pTmp, nBytes);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001462 Dec( count, nBytes);
1463 Inc( result, nBytes);
1464 end;
1465end;
1466
1467function TTcpSocketStreamImpl.ToArray: TBytes;
1468// new sockets version
1469var len : Integer;
1470begin
1471 len := 0;
1472 try
1473 if FTcpClient.Peek then
1474 repeat
1475 SetLength(Result, Length(Result) + 1024);
1476 len := FTcpClient.Read(Result[Length(Result) - 1024], 1024);
1477 until len < 1024;
1478 except
1479 on TTransportException do begin { don't allow default exceptions } end;
1480 else raise;
1481 end;
1482 if len > 0 then
1483 SetLength(Result, Length(Result) - 1024 + len);
1484end;
1485
Jens Geyer17c3ad92017-09-05 20:31:27 +02001486procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001487// new sockets version
Jens Geyer5089b0a2018-02-01 22:37:18 +01001488var pTmp : PByte;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001489begin
1490 inherited;
1491
1492 if not FTcpClient.IsOpen
Kyle Johnsone363a342016-04-22 19:11:16 -05001493 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001494
Jens Geyer5089b0a2018-02-01 22:37:18 +01001495 pTmp := pBuf;
1496 Inc( pTmp, offset);
1497 FTcpClient.Write( pTmp^, count);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001498end;
1499
Jens Geyer23d67462015-12-19 11:44:57 +01001500{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001501
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001502
Jens Geyerd5436f52014-10-03 19:50:38 +02001503{$IF CompilerVersion < 21.0}
1504initialization
1505begin
1506 TFramedTransportImpl_Initialize;
1507end;
1508{$IFEND}
1509
1510
1511end.