blob: c2071df89da914a643634e17902394341c71041e [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 Geyer47f63172019-06-06 22:42:58 +0200121 TSecureProtocol = (
122 SSL_2, SSL_3, TLS_1, // outdated, for compatibilty only
123 TLS_1_1, TLS_1_2 // secure (as of today)
124 );
125
126 TSecureProtocols = set of TSecureProtocol;
127
Jens Geyerd5436f52014-10-03 19:50:38 +0200128 IHTTPClient = interface( ITransport )
Jens Geyer47f63172019-06-06 22:42:58 +0200129 ['{7BF615DD-8680-4004-A5B2-88947BA3BA3D}']
Jens Geyer20e727e2018-06-22 22:39:57 +0200130 procedure SetDnsResolveTimeout(const Value: Integer);
131 function GetDnsResolveTimeout: Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200132 procedure SetConnectionTimeout(const Value: Integer);
133 function GetConnectionTimeout: Integer;
Jens Geyer20e727e2018-06-22 22:39:57 +0200134 procedure SetSendTimeout(const Value: Integer);
135 function GetSendTimeout: Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200136 procedure SetReadTimeout(const Value: Integer);
137 function GetReadTimeout: Integer;
138 function GetCustomHeaders: IThriftDictionary<string,string>;
139 procedure SendRequest;
Jens Geyer47f63172019-06-06 22:42:58 +0200140 function GetSecureProtocols : TSecureProtocols;
141 procedure SetSecureProtocols( const value : TSecureProtocols);
Jens Geyer20e727e2018-06-22 22:39:57 +0200142
143 property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
Jens Geyerd5436f52014-10-03 19:50:38 +0200144 property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
Jens Geyer20e727e2018-06-22 22:39:57 +0200145 property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
Jens Geyerd5436f52014-10-03 19:50:38 +0200146 property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
147 property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
Jens Geyer47f63172019-06-06 22:42:58 +0200148 property SecureProtocols : TSecureProtocols read GetSecureProtocols write SetSecureProtocols;
Jens Geyerd5436f52014-10-03 19:50:38 +0200149 end;
150
Jens Geyerd5436f52014-10-03 19:50:38 +0200151 IServerTransport = interface
152 ['{C43B87ED-69EA-47C4-B77C-15E288252900}']
153 procedure Listen;
154 procedure Close;
155 function Accept( const fnAccepting: TProc): ITransport;
156 end;
157
158 TServerTransportImpl = class( TInterfacedObject, IServerTransport)
159 protected
160 procedure Listen; virtual; abstract;
161 procedure Close; virtual; abstract;
162 function Accept( const fnAccepting: TProc): ITransport; virtual; abstract;
163 end;
164
165 ITransportFactory = interface
166 ['{DD809446-000F-49E1-9BFF-E0D0DC76A9D7}']
167 function GetTransport( const ATrans: ITransport): ITransport;
168 end;
169
170 TTransportFactoryImpl = class( TInterfacedObject, ITransportFactory)
171 function GetTransport( const ATrans: ITransport): ITransport; virtual;
172 end;
173
174 TTcpSocketStreamImpl = class( TThriftStreamImpl )
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200175{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200176 private type
177 TWaitForData = ( wfd_HaveData, wfd_Timeout, wfd_Error);
178 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200179 FTcpClient : TCustomIpClient;
Jens Geyerd5436f52014-10-03 19:50:38 +0200180 FTimeout : Integer;
181 function Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
182 TimeOut: Integer; var wsaError : Integer): Integer;
183 function WaitForData( TimeOut : Integer; pBuf : Pointer; DesiredBytes: Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +0200184 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200185{$ELSE}
186 FTcpClient: TSocket;
187 protected const
188 SLEEP_TIME = 200;
189{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200190 protected
Jens Geyer17c3ad92017-09-05 20:31:27 +0200191 procedure Write( const pBuf : Pointer; offset, count: Integer); override;
192 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200193 procedure Open; override;
194 procedure Close; override;
195 procedure Flush; override;
196
197 function IsOpen: Boolean; override;
198 function ToArray: TBytes; override;
199 public
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200200{$IFDEF OLD_SOCKETS}
201 constructor Create( const ATcpClient: TCustomIpClient; const aTimeout : Integer = 0);
202{$ELSE}
203 constructor Create( const ATcpClient: TSocket; const aTimeout : Longword = 0);
204{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200205 end;
206
207 IStreamTransport = interface( ITransport )
208 ['{A8479B47-2A3E-4421-A9A0-D5A9EDCC634A}']
209 function GetInputStream: IThriftStream;
210 function GetOutputStream: IThriftStream;
211 property InputStream : IThriftStream read GetInputStream;
212 property OutputStream : IThriftStream read GetOutputStream;
213 end;
214
215 TStreamTransportImpl = class( TTransportImpl, IStreamTransport)
216 protected
217 FInputStream : IThriftStream;
218 FOutputStream : IThriftStream;
219 protected
220 function GetIsOpen: Boolean; override;
221
222 function GetInputStream: IThriftStream;
223 function GetOutputStream: IThriftStream;
224 public
225 property InputStream : IThriftStream read GetInputStream;
226 property OutputStream : IThriftStream read GetOutputStream;
227
228 procedure Open; override;
229 procedure Close; override;
230 procedure Flush; override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200231 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
232 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200233 constructor Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream);
234 destructor Destroy; override;
235 end;
236
237 TBufferedStreamImpl = class( TThriftStreamImpl)
238 private
239 FStream : IThriftStream;
240 FBufSize : Integer;
241 FReadBuffer : TMemoryStream;
242 FWriteBuffer : TMemoryStream;
243 protected
Jens Geyer17c3ad92017-09-05 20:31:27 +0200244 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
245 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200246 procedure Open; override;
247 procedure Close; override;
248 procedure Flush; override;
249 function IsOpen: Boolean; override;
250 function ToArray: TBytes; override;
251 public
252 constructor Create( const AStream: IThriftStream; ABufSize: Integer);
253 destructor Destroy; override;
254 end;
255
256 TServerSocketImpl = class( TServerTransportImpl)
257 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200258{$IFDEF OLD_SOCKETS}
259 FServer : TTcpServer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200260 FPort : Integer;
261 FClientTimeout : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200262{$ELSE}
263 FServer: TServerSocket;
264{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200265 FUseBufferedSocket : Boolean;
266 FOwnsServer : Boolean;
267 protected
268 function Accept( const fnAccepting: TProc) : ITransport; override;
269 public
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200270{$IFDEF OLD_SOCKETS}
271 constructor Create( const AServer: TTcpServer; AClientTimeout: Integer = 0); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +0200272 constructor Create( APort: Integer; AClientTimeout: Integer = 0; AUseBufferedSockets: Boolean = FALSE); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200273{$ELSE}
274 constructor Create( const AServer: TServerSocket; AClientTimeout: Longword = 0); overload;
275 constructor Create( APort: Integer; AClientTimeout: Longword = 0; AUseBufferedSockets: Boolean = FALSE); overload;
276{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200277 destructor Destroy; override;
278 procedure Listen; override;
279 procedure Close; override;
280 end;
281
282 TBufferedTransportImpl = class( TTransportImpl )
283 private
284 FInputBuffer : IThriftStream;
285 FOutputBuffer : IThriftStream;
286 FTransport : IStreamTransport;
287 FBufSize : Integer;
288
289 procedure InitBuffers;
290 function GetUnderlyingTransport: ITransport;
291 protected
292 function GetIsOpen: Boolean; override;
293 procedure Flush; override;
294 public
295 procedure Open(); override;
296 procedure Close(); override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200297 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
298 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200299 constructor Create( const ATransport : IStreamTransport ); overload;
300 constructor Create( const ATransport : IStreamTransport; ABufSize: Integer); overload;
301 property UnderlyingTransport: ITransport read GetUnderlyingTransport;
302 property IsOpen: Boolean read GetIsOpen;
303 end;
304
305 TSocketImpl = class(TStreamTransportImpl)
306 private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200307{$IFDEF OLD_SOCKETS}
308 FClient : TCustomIpClient;
309{$ELSE}
310 FClient: TSocket;
311{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200312 FOwnsClient : Boolean;
313 FHost : string;
314 FPort : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200315{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200316 FTimeout : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200317{$ELSE}
318 FTimeout : Longword;
319{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200320
321 procedure InitSocket;
322 protected
323 function GetIsOpen: Boolean; override;
324 public
325 procedure Open; override;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200326{$IFDEF OLD_SOCKETS}
327 constructor Create( const AClient : TCustomIpClient; aOwnsClient : Boolean; ATimeout: Integer = 0); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +0200328 constructor Create( const AHost: string; APort: Integer; ATimeout: Integer = 0); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200329{$ELSE}
330 constructor Create(const AClient: TSocket; aOwnsClient: Boolean); overload;
331 constructor Create( const AHost: string; APort: Integer; ATimeout: Longword = 0); overload;
332{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200333 destructor Destroy; override;
334 procedure Close; override;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200335{$IFDEF OLD_SOCKETS}
336 property TcpClient: TCustomIpClient read FClient;
337{$ELSE}
338 property TcpClient: TSocket read FClient;
339{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200340 property Host : string read FHost;
341 property Port: Integer read FPort;
342 end;
343
344 TFramedTransportImpl = class( TTransportImpl)
345 private const
346 FHeaderSize : Integer = 4;
347 private class var
348 FHeader_Dummy : array of Byte;
349 protected
350 FTransport : ITransport;
351 FWriteBuffer : TMemoryStream;
352 FReadBuffer : TMemoryStream;
353
354 procedure InitWriteBuffer;
355 procedure ReadFrame;
356 public
357 type
358 TFactory = class( TTransportFactoryImpl )
359 public
360 function GetTransport( const ATrans: ITransport): ITransport; override;
361 end;
362
Jens Geyere0e32402016-04-20 21:50:48 +0200363 {$IFDEF HAVE_CLASS_CTOR}
Jens Geyerd5436f52014-10-03 19:50:38 +0200364 class constructor Create;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200365 {$ENDIF}
Jens Geyere0e32402016-04-20 21:50:48 +0200366
Jens Geyerd5436f52014-10-03 19:50:38 +0200367 constructor Create; overload;
368 constructor Create( const ATrans: ITransport); overload;
369 destructor Destroy; override;
370
371 procedure Open(); override;
372 function GetIsOpen: Boolean; override;
373
374 procedure Close(); override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200375 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
376 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200377 procedure Flush; override;
378 end;
379
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200380{$IFNDEF HAVE_CLASS_CTOR}
Jens Geyerd5436f52014-10-03 19:50:38 +0200381procedure TFramedTransportImpl_Initialize;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200382{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200383
384const
385 DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms
Jens Geyer47f63172019-06-06 22:42:58 +0200386 DEFAULT_THRIFT_SECUREPROTOCOLS = [ TSecureProtocol.TLS_1_1, TSecureProtocol.TLS_1_2];
387
Jens Geyerd5436f52014-10-03 19:50:38 +0200388
389
390implementation
391
392{ TTransportImpl }
393
394procedure TTransportImpl.Flush;
395begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200396 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200397end;
398
399function TTransportImpl.Peek: Boolean;
400begin
401 Result := IsOpen;
402end;
403
Jens Geyer17c3ad92017-09-05 20:31:27 +0200404function TTransportImpl.Read(var buf: TBytes; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200405begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200406 if Length(buf) > 0
407 then result := Read( @buf[0], Length(buf), off, len)
408 else result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200409end;
410
411function TTransportImpl.ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer;
412begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200413 if Length(buf) > 0
414 then result := ReadAll( @buf[0], Length(buf), off, len)
415 else result := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +0200416end;
417
418procedure TTransportImpl.Write( const buf: TBytes);
419begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200420 if Length(buf) > 0
421 then Write( @buf[0], 0, Length(buf));
Jens Geyer17c3ad92017-09-05 20:31:27 +0200422end;
423
424procedure TTransportImpl.Write( const buf: TBytes; off: Integer; len: Integer);
425begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200426 if Length(buf) > 0
427 then Write( @buf[0], off, len);
Jens Geyer17c3ad92017-09-05 20:31:27 +0200428end;
429
430function TTransportImpl.ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
431var ret : Integer;
432begin
433 result := 0;
434 while result < len do begin
435 ret := Read( pBuf, buflen, off + result, len - result);
436 if ret > 0
437 then Inc( result, ret)
438 else raise TTransportExceptionNotOpen.Create( 'Cannot read, Remote side has closed' );
439 end;
440end;
441
442procedure TTransportImpl.Write( const pBuf : Pointer; len : Integer);
443begin
444 Self.Write( pBuf, 0, len);
Jens Geyerd5436f52014-10-03 19:50:38 +0200445end;
446
Jens Geyerd5436f52014-10-03 19:50:38 +0200447{ TTransportException }
448
Jens Geyere0e32402016-04-20 21:50:48 +0200449function TTransportException.GetType: TExceptionType;
450begin
451 if Self is TTransportExceptionNotOpen then Result := TExceptionType.NotOpen
452 else if Self is TTransportExceptionAlreadyOpen then Result := TExceptionType.AlreadyOpen
453 else if Self is TTransportExceptionTimedOut then Result := TExceptionType.TimedOut
454 else if Self is TTransportExceptionEndOfFile then Result := TExceptionType.EndOfFile
455 else if Self is TTransportExceptionBadArgs then Result := TExceptionType.BadArgs
456 else if Self is TTransportExceptionInterrupted then Result := TExceptionType.Interrupted
457 else Result := TExceptionType.Unknown;
458end;
459
460constructor TTransportException.HiddenCreate(const Msg: string);
461begin
462 inherited Create(Msg);
463end;
464
465class function TTransportException.Create(AType: TExceptionType): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200466begin
467 //no inherited;
Jens Geyere0e32402016-04-20 21:50:48 +0200468{$WARN SYMBOL_DEPRECATED OFF}
469 Result := Create(AType, '')
470{$WARN SYMBOL_DEPRECATED DEFAULT}
Jens Geyerd5436f52014-10-03 19:50:38 +0200471end;
472
Jens Geyere0e32402016-04-20 21:50:48 +0200473class function TTransportException.Create(AType: TExceptionType;
474 const msg: string): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200475begin
Jens Geyere0e32402016-04-20 21:50:48 +0200476 case AType of
477 TExceptionType.NotOpen: Result := TTransportExceptionNotOpen.Create(msg);
478 TExceptionType.AlreadyOpen: Result := TTransportExceptionAlreadyOpen.Create(msg);
479 TExceptionType.TimedOut: Result := TTransportExceptionTimedOut.Create(msg);
480 TExceptionType.EndOfFile: Result := TTransportExceptionEndOfFile.Create(msg);
481 TExceptionType.BadArgs: Result := TTransportExceptionBadArgs.Create(msg);
482 TExceptionType.Interrupted: Result := TTransportExceptionInterrupted.Create(msg);
483 else
484 Result := TTransportExceptionUnknown.Create(msg);
485 end;
Jens Geyerd5436f52014-10-03 19:50:38 +0200486end;
487
Jens Geyere0e32402016-04-20 21:50:48 +0200488class function TTransportException.Create(const msg: string): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200489begin
Jens Geyere0e32402016-04-20 21:50:48 +0200490 Result := TTransportExceptionUnknown.Create(Msg);
491end;
492
493{ TTransportExceptionSpecialized }
494
495constructor TTransportExceptionSpecialized.Create(const Msg: string);
496begin
497 inherited HiddenCreate(Msg);
Jens Geyerd5436f52014-10-03 19:50:38 +0200498end;
499
500{ TTransportFactoryImpl }
501
502function TTransportFactoryImpl.GetTransport( const ATrans: ITransport): ITransport;
503begin
504 Result := ATrans;
505end;
506
507{ TServerSocket }
508
Jens Geyer23d67462015-12-19 11:44:57 +0100509{$IFDEF OLD_SOCKETS}
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200510constructor TServerSocketImpl.Create( const AServer: TTcpServer; AClientTimeout: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200511begin
512 inherited Create;
513 FServer := AServer;
514 FClientTimeout := AClientTimeout;
515end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200516{$ELSE}
517constructor TServerSocketImpl.Create( const AServer: TServerSocket; AClientTimeout: Longword);
Jens Geyerd5436f52014-10-03 19:50:38 +0200518begin
519 inherited Create;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200520 FServer := AServer;
521 FServer.RecvTimeout := AClientTimeout;
522 FServer.SendTimeout := AClientTimeout;
523end;
524{$ENDIF}
525
526{$IFDEF OLD_SOCKETS}
527constructor TServerSocketImpl.Create(APort, AClientTimeout: Integer; AUseBufferedSockets: Boolean);
528{$ELSE}
529constructor TServerSocketImpl.Create(APort: Integer; AClientTimeout: Longword; AUseBufferedSockets: Boolean);
530{$ENDIF}
531begin
532 inherited Create;
533{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200534 FPort := APort;
535 FClientTimeout := AClientTimeout;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200536 FServer := TTcpServer.Create( nil );
Jens Geyerd5436f52014-10-03 19:50:38 +0200537 FServer.BlockMode := bmBlocking;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200538 {$IF CompilerVersion >= 21.0}
Jens Geyerd5436f52014-10-03 19:50:38 +0200539 FServer.LocalPort := AnsiString( IntToStr( FPort));
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200540 {$ELSE}
Jens Geyerd5436f52014-10-03 19:50:38 +0200541 FServer.LocalPort := IntToStr( FPort);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200542 {$IFEND}
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200543{$ELSE}
544 FServer := TServerSocket.Create(APort, AClientTimeout, AClientTimeout);
545{$ENDIF}
546 FUseBufferedSocket := AUseBufferedSockets;
547 FOwnsServer := True;
Jens Geyerd5436f52014-10-03 19:50:38 +0200548end;
549
550destructor TServerSocketImpl.Destroy;
551begin
552 if FOwnsServer then begin
553 FServer.Free;
554 FServer := nil;
555 end;
556 inherited;
557end;
558
559function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport;
560var
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200561{$IFDEF OLD_SOCKETS}
562 client : TCustomIpClient;
563{$ELSE}
564 client: TSocket;
565{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200566 trans : IStreamTransport;
567begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100568 if FServer = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200569 raise TTransportExceptionNotOpen.Create('No underlying server socket.');
Jens Geyerd5436f52014-10-03 19:50:38 +0200570 end;
571
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200572{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200573 client := nil;
574 try
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200575 client := TCustomIpClient.Create(nil);
Jens Geyerd5436f52014-10-03 19:50:38 +0200576
577 if Assigned(fnAccepting)
578 then fnAccepting();
579
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100580 if not FServer.Accept( client) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200581 client.Free;
582 Result := nil;
583 Exit;
584 end;
585
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100586 if client = nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200587 Result := nil;
588 Exit;
589 end;
590
591 trans := TSocketImpl.Create( client, TRUE, FClientTimeout);
592 client := nil; // trans owns it now
593
594 if FUseBufferedSocket
595 then result := TBufferedTransportImpl.Create( trans)
596 else result := trans;
597
598 except
599 on E: Exception do begin
600 client.Free;
Jens Geyere0e32402016-04-20 21:50:48 +0200601 raise TTransportExceptionUnknown.Create(E.ToString);
Jens Geyerd5436f52014-10-03 19:50:38 +0200602 end;
603 end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200604{$ELSE}
605 if Assigned(fnAccepting) then
606 fnAccepting();
607
608 client := FServer.Accept;
609 try
610 trans := TSocketImpl.Create(client, True);
611 client := nil;
612
613 if FUseBufferedSocket then
614 Result := TBufferedTransportImpl.Create(trans)
615 else
616 Result := trans;
617 except
618 client.Free;
619 raise;
620 end;
621{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200622end;
623
624procedure TServerSocketImpl.Listen;
625begin
626 if FServer <> nil then
627 begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200628{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200629 try
630 FServer.Active := True;
631 except
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200632 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200633 do raise TTransportExceptionUnknown.Create('Could not accept on listening socket: ' + E.Message);
Jens Geyerd5436f52014-10-03 19:50:38 +0200634 end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200635{$ELSE}
636 FServer.Listen;
637{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200638 end;
639end;
640
641procedure TServerSocketImpl.Close;
642begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200643 if FServer <> nil then
644{$IFDEF OLD_SOCKETS}
645 try
646 FServer.Active := False;
647 except
648 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200649 do raise TTransportExceptionUnknown.Create('Error on closing socket : ' + E.Message);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200650 end;
651{$ELSE}
652 FServer.Close;
653{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200654end;
655
656{ TSocket }
657
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200658{$IFDEF OLD_SOCKETS}
659constructor TSocketImpl.Create( const AClient : TCustomIpClient; aOwnsClient : Boolean; ATimeout: Integer = 0);
Jens Geyerd5436f52014-10-03 19:50:38 +0200660var stream : IThriftStream;
661begin
662 FClient := AClient;
663 FTimeout := ATimeout;
664 FOwnsClient := aOwnsClient;
665 stream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
666 inherited Create( stream, stream);
667end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200668{$ELSE}
669constructor TSocketImpl.Create(const AClient: TSocket; aOwnsClient: Boolean);
670var stream : IThriftStream;
671begin
672 FClient := AClient;
673 FTimeout := AClient.RecvTimeout;
674 FOwnsClient := aOwnsClient;
675 stream := TTcpSocketStreamImpl.Create(FClient, FTimeout);
676 inherited Create(stream, stream);
677end;
678{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200679
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200680{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200681constructor TSocketImpl.Create(const AHost: string; APort, ATimeout: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200682{$ELSE}
683constructor TSocketImpl.Create(const AHost: string; APort: Integer; ATimeout: Longword);
684{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200685begin
686 inherited Create(nil,nil);
687 FHost := AHost;
688 FPort := APort;
689 FTimeout := ATimeout;
690 InitSocket;
691end;
692
693destructor TSocketImpl.Destroy;
694begin
695 if FOwnsClient
696 then FreeAndNil( FClient);
697 inherited;
698end;
699
700procedure TSocketImpl.Close;
701begin
702 inherited Close;
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200703
704 FInputStream := nil;
705 FOutputStream := nil;
706
Jens Geyerd5436f52014-10-03 19:50:38 +0200707 if FOwnsClient
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200708 then FreeAndNil( FClient)
709 else FClient := nil;
Jens Geyerd5436f52014-10-03 19:50:38 +0200710end;
711
712function TSocketImpl.GetIsOpen: Boolean;
713begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200714{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200715 Result := (FClient <> nil) and FClient.Connected;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200716{$ELSE}
717 Result := (FClient <> nil) and FClient.IsOpen
718{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200719end;
720
721procedure TSocketImpl.InitSocket;
722var
723 stream : IThriftStream;
724begin
725 if FOwnsClient
726 then FreeAndNil( FClient)
727 else FClient := nil;
728
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200729{$IFDEF OLD_SOCKETS}
730 FClient := TTcpClient.Create( nil);
731{$ELSE}
732 FClient := TSocket.Create(FHost, FPort);
733{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200734 FOwnsClient := True;
735
736 stream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
737 FInputStream := stream;
738 FOutputStream := stream;
739end;
740
741procedure TSocketImpl.Open;
742begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100743 if IsOpen then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200744 raise TTransportExceptionAlreadyOpen.Create('Socket already connected');
Jens Geyerd5436f52014-10-03 19:50:38 +0200745 end;
746
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100747 if FHost = '' then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200748 raise TTransportExceptionNotOpen.Create('Cannot open null host');
Jens Geyerd5436f52014-10-03 19:50:38 +0200749 end;
750
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100751 if Port <= 0 then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200752 raise TTransportExceptionNotOpen.Create('Cannot open without port');
Jens Geyerd5436f52014-10-03 19:50:38 +0200753 end;
754
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100755 if FClient = nil
756 then InitSocket;
Jens Geyerd5436f52014-10-03 19:50:38 +0200757
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200758{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200759 FClient.RemoteHost := TSocketHost( Host);
760 FClient.RemotePort := TSocketPort( IntToStr( Port));
761 FClient.Connect;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200762{$ELSE}
763 FClient.Open;
764{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200765
766 FInputStream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
767 FOutputStream := FInputStream;
768end;
769
770{ TBufferedStream }
771
772procedure TBufferedStreamImpl.Close;
773begin
774 Flush;
775 FStream := nil;
776
777 FReadBuffer.Free;
778 FReadBuffer := nil;
779
780 FWriteBuffer.Free;
781 FWriteBuffer := nil;
782end;
783
784constructor TBufferedStreamImpl.Create( const AStream: IThriftStream; ABufSize: Integer);
785begin
786 inherited Create;
787 FStream := AStream;
788 FBufSize := ABufSize;
789 FReadBuffer := TMemoryStream.Create;
790 FWriteBuffer := TMemoryStream.Create;
791end;
792
793destructor TBufferedStreamImpl.Destroy;
794begin
795 Close;
796 inherited;
797end;
798
799procedure TBufferedStreamImpl.Flush;
800var
801 buf : TBytes;
802 len : Integer;
803begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200804 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200805 len := FWriteBuffer.Size;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200806 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200807 SetLength( buf, len );
808 FWriteBuffer.Position := 0;
809 FWriteBuffer.Read( Pointer(@buf[0])^, len );
810 FStream.Write( buf, 0, len );
811 end;
812 FWriteBuffer.Clear;
813 end;
814end;
815
816function TBufferedStreamImpl.IsOpen: Boolean;
817begin
818 Result := (FWriteBuffer <> nil)
819 and (FReadBuffer <> nil)
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200820 and (FStream <> nil)
821 and FStream.IsOpen;
Jens Geyerd5436f52014-10-03 19:50:38 +0200822end;
823
824procedure TBufferedStreamImpl.Open;
825begin
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200826 FStream.Open;
Jens Geyerd5436f52014-10-03 19:50:38 +0200827end;
828
Jens Geyer17c3ad92017-09-05 20:31:27 +0200829function TBufferedStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200830var
831 nRead : Integer;
832 tempbuf : TBytes;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100833 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200834begin
835 inherited;
836 Result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +0100837
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200838 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200839 while count > 0 do begin
840
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200841 if FReadBuffer.Position >= FReadBuffer.Size then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200842 FReadBuffer.Clear;
843 SetLength( tempbuf, FBufSize);
844 nRead := FStream.Read( tempbuf, 0, FBufSize );
845 if nRead = 0 then Break; // avoid infinite loop
846
847 FReadBuffer.WriteBuffer( Pointer(@tempbuf[0])^, nRead );
848 FReadBuffer.Position := 0;
849 end;
850
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200851 if FReadBuffer.Position < FReadBuffer.Size then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100852 nRead := Min( FReadBuffer.Size - FReadBuffer.Position, count);
853 pTmp := pBuf;
854 Inc( pTmp, offset);
855 Inc( Result, FReadBuffer.Read( pTmp^, nRead));
Jens Geyerd5436f52014-10-03 19:50:38 +0200856 Dec( count, nRead);
857 Inc( offset, nRead);
858 end;
859 end;
860 end;
861end;
862
863function TBufferedStreamImpl.ToArray: TBytes;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200864var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200865begin
866 len := 0;
867
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200868 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200869 len := FReadBuffer.Size;
870 end;
871
872 SetLength( Result, len);
873
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200874 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200875 FReadBuffer.Position := 0;
876 FReadBuffer.Read( Pointer(@Result[0])^, len );
877 end;
878end;
879
Jens Geyer17c3ad92017-09-05 20:31:27 +0200880procedure TBufferedStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +0100881var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +0200882begin
883 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200884 if count > 0 then begin
885 if IsOpen then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +0100886 pTmp := pBuf;
887 Inc( pTmp, offset);
888 FWriteBuffer.Write( pTmp^, count );
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200889 if FWriteBuffer.Size > FBufSize then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200890 Flush;
891 end;
892 end;
893 end;
894end;
895
896{ TStreamTransportImpl }
897
Jens Geyerd5436f52014-10-03 19:50:38 +0200898constructor TStreamTransportImpl.Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream);
899begin
900 inherited Create;
901 FInputStream := AInputStream;
902 FOutputStream := AOutputStream;
903end;
904
905destructor TStreamTransportImpl.Destroy;
906begin
907 FInputStream := nil;
908 FOutputStream := nil;
909 inherited;
910end;
911
Jens Geyer20e727e2018-06-22 22:39:57 +0200912procedure TStreamTransportImpl.Close;
913begin
914 FInputStream := nil;
915 FOutputStream := nil;
916end;
917
Jens Geyerd5436f52014-10-03 19:50:38 +0200918procedure TStreamTransportImpl.Flush;
919begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100920 if FOutputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200921 raise TTransportExceptionNotOpen.Create('Cannot flush null outputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +0200922 end;
923
924 FOutputStream.Flush;
925end;
926
927function TStreamTransportImpl.GetInputStream: IThriftStream;
928begin
929 Result := FInputStream;
930end;
931
932function TStreamTransportImpl.GetIsOpen: Boolean;
933begin
934 Result := True;
935end;
936
937function TStreamTransportImpl.GetOutputStream: IThriftStream;
938begin
Jens Geyer02fbe0e2018-03-19 17:35:44 +0100939 Result := FOutputStream;
Jens Geyerd5436f52014-10-03 19:50:38 +0200940end;
941
942procedure TStreamTransportImpl.Open;
943begin
944
945end;
946
Jens Geyer17c3ad92017-09-05 20:31:27 +0200947function TStreamTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200948begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100949 if FInputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200950 raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +0200951 end;
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100952
Jens Geyer17c3ad92017-09-05 20:31:27 +0200953 Result := FInputStream.Read( pBuf,buflen, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +0200954end;
955
Jens Geyer17c3ad92017-09-05 20:31:27 +0200956procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200957begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100958 if FOutputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200959 raise TTransportExceptionNotOpen.Create('Cannot write to null outputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +0200960 end;
961
Jens Geyer17c3ad92017-09-05 20:31:27 +0200962 FOutputStream.Write( pBuf, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +0200963end;
964
965{ TBufferedTransportImpl }
966
967constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport);
968begin
969 //no inherited;
970 Create( ATransport, 1024 );
971end;
972
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200973constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport; ABufSize: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200974begin
975 inherited Create;
976 FTransport := ATransport;
977 FBufSize := ABufSize;
978 InitBuffers;
979end;
980
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200981procedure TBufferedTransportImpl.Close;
982begin
983 FTransport.Close;
984 FInputBuffer := nil;
985 FOutputBuffer := nil;
986end;
987
Jens Geyerd5436f52014-10-03 19:50:38 +0200988procedure TBufferedTransportImpl.Flush;
989begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200990 if FOutputBuffer <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200991 FOutputBuffer.Flush;
992 end;
993end;
994
995function TBufferedTransportImpl.GetIsOpen: Boolean;
996begin
997 Result := FTransport.IsOpen;
998end;
999
1000function TBufferedTransportImpl.GetUnderlyingTransport: ITransport;
1001begin
1002 Result := FTransport;
1003end;
1004
1005procedure TBufferedTransportImpl.InitBuffers;
1006begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001007 if FTransport.InputStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001008 FInputBuffer := TBufferedStreamImpl.Create( FTransport.InputStream, FBufSize );
1009 end;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001010 if FTransport.OutputStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001011 FOutputBuffer := TBufferedStreamImpl.Create( FTransport.OutputStream, FBufSize );
1012 end;
1013end;
1014
1015procedure TBufferedTransportImpl.Open;
1016begin
Jens Geyera0cf38e2018-04-04 17:31:52 +02001017 FTransport.Open;
Jens Geyer3c0edfa2018-04-02 13:57:55 +02001018 InitBuffers; // we need to get the buffers to match FTransport substreams again
Jens Geyerd5436f52014-10-03 19:50:38 +02001019end;
1020
Jens Geyer17c3ad92017-09-05 20:31:27 +02001021function TBufferedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001022begin
1023 Result := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001024 if FInputBuffer <> nil then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001025 Result := FInputBuffer.Read( pBuf,buflen, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +02001026 end;
1027end;
1028
Jens Geyer17c3ad92017-09-05 20:31:27 +02001029procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001030begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001031 if FOutputBuffer <> nil then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001032 FOutputBuffer.Write( pBuf, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +02001033 end;
1034end;
1035
1036{ TFramedTransportImpl }
1037
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001038{$IFDEF HAVE_CLASS_CTOR}
1039class constructor TFramedTransportImpl.Create;
1040begin
1041 SetLength( FHeader_Dummy, FHeaderSize);
1042 FillChar( FHeader_Dummy[0], Length( FHeader_Dummy) * SizeOf( Byte ), 0);
1043end;
1044{$ELSE}
Jens Geyerd5436f52014-10-03 19:50:38 +02001045procedure TFramedTransportImpl_Initialize;
1046begin
1047 SetLength( TFramedTransportImpl.FHeader_Dummy, TFramedTransportImpl.FHeaderSize);
1048 FillChar( TFramedTransportImpl.FHeader_Dummy[0],
1049 Length( TFramedTransportImpl.FHeader_Dummy) * SizeOf( Byte ), 0);
1050end;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001051{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001052
1053constructor TFramedTransportImpl.Create;
1054begin
1055 inherited Create;
1056 InitWriteBuffer;
1057end;
1058
1059procedure TFramedTransportImpl.Close;
1060begin
1061 FTransport.Close;
1062end;
1063
1064constructor TFramedTransportImpl.Create( const ATrans: ITransport);
1065begin
1066 inherited Create;
1067 InitWriteBuffer;
1068 FTransport := ATrans;
1069end;
1070
1071destructor TFramedTransportImpl.Destroy;
1072begin
1073 FWriteBuffer.Free;
1074 FReadBuffer.Free;
1075 inherited;
1076end;
1077
1078procedure TFramedTransportImpl.Flush;
1079var
1080 buf : TBytes;
1081 len : Integer;
1082 data_len : Integer;
1083
1084begin
1085 len := FWriteBuffer.Size;
1086 SetLength( buf, len);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001087 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001088 System.Move( FWriteBuffer.Memory^, buf[0], len );
1089 end;
1090
1091 data_len := len - FHeaderSize;
Jens Geyer30ed90e2016-03-10 20:12:49 +01001092 if (data_len < 0) then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001093 raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: data_len < 0' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001094 end;
1095
1096 InitWriteBuffer;
1097
1098 buf[0] := Byte($FF and (data_len shr 24));
1099 buf[1] := Byte($FF and (data_len shr 16));
1100 buf[2] := Byte($FF and (data_len shr 8));
1101 buf[3] := Byte($FF and data_len);
1102
1103 FTransport.Write( buf, 0, len );
1104 FTransport.Flush;
1105end;
1106
1107function TFramedTransportImpl.GetIsOpen: Boolean;
1108begin
1109 Result := FTransport.IsOpen;
1110end;
1111
1112type
1113 TAccessMemoryStream = class(TMemoryStream)
1114 end;
1115
1116procedure TFramedTransportImpl.InitWriteBuffer;
1117begin
1118 FWriteBuffer.Free;
1119 FWriteBuffer := TMemoryStream.Create;
1120 TAccessMemoryStream(FWriteBuffer).Capacity := 1024;
1121 FWriteBuffer.Write( Pointer(@FHeader_Dummy[0])^, FHeaderSize);
1122end;
1123
1124procedure TFramedTransportImpl.Open;
1125begin
1126 FTransport.Open;
1127end;
1128
Jens Geyer17c3ad92017-09-05 20:31:27 +02001129function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001130var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001131begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001132 if len > (buflen-off)
1133 then len := buflen-off;
1134
Jens Geyer5089b0a2018-02-01 22:37:18 +01001135 pTmp := pBuf;
1136 Inc( pTmp, off);
1137
Jens Geyer17c3ad92017-09-05 20:31:27 +02001138 if (FReadBuffer <> nil) and (len > 0) then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001139 result := FReadBuffer.Read( pTmp^, len);
Jens Geyer17c3ad92017-09-05 20:31:27 +02001140 if result > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001141 Exit;
1142 end;
1143 end;
1144
1145 ReadFrame;
1146 if len > 0
Jens Geyer5089b0a2018-02-01 22:37:18 +01001147 then Result := FReadBuffer.Read( pTmp^, len)
Jens Geyerd5436f52014-10-03 19:50:38 +02001148 else Result := 0;
1149end;
1150
1151procedure TFramedTransportImpl.ReadFrame;
1152var
1153 i32rd : TBytes;
1154 size : Integer;
1155 buff : TBytes;
1156begin
1157 SetLength( i32rd, FHeaderSize );
1158 FTransport.ReadAll( i32rd, 0, FHeaderSize);
1159 size :=
1160 ((i32rd[0] and $FF) shl 24) or
1161 ((i32rd[1] and $FF) shl 16) or
1162 ((i32rd[2] and $FF) shl 8) or
1163 (i32rd[3] and $FF);
1164 SetLength( buff, size );
1165 FTransport.ReadAll( buff, 0, size );
1166 FReadBuffer.Free;
1167 FReadBuffer := TMemoryStream.Create;
Jens Geyera76e6c72017-09-08 21:03:30 +02001168 if Length(buff) > 0
1169 then FReadBuffer.Write( Pointer(@buff[0])^, size );
Jens Geyerd5436f52014-10-03 19:50:38 +02001170 FReadBuffer.Position := 0;
1171end;
1172
Jens Geyer17c3ad92017-09-05 20:31:27 +02001173procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001174var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001175begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001176 if len > 0 then begin
1177 pTmp := pBuf;
1178 Inc( pTmp, off);
1179
1180 FWriteBuffer.Write( pTmp^, len );
1181 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001182end;
1183
1184{ TFramedTransport.TFactory }
1185
1186function TFramedTransportImpl.TFactory.GetTransport( const ATrans: ITransport): ITransport;
1187begin
1188 Result := TFramedTransportImpl.Create( ATrans );
1189end;
1190
1191{ TTcpSocketStreamImpl }
1192
1193procedure TTcpSocketStreamImpl.Close;
1194begin
1195 FTcpClient.Close;
1196end;
1197
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001198{$IFDEF OLD_SOCKETS}
1199constructor TTcpSocketStreamImpl.Create( const ATcpClient: TCustomIpClient; const aTimeout : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001200begin
1201 inherited Create;
1202 FTcpClient := ATcpClient;
1203 FTimeout := aTimeout;
1204end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001205{$ELSE}
1206constructor TTcpSocketStreamImpl.Create( const ATcpClient: TSocket; const aTimeout : Longword);
1207begin
1208 inherited Create;
1209 FTcpClient := ATcpClient;
1210 if aTimeout = 0 then
1211 FTcpClient.RecvTimeout := SLEEP_TIME
1212 else
1213 FTcpClient.RecvTimeout := aTimeout;
1214 FTcpClient.SendTimeout := aTimeout;
1215end;
1216{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001217
1218procedure TTcpSocketStreamImpl.Flush;
1219begin
1220
1221end;
1222
1223function TTcpSocketStreamImpl.IsOpen: Boolean;
1224begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001225{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001226 Result := FTcpClient.Active;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001227{$ELSE}
1228 Result := FTcpClient.IsOpen;
1229{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001230end;
1231
1232procedure TTcpSocketStreamImpl.Open;
1233begin
1234 FTcpClient.Open;
1235end;
1236
1237
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001238{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001239function TTcpSocketStreamImpl.Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
1240 TimeOut: Integer; var wsaError : Integer): Integer;
1241var
1242 ReadFds: TFDset;
1243 ReadFdsptr: PFDset;
1244 WriteFds: TFDset;
1245 WriteFdsptr: PFDset;
1246 ExceptFds: TFDset;
1247 ExceptFdsptr: PFDset;
1248 tv: timeval;
1249 Timeptr: PTimeval;
1250 socket : TSocket;
1251begin
1252 if not FTcpClient.Active then begin
1253 wsaError := WSAEINVAL;
1254 Exit( SOCKET_ERROR);
1255 end;
1256
1257 socket := FTcpClient.Handle;
1258
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001259 if Assigned(ReadReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001260 ReadFdsptr := @ReadFds;
1261 FD_ZERO(ReadFds);
1262 FD_SET(socket, ReadFds);
1263 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001264 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001265 ReadFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001266 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001267
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001268 if Assigned(WriteReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001269 WriteFdsptr := @WriteFds;
1270 FD_ZERO(WriteFds);
1271 FD_SET(socket, WriteFds);
1272 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001273 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001274 WriteFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001275 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001276
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001277 if Assigned(ExceptFlag) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001278 ExceptFdsptr := @ExceptFds;
1279 FD_ZERO(ExceptFds);
1280 FD_SET(socket, ExceptFds);
1281 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001282 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001283 ExceptFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001284 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001285
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001286 if TimeOut >= 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001287 tv.tv_sec := TimeOut div 1000;
1288 tv.tv_usec := 1000 * (TimeOut mod 1000);
1289 Timeptr := @tv;
1290 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001291 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001292 Timeptr := nil; // wait forever
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001293 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001294
1295 wsaError := 0;
1296 try
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001297 {$IFDEF MSWINDOWS}
1298 {$IFDEF OLD_UNIT_NAMES}
1299 result := WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1300 {$ELSE}
1301 result := Winapi.WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1302 {$ENDIF}
1303 {$ENDIF}
1304 {$IFDEF LINUX}
1305 result := Libc.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1306 {$ENDIF}
1307
Jens Geyerd5436f52014-10-03 19:50:38 +02001308 if result = SOCKET_ERROR
1309 then wsaError := WSAGetLastError;
1310
1311 except
1312 result := SOCKET_ERROR;
1313 end;
1314
1315 if Assigned(ReadReady) then
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001316 ReadReady^ := FD_ISSET(socket, ReadFds);
1317
Jens Geyerd5436f52014-10-03 19:50:38 +02001318 if Assigned(WriteReady) then
1319 WriteReady^ := FD_ISSET(socket, WriteFds);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001320
Jens Geyerd5436f52014-10-03 19:50:38 +02001321 if Assigned(ExceptFlag) then
1322 ExceptFlag^ := FD_ISSET(socket, ExceptFds);
1323end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001324{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001325
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001326{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001327function TTcpSocketStreamImpl.WaitForData( TimeOut : Integer; pBuf : Pointer;
1328 DesiredBytes : Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001329 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001330var bCanRead, bError : Boolean;
1331 retval : Integer;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001332const
1333 MSG_PEEK = {$IFDEF OLD_UNIT_NAMES} WinSock.MSG_PEEK {$ELSE} Winapi.WinSock.MSG_PEEK {$ENDIF};
Jens Geyerd5436f52014-10-03 19:50:38 +02001334begin
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001335 bytesReady := 0;
1336
Jens Geyerd5436f52014-10-03 19:50:38 +02001337 // The select function returns the total number of socket handles that are ready
1338 // and contained in the fd_set structures, zero if the time limit expired,
1339 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1340 // WSAGetLastError can be used to retrieve a specific error code.
1341 retval := Self.Select( @bCanRead, nil, @bError, TimeOut, wsaError);
1342 if retval = SOCKET_ERROR
1343 then Exit( TWaitForData.wfd_Error);
1344 if (retval = 0) or not bCanRead
1345 then Exit( TWaitForData.wfd_Timeout);
1346
1347 // recv() returns the number of bytes received, or -1 if an error occurred.
1348 // The return value will be 0 when the peer has performed an orderly shutdown.
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001349
1350 retval := recv( FTcpClient.Handle, pBuf^, DesiredBytes, MSG_PEEK);
Jens Geyerd5436f52014-10-03 19:50:38 +02001351 if retval <= 0
1352 then Exit( TWaitForData.wfd_Error);
1353
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001354 // at least we have some data
1355 bytesReady := Min( retval, DesiredBytes);
1356 result := TWaitForData.wfd_HaveData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001357end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001358{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001359
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001360{$IFDEF OLD_SOCKETS}
Jens Geyer17c3ad92017-09-05 20:31:27 +02001361function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001362// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001363var wfd : TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001364 wsaError,
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001365 msecs : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001366 nBytes : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001367 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001368begin
1369 inherited;
1370
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001371 if FTimeout > 0
1372 then msecs := FTimeout
1373 else msecs := DEFAULT_THRIFT_TIMEOUT;
1374
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001375 result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001376 pTmp := pBuf;
1377 Inc( pTmp, offset);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001378 while count > 0 do begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001379
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001380 while TRUE do begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001381 wfd := WaitForData( msecs, pTmp, count, wsaError, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001382 case wfd of
Jens Geyer65b17462016-03-09 00:07:46 +01001383 TWaitForData.wfd_Error : Exit;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001384 TWaitForData.wfd_HaveData : Break;
1385 TWaitForData.wfd_Timeout : begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001386 if (FTimeout = 0)
1387 then Exit
1388 else begin
Jens Geyere0e32402016-04-20 21:50:48 +02001389 raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001390
1391 end;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001392 end;
1393 else
1394 ASSERT( FALSE);
Jens Geyerd5436f52014-10-03 19:50:38 +02001395 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001396 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001397
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001398 // reduce the timeout once we got data
1399 if FTimeout > 0
1400 then msecs := FTimeout div 10
1401 else msecs := DEFAULT_THRIFT_TIMEOUT div 10;
1402 msecs := Max( msecs, 200);
1403
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001404 ASSERT( nBytes <= count);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001405 nBytes := FTcpClient.ReceiveBuf( pTmp^, nBytes);
1406 Inc( pTmp, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001407 Dec( count, nBytes);
1408 Inc( result, nBytes);
1409 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001410end;
1411
1412function TTcpSocketStreamImpl.ToArray: TBytes;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001413// old sockets version
1414var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001415begin
1416 len := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001417 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001418 len := FTcpClient.BytesReceived;
1419 end;
1420
1421 SetLength( Result, len );
1422
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001423 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001424 FTcpClient.ReceiveBuf( Pointer(@Result[0])^, len);
1425 end;
1426end;
1427
Jens Geyer17c3ad92017-09-05 20:31:27 +02001428procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001429// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001430var bCanWrite, bError : Boolean;
1431 retval, wsaError : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001432 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001433begin
1434 inherited;
1435
1436 if not FTcpClient.Active
Jens Geyere0e32402016-04-20 21:50:48 +02001437 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerd5436f52014-10-03 19:50:38 +02001438
1439 // The select function returns the total number of socket handles that are ready
1440 // and contained in the fd_set structures, zero if the time limit expired,
1441 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1442 // WSAGetLastError can be used to retrieve a specific error code.
1443 retval := Self.Select( nil, @bCanWrite, @bError, FTimeOut, wsaError);
1444 if retval = SOCKET_ERROR
Jens Geyere0e32402016-04-20 21:50:48 +02001445 then raise TTransportExceptionUnknown.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001446
Jens Geyerd5436f52014-10-03 19:50:38 +02001447 if (retval = 0)
Jens Geyere0e32402016-04-20 21:50:48 +02001448 then raise TTransportExceptionTimedOut.Create('timed out');
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001449
Jens Geyerd5436f52014-10-03 19:50:38 +02001450 if bError or not bCanWrite
Jens Geyere0e32402016-04-20 21:50:48 +02001451 then raise TTransportExceptionUnknown.Create('unknown error');
Jens Geyerd5436f52014-10-03 19:50:38 +02001452
Jens Geyer5089b0a2018-02-01 22:37:18 +01001453 pTmp := pBuf;
1454 Inc( pTmp, offset);
1455 FTcpClient.SendBuf( pTmp^, count);
Jens Geyerd5436f52014-10-03 19:50:38 +02001456end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001457
1458{$ELSE}
1459
Jens Geyer17c3ad92017-09-05 20:31:27 +02001460function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001461// new sockets version
1462var nBytes : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001463 pTmp : PByte;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001464begin
1465 inherited;
1466
1467 result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001468 pTmp := pBuf;
1469 Inc( pTmp, offset);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001470 while count > 0 do begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001471 nBytes := FTcpClient.Read( pTmp^, count);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001472 if nBytes = 0 then Exit;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001473 Inc( pTmp, nBytes);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001474 Dec( count, nBytes);
1475 Inc( result, nBytes);
1476 end;
1477end;
1478
1479function TTcpSocketStreamImpl.ToArray: TBytes;
1480// new sockets version
1481var len : Integer;
1482begin
1483 len := 0;
1484 try
1485 if FTcpClient.Peek then
1486 repeat
1487 SetLength(Result, Length(Result) + 1024);
1488 len := FTcpClient.Read(Result[Length(Result) - 1024], 1024);
1489 until len < 1024;
1490 except
1491 on TTransportException do begin { don't allow default exceptions } end;
1492 else raise;
1493 end;
1494 if len > 0 then
1495 SetLength(Result, Length(Result) - 1024 + len);
1496end;
1497
Jens Geyer17c3ad92017-09-05 20:31:27 +02001498procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001499// new sockets version
Jens Geyer5089b0a2018-02-01 22:37:18 +01001500var pTmp : PByte;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001501begin
1502 inherited;
1503
1504 if not FTcpClient.IsOpen
Kyle Johnsone363a342016-04-22 19:11:16 -05001505 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001506
Jens Geyer5089b0a2018-02-01 22:37:18 +01001507 pTmp := pBuf;
1508 Inc( pTmp, offset);
1509 FTcpClient.Write( pTmp^, count);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001510end;
1511
Jens Geyer23d67462015-12-19 11:44:57 +01001512{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001513
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001514
Jens Geyerd5436f52014-10-03 19:50:38 +02001515{$IF CompilerVersion < 21.0}
1516initialization
1517begin
1518 TFramedTransportImpl_Initialize;
1519end;
1520{$IFEND}
1521
1522
1523end.