THRIFT-5007 Implement MAX_MESSAGE_SIZE and remaining read bytes control
Client: Delphi
Patch: Jens Geyer

This closes #1932
diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas
index 0bf7e45..ec8c87f 100644
--- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas
+++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas
@@ -58,16 +58,19 @@
       THTTPResponseStream = class( TThriftStreamImpl)
       strict private
         FRequest : IWinHTTPRequest;
+        FTransportControl : ITransportControl;
       strict protected
         procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
         function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
+        procedure CheckReadBytesAvailable( const value : Integer);  override;
+        procedure ConsumeReadBytes( const count : Integer);
         procedure Open; override;
         procedure Close; override;
         procedure Flush; override;
         function IsOpen: Boolean; override;
         function ToArray: TBytes; override;
       public
-        constructor Create( const aRequest : IWinHTTPRequest);
+        constructor Create( const aRequest : IWinHTTPRequest; const aTransportCtl : ITransportControl);
         destructor Destroy; override;
       end;
 
@@ -78,6 +81,7 @@
     function  Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
     procedure Write( const pBuf : Pointer; off, len : Integer); override;
     procedure Flush; override;
+    procedure CheckReadBytesAvailable( const value : Integer); override;
 
     procedure SetDnsResolveTimeout(const Value: Integer);
     function GetDnsResolveTimeout: Integer;
@@ -99,7 +103,7 @@
     property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
     property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
   public
-    constructor Create( const AUri: string);
+    constructor Create( const AUri: string; const aTransportCtl : ITransportControl = nil);
     destructor Destroy; override;
   end;
 
@@ -108,9 +112,9 @@
 
 { TWinHTTPClientImpl }
 
-constructor TWinHTTPClientImpl.Create(const AUri: string);
+constructor TWinHTTPClientImpl.Create(const AUri: string; const aTransportCtl : ITransportControl);
 begin
-  inherited Create;
+  inherited Create( aTransportCtl);
   FUri := AUri;
 
   // defaults according to MSDN
@@ -284,6 +288,13 @@
   end;
 end;
 
+procedure TWinHTTPClientImpl.CheckReadBytesAvailable( const value : Integer);
+begin
+  if FInputStream <> nil
+  then FInputStream.CheckReadBytesAvailable( value)
+  else raise TTransportExceptionNotOpen.Create('No request has been sent');
+end;
+
 function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
 begin
   if FInputStream = nil then begin
@@ -291,7 +302,8 @@
   end;
 
   try
-    Result := FInputStream.Read( pBuf, buflen, off, len)
+    Result := FInputStream.Read( pBuf, buflen, off, len);
+    ConsumeReadBytes( result);
   except
     on E: Exception
     do raise TTransportExceptionUnknown.Create(E.Message);
@@ -301,6 +313,7 @@
 procedure TWinHTTPClientImpl.SendRequest;
 var
   http  : IWinHTTPRequest;
+  ctrl  : ITransportControl;
   pData : PByte;
   len   : Integer;
   error : Cardinal;
@@ -327,7 +340,8 @@
     else raise TTransportExceptionInterrupted.Create( sMsg);
   end;
 
-  FInputStream := THTTPResponseStream.Create(http);
+  ctrl := TTransportControlImpl.Create( TransportControl.MaxAllowedMessageSize);
+  FInputStream := THTTPResponseStream.Create( http, ctrl);
 end;
 
 procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer);
@@ -341,10 +355,12 @@
 
 { TWinHTTPClientImpl.THTTPResponseStream }
 
-constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest);
+constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest; const aTransportCtl : ITransportControl);
 begin
   inherited Create;
   FRequest := aRequest;
+  FTransportControl := aTransportCtl;
+  ASSERT( FTransportControl <> nil);
 end;
 
 destructor TWinHTTPClientImpl.THTTPResponseStream.Destroy;
@@ -390,6 +406,8 @@
   if count >= buflen-offset
   then count := buflen-offset;
 
+  CheckReadBytesAvailable(count);
+
   if count > 0 then begin
     pTmp   := pBuf;
     Inc( pTmp, offset);
@@ -397,6 +415,20 @@
     ASSERT( Result >= 0);
   end
   else Result := 0;
+
+  ConsumeReadBytes( result);
+end;
+
+procedure TWinHTTPClientImpl.THTTPResponseStream.ConsumeReadBytes( const count : Integer);
+begin
+  if FTransportControl <> nil
+  then FTransportControl.ConsumeReadBytes( count);
+end;
+
+procedure TWinHTTPClientImpl.THTTPResponseStream.CheckReadBytesAvailable( const value : Integer);
+begin
+  if Int64(value) > Int64(FRequest.QueryDataAvailable)
+  then raise TTransportExceptionEndOfFile.Create('Not enough input data');
 end;
 
 function TWinHTTPClientImpl.THTTPResponseStream.ToArray: TBytes;