blob: a3476bf2a3ed272d0a3ef49fc0eae7137032504d [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
1311 len := FWriteBuffer.Size;
1312 SetLength( buf, len);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001313 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001314 System.Move( FWriteBuffer.Memory^, buf[0], len );
1315 end;
1316
Jens Geyer2646bd62019-11-09 23:24:52 +01001317 data_len := len - SizeOf(TFramedHeader);
Jens Geyer30ed90e2016-03-10 20:12:49 +01001318 if (data_len < 0) then begin
Jens Geyere0e32402016-04-20 21:50:48 +02001319 raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: data_len < 0' );
Jens Geyerd5436f52014-10-03 19:50:38 +02001320 end;
1321
1322 InitWriteBuffer;
1323
1324 buf[0] := Byte($FF and (data_len shr 24));
1325 buf[1] := Byte($FF and (data_len shr 16));
1326 buf[2] := Byte($FF and (data_len shr 8));
1327 buf[3] := Byte($FF and data_len);
1328
1329 FTransport.Write( buf, 0, len );
1330 FTransport.Flush;
1331end;
1332
1333function TFramedTransportImpl.GetIsOpen: Boolean;
1334begin
1335 Result := FTransport.IsOpen;
1336end;
1337
1338type
1339 TAccessMemoryStream = class(TMemoryStream)
1340 end;
1341
1342procedure TFramedTransportImpl.InitWriteBuffer;
Jens Geyer2646bd62019-11-09 23:24:52 +01001343const DUMMY_HEADER : TFramedHeader = 0;
Jens Geyerd5436f52014-10-03 19:50:38 +02001344begin
1345 FWriteBuffer.Free;
1346 FWriteBuffer := TMemoryStream.Create;
1347 TAccessMemoryStream(FWriteBuffer).Capacity := 1024;
Jens Geyer2646bd62019-11-09 23:24:52 +01001348 FWriteBuffer.Write( DUMMY_HEADER, SizeOf(DUMMY_HEADER));
Jens Geyerd5436f52014-10-03 19:50:38 +02001349end;
1350
1351procedure TFramedTransportImpl.Open;
1352begin
1353 FTransport.Open;
1354end;
1355
Jens Geyer17c3ad92017-09-05 20:31:27 +02001356function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001357var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001358begin
Jens Geyer17c3ad92017-09-05 20:31:27 +02001359 if len > (buflen-off)
1360 then len := buflen-off;
1361
Jens Geyer5089b0a2018-02-01 22:37:18 +01001362 pTmp := pBuf;
1363 Inc( pTmp, off);
1364
Jens Geyer17c3ad92017-09-05 20:31:27 +02001365 if (FReadBuffer <> nil) and (len > 0) then begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001366 result := FReadBuffer.Read( pTmp^, len);
Jens Geyered994552019-11-09 23:24:52 +01001367 if result > 0 then Exit;
Jens Geyerd5436f52014-10-03 19:50:38 +02001368 end;
1369
1370 ReadFrame;
1371 if len > 0
Jens Geyer5089b0a2018-02-01 22:37:18 +01001372 then Result := FReadBuffer.Read( pTmp^, len)
Jens Geyerd5436f52014-10-03 19:50:38 +02001373 else Result := 0;
1374end;
1375
1376procedure TFramedTransportImpl.ReadFrame;
1377var
Jens Geyer2646bd62019-11-09 23:24:52 +01001378 i32rd : packed array[0..SizeOf(TFramedHeader)-1] of Byte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001379 size : Integer;
1380 buff : TBytes;
1381begin
Jens Geyer2646bd62019-11-09 23:24:52 +01001382 FTransport.ReadAll( @i32rd[0], SizeOf(i32rd), 0, SizeOf(i32rd));
Jens Geyerd5436f52014-10-03 19:50:38 +02001383 size :=
1384 ((i32rd[0] and $FF) shl 24) or
1385 ((i32rd[1] and $FF) shl 16) or
1386 ((i32rd[2] and $FF) shl 8) or
1387 (i32rd[3] and $FF);
Jens Geyer2646bd62019-11-09 23:24:52 +01001388
1389 if size < 0 then begin
1390 Close();
1391 raise TTransportExceptionCorruptedData.Create('Read a negative frame size ('+IntToStr(size)+')');
1392 end;
1393
1394 if size > FMaxFrameSize then begin
1395 Close();
1396 raise TTransportExceptionCorruptedData.Create('Frame size ('+IntToStr(size)+') larger than allowed maximum ('+IntToStr(FMaxFrameSize)+')');
1397 end;
1398
Jens Geyer41f47af2019-11-09 23:24:52 +01001399 FTransport.CheckReadBytesAvailable( size);
Jens Geyerd5436f52014-10-03 19:50:38 +02001400 SetLength( buff, size );
1401 FTransport.ReadAll( buff, 0, size );
Jens Geyered994552019-11-09 23:24:52 +01001402
1403 FreeAndNil( FReadBuffer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001404 FReadBuffer := TMemoryStream.Create;
Jens Geyera76e6c72017-09-08 21:03:30 +02001405 if Length(buff) > 0
1406 then FReadBuffer.Write( Pointer(@buff[0])^, size );
Jens Geyerd5436f52014-10-03 19:50:38 +02001407 FReadBuffer.Position := 0;
1408end;
1409
Jens Geyer17c3ad92017-09-05 20:31:27 +02001410procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001411var pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001412begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001413 if len > 0 then begin
1414 pTmp := pBuf;
1415 Inc( pTmp, off);
1416
1417 FWriteBuffer.Write( pTmp^, len );
1418 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001419end;
1420
Jens Geyered994552019-11-09 23:24:52 +01001421
Jens Geyer41f47af2019-11-09 23:24:52 +01001422procedure TFramedTransportImpl.CheckReadBytesAvailable( const value : Integer);
1423var nRemaining : Int64;
1424begin
1425 if FReadBuffer = nil
1426 then raise TTransportExceptionEndOfFile.Create('Cannot read from null inputstream');
1427
1428 nRemaining := FReadBuffer.Size - FReadBuffer.Position;
1429 if value > nRemaining
1430 then raise TTransportExceptionEndOfFile.Create('Not enough input data');
1431end;
1432
1433
Jens Geyerd5436f52014-10-03 19:50:38 +02001434{ TFramedTransport.TFactory }
1435
Jens Geyered994552019-11-09 23:24:52 +01001436function TFramedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport;
Jens Geyerd5436f52014-10-03 19:50:38 +02001437begin
Jens Geyered994552019-11-09 23:24:52 +01001438 Result := TFramedTransportImpl.Create( aTransport);
Jens Geyerd5436f52014-10-03 19:50:38 +02001439end;
1440
1441{ TTcpSocketStreamImpl }
1442
1443procedure TTcpSocketStreamImpl.Close;
1444begin
1445 FTcpClient.Close;
1446end;
1447
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001448{$IFDEF OLD_SOCKETS}
Jens Geyered994552019-11-09 23:24:52 +01001449constructor TTcpSocketStreamImpl.Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer);
Jens Geyerd5436f52014-10-03 19:50:38 +02001450begin
1451 inherited Create;
Jens Geyered994552019-11-09 23:24:52 +01001452 FTcpClient := aTcpClient;
Jens Geyerd5436f52014-10-03 19:50:38 +02001453 FTimeout := aTimeout;
1454end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001455{$ELSE}
Jens Geyered994552019-11-09 23:24:52 +01001456constructor TTcpSocketStreamImpl.Create( const aTcpClient: TSocket; const aTimeout : Longword);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001457begin
1458 inherited Create;
Jens Geyered994552019-11-09 23:24:52 +01001459 FTcpClient := aTcpClient;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001460 if aTimeout = 0 then
1461 FTcpClient.RecvTimeout := SLEEP_TIME
1462 else
1463 FTcpClient.RecvTimeout := aTimeout;
1464 FTcpClient.SendTimeout := aTimeout;
1465end;
1466{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001467
1468procedure TTcpSocketStreamImpl.Flush;
1469begin
1470
1471end;
1472
1473function TTcpSocketStreamImpl.IsOpen: Boolean;
1474begin
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001475{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001476 Result := FTcpClient.Active;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001477{$ELSE}
1478 Result := FTcpClient.IsOpen;
1479{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001480end;
1481
1482procedure TTcpSocketStreamImpl.Open;
1483begin
1484 FTcpClient.Open;
1485end;
1486
1487
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001488{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001489function TTcpSocketStreamImpl.Select( ReadReady, WriteReady, ExceptFlag: PBoolean;
1490 TimeOut: Integer; var wsaError : Integer): Integer;
1491var
1492 ReadFds: TFDset;
1493 ReadFdsptr: PFDset;
1494 WriteFds: TFDset;
1495 WriteFdsptr: PFDset;
1496 ExceptFds: TFDset;
1497 ExceptFdsptr: PFDset;
1498 tv: timeval;
1499 Timeptr: PTimeval;
1500 socket : TSocket;
1501begin
1502 if not FTcpClient.Active then begin
1503 wsaError := WSAEINVAL;
1504 Exit( SOCKET_ERROR);
1505 end;
1506
1507 socket := FTcpClient.Handle;
1508
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001509 if Assigned(ReadReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001510 ReadFdsptr := @ReadFds;
1511 FD_ZERO(ReadFds);
1512 FD_SET(socket, ReadFds);
1513 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001514 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001515 ReadFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001516 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001517
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001518 if Assigned(WriteReady) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001519 WriteFdsptr := @WriteFds;
1520 FD_ZERO(WriteFds);
1521 FD_SET(socket, WriteFds);
1522 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001523 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001524 WriteFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001525 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001526
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001527 if Assigned(ExceptFlag) then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001528 ExceptFdsptr := @ExceptFds;
1529 FD_ZERO(ExceptFds);
1530 FD_SET(socket, ExceptFds);
1531 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001532 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001533 ExceptFdsptr := nil;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001534 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001535
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001536 if TimeOut >= 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001537 tv.tv_sec := TimeOut div 1000;
1538 tv.tv_usec := 1000 * (TimeOut mod 1000);
1539 Timeptr := @tv;
1540 end
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001541 else begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001542 Timeptr := nil; // wait forever
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001543 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001544
1545 wsaError := 0;
1546 try
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001547 {$IFDEF MSWINDOWS}
1548 {$IFDEF OLD_UNIT_NAMES}
1549 result := WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1550 {$ELSE}
1551 result := Winapi.WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1552 {$ENDIF}
1553 {$ENDIF}
1554 {$IFDEF LINUX}
1555 result := Libc.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr);
1556 {$ENDIF}
1557
Jens Geyerd5436f52014-10-03 19:50:38 +02001558 if result = SOCKET_ERROR
1559 then wsaError := WSAGetLastError;
1560
1561 except
1562 result := SOCKET_ERROR;
1563 end;
1564
1565 if Assigned(ReadReady) then
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001566 ReadReady^ := FD_ISSET(socket, ReadFds);
1567
Jens Geyerd5436f52014-10-03 19:50:38 +02001568 if Assigned(WriteReady) then
1569 WriteReady^ := FD_ISSET(socket, WriteFds);
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001570
Jens Geyerd5436f52014-10-03 19:50:38 +02001571 if Assigned(ExceptFlag) then
1572 ExceptFlag^ := FD_ISSET(socket, ExceptFds);
1573end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001574{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001575
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001576{$IFDEF OLD_SOCKETS}
Jens Geyerd5436f52014-10-03 19:50:38 +02001577function TTcpSocketStreamImpl.WaitForData( TimeOut : Integer; pBuf : Pointer;
1578 DesiredBytes : Integer;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001579 var wsaError, bytesReady : Integer): TWaitForData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001580var bCanRead, bError : Boolean;
1581 retval : Integer;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001582const
1583 MSG_PEEK = {$IFDEF OLD_UNIT_NAMES} WinSock.MSG_PEEK {$ELSE} Winapi.WinSock.MSG_PEEK {$ENDIF};
Jens Geyerd5436f52014-10-03 19:50:38 +02001584begin
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001585 bytesReady := 0;
1586
Jens Geyerd5436f52014-10-03 19:50:38 +02001587 // The select function returns the total number of socket handles that are ready
1588 // and contained in the fd_set structures, zero if the time limit expired,
1589 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1590 // WSAGetLastError can be used to retrieve a specific error code.
1591 retval := Self.Select( @bCanRead, nil, @bError, TimeOut, wsaError);
1592 if retval = SOCKET_ERROR
1593 then Exit( TWaitForData.wfd_Error);
1594 if (retval = 0) or not bCanRead
1595 then Exit( TWaitForData.wfd_Timeout);
1596
1597 // recv() returns the number of bytes received, or -1 if an error occurred.
1598 // The return value will be 0 when the peer has performed an orderly shutdown.
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001599
1600 retval := recv( FTcpClient.Handle, pBuf^, DesiredBytes, MSG_PEEK);
Jens Geyerd5436f52014-10-03 19:50:38 +02001601 if retval <= 0
1602 then Exit( TWaitForData.wfd_Error);
1603
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001604 // at least we have some data
1605 bytesReady := Min( retval, DesiredBytes);
1606 result := TWaitForData.wfd_HaveData;
Jens Geyerd5436f52014-10-03 19:50:38 +02001607end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001608{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001609
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001610{$IFDEF OLD_SOCKETS}
Jens Geyer17c3ad92017-09-05 20:31:27 +02001611function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001612// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001613var wfd : TWaitForData;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001614 wsaError,
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001615 msecs : Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001616 nBytes : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001617 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001618begin
1619 inherited;
1620
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001621 if FTimeout > 0
1622 then msecs := FTimeout
1623 else msecs := DEFAULT_THRIFT_TIMEOUT;
1624
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001625 result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001626 pTmp := pBuf;
1627 Inc( pTmp, offset);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001628 while count > 0 do begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001629
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001630 while TRUE do begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001631 wfd := WaitForData( msecs, pTmp, count, wsaError, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001632 case wfd of
Jens Geyer65b17462016-03-09 00:07:46 +01001633 TWaitForData.wfd_Error : Exit;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001634 TWaitForData.wfd_HaveData : Break;
1635 TWaitForData.wfd_Timeout : begin
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001636 if (FTimeout = 0)
1637 then Exit
1638 else begin
Jens Geyere0e32402016-04-20 21:50:48 +02001639 raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001640
1641 end;
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001642 end;
1643 else
1644 ASSERT( FALSE);
Jens Geyerd5436f52014-10-03 19:50:38 +02001645 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001646 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001647
Jens Geyer6f6aa8a2016-03-10 19:47:12 +01001648 // reduce the timeout once we got data
1649 if FTimeout > 0
1650 then msecs := FTimeout div 10
1651 else msecs := DEFAULT_THRIFT_TIMEOUT div 10;
1652 msecs := Max( msecs, 200);
1653
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001654 ASSERT( nBytes <= count);
Jens Geyer5089b0a2018-02-01 22:37:18 +01001655 nBytes := FTcpClient.ReceiveBuf( pTmp^, nBytes);
1656 Inc( pTmp, nBytes);
Jens Geyerbcb17bc2015-07-17 23:11:14 +02001657 Dec( count, nBytes);
1658 Inc( result, nBytes);
1659 end;
Jens Geyerd5436f52014-10-03 19:50:38 +02001660end;
1661
1662function TTcpSocketStreamImpl.ToArray: TBytes;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001663// old sockets version
1664var len : Integer;
Jens Geyerd5436f52014-10-03 19:50:38 +02001665begin
1666 len := 0;
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001667 if IsOpen then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001668 len := FTcpClient.BytesReceived;
1669 end;
1670
1671 SetLength( Result, len );
1672
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001673 if len > 0 then begin
Jens Geyerd5436f52014-10-03 19:50:38 +02001674 FTcpClient.ReceiveBuf( Pointer(@Result[0])^, len);
1675 end;
1676end;
1677
Jens Geyer17c3ad92017-09-05 20:31:27 +02001678procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001679// old sockets version
Jens Geyerd5436f52014-10-03 19:50:38 +02001680var bCanWrite, bError : Boolean;
1681 retval, wsaError : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001682 pTmp : PByte;
Jens Geyerd5436f52014-10-03 19:50:38 +02001683begin
1684 inherited;
1685
1686 if not FTcpClient.Active
Jens Geyere0e32402016-04-20 21:50:48 +02001687 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerd5436f52014-10-03 19:50:38 +02001688
1689 // The select function returns the total number of socket handles that are ready
1690 // and contained in the fd_set structures, zero if the time limit expired,
1691 // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR,
1692 // WSAGetLastError can be used to retrieve a specific error code.
1693 retval := Self.Select( nil, @bCanWrite, @bError, FTimeOut, wsaError);
1694 if retval = SOCKET_ERROR
Jens Geyere0e32402016-04-20 21:50:48 +02001695 then raise TTransportExceptionUnknown.Create(SysErrorMessage(Cardinal(wsaError)));
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001696
Jens Geyerd5436f52014-10-03 19:50:38 +02001697 if (retval = 0)
Jens Geyere0e32402016-04-20 21:50:48 +02001698 then raise TTransportExceptionTimedOut.Create('timed out');
Jens Geyer9f7f11e2016-04-14 21:37:11 +02001699
Jens Geyerd5436f52014-10-03 19:50:38 +02001700 if bError or not bCanWrite
Jens Geyere0e32402016-04-20 21:50:48 +02001701 then raise TTransportExceptionUnknown.Create('unknown error');
Jens Geyerd5436f52014-10-03 19:50:38 +02001702
Jens Geyer5089b0a2018-02-01 22:37:18 +01001703 pTmp := pBuf;
1704 Inc( pTmp, offset);
1705 FTcpClient.SendBuf( pTmp^, count);
Jens Geyerd5436f52014-10-03 19:50:38 +02001706end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001707
1708{$ELSE}
1709
Jens Geyer17c3ad92017-09-05 20:31:27 +02001710function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001711// new sockets version
1712var nBytes : Integer;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001713 pTmp : PByte;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001714begin
1715 inherited;
1716
1717 result := 0;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001718 pTmp := pBuf;
1719 Inc( pTmp, offset);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001720 while count > 0 do begin
Jens Geyer5089b0a2018-02-01 22:37:18 +01001721 nBytes := FTcpClient.Read( pTmp^, count);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001722 if nBytes = 0 then Exit;
Jens Geyer5089b0a2018-02-01 22:37:18 +01001723 Inc( pTmp, nBytes);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001724 Dec( count, nBytes);
1725 Inc( result, nBytes);
1726 end;
1727end;
1728
1729function TTcpSocketStreamImpl.ToArray: TBytes;
1730// new sockets version
1731var len : Integer;
1732begin
1733 len := 0;
1734 try
1735 if FTcpClient.Peek then
1736 repeat
1737 SetLength(Result, Length(Result) + 1024);
1738 len := FTcpClient.Read(Result[Length(Result) - 1024], 1024);
1739 until len < 1024;
1740 except
1741 on TTransportException do begin { don't allow default exceptions } end;
1742 else raise;
1743 end;
1744 if len > 0 then
1745 SetLength(Result, Length(Result) - 1024 + len);
1746end;
1747
Jens Geyer17c3ad92017-09-05 20:31:27 +02001748procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001749// new sockets version
Jens Geyer5089b0a2018-02-01 22:37:18 +01001750var pTmp : PByte;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001751begin
1752 inherited;
1753
1754 if not FTcpClient.IsOpen
Kyle Johnsone363a342016-04-22 19:11:16 -05001755 then raise TTransportExceptionNotOpen.Create('not open');
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001756
Jens Geyer5089b0a2018-02-01 22:37:18 +01001757 pTmp := pBuf;
1758 Inc( pTmp, offset);
1759 FTcpClient.Write( pTmp^, count);
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001760end;
1761
Jens Geyer23d67462015-12-19 11:44:57 +01001762{$ENDIF}
Jens Geyerd5436f52014-10-03 19:50:38 +02001763
Jens Geyer41f47af2019-11-09 23:24:52 +01001764procedure TTcpSocketStreamImpl.CheckReadBytesAvailable( const value : Integer);
1765begin
1766 // we can't really tell, no further checks possible
1767end;
Jens Geyerbea9bbe2016-04-20 00:02:40 +02001768
Jens Geyerd5436f52014-10-03 19:50:38 +02001769
1770end.