blob: 7695b22daec095aff06af07703e444d1323163ae [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
Jens Geyer41f47af2019-11-09 23:24:52 +010047const
48 DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; // 100 MB
49 DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms
50
Jens Geyerd5436f52014-10-03 19:50:38 +020051type
Jens Geyer41f47af2019-11-09 23:24:52 +010052 ITransportControl = interface
53 ['{CDA35E2C-F1D2-4BE3-9927-7F1540923265}']
54 function MaxAllowedMessageSize : Integer;
55 procedure ConsumeReadBytes( const count : Integer);
56 procedure ResetConsumedMessageSize;
57 end;
58
59 TTransportControlImpl = class( TInterfacedObject, ITransportControl)
60 strict private
61 FMaxAllowedMsgSize : Integer;
62 FRemainingMsgSize : Integer;
63 strict protected
64 // ITransportControl
65 function MaxAllowedMessageSize : Integer;
66 procedure ConsumeReadBytes( const count : Integer);
67 procedure ResetConsumedMessageSize;
68 public
69 constructor Create( const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); reintroduce;
70 end;
71
Jens Geyerd5436f52014-10-03 19:50:38 +020072 ITransport = interface
Jens Geyer41f47af2019-11-09 23:24:52 +010073 ['{938F6EB5-1848-43D5-8AC4-07633C55B229}']
Jens Geyerd5436f52014-10-03 19:50:38 +020074 function GetIsOpen: Boolean;
75 property IsOpen: Boolean read GetIsOpen;
76 function Peek: Boolean;
77 procedure Open;
78 procedure Close;
Jens Geyer41f47af2019-11-09 23:24:52 +010079
Jens Geyer17c3ad92017-09-05 20:31:27 +020080 function Read(var buf: TBytes; off: Integer; len: Integer): Integer; overload;
81 function Read(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload;
82 function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; overload;
83 function ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload;
Jens Geyerd5436f52014-10-03 19:50:38 +020084 procedure Write( const buf: TBytes); overload;
85 procedure Write( const buf: TBytes; off: Integer; len: Integer); overload;
Jens Geyer17c3ad92017-09-05 20:31:27 +020086 procedure Write( const pBuf : Pointer; off, len : Integer); overload;
87 procedure Write( const pBuf : Pointer; len : Integer); overload;
Jens Geyerd5436f52014-10-03 19:50:38 +020088 procedure Flush;
Jens Geyer41f47af2019-11-09 23:24:52 +010089
90 function TransportControl : ITransportControl;
91 procedure CheckReadBytesAvailable( const value : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +020092 end;
93
94 TTransportImpl = class( TInterfacedObject, ITransport)
Jens Geyer41f47af2019-11-09 23:24:52 +010095 strict private
96 FTransportControl : ITransportControl;
97
Jens Geyerfad7fd32019-11-09 23:24:52 +010098 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +020099 function GetIsOpen: Boolean; virtual; abstract;
100 property IsOpen: Boolean read GetIsOpen;
101 function Peek: Boolean; virtual;
102 procedure Open(); virtual; abstract;
103 procedure Close(); virtual; abstract;
Jens Geyer41f47af2019-11-09 23:24:52 +0100104
Jens Geyer17c3ad92017-09-05 20:31:27 +0200105 function Read(var buf: TBytes; off: Integer; len: Integer): Integer; overload; inline;
106 function Read(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; virtual; abstract;
107 function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; overload; inline;
108 function ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; virtual;
109 procedure Write( const buf: TBytes); overload; inline;
110 procedure Write( const buf: TBytes; off: Integer; len: Integer); overload; inline;
111 procedure Write( const pBuf : Pointer; len : Integer); overload; inline;
112 procedure Write( const pBuf : Pointer; off, len : Integer); overload; virtual; abstract;
Jens Geyerd5436f52014-10-03 19:50:38 +0200113 procedure Flush; virtual;
Jens Geyer41f47af2019-11-09 23:24:52 +0100114
115 function TransportControl : ITransportControl; inline;
116 procedure ConsumeReadBytes( const count : Integer); inline;
117 procedure CheckReadBytesAvailable( const value : Integer); virtual; abstract;
118
119 public
120 constructor Create( const aTransportCtl : ITransportControl); reintroduce;
Jens Geyerd5436f52014-10-03 19:50:38 +0200121 end;
122
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100123 TTransportException = class abstract( TException)
Jens Geyerd5436f52014-10-03 19:50:38 +0200124 public
125 type
126 TExceptionType = (
127 Unknown,
128 NotOpen,
129 AlreadyOpen,
130 TimedOut,
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200131 EndOfFile,
132 BadArgs,
Jens Geyer2646bd62019-11-09 23:24:52 +0100133 Interrupted,
134 CorruptedData
Jens Geyerd5436f52014-10-03 19:50:38 +0200135 );
Jens Geyerfad7fd32019-11-09 23:24:52 +0100136 strict protected
Jens Geyere0e32402016-04-20 21:50:48 +0200137 constructor HiddenCreate(const Msg: string);
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100138 class function GetType: TExceptionType; virtual; abstract;
Jens Geyerd5436f52014-10-03 19:50:38 +0200139 public
Jens Geyer41f47af2019-11-09 23:24:52 +0100140 class function Create( aType: TExceptionType): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
Jens Geyere0e32402016-04-20 21:50:48 +0200141 class function Create( const msg: string): TTransportException; reintroduce; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
Jens Geyer41f47af2019-11-09 23:24:52 +0100142 class function Create( aType: TExceptionType; const msg: string): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)';
Jens Geyere0e32402016-04-20 21:50:48 +0200143 property Type_: TExceptionType read GetType;
Jens Geyerd5436f52014-10-03 19:50:38 +0200144 end;
145
Jens Geyere0e32402016-04-20 21:50:48 +0200146 // Needed to remove deprecation warning
147 TTransportExceptionSpecialized = class abstract (TTransportException)
148 public
149 constructor Create(const Msg: string);
150 end;
151
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100152 TTransportExceptionUnknown = class (TTransportExceptionSpecialized)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100153 strict protected
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100154 class function GetType: TTransportException.TExceptionType; override;
155 end;
156
157 TTransportExceptionNotOpen = class (TTransportExceptionSpecialized)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100158 strict protected
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100159 class function GetType: TTransportException.TExceptionType; override;
160 end;
161
162 TTransportExceptionAlreadyOpen = class (TTransportExceptionSpecialized)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100163 strict protected
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100164 class function GetType: TTransportException.TExceptionType; override;
165 end;
166
167 TTransportExceptionTimedOut = class (TTransportExceptionSpecialized)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100168 strict protected
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100169 class function GetType: TTransportException.TExceptionType; override;
170 end;
171
172 TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100173 strict protected
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100174 class function GetType: TTransportException.TExceptionType; override;
175 end;
176
177 TTransportExceptionBadArgs = class (TTransportExceptionSpecialized)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100178 strict protected
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100179 class function GetType: TTransportException.TExceptionType; override;
180 end;
181
182 TTransportExceptionInterrupted = class (TTransportExceptionSpecialized)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100183 strict protected
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100184 class function GetType: TTransportException.TExceptionType; override;
185 end;
Jens Geyere0e32402016-04-20 21:50:48 +0200186
Jens Geyer2646bd62019-11-09 23:24:52 +0100187 TTransportExceptionCorruptedData = class (TTransportExceptionSpecialized)
188 protected
189 class function GetType: TTransportException.TExceptionType; override;
190 end;
191
Jens Geyer47f63172019-06-06 22:42:58 +0200192 TSecureProtocol = (
193 SSL_2, SSL_3, TLS_1, // outdated, for compatibilty only
194 TLS_1_1, TLS_1_2 // secure (as of today)
195 );
196
197 TSecureProtocols = set of TSecureProtocol;
198
Jens Geyerd5436f52014-10-03 19:50:38 +0200199 IHTTPClient = interface( ITransport )
Jens Geyer47f63172019-06-06 22:42:58 +0200200 ['{7BF615DD-8680-4004-A5B2-88947BA3BA3D}']
Jens Geyer20e727e2018-06-22 22:39:57 +0200201 procedure SetDnsResolveTimeout(const Value: Integer);
202 function GetDnsResolveTimeout: Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200203 procedure SetConnectionTimeout(const Value: Integer);
204 function GetConnectionTimeout: Integer;
Jens Geyer20e727e2018-06-22 22:39:57 +0200205 procedure SetSendTimeout(const Value: Integer);
206 function GetSendTimeout: Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200207 procedure SetReadTimeout(const Value: Integer);
208 function GetReadTimeout: Integer;
209 function GetCustomHeaders: IThriftDictionary<string,string>;
210 procedure SendRequest;
Jens Geyer47f63172019-06-06 22:42:58 +0200211 function GetSecureProtocols : TSecureProtocols;
212 procedure SetSecureProtocols( const value : TSecureProtocols);
Jens Geyer20e727e2018-06-22 22:39:57 +0200213
214 property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
Jens Geyerd5436f52014-10-03 19:50:38 +0200215 property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
Jens Geyer20e727e2018-06-22 22:39:57 +0200216 property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
Jens Geyerd5436f52014-10-03 19:50:38 +0200217 property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
218 property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
Jens Geyer47f63172019-06-06 22:42:58 +0200219 property SecureProtocols : TSecureProtocols read GetSecureProtocols write SetSecureProtocols;
Jens Geyerd5436f52014-10-03 19:50:38 +0200220 end;
221
Jens Geyerd5436f52014-10-03 19:50:38 +0200222 IServerTransport = interface
223 ['{C43B87ED-69EA-47C4-B77C-15E288252900}']
224 procedure Listen;
225 procedure Close;
226 function Accept( const fnAccepting: TProc): ITransport;
227 end;
228
229 TServerTransportImpl = class( TInterfacedObject, IServerTransport)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100230 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +0200231 procedure Listen; virtual; abstract;
232 procedure Close; virtual; abstract;
233 function Accept( const fnAccepting: TProc): ITransport; virtual; abstract;
234 end;
235
236 ITransportFactory = interface
237 ['{DD809446-000F-49E1-9BFF-E0D0DC76A9D7}']
Jens Geyer41f47af2019-11-09 23:24:52 +0100238 function GetTransport( const aTransport: ITransport): ITransport;
Jens Geyerd5436f52014-10-03 19:50:38 +0200239 end;
240
241 TTransportFactoryImpl = class( TInterfacedObject, ITransportFactory)
Jens Geyered994552019-11-09 23:24:52 +0100242 function GetTransport( const aTransport: ITransport): ITransport; virtual;
Jens Geyerd5436f52014-10-03 19:50:38 +0200243 end;
244
245 TTcpSocketStreamImpl = class( TThriftStreamImpl )
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200246{$IFDEF OLD_SOCKETS}
Jens Geyerfad7fd32019-11-09 23:24:52 +0100247 strict private type
Jens Geyerd5436f52014-10-03 19:50:38 +0200248 TWaitForData = ( wfd_HaveData, wfd_Timeout, wfd_Error);
Jens Geyerfad7fd32019-11-09 23:24:52 +0100249 strict private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200250 FTcpClient : TCustomIpClient;
Jens Geyerd5436f52014-10-03 19:50:38 +0200251 FTimeout : Integer;
252 function Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
253 TimeOut: Integer; var wsaError : Integer): Integer;
254 function WaitForData( TimeOut : Integer; pBuf : Pointer; DesiredBytes: Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +0200255 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200256{$ELSE}
257 FTcpClient: TSocket;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100258 strict protected const
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200259 SLEEP_TIME = 200;
260{$ENDIF}
Jens Geyerfad7fd32019-11-09 23:24:52 +0100261 strict protected
Jens Geyer17c3ad92017-09-05 20:31:27 +0200262 procedure Write( const pBuf : Pointer; offset, count: Integer); override;
263 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyer41f47af2019-11-09 23:24:52 +0100264 procedure CheckReadBytesAvailable( const value : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200265 procedure Open; override;
266 procedure Close; override;
267 procedure Flush; override;
268
269 function IsOpen: Boolean; override;
270 function ToArray: TBytes; override;
271 public
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200272{$IFDEF OLD_SOCKETS}
Jens Geyer41f47af2019-11-09 23:24:52 +0100273 constructor Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer = 0);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200274{$ELSE}
Jens Geyer41f47af2019-11-09 23:24:52 +0100275 constructor Create( const aTcpClient: TSocket; const aTimeout : Longword = 0);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200276{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200277 end;
278
279 IStreamTransport = interface( ITransport )
280 ['{A8479B47-2A3E-4421-A9A0-D5A9EDCC634A}']
281 function GetInputStream: IThriftStream;
282 function GetOutputStream: IThriftStream;
283 property InputStream : IThriftStream read GetInputStream;
284 property OutputStream : IThriftStream read GetOutputStream;
285 end;
286
287 TStreamTransportImpl = class( TTransportImpl, IStreamTransport)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100288 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +0200289 FInputStream : IThriftStream;
290 FOutputStream : IThriftStream;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100291 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +0200292 function GetIsOpen: Boolean; override;
293
294 function GetInputStream: IThriftStream;
295 function GetOutputStream: IThriftStream;
Jens Geyerd5436f52014-10-03 19:50:38 +0200296
Jens Geyer41f47af2019-11-09 23:24:52 +0100297 procedure CheckReadBytesAvailable( const value : Integer); override;
298 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +0200299 procedure Open; override;
300 procedure Close; override;
301 procedure Flush; override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200302 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
303 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyered994552019-11-09 23:24:52 +0100304 public
Jens Geyer41f47af2019-11-09 23:24:52 +0100305 constructor Create( const aInputStream, aOutputStream : IThriftStream; const aTransportCtl : ITransportControl = nil);
Jens Geyerd5436f52014-10-03 19:50:38 +0200306 destructor Destroy; override;
Jens Geyered994552019-11-09 23:24:52 +0100307
308 property InputStream : IThriftStream read GetInputStream;
309 property OutputStream : IThriftStream read GetOutputStream;
Jens Geyerd5436f52014-10-03 19:50:38 +0200310 end;
311
312 TBufferedStreamImpl = class( TThriftStreamImpl)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100313 strict private
Jens Geyerd5436f52014-10-03 19:50:38 +0200314 FStream : IThriftStream;
315 FBufSize : Integer;
316 FReadBuffer : TMemoryStream;
317 FWriteBuffer : TMemoryStream;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100318 strict protected
Jens Geyer17c3ad92017-09-05 20:31:27 +0200319 procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
320 function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
Jens Geyer41f47af2019-11-09 23:24:52 +0100321 procedure CheckReadBytesAvailable( const value : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200322 procedure Open; override;
323 procedure Close; override;
324 procedure Flush; override;
325 function IsOpen: Boolean; override;
326 function ToArray: TBytes; override;
327 public
Jens Geyered994552019-11-09 23:24:52 +0100328 constructor Create( const aStream: IThriftStream; const aBufSize : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200329 destructor Destroy; override;
330 end;
331
332 TServerSocketImpl = class( TServerTransportImpl)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100333 strict private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200334{$IFDEF OLD_SOCKETS}
335 FServer : TTcpServer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200336 FPort : Integer;
337 FClientTimeout : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200338{$ELSE}
339 FServer: TServerSocket;
340{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200341 FUseBufferedSocket : Boolean;
342 FOwnsServer : Boolean;
Jens Geyer41f47af2019-11-09 23:24:52 +0100343 FTransportControl : ITransportControl;
344
Jens Geyerfad7fd32019-11-09 23:24:52 +0100345 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +0200346 function Accept( const fnAccepting: TProc) : ITransport; override;
Jens Geyer41f47af2019-11-09 23:24:52 +0100347 property TransportControl : ITransportControl read FTransportControl;
348
Jens Geyerd5436f52014-10-03 19:50:38 +0200349 public
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200350{$IFDEF OLD_SOCKETS}
Jens Geyer41f47af2019-11-09 23:24:52 +0100351 constructor Create( const aServer: TTcpServer; const aClientTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload;
352 constructor Create( const aPort: Integer; const aClientTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aTransportCtl : ITransportControl = nil); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200353{$ELSE}
Jens Geyer41f47af2019-11-09 23:24:52 +0100354 constructor Create( const aServer: TServerSocket; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload;
355 constructor Create( const aPort: Integer; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aTransportCtl : ITransportControl = nil); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200356{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200357 destructor Destroy; override;
358 procedure Listen; override;
359 procedure Close; override;
360 end;
361
362 TBufferedTransportImpl = class( TTransportImpl )
Jens Geyerfad7fd32019-11-09 23:24:52 +0100363 strict private
Jens Geyerd5436f52014-10-03 19:50:38 +0200364 FInputBuffer : IThriftStream;
365 FOutputBuffer : IThriftStream;
366 FTransport : IStreamTransport;
367 FBufSize : Integer;
368
369 procedure InitBuffers;
370 function GetUnderlyingTransport: ITransport;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100371 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +0200372 function GetIsOpen: Boolean; override;
373 procedure Flush; override;
Jens Geyer41f47af2019-11-09 23:24:52 +0100374 procedure CheckReadBytesAvailable( const value : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200375 public
Jens Geyered994552019-11-09 23:24:52 +0100376 type
377 TFactory = class( TTransportFactoryImpl )
378 public
379 function GetTransport( const aTransport: ITransport): ITransport; override;
380 end;
381
382 constructor Create( const aTransport : IStreamTransport; const aBufSize: Integer = 1024);
Jens Geyerd5436f52014-10-03 19:50:38 +0200383 procedure Open(); override;
384 procedure Close(); override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200385 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
386 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200387 property UnderlyingTransport: ITransport read GetUnderlyingTransport;
388 property IsOpen: Boolean read GetIsOpen;
389 end;
390
391 TSocketImpl = class(TStreamTransportImpl)
Jens Geyerfad7fd32019-11-09 23:24:52 +0100392 strict private
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200393{$IFDEF OLD_SOCKETS}
394 FClient : TCustomIpClient;
395{$ELSE}
396 FClient: TSocket;
397{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200398 FOwnsClient : Boolean;
399 FHost : string;
400 FPort : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200401{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200402 FTimeout : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200403{$ELSE}
404 FTimeout : Longword;
405{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200406
407 procedure InitSocket;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100408 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +0200409 function GetIsOpen: Boolean; override;
410 public
411 procedure Open; override;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200412{$IFDEF OLD_SOCKETS}
Jens Geyer41f47af2019-11-09 23:24:52 +0100413 constructor Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload;
414 constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200415{$ELSE}
Jens Geyer41f47af2019-11-09 23:24:52 +0100416 constructor Create(const aClient: TSocket; const aOwnsClient: Boolean; const aTransportCtl : ITransportControl = nil); overload;
417 constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200418{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200419 destructor Destroy; override;
420 procedure Close; override;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200421{$IFDEF OLD_SOCKETS}
422 property TcpClient: TCustomIpClient read FClient;
423{$ELSE}
424 property TcpClient: TSocket read FClient;
425{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200426 property Host : string read FHost;
427 property Port: Integer read FPort;
428 end;
429
430 TFramedTransportImpl = class( TTransportImpl)
Jens Geyer2646bd62019-11-09 23:24:52 +0100431 strict protected const
432 DEFAULT_MAX_LENGTH = 16384000; // this value is used by all Thrift libraries
433 strict protected type
434 TFramedHeader = Int32;
Jens Geyerfad7fd32019-11-09 23:24:52 +0100435 strict protected
Jens Geyerd5436f52014-10-03 19:50:38 +0200436 FTransport : ITransport;
437 FWriteBuffer : TMemoryStream;
438 FReadBuffer : TMemoryStream;
Jens Geyer2646bd62019-11-09 23:24:52 +0100439 FMaxFrameSize : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200440
Jens Geyer2646bd62019-11-09 23:24:52 +0100441 procedure InitMaxFrameSize;
Jens Geyerd5436f52014-10-03 19:50:38 +0200442 procedure InitWriteBuffer;
443 procedure ReadFrame;
Jens Geyerd5436f52014-10-03 19:50:38 +0200444
445 procedure Open(); override;
446 function GetIsOpen: Boolean; override;
447
448 procedure Close(); override;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200449 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
450 procedure Write( const pBuf : Pointer; off, len : Integer); override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200451 procedure Flush; override;
Jens Geyer41f47af2019-11-09 23:24:52 +0100452 procedure CheckReadBytesAvailable( const value : Integer); override;
Jens Geyered994552019-11-09 23:24:52 +0100453 public
454 type
455 TFactory = class( TTransportFactoryImpl )
456 public
457 function GetTransport( const aTransport: ITransport): ITransport; override;
458 end;
459
Jens Geyer41f47af2019-11-09 23:24:52 +0100460 constructor Create( const aTransportCtl : ITransportControl); overload;
Jens Geyered994552019-11-09 23:24:52 +0100461 constructor Create( const aTransport: ITransport); overload;
462 destructor Destroy; override;
Jens Geyerd5436f52014-10-03 19:50:38 +0200463 end;
464
Jens Geyerd5436f52014-10-03 19:50:38 +0200465
466const
Jens Geyer47f63172019-06-06 22:42:58 +0200467 DEFAULT_THRIFT_SECUREPROTOCOLS = [ TSecureProtocol.TLS_1_1, TSecureProtocol.TLS_1_2];
468
Jens Geyerd5436f52014-10-03 19:50:38 +0200469implementation
470
Jens Geyered994552019-11-09 23:24:52 +0100471
Jens Geyer41f47af2019-11-09 23:24:52 +0100472{ TTransportControlImpl }
473
474constructor TTransportControlImpl.Create( const aMaxMessageSize : Integer);
475begin
476 inherited Create;
477
478 if aMaxMessageSize > 0
479 then FMaxAllowedMsgSize := aMaxMessageSize
480 else FMaxAllowedMsgSize := DEFAULT_MAX_MESSAGE_SIZE;
481
482 ResetConsumedMessageSize;
483end;
484
485function TTransportControlImpl.MaxAllowedMessageSize : Integer;
486begin
487 result := FMaxAllowedMsgSize;
488end;
489
490procedure TTransportControlImpl.ResetConsumedMessageSize;
491begin
492 FRemainingMsgSize := MaxAllowedMessageSize;
493end;
494
495
496procedure TTransportControlImpl.ConsumeReadBytes( const count : Integer);
497begin
498 if FRemainingMsgSize >= count
499 then Dec( FRemainingMsgSize, count)
500 else begin
501 FRemainingMsgSize := 0;
502 if FRemainingMsgSize < count
503 then raise TTransportExceptionEndOfFile.Create('Maximum message size reached');
504 end;
505end;
506
507
Jens Geyerd5436f52014-10-03 19:50:38 +0200508{ TTransportImpl }
509
Jens Geyer41f47af2019-11-09 23:24:52 +0100510constructor TTransportImpl.Create( const aTransportCtl : ITransportControl);
511begin
512 inherited Create;
513
514 if aTransportCtl <> nil
515 then FTransportControl := aTransportCtl
516 else FTransportControl := TTransportControlImpl.Create;
517 ASSERT( FTransportControl <> nil);
518end;
519
520
Jens Geyerd5436f52014-10-03 19:50:38 +0200521procedure TTransportImpl.Flush;
522begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200523 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +0200524end;
525
526function TTransportImpl.Peek: Boolean;
527begin
528 Result := IsOpen;
529end;
530
Jens Geyer17c3ad92017-09-05 20:31:27 +0200531function TTransportImpl.Read(var buf: TBytes; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +0200532begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200533 if Length(buf) > 0
534 then result := Read( @buf[0], Length(buf), off, len)
535 else result := 0;
Jens Geyer17c3ad92017-09-05 20:31:27 +0200536end;
537
538function TTransportImpl.ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer;
539begin
Jens Geyera76e6c72017-09-08 21:03:30 +0200540 if Length(buf) > 0
541 then result := ReadAll( @buf[0], Length(buf), off, len)
542 else result := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +0200543end;
544
Jens Geyer17c3ad92017-09-05 20:31:27 +0200545function TTransportImpl.ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
546var ret : Integer;
547begin
548 result := 0;
549 while result < len do begin
550 ret := Read( pBuf, buflen, off + result, len - result);
551 if ret > 0
552 then Inc( result, ret)
553 else raise TTransportExceptionNotOpen.Create( 'Cannot read, Remote side has closed' );
554 end;
555end;
556
Jens Geyered994552019-11-09 23:24:52 +0100557procedure TTransportImpl.Write( const buf: TBytes);
558begin
559 if Length(buf) > 0
560 then Write( @buf[0], 0, Length(buf));
561end;
562
563procedure TTransportImpl.Write( const buf: TBytes; off: Integer; len: Integer);
564begin
565 if Length(buf) > 0
566 then Write( @buf[0], off, len);
567end;
568
Jens Geyer17c3ad92017-09-05 20:31:27 +0200569procedure TTransportImpl.Write( const pBuf : Pointer; len : Integer);
570begin
571 Self.Write( pBuf, 0, len);
Jens Geyerd5436f52014-10-03 19:50:38 +0200572end;
573
Jens Geyered994552019-11-09 23:24:52 +0100574
Jens Geyer41f47af2019-11-09 23:24:52 +0100575function TTransportImpl.TransportControl : ITransportControl;
576begin
577 result := FTransportControl;
578end;
579
580
581procedure TTransportImpl.ConsumeReadBytes( const count : Integer);
582begin
583 if FTransportControl <> nil
584 then FTransportControl.ConsumeReadBytes( count);
585end;
586
587
Jens Geyerd5436f52014-10-03 19:50:38 +0200588{ TTransportException }
589
Jens Geyere0e32402016-04-20 21:50:48 +0200590constructor TTransportException.HiddenCreate(const Msg: string);
591begin
592 inherited Create(Msg);
593end;
594
Jens Geyered994552019-11-09 23:24:52 +0100595class function TTransportException.Create(aType: TExceptionType): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200596begin
597 //no inherited;
Jens Geyere0e32402016-04-20 21:50:48 +0200598{$WARN SYMBOL_DEPRECATED OFF}
Jens Geyered994552019-11-09 23:24:52 +0100599 Result := Create(aType, '')
Jens Geyere0e32402016-04-20 21:50:48 +0200600{$WARN SYMBOL_DEPRECATED DEFAULT}
Jens Geyerd5436f52014-10-03 19:50:38 +0200601end;
602
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100603class function TTransportException.Create(aType: TExceptionType; const msg: string): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200604begin
Jens Geyered994552019-11-09 23:24:52 +0100605 case aType of
Jens Geyere0e32402016-04-20 21:50:48 +0200606 TExceptionType.NotOpen: Result := TTransportExceptionNotOpen.Create(msg);
607 TExceptionType.AlreadyOpen: Result := TTransportExceptionAlreadyOpen.Create(msg);
608 TExceptionType.TimedOut: Result := TTransportExceptionTimedOut.Create(msg);
609 TExceptionType.EndOfFile: Result := TTransportExceptionEndOfFile.Create(msg);
610 TExceptionType.BadArgs: Result := TTransportExceptionBadArgs.Create(msg);
611 TExceptionType.Interrupted: Result := TTransportExceptionInterrupted.Create(msg);
612 else
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100613 ASSERT( TExceptionType.Unknown = aType);
Jens Geyere0e32402016-04-20 21:50:48 +0200614 Result := TTransportExceptionUnknown.Create(msg);
615 end;
Jens Geyerd5436f52014-10-03 19:50:38 +0200616end;
617
Jens Geyere0e32402016-04-20 21:50:48 +0200618class function TTransportException.Create(const msg: string): TTransportException;
Jens Geyerd5436f52014-10-03 19:50:38 +0200619begin
Jens Geyere0e32402016-04-20 21:50:48 +0200620 Result := TTransportExceptionUnknown.Create(Msg);
621end;
622
623{ TTransportExceptionSpecialized }
624
625constructor TTransportExceptionSpecialized.Create(const Msg: string);
626begin
627 inherited HiddenCreate(Msg);
Jens Geyerd5436f52014-10-03 19:50:38 +0200628end;
629
Jens Geyer9f11c1e2019-11-09 19:39:20 +0100630{ specialized TTransportExceptions }
631
632class function TTransportExceptionUnknown.GetType: TTransportException.TExceptionType;
633begin
634 result := TExceptionType.Unknown;
635end;
636
637class function TTransportExceptionNotOpen.GetType: TTransportException.TExceptionType;
638begin
639 result := TExceptionType.NotOpen;
640end;
641
642class function TTransportExceptionAlreadyOpen.GetType: TTransportException.TExceptionType;
643begin
644 result := TExceptionType.AlreadyOpen;
645end;
646
647class function TTransportExceptionTimedOut.GetType: TTransportException.TExceptionType;
648begin
649 result := TExceptionType.TimedOut;
650end;
651
652class function TTransportExceptionEndOfFile.GetType: TTransportException.TExceptionType;
653begin
654 result := TExceptionType.EndOfFile;
655end;
656
657class function TTransportExceptionBadArgs.GetType: TTransportException.TExceptionType;
658begin
659 result := TExceptionType.BadArgs;
660end;
661
662class function TTransportExceptionInterrupted.GetType: TTransportException.TExceptionType;
663begin
664 result := TExceptionType.Interrupted;
665end;
666
Jens Geyer2646bd62019-11-09 23:24:52 +0100667class function TTransportExceptionCorruptedData.GetType: TTransportException.TExceptionType;
668begin
669 result := TExceptionType.CorruptedData;
670end;
671
Jens Geyerd5436f52014-10-03 19:50:38 +0200672{ TTransportFactoryImpl }
673
Jens Geyered994552019-11-09 23:24:52 +0100674function TTransportFactoryImpl.GetTransport( const aTransport: ITransport): ITransport;
Jens Geyerd5436f52014-10-03 19:50:38 +0200675begin
Jens Geyered994552019-11-09 23:24:52 +0100676 Result := aTransport;
Jens Geyerd5436f52014-10-03 19:50:38 +0200677end;
678
679{ TServerSocket }
680
Jens Geyer23d67462015-12-19 11:44:57 +0100681{$IFDEF OLD_SOCKETS}
Jens Geyer41f47af2019-11-09 23:24:52 +0100682constructor TServerSocketImpl.Create( const aServer: TTcpServer; const aClientTimeout : Integer; const aTransportCtl : ITransportControl);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200683{$ELSE}
Jens Geyer41f47af2019-11-09 23:24:52 +0100684constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClientTimeout: Longword; const aTransportCtl : ITransportControl);
Jens Geyered994552019-11-09 23:24:52 +0100685{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200686begin
687 inherited Create;
Jens Geyered994552019-11-09 23:24:52 +0100688 FServer := aServer;
Jens Geyer41f47af2019-11-09 23:24:52 +0100689 FTransportControl := aTransportCtl;
690 ASSERT( FTransportControl <> nil);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200691
692{$IFDEF OLD_SOCKETS}
Jens Geyered994552019-11-09 23:24:52 +0100693 FClientTimeout := aClientTimeout;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200694{$ELSE}
Jens Geyered994552019-11-09 23:24:52 +0100695 FServer.RecvTimeout := aClientTimeout;
696 FServer.SendTimeout := aClientTimeout;
697{$ENDIF}
698end;
699
700
701{$IFDEF OLD_SOCKETS}
Jens Geyer41f47af2019-11-09 23:24:52 +0100702constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Integer; aUseBufferedSockets: Boolean; const aTransportCtl : ITransportControl);
Jens Geyered994552019-11-09 23:24:52 +0100703{$ELSE}
Jens Geyer41f47af2019-11-09 23:24:52 +0100704constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Longword; aUseBufferedSockets: Boolean; const aTransportCtl : ITransportControl);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200705{$ENDIF}
706begin
707 inherited Create;
Jens Geyered994552019-11-09 23:24:52 +0100708
Jens Geyer41f47af2019-11-09 23:24:52 +0100709 if aTransportCtl <> nil
710 then FTransportControl := aTransportCtl
711 else FTransportControl := TTransportControlImpl.Create;
712 ASSERT( FTransportControl <> nil);
713
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200714{$IFDEF OLD_SOCKETS}
Jens Geyered994552019-11-09 23:24:52 +0100715 FPort := aPort;
716 FClientTimeout := aClientTimeout;
717
718 FOwnsServer := True;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200719 FServer := TTcpServer.Create( nil );
Jens Geyerd5436f52014-10-03 19:50:38 +0200720 FServer.BlockMode := bmBlocking;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200721 {$IF CompilerVersion >= 21.0}
Jens Geyerd5436f52014-10-03 19:50:38 +0200722 FServer.LocalPort := AnsiString( IntToStr( FPort));
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200723 {$ELSE}
Jens Geyerd5436f52014-10-03 19:50:38 +0200724 FServer.LocalPort := IntToStr( FPort);
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200725 {$IFEND}
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200726{$ELSE}
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200727 FOwnsServer := True;
Jens Geyered994552019-11-09 23:24:52 +0100728 FServer := TServerSocket.Create(aPort, aClientTimeout, aClientTimeout);
729{$ENDIF}
730
731 FUseBufferedSocket := aUseBufferedSockets;
Jens Geyerd5436f52014-10-03 19:50:38 +0200732end;
733
734destructor TServerSocketImpl.Destroy;
735begin
736 if FOwnsServer then begin
737 FServer.Free;
738 FServer := nil;
739 end;
740 inherited;
741end;
742
743function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport;
744var
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200745{$IFDEF OLD_SOCKETS}
746 client : TCustomIpClient;
747{$ELSE}
748 client: TSocket;
749{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200750 trans : IStreamTransport;
751begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100752 if FServer = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200753 raise TTransportExceptionNotOpen.Create('No underlying server socket.');
Jens Geyerd5436f52014-10-03 19:50:38 +0200754 end;
755
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200756{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200757 client := nil;
758 try
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200759 client := TCustomIpClient.Create(nil);
Jens Geyerd5436f52014-10-03 19:50:38 +0200760
761 if Assigned(fnAccepting)
762 then fnAccepting();
763
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100764 if not FServer.Accept( client) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200765 client.Free;
766 Result := nil;
767 Exit;
768 end;
769
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100770 if client = nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200771 Result := nil;
772 Exit;
773 end;
774
Jens Geyer41f47af2019-11-09 23:24:52 +0100775 trans := TSocketImpl.Create( client, TRUE, FClientTimeout, TransportControl);
Jens Geyerd5436f52014-10-03 19:50:38 +0200776 client := nil; // trans owns it now
777
778 if FUseBufferedSocket
779 then result := TBufferedTransportImpl.Create( trans)
780 else result := trans;
781
782 except
783 on E: Exception do begin
784 client.Free;
Jens Geyere0e32402016-04-20 21:50:48 +0200785 raise TTransportExceptionUnknown.Create(E.ToString);
Jens Geyerd5436f52014-10-03 19:50:38 +0200786 end;
787 end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200788{$ELSE}
789 if Assigned(fnAccepting) then
790 fnAccepting();
791
792 client := FServer.Accept;
793 try
Jens Geyer41f47af2019-11-09 23:24:52 +0100794 trans := TSocketImpl.Create(client, True, TransportControl);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200795 client := nil;
796
797 if FUseBufferedSocket then
798 Result := TBufferedTransportImpl.Create(trans)
799 else
800 Result := trans;
801 except
802 client.Free;
803 raise;
804 end;
805{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200806end;
807
808procedure TServerSocketImpl.Listen;
809begin
810 if FServer <> nil then
811 begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200812{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200813 try
814 FServer.Active := True;
815 except
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200816 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200817 do raise TTransportExceptionUnknown.Create('Could not accept on listening socket: ' + E.Message);
Jens Geyerd5436f52014-10-03 19:50:38 +0200818 end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200819{$ELSE}
820 FServer.Listen;
821{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200822 end;
823end;
824
825procedure TServerSocketImpl.Close;
826begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200827 if FServer <> nil then
828{$IFDEF OLD_SOCKETS}
829 try
830 FServer.Active := False;
831 except
832 on E: Exception
Jens Geyere0e32402016-04-20 21:50:48 +0200833 do raise TTransportExceptionUnknown.Create('Error on closing socket : ' + E.Message);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200834 end;
835{$ELSE}
836 FServer.Close;
837{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200838end;
839
840{ TSocket }
841
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200842{$IFDEF OLD_SOCKETS}
Jens Geyer41f47af2019-11-09 23:24:52 +0100843constructor TSocketImpl.Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer; const aTransportCtl : ITransportControl);
Jens Geyered994552019-11-09 23:24:52 +0100844{$ELSE}
Jens Geyer41f47af2019-11-09 23:24:52 +0100845constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolean; const aTransportCtl : ITransportControl);
Jens Geyered994552019-11-09 23:24:52 +0100846{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200847var stream : IThriftStream;
848begin
Jens Geyered994552019-11-09 23:24:52 +0100849 FClient := aClient;
Jens Geyerd5436f52014-10-03 19:50:38 +0200850 FOwnsClient := aOwnsClient;
Jens Geyered994552019-11-09 23:24:52 +0100851
852{$IFDEF OLD_SOCKETS}
853 FTimeout := aTimeout;
854{$ELSE}
855 FTimeout := aClient.RecvTimeout;
856{$ENDIF}
857
Jens Geyerd5436f52014-10-03 19:50:38 +0200858 stream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
Jens Geyer41f47af2019-11-09 23:24:52 +0100859 inherited Create( stream, stream, aTransportCtl);
Jens Geyerd5436f52014-10-03 19:50:38 +0200860end;
861
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200862{$IFDEF OLD_SOCKETS}
Jens Geyer41f47af2019-11-09 23:24:52 +0100863constructor TSocketImpl.Create(const aHost: string; const aPort, aTimeout: Integer; const aTransportCtl : ITransportControl);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200864{$ELSE}
Jens Geyer41f47af2019-11-09 23:24:52 +0100865constructor TSocketImpl.Create(const aHost: string; const aPort : Integer; const aTimeout: Longword; const aTransportCtl : ITransportControl);
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200866{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200867begin
Jens Geyer41f47af2019-11-09 23:24:52 +0100868 inherited Create(nil,nil, aTransportCtl);
Jens Geyered994552019-11-09 23:24:52 +0100869 FHost := aHost;
870 FPort := aPort;
871 FTimeout := aTimeout;
Jens Geyerd5436f52014-10-03 19:50:38 +0200872 InitSocket;
873end;
874
875destructor TSocketImpl.Destroy;
876begin
877 if FOwnsClient
878 then FreeAndNil( FClient);
879 inherited;
880end;
881
882procedure TSocketImpl.Close;
883begin
884 inherited Close;
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200885
886 FInputStream := nil;
887 FOutputStream := nil;
888
Jens Geyerd5436f52014-10-03 19:50:38 +0200889 if FOwnsClient
Jens Geyer3c0edfa2018-04-02 13:57:55 +0200890 then FreeAndNil( FClient)
891 else FClient := nil;
Jens Geyerd5436f52014-10-03 19:50:38 +0200892end;
893
894function TSocketImpl.GetIsOpen: Boolean;
895begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200896{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200897 Result := (FClient <> nil) and FClient.Connected;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200898{$ELSE}
899 Result := (FClient <> nil) and FClient.IsOpen
900{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200901end;
902
903procedure TSocketImpl.InitSocket;
904var
905 stream : IThriftStream;
906begin
907 if FOwnsClient
908 then FreeAndNil( FClient)
909 else FClient := nil;
910
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200911{$IFDEF OLD_SOCKETS}
912 FClient := TTcpClient.Create( nil);
913{$ELSE}
914 FClient := TSocket.Create(FHost, FPort);
915{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200916 FOwnsClient := True;
917
918 stream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
919 FInputStream := stream;
920 FOutputStream := stream;
921end;
922
923procedure TSocketImpl.Open;
924begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100925 if IsOpen then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200926 raise TTransportExceptionAlreadyOpen.Create('Socket already connected');
Jens Geyerd5436f52014-10-03 19:50:38 +0200927 end;
928
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100929 if FHost = '' then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200930 raise TTransportExceptionNotOpen.Create('Cannot open null host');
Jens Geyerd5436f52014-10-03 19:50:38 +0200931 end;
932
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100933 if Port <= 0 then begin
Jens Geyere0e32402016-04-20 21:50:48 +0200934 raise TTransportExceptionNotOpen.Create('Cannot open without port');
Jens Geyerd5436f52014-10-03 19:50:38 +0200935 end;
936
Jens Geyer6f6aa8a2016-03-10 19:47:12 +0100937 if FClient = nil
938 then InitSocket;
Jens Geyerd5436f52014-10-03 19:50:38 +0200939
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200940{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +0200941 FClient.RemoteHost := TSocketHost( Host);
942 FClient.RemotePort := TSocketPort( IntToStr( Port));
943 FClient.Connect;
Jens Geyerbea9bbe2016-04-20 00:02:40 +0200944{$ELSE}
945 FClient.Open;
946{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +0200947
948 FInputStream := TTcpSocketStreamImpl.Create( FClient, FTimeout);
949 FOutputStream := FInputStream;
950end;
951
952{ TBufferedStream }
953
954procedure TBufferedStreamImpl.Close;
955begin
956 Flush;
957 FStream := nil;
958
959 FReadBuffer.Free;
960 FReadBuffer := nil;
961
962 FWriteBuffer.Free;
963 FWriteBuffer := nil;
964end;
965
Jens Geyered994552019-11-09 23:24:52 +0100966constructor TBufferedStreamImpl.Create( const aStream: IThriftStream; const aBufSize : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +0200967begin
968 inherited Create;
Jens Geyered994552019-11-09 23:24:52 +0100969 FStream := aStream;
970 FBufSize := aBufSize;
Jens Geyerd5436f52014-10-03 19:50:38 +0200971 FReadBuffer := TMemoryStream.Create;
972 FWriteBuffer := TMemoryStream.Create;
973end;
974
975destructor TBufferedStreamImpl.Destroy;
976begin
977 Close;
978 inherited;
979end;
980
981procedure TBufferedStreamImpl.Flush;
982var
983 buf : TBytes;
984 len : Integer;
985begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200986 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200987 len := FWriteBuffer.Size;
Jens Geyer9f7f11e2016-04-14 21:37:11 +0200988 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +0200989 SetLength( buf, len );
990 FWriteBuffer.Position := 0;
991 FWriteBuffer.Read( Pointer(@buf[0])^, len );
992 FStream.Write( buf, 0, len );
993 end;
994 FWriteBuffer.Clear;
995 end;
996end;
997
998function TBufferedStreamImpl.IsOpen: Boolean;
999begin
1000 Result := (FWriteBuffer <> nil)
1001 and (FReadBuffer <> nil)
Jens Geyer3c0edfa2018-04-02 13:57:55 +02001002 and (FStream <> nil)
1003 and FStream.IsOpen;
Jens Geyerd5436f52014-10-03 19:50:38 +02001004end;
1005
1006procedure TBufferedStreamImpl.Open;
1007begin
Jens Geyer3c0edfa2018-04-02 13:57:55 +02001008 FStream.Open;
Jens Geyerd5436f52014-10-03 19:50:38 +02001009end;
1010
Jens Geyer17c3ad92017-09-05 20:31:27 +02001011function TBufferedStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001012var
1013 nRead : Integer;
1014 tempbuf : TBytes;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001015 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001016begin
1017 inherited;
1018 Result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001019
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001020 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001021 while count > 0 do begin
1022
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001023 if FReadBuffer.Position >= FReadBuffer.Size then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001024 FReadBuffer.Clear;
1025 SetLength( tempbuf, FBufSize);
1026 nRead := FStream.Read( tempbuf, 0, FBufSize );
1027 if nRead = 0 then Break; // avoid infinite loop
1028
1029 FReadBuffer.WriteBuffer( Pointer(@tempbuf[0])^, nRead );
1030 FReadBuffer.Position := 0;
1031 end;
1032
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001033 if FReadBuffer.Position < FReadBuffer.Size then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001034 nRead := Min( FReadBuffer.Size - FReadBuffer.Position, count);
1035 pTmp := pBuf;
1036 Inc( pTmp, offset);
1037 Inc( Result, FReadBuffer.Read( pTmp^, nRead));
Jens Geyerd5436f52014-10-03 19:50:38 +02001038 Dec( count, nRead);
1039 Inc( offset, nRead);
1040 end;
1041 end;
1042 end;
1043end;
1044
Jens Geyered994552019-11-09 23:24:52 +01001045
Jens Geyer41f47af2019-11-09 23:24:52 +01001046procedure TBufferedStreamImpl.CheckReadBytesAvailable( const value : Integer);
1047var nRequired : Integer;
1048begin
1049 nRequired := value;
1050
1051 if FReadBuffer <> nil then begin
1052 Dec( nRequired, (FReadBuffer.Position - FReadBuffer.Size));
1053 if nRequired <= 0 then Exit;
1054 end;
1055
1056 if FStream <> nil
1057 then FStream.CheckReadBytesAvailable( nRequired)
1058 else raise TTransportExceptionEndOfFile.Create('Not enough input data');
1059end;
1060
1061
Jens Geyerd5436f52014-10-03 19:50:38 +02001062function TBufferedStreamImpl.ToArray: TBytes;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001063var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001064begin
1065 len := 0;
1066
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001067 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001068 len := FReadBuffer.Size;
1069 end;
1070
1071 SetLength( Result, len);
1072
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001073 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001074 FReadBuffer.Position := 0;
1075 FReadBuffer.Read( Pointer(@Result[0])^, len );
1076 end;
1077end;
1078
Jens Geyer17c3ad92017-09-05 20:31:27 +02001079procedure TBufferedStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001080var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001081begin
1082 inherited;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001083 if count > 0 then begin
1084 if IsOpen then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001085 pTmp := pBuf;
1086 Inc( pTmp, offset);
1087 FWriteBuffer.Write( pTmp^, count );
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001088 if FWriteBuffer.Size > FBufSize then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001089 Flush;
1090 end;
1091 end;
1092 end;
1093end;
1094
1095{ TStreamTransportImpl }
1096
Jens Geyer41f47af2019-11-09 23:24:52 +01001097constructor TStreamTransportImpl.Create( const aInputStream, aOutputStream : IThriftStream; const aTransportCtl : ITransportControl);
Jens Geyerd5436f52014-10-03 19:50:38 +02001098begin
Jens Geyer41f47af2019-11-09 23:24:52 +01001099 inherited Create( aTransportCtl);
Jens Geyered994552019-11-09 23:24:52 +01001100 FInputStream := aInputStream;
1101 FOutputStream := aOutputStream;
Jens Geyerd5436f52014-10-03 19:50:38 +02001102end;
1103
1104destructor TStreamTransportImpl.Destroy;
1105begin
1106 FInputStream := nil;
1107 FOutputStream := nil;
1108 inherited;
1109end;
1110
Jens Geyer20e727e2018-06-22 22:39:57 +02001111procedure TStreamTransportImpl.Close;
1112begin
1113 FInputStream := nil;
1114 FOutputStream := nil;
1115end;
1116
Jens Geyerd5436f52014-10-03 19:50:38 +02001117procedure TStreamTransportImpl.Flush;
1118begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001119 if FOutputStream = nil then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001120 raise TTransportExceptionNotOpen.Create('Cannot flush null outputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001121 end;
1122
1123 FOutputStream.Flush;
1124end;
1125
1126function TStreamTransportImpl.GetInputStream: IThriftStream;
1127begin
1128 Result := FInputStream;
1129end;
1130
1131function TStreamTransportImpl.GetIsOpen: Boolean;
1132begin
1133 Result := True;
1134end;
1135
1136function TStreamTransportImpl.GetOutputStream: IThriftStream;
1137begin
Jens Geyer02fbe0e2018-03-19 17:35:44 +01001138 Result := FOutputStream;
Jens Geyerd5436f52014-10-03 19:50:38 +02001139end;
1140
1141procedure TStreamTransportImpl.Open;
1142begin
Jens Geyer2646bd62019-11-09 23:24:52 +01001143 // nothing to do
Jens Geyerd5436f52014-10-03 19:50:38 +02001144end;
1145
Jens Geyer17c3ad92017-09-05 20:31:27 +02001146function TStreamTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001147begin
Jens Geyered994552019-11-09 23:24:52 +01001148 if FInputStream = nil
1149 then raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' );
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001150
Jens Geyer17c3ad92017-09-05 20:31:27 +02001151 Result := FInputStream.Read( pBuf,buflen, off, len );
Jens Geyer41f47af2019-11-09 23:24:52 +01001152 ConsumeReadBytes( result);
Jens Geyerd5436f52014-10-03 19:50:38 +02001153end;
1154
Jens Geyer17c3ad92017-09-05 20:31:27 +02001155procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001156begin
Jens Geyered994552019-11-09 23:24:52 +01001157 if FOutputStream = nil
1158 then raise TTransportExceptionNotOpen.Create('Cannot write to null outputstream' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001159
Jens Geyer17c3ad92017-09-05 20:31:27 +02001160 FOutputStream.Write( pBuf, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +02001161end;
1162
Jens Geyer41f47af2019-11-09 23:24:52 +01001163procedure TStreamTransportImpl.CheckReadBytesAvailable( const value : Integer);
1164begin
1165 if FInputStream <> nil
1166 then FInputStream.CheckReadBytesAvailable( value)
1167 else raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' );
1168end;
1169
Jens Geyered994552019-11-09 23:24:52 +01001170
Jens Geyerd5436f52014-10-03 19:50:38 +02001171{ TBufferedTransportImpl }
1172
Jens Geyered994552019-11-09 23:24:52 +01001173constructor TBufferedTransportImpl.Create( const aTransport : IStreamTransport; const aBufSize: Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001174begin
Jens Geyered994552019-11-09 23:24:52 +01001175 ASSERT( aTransport <> nil);
Jens Geyer41f47af2019-11-09 23:24:52 +01001176 inherited Create( aTransport.TransportControl);
Jens Geyered994552019-11-09 23:24:52 +01001177 FTransport := aTransport;
1178 FBufSize := aBufSize;
Jens Geyerd5436f52014-10-03 19:50:38 +02001179 InitBuffers;
1180end;
1181
Jens Geyer3c0edfa2018-04-02 13:57:55 +02001182procedure TBufferedTransportImpl.Close;
1183begin
1184 FTransport.Close;
1185 FInputBuffer := nil;
Jens Geyered994552019-11-09 23:24:52 +01001186 FOutputBuffer := nil;
Jens Geyer3c0edfa2018-04-02 13:57:55 +02001187end;
1188
Jens Geyerd5436f52014-10-03 19:50:38 +02001189procedure TBufferedTransportImpl.Flush;
1190begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001191 if FOutputBuffer <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001192 FOutputBuffer.Flush;
1193 end;
1194end;
1195
1196function TBufferedTransportImpl.GetIsOpen: Boolean;
1197begin
1198 Result := FTransport.IsOpen;
1199end;
1200
1201function TBufferedTransportImpl.GetUnderlyingTransport: ITransport;
1202begin
1203 Result := FTransport;
1204end;
1205
1206procedure TBufferedTransportImpl.InitBuffers;
1207begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001208 if FTransport.InputStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001209 FInputBuffer := TBufferedStreamImpl.Create( FTransport.InputStream, FBufSize );
1210 end;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001211 if FTransport.OutputStream <> nil then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001212 FOutputBuffer := TBufferedStreamImpl.Create( FTransport.OutputStream, FBufSize );
1213 end;
1214end;
1215
1216procedure TBufferedTransportImpl.Open;
1217begin
Jens Geyera0cf38e2018-04-04 17:31:52 +02001218 FTransport.Open;
Jens Geyer3c0edfa2018-04-02 13:57:55 +02001219 InitBuffers; // we need to get the buffers to match FTransport substreams again
Jens Geyerd5436f52014-10-03 19:50:38 +02001220end;
1221
Jens Geyer17c3ad92017-09-05 20:31:27 +02001222function TBufferedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001223begin
Jens Geyered994552019-11-09 23:24:52 +01001224 if FInputBuffer <> nil
1225 then Result := FInputBuffer.Read( pBuf,buflen, off, len)
1226 else Result := 0;
Jens Geyerd5436f52014-10-03 19:50:38 +02001227end;
1228
Jens Geyer17c3ad92017-09-05 20:31:27 +02001229procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001230begin
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001231 if FOutputBuffer <> nil then begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001232 FOutputBuffer.Write( pBuf, off, len );
Jens Geyerd5436f52014-10-03 19:50:38 +02001233 end;
1234end;
1235
Jens Geyer41f47af2019-11-09 23:24:52 +01001236procedure TBufferedTransportImpl.CheckReadBytesAvailable( const value : Integer);
1237var stm2 : IThriftStream2;
1238 need : Integer;
1239begin
1240 need := value;
1241
1242 // buffered bytes
1243 if Supports( FInputBuffer, IThriftStream2, stm2) then begin
1244 Dec( need, stm2.Size - stm2.Position);
1245 if need <= 0 then Exit;
1246 end;
1247
1248 if FInputBuffer <> nil
1249 then FInputBuffer.CheckReadBytesAvailable( need)
1250 else raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' );
1251end;
1252
Jens Geyered994552019-11-09 23:24:52 +01001253{ TBufferedTransportImpl.TFactory }
Jens Geyerd5436f52014-10-03 19:50:38 +02001254
Jens Geyered994552019-11-09 23:24:52 +01001255function TBufferedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport;
Jens Geyerd5436f52014-10-03 19:50:38 +02001256begin
Jens Geyered994552019-11-09 23:24:52 +01001257 Result := TFramedTransportImpl.Create( aTransport);
Jens Geyerd5436f52014-10-03 19:50:38 +02001258end;
1259
Jens Geyered994552019-11-09 23:24:52 +01001260
1261{ TFramedTransportImpl }
1262
Jens Geyer41f47af2019-11-09 23:24:52 +01001263constructor TFramedTransportImpl.Create( const aTransportCtl : ITransportControl);
1264begin
1265 inherited Create( aTransportCtl);
1266
1267 InitMaxFrameSize;
1268 InitWriteBuffer;
1269end;
1270
Jens Geyered994552019-11-09 23:24:52 +01001271constructor TFramedTransportImpl.Create( const aTransport: ITransport);
Jens Geyerd5436f52014-10-03 19:50:38 +02001272begin
Jens Geyered994552019-11-09 23:24:52 +01001273 ASSERT( aTransport <> nil);
Jens Geyer41f47af2019-11-09 23:24:52 +01001274 inherited Create( aTransport.TransportControl);
Jens Geyer2646bd62019-11-09 23:24:52 +01001275
1276 InitMaxFrameSize;
Jens Geyerd5436f52014-10-03 19:50:38 +02001277 InitWriteBuffer;
Jens Geyered994552019-11-09 23:24:52 +01001278 FTransport := aTransport;
Jens Geyerd5436f52014-10-03 19:50:38 +02001279end;
1280
1281destructor TFramedTransportImpl.Destroy;
1282begin
1283 FWriteBuffer.Free;
1284 FReadBuffer.Free;
1285 inherited;
1286end;
1287
Jens Geyer2646bd62019-11-09 23:24:52 +01001288procedure TFramedTransportImpl.InitMaxFrameSize;
Jens Geyer41f47af2019-11-09 23:24:52 +01001289var maxLen : Integer;
Jens Geyer2646bd62019-11-09 23:24:52 +01001290begin
1291 FMaxFrameSize := DEFAULT_MAX_LENGTH;
Jens Geyer41f47af2019-11-09 23:24:52 +01001292
1293 // MaxAllowedMessageSize may be smaller, but not larger
1294 if TransportControl <> nil then begin
1295 maxLen := TransportControl.MaxAllowedMessageSize - SizeOf(TFramedHeader);
1296 FMaxFrameSize := Min( FMaxFrameSize, maxLen);
1297 end;
Jens Geyer2646bd62019-11-09 23:24:52 +01001298end;
1299
1300procedure TFramedTransportImpl.Close;
1301begin
1302 FTransport.Close;
1303end;
1304
Jens Geyerd5436f52014-10-03 19:50:38 +02001305procedure TFramedTransportImpl.Flush;
1306var
1307 buf : TBytes;
1308 len : Integer;
1309 data_len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001310begin
Jens Geyer528a0f02019-11-18 20:17:03 +01001311 if not IsOpen
1312 then raise TTransportExceptionNotOpen.Create('not open');
1313
Jens Geyerd5436f52014-10-03 19:50:38 +02001314 len := FWriteBuffer.Size;
1315 SetLength( buf, len);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001316 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001317 System.Move( FWriteBuffer.Memory^, buf[0], len );
1318 end;
1319
Jens Geyer2646bd62019-11-09 23:24:52 +01001320 data_len := len - SizeOf(TFramedHeader);
Jens Geyer30ed90e2016-03-10 20:12:49 +01001321 if (data_len < 0) then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001322 raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: data_len < 0' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001323 end;
1324
1325 InitWriteBuffer;
1326
1327 buf[0] := Byte($FF and (data_len shr 24));
1328 buf[1] := Byte($FF and (data_len shr 16));
1329 buf[2] := Byte($FF and (data_len shr 8));
1330 buf[3] := Byte($FF and data_len);
1331
1332 FTransport.Write( buf, 0, len );
1333 FTransport.Flush;
1334end;
1335
1336function TFramedTransportImpl.GetIsOpen: Boolean;
1337begin
1338 Result := FTransport.IsOpen;
1339end;
1340
1341type
1342 TAccessMemoryStream = class(TMemoryStream)
1343 end;
1344
1345procedure TFramedTransportImpl.InitWriteBuffer;
Jens Geyer2646bd62019-11-09 23:24:52 +01001346const DUMMY_HEADER : TFramedHeader = 0;
Jens Geyerd5436f52014-10-03 19:50:38 +02001347begin
Jens Geyer528a0f02019-11-18 20:17:03 +01001348 FreeAndNil( FWriteBuffer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001349 FWriteBuffer := TMemoryStream.Create;
1350 TAccessMemoryStream(FWriteBuffer).Capacity := 1024;
Jens Geyer2646bd62019-11-09 23:24:52 +01001351 FWriteBuffer.Write( DUMMY_HEADER, SizeOf(DUMMY_HEADER));
Jens Geyerd5436f52014-10-03 19:50:38 +02001352end;
1353
1354procedure TFramedTransportImpl.Open;
1355begin
1356 FTransport.Open;
1357end;
1358
Jens Geyer17c3ad92017-09-05 20:31:27 +02001359function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001360var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001361begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001362 if len > (buflen-off)
1363 then len := buflen-off;
1364
Jens Geyer5089b0a2018-02-01 22:37:18 +01001365 pTmp := pBuf;
1366 Inc( pTmp, off);
1367
Jens Geyer17c3ad92017-09-05 20:31:27 +02001368 if (FReadBuffer <> nil) and (len > 0) then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001369 result := FReadBuffer.Read( pTmp^, len);
Jens Geyered994552019-11-09 23:24:52 +01001370 if result > 0 then Exit;
Jens Geyerd5436f52014-10-03 19:50:38 +02001371 end;
1372
1373 ReadFrame;
1374 if len > 0
Jens Geyer5089b0a2018-02-01 22:37:18 +01001375 then Result := FReadBuffer.Read( pTmp^, len)
Jens Geyerd5436f52014-10-03 19:50:38 +02001376 else Result := 0;
1377end;
1378
1379procedure TFramedTransportImpl.ReadFrame;
1380var
Jens Geyer2646bd62019-11-09 23:24:52 +01001381 i32rd : packed array[0..SizeOf(TFramedHeader)-1] of Byte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001382 size : Integer;
1383 buff : TBytes;
1384begin
Jens Geyer2646bd62019-11-09 23:24:52 +01001385 FTransport.ReadAll( @i32rd[0], SizeOf(i32rd), 0, SizeOf(i32rd));
Jens Geyerd5436f52014-10-03 19:50:38 +02001386 size :=
1387 ((i32rd[0] and $FF) shl 24) or
1388 ((i32rd[1] and $FF) shl 16) or
1389 ((i32rd[2] and $FF) shl 8) or
1390 (i32rd[3] and $FF);
Jens Geyer2646bd62019-11-09 23:24:52 +01001391
1392 if size < 0 then begin
1393 Close();
1394 raise TTransportExceptionCorruptedData.Create('Read a negative frame size ('+IntToStr(size)+')');
1395 end;
1396
1397 if size > FMaxFrameSize then begin
1398 Close();
1399 raise TTransportExceptionCorruptedData.Create('Frame size ('+IntToStr(size)+') larger than allowed maximum ('+IntToStr(FMaxFrameSize)+')');
1400 end;
1401
Jens Geyer41f47af2019-11-09 23:24:52 +01001402 FTransport.CheckReadBytesAvailable( size);
Jens Geyerd5436f52014-10-03 19:50:38 +02001403 SetLength( buff, size );
1404 FTransport.ReadAll( buff, 0, size );
Jens Geyered994552019-11-09 23:24:52 +01001405
1406 FreeAndNil( FReadBuffer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001407 FReadBuffer := TMemoryStream.Create;
Jens Geyera76e6c72017-09-08 21:03:30 +02001408 if Length(buff) > 0
1409 then FReadBuffer.Write( Pointer(@buff[0])^, size );
Jens Geyerd5436f52014-10-03 19:50:38 +02001410 FReadBuffer.Position := 0;
1411end;
1412
Jens Geyer17c3ad92017-09-05 20:31:27 +02001413procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001414var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001415begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001416 if len > 0 then begin
1417 pTmp := pBuf;
1418 Inc( pTmp, off);
1419
1420 FWriteBuffer.Write( pTmp^, len );
1421 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001422end;
1423
Jens Geyered994552019-11-09 23:24:52 +01001424
Jens Geyer41f47af2019-11-09 23:24:52 +01001425procedure TFramedTransportImpl.CheckReadBytesAvailable( const value : Integer);
1426var nRemaining : Int64;
1427begin
1428 if FReadBuffer = nil
1429 then raise TTransportExceptionEndOfFile.Create('Cannot read from null inputstream');
1430
1431 nRemaining := FReadBuffer.Size - FReadBuffer.Position;
1432 if value > nRemaining
1433 then raise TTransportExceptionEndOfFile.Create('Not enough input data');
1434end;
1435
1436
Jens Geyerd5436f52014-10-03 19:50:38 +02001437{ TFramedTransport.TFactory }
1438
Jens Geyered994552019-11-09 23:24:52 +01001439function TFramedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport;
Jens Geyerd5436f52014-10-03 19:50:38 +02001440begin
Jens Geyered994552019-11-09 23:24:52 +01001441 Result := TFramedTransportImpl.Create( aTransport);
Jens Geyerd5436f52014-10-03 19:50:38 +02001442end;
1443
1444{ TTcpSocketStreamImpl }
1445
1446procedure TTcpSocketStreamImpl.Close;
1447begin
1448 FTcpClient.Close;
1449end;
1450
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001451{$IFDEF OLD_SOCKETS}
Jens Geyered994552019-11-09 23:24:52 +01001452constructor TTcpSocketStreamImpl.Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001453begin
1454 inherited Create;
Jens Geyered994552019-11-09 23:24:52 +01001455 FTcpClient := aTcpClient;
Jens Geyerd5436f52014-10-03 19:50:38 +02001456 FTimeout := aTimeout;
1457end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001458{$ELSE}
Jens Geyered994552019-11-09 23:24:52 +01001459constructor TTcpSocketStreamImpl.Create( const aTcpClient: TSocket; const aTimeout : Longword);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001460begin
1461 inherited Create;
Jens Geyered994552019-11-09 23:24:52 +01001462 FTcpClient := aTcpClient;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001463 if aTimeout = 0 then
1464 FTcpClient.RecvTimeout := SLEEP_TIME
1465 else
1466 FTcpClient.RecvTimeout := aTimeout;
1467 FTcpClient.SendTimeout := aTimeout;
1468end;
1469{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001470
1471procedure TTcpSocketStreamImpl.Flush;
1472begin
1473
1474end;
1475
1476function TTcpSocketStreamImpl.IsOpen: Boolean;
1477begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001478{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001479 Result := FTcpClient.Active;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001480{$ELSE}
1481 Result := FTcpClient.IsOpen;
1482{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001483end;
1484
1485procedure TTcpSocketStreamImpl.Open;
1486begin
1487 FTcpClient.Open;
1488end;
1489
1490
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001491{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001492function TTcpSocketStreamImpl.Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
1493 TimeOut: Integer; var wsaError : Integer): Integer;
1494var
1495 ReadFds: TFDset;
1496 ReadFdsptr: PFDset;
1497 WriteFds: TFDset;
1498 WriteFdsptr: PFDset;
1499 ExceptFds: TFDset;
1500 ExceptFdsptr: PFDset;
1501 tv: timeval;
1502 Timeptr: PTimeval;
1503 socket : TSocket;
1504begin
1505 if not FTcpClient.Active then begin
1506 wsaError := WSAEINVAL;
1507 Exit( SOCKET_ERROR);
1508 end;
1509
1510 socket := FTcpClient.Handle;
1511
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001512 if Assigned(ReadReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001513 ReadFdsptr := @ReadFds;
1514 FD_ZERO(ReadFds);
1515 FD_SET(socket, ReadFds);
1516 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001517 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001518 ReadFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001519 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001520
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001521 if Assigned(WriteReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001522 WriteFdsptr := @WriteFds;
1523 FD_ZERO(WriteFds);
1524 FD_SET(socket, WriteFds);
1525 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001526 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001527 WriteFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001528 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001529
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001530 if Assigned(ExceptFlag) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001531 ExceptFdsptr := @ExceptFds;
1532 FD_ZERO(ExceptFds);
1533 FD_SET(socket, ExceptFds);
1534 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001535 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001536 ExceptFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001537 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001538
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001539 if TimeOut >= 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001540 tv.tv_sec := TimeOut div 1000;
1541 tv.tv_usec := 1000 * (TimeOut mod 1000);
1542 Timeptr := @tv;
1543 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001544 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001545 Timeptr := nil; // wait forever
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001546 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001547
1548 wsaError := 0;
1549 try
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001550 {$IFDEF MSWINDOWS}
1551 {$IFDEF OLD_UNIT_NAMES}
1552 result := WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1553 {$ELSE}
1554 result := Winapi.WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1555 {$ENDIF}
1556 {$ENDIF}
1557 {$IFDEF LINUX}
1558 result := Libc.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1559 {$ENDIF}
1560
Jens Geyerd5436f52014-10-03 19:50:38 +02001561 if result = SOCKET_ERROR
1562 then wsaError := WSAGetLastError;
1563
1564 except
1565 result := SOCKET_ERROR;
1566 end;
1567
1568 if Assigned(ReadReady) then
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001569 ReadReady^ := FD_ISSET(socket, ReadFds);
1570
Jens Geyerd5436f52014-10-03 19:50:38 +02001571 if Assigned(WriteReady) then
1572 WriteReady^ := FD_ISSET(socket, WriteFds);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001573
Jens Geyerd5436f52014-10-03 19:50:38 +02001574 if Assigned(ExceptFlag) then
1575 ExceptFlag^ := FD_ISSET(socket, ExceptFds);
1576end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001577{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001578
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001579{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001580function TTcpSocketStreamImpl.WaitForData( TimeOut : Integer; pBuf : Pointer;
1581 DesiredBytes : Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001582 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001583var bCanRead, bError : Boolean;
1584 retval : Integer;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001585const
1586 MSG_PEEK = {$IFDEF OLD_UNIT_NAMES} WinSock.MSG_PEEK {$ELSE} Winapi.WinSock.MSG_PEEK {$ENDIF};
Jens Geyerd5436f52014-10-03 19:50:38 +02001587begin
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001588 bytesReady := 0;
1589
Jens Geyerd5436f52014-10-03 19:50:38 +02001590 // The select function returns the total number of socket handles that are ready
1591 // and contained in the fd_set structures, zero if the time limit expired,
1592 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1593 // WSAGetLastError can be used to retrieve a specific error code.
1594 retval := Self.Select( @bCanRead, nil, @bError, TimeOut, wsaError);
1595 if retval = SOCKET_ERROR
1596 then Exit( TWaitForData.wfd_Error);
1597 if (retval = 0) or not bCanRead
1598 then Exit( TWaitForData.wfd_Timeout);
1599
1600 // recv() returns the number of bytes received, or -1 if an error occurred.
1601 // The return value will be 0 when the peer has performed an orderly shutdown.
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001602
1603 retval := recv( FTcpClient.Handle, pBuf^, DesiredBytes, MSG_PEEK);
Jens Geyerd5436f52014-10-03 19:50:38 +02001604 if retval <= 0
1605 then Exit( TWaitForData.wfd_Error);
1606
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001607 // at least we have some data
1608 bytesReady := Min( retval, DesiredBytes);
1609 result := TWaitForData.wfd_HaveData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001610end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001611{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001612
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001613{$IFDEF OLD_SOCKETS}
Jens Geyer17c3ad92017-09-05 20:31:27 +02001614function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001615// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001616var wfd : TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001617 wsaError,
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001618 msecs : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001619 nBytes : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001620 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001621begin
1622 inherited;
1623
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001624 if FTimeout > 0
1625 then msecs := FTimeout
1626 else msecs := DEFAULT_THRIFT_TIMEOUT;
1627
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001628 result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001629 pTmp := pBuf;
1630 Inc( pTmp, offset);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001631 while count > 0 do begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001632
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001633 while TRUE do begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001634 wfd := WaitForData( msecs, pTmp, count, wsaError, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001635 case wfd of
Jens Geyer65b17462016-03-09 00:07:46 +01001636 TWaitForData.wfd_Error : Exit;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001637 TWaitForData.wfd_HaveData : Break;
1638 TWaitForData.wfd_Timeout : begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001639 if (FTimeout = 0)
1640 then Exit
1641 else begin
Jens Geyere0e32402016-04-20 21:50:48 +02001642 raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001643
1644 end;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001645 end;
1646 else
1647 ASSERT( FALSE);
Jens Geyerd5436f52014-10-03 19:50:38 +02001648 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001649 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001650
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001651 // reduce the timeout once we got data
1652 if FTimeout > 0
1653 then msecs := FTimeout div 10
1654 else msecs := DEFAULT_THRIFT_TIMEOUT div 10;
1655 msecs := Max( msecs, 200);
1656
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001657 ASSERT( nBytes <= count);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001658 nBytes := FTcpClient.ReceiveBuf( pTmp^, nBytes);
1659 Inc( pTmp, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001660 Dec( count, nBytes);
1661 Inc( result, nBytes);
1662 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001663end;
1664
1665function TTcpSocketStreamImpl.ToArray: TBytes;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001666// old sockets version
1667var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001668begin
1669 len := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001670 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001671 len := FTcpClient.BytesReceived;
1672 end;
1673
1674 SetLength( Result, len );
1675
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001676 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001677 FTcpClient.ReceiveBuf( Pointer(@Result[0])^, len);
1678 end;
1679end;
1680
Jens Geyer17c3ad92017-09-05 20:31:27 +02001681procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001682// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001683var bCanWrite, bError : Boolean;
1684 retval, wsaError : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001685 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001686begin
1687 inherited;
1688
1689 if not FTcpClient.Active
Jens Geyere0e32402016-04-20 21:50:48 +02001690 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerd5436f52014-10-03 19:50:38 +02001691
1692 // The select function returns the total number of socket handles that are ready
1693 // and contained in the fd_set structures, zero if the time limit expired,
1694 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1695 // WSAGetLastError can be used to retrieve a specific error code.
1696 retval := Self.Select( nil, @bCanWrite, @bError, FTimeOut, wsaError);
1697 if retval = SOCKET_ERROR
Jens Geyere0e32402016-04-20 21:50:48 +02001698 then raise TTransportExceptionUnknown.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001699
Jens Geyerd5436f52014-10-03 19:50:38 +02001700 if (retval = 0)
Jens Geyere0e32402016-04-20 21:50:48 +02001701 then raise TTransportExceptionTimedOut.Create('timed out');
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001702
Jens Geyerd5436f52014-10-03 19:50:38 +02001703 if bError or not bCanWrite
Jens Geyere0e32402016-04-20 21:50:48 +02001704 then raise TTransportExceptionUnknown.Create('unknown error');
Jens Geyerd5436f52014-10-03 19:50:38 +02001705
Jens Geyer5089b0a2018-02-01 22:37:18 +01001706 pTmp := pBuf;
1707 Inc( pTmp, offset);
1708 FTcpClient.SendBuf( pTmp^, count);
Jens Geyerd5436f52014-10-03 19:50:38 +02001709end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001710
1711{$ELSE}
1712
Jens Geyer17c3ad92017-09-05 20:31:27 +02001713function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001714// new sockets version
1715var nBytes : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001716 pTmp : PByte;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001717begin
1718 inherited;
1719
1720 result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001721 pTmp := pBuf;
1722 Inc( pTmp, offset);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001723 while count > 0 do begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001724 nBytes := FTcpClient.Read( pTmp^, count);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001725 if nBytes = 0 then Exit;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001726 Inc( pTmp, nBytes);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001727 Dec( count, nBytes);
1728 Inc( result, nBytes);
1729 end;
1730end;
1731
1732function TTcpSocketStreamImpl.ToArray: TBytes;
1733// new sockets version
1734var len : Integer;
1735begin
1736 len := 0;
1737 try
1738 if FTcpClient.Peek then
1739 repeat
1740 SetLength(Result, Length(Result) + 1024);
1741 len := FTcpClient.Read(Result[Length(Result) - 1024], 1024);
1742 until len < 1024;
1743 except
1744 on TTransportException do begin { don't allow default exceptions } end;
1745 else raise;
1746 end;
1747 if len > 0 then
1748 SetLength(Result, Length(Result) - 1024 + len);
1749end;
1750
Jens Geyer17c3ad92017-09-05 20:31:27 +02001751procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001752// new sockets version
Jens Geyer5089b0a2018-02-01 22:37:18 +01001753var pTmp : PByte;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001754begin
1755 inherited;
1756
1757 if not FTcpClient.IsOpen
Kyle Johnsone363a342016-04-22 19:11:16 -05001758 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001759
Jens Geyer5089b0a2018-02-01 22:37:18 +01001760 pTmp := pBuf;
1761 Inc( pTmp, offset);
1762 FTcpClient.Write( pTmp^, count);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001763end;
1764
Jens Geyer23d67462015-12-19 11:44:57 +01001765{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001766
Jens Geyer41f47af2019-11-09 23:24:52 +01001767procedure TTcpSocketStreamImpl.CheckReadBytesAvailable( const value : Integer);
1768begin
1769 // we can't really tell, no further checks possible
1770end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001771
Jens Geyerd5436f52014-10-03 19:50:38 +02001772
1773end.