www.pudn.com > indyprelim.zip > IdIOHandlerStream.pas
{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.21 3/10/05 3:24:30 PM RLebeau
Updated ReadFromSource() and WriteDirect() to access the Intercept property
directly.
Rev 1.20 10/21/2004 11:07:30 PM BGooijen
works in win32 now too
Rev 1.19 10/21/2004 1:52:56 PM BGooijen
Raid 214235
Rev 1.18 7/23/04 6:20:52 PM RLebeau
Removed memory leaks in Send/ReceiveStream property setters
Rev 1.17 2004.05.20 11:39:08 AM czhower
IdStreamVCL
Rev 1.16 23/04/2004 20:29:36 CCostelloe
Minor change to support IdMessageClient's new TIdIOHandlerStreamMsg
Rev 1.15 2004.04.16 11:30:32 PM czhower
Size fix to IdBuffer, optimizations, and memory leaks
Rev 1.14 2004.04.08 3:56:36 PM czhower
Fixed bug with Intercept byte count. Also removed Bytes from Buffer.
Rev 1.13 2004.03.07 11:48:46 AM czhower
Flushbuffer fix + other minor ones found
Rev 1.12 2004.03.03 11:55:04 AM czhower
IdStream change
Rev 1.11 2004.02.03 4:17:16 PM czhower
For unit name changes.
Rev 1.10 11/01/2004 19:52:44 CCostelloe
Revisions for TIdMessage SaveToFile & LoadFromFile for D7 & D8
Rev 1.8 08/01/2004 23:37:16 CCostelloe
Minor changes
Rev 1.7 1/8/2004 1:01:22 PM BGooijen
Cleaned up
Rev 1.6 1/8/2004 4:23:06 AM BGooijen
temp fixed TIdIOHandlerStream.WriteToDestination
Rev 1.5 08/01/2004 00:25:22 CCostelloe
Start of reimplementing LoadFrom/SaveToFile
Rev 1.4 2003.12.31 7:44:54 PM czhower
Matched constructors visibility to ancestor.
Rev 1.3 2003.10.24 10:44:54 AM czhower
IdStream implementation, bug fixes.
Rev 1.2 2003.10.14 11:19:14 PM czhower
Updated for better functionality.
Rev 1.1 2003.10.14 1:27:14 PM czhower
Uupdates + Intercept support
Rev 1.0 2003.10.13 6:40:40 PM czhower
Moved from root
Rev 1.9 2003.10.11 10:00:36 PM czhower
Compiles again.
Rev 1.8 10/10/2003 10:53:42 PM BGooijen
Changed const-ness of some methods to reflect base class changes
Rev 1.7 7/10/2003 6:07:58 PM SGrobety
.net
Rev 1.6 17/07/2003 00:01:24 CCostelloe
Added (empty) procedures for the base classes' abstract CheckForDataOnSource
and CheckForDisconnect
Rev 1.5 7/1/2003 12:45:56 PM BGooijen
changed FInputBuffer.Size := 0 to FInputBuffer.Clear
Rev 1.4 12-8-2002 21:05:28 BGooijen
Removed call to Close in .Destroy, this is already done in
TIdIOHandler.Destroy
Rev 1.3 12/7/2002 06:42:44 PM JPMugaas
These should now compile except for Socks server. IPVersion has to be a
property someplace for that.
Rev 1.2 12/5/2002 02:53:52 PM JPMugaas
Updated for new API definitions.
Rev 1.1 05/12/2002 15:29:16 AO'Neill
Rev 1.0 11/13/2002 07:55:08 AM JPMugaas
}
unit IdIOHandlerStream;
interface
{$I IdCompilerDefines.inc}
//Put FPC into Delphi mode
uses
IdBaseComponent,
IdGlobal,
IdIOHandler,
IdObjs,
IdStream,
IdSys;
type
TIdIOHandlerStream = class;
TIdIOHandlerStreamType = (stRead, stWrite, stReadWrite);
TIdOnGetStreams = procedure(
ASender: TIdIOHandlerStream;
var VReceiveStream: TIdStream;
var VSendStream: TIdStream
) of object;
TIdIOHandlerStream = class(TIdIOHandler)
protected
FFreeStreams: Boolean;
FOnGetStreams: TIdOnGetStreams;
fReceiveStream: TIdStream;
fSendStream: TIdStream;
FStreamType: TIdIOHandlerStreamType;
//
function GetReceiveStream: TIdStream;
function GetSendStream: TIdStream;
procedure SetReceiveStream(AStream: TIdStream);
procedure SetSendStream(AStream: TIdStream);
function ReadFromSource(
ARaiseExceptionIfDisconnected: Boolean = True;
ATimeout: Integer = IdTimeoutDefault;
ARaiseExceptionOnTimeout: Boolean = True
): Integer; override;
public
procedure CheckForDataOnSource(
ATimeout: Integer = 0
); override;
procedure CheckForDisconnect(
ARaiseExceptionIfDisconnected: Boolean = True;
AIgnoreBuffer: Boolean = False
); override;
constructor Create(
AOwner: TIdNativeComponent;
AReceiveStream: TIdStream;
ASendStream: TIdStream = nil
); reintroduce; overload; virtual;
constructor Create(
AOwner: TIdNativeComponent
); reintroduce; overload;
function Connected
: Boolean;
override;
procedure Close;
override;
procedure Open;
override;
function Readable(AMSec: integer = IdTimeoutDefault): boolean; override;
procedure WriteDirect(
var aBuffer: TIdBytes
); override;
//
property ReceiveStream: TIdStream read GetReceiveStream {write SetReceiveStream};
property SendStream: TIdStream read GetSendStream {write SetSendStream};
published
property FreeStreams: Boolean read FFreeStreams write FFreeStreams;
property StreamType: TIdIOHandlerStreamType read FStreamType
write FStreamType;
//
property OnGetStreams: TIdOnGetStreams read FOnGetStreams
write FOnGetStreams;
end;
implementation
{ TIdIOHandlerStream }
procedure TIdIOHandlerStream.CheckForDataOnSource(ATimeout: Integer = 0);
begin
// All that we are doing here is implementing the base class's abstract function
end;
procedure TIdIOHandlerStream.CheckForDisconnect(
ARaiseExceptionIfDisconnected: Boolean = True;
AIgnoreBuffer: Boolean = False);
begin
fClosedGracefully := (fSendStream = nil) and (fReceiveStream = nil);
if fClosedGracefully and ARaiseExceptionIfDisconnected then begin
RaiseConnClosedGracefully;
end;
end;
procedure TIdIOHandlerStream.Close;
begin
inherited Close;
if FreeStreams then begin
Sys.FreeAndNil(FReceiveStream);
Sys.FreeAndNil(FSendStream);
end;
end;
function TIdIOHandlerStream.Connected: Boolean;
begin
Result := False; // Just to avoid warning message
case FStreamType of
stRead: Result := ReceiveStream <> nil;
stWrite: Result := SendStream <> nil;
stReadWrite: Result := (ReceiveStream <> nil) and (SendStream <> nil);
end;
end;
constructor TIdIOHandlerStream.Create( AOwner: TIdNativeComponent );
begin
inherited Create(AOwner);
FFreeStreams := True;
//
FStreamType := stReadWrite;
end;
constructor TIdIOHandlerStream.Create(
AOwner: TIdNativeComponent;
AReceiveStream: TIdStream;
ASendStream: TIdStream = nil
);
begin
inherited Create(AOwner);
FFreeStreams := True;
//
FStreamType := stReadWrite;
if (AReceiveStream <> nil) and (ASendStream = nil) then begin
FStreamType := stWrite;
end else if (AReceiveStream = nil) and (ASendStream <> nil) then begin
FStreamType := stRead;
end;
SetReceiveStream(AReceiveStream);
SetSendStream(ASendStream);
end;
procedure TIdIOHandlerStream.Open;
begin
inherited Open;
if Assigned(OnGetStreams) then begin
OnGetStreams(Self, FReceiveStream, FSendStream);
end;
end;
function TIdIOHandlerStream.Readable(AMSec: integer): boolean;
begin
Result := ReceiveStream <> nil;
if Result then begin
Result := ReceiveStream.Position < ReceiveStream.Size;
end;
end;
function TIdIOHandlerStream.ReadFromSource(
ARaiseExceptionIfDisconnected: Boolean; ATimeout: Integer;
ARaiseExceptionOnTimeout: Boolean): Integer;
var
LBuffer: TIdBytes;
begin
Result := 0;
if ReceiveStream <> nil then begin
// We dont want to read the whole stream in at a time. If its a big file will consume way too
// much memory by loading it all at once. So lets read it in chunks.
Result := Min(32 * 1024, FReceiveStream.Size - FReceiveStream.Position);
if Result > 0 then begin
SetLength(LBuffer, Result);
TIdStreamHelper.ReadBytes(FReceiveStream,LBuffer,Result);
if Intercept <> nil then begin
Intercept.Receive(LBuffer);
Result := Length(LBuffer);
end;
if Result > 0 then begin
FInputBuffer.Write(LBuffer);
end;
end;
end else begin
FInputBuffer.Clear;
end;
end;
procedure TIdIOHandlerStream.WriteDirect(
var aBuffer: TIdBytes
);
begin
inherited WriteDirect(aBuffer);
if fSendStream <> nil then begin
TIdStreamHelper.Write(fSendStream, aBuffer);
end;
end;
function TIdIOHandlerStream.GetReceiveStream: TIdStream;
begin
Result := FReceiveStream;
end;
function TIdIOHandlerStream.GetSendStream: TIdStream;
begin
Result := FSendStream;
end;
procedure TIdIOHandlerStream.SetReceiveStream(AStream: TIdStream);
begin
if AStream <> nil then begin
FReceiveStream := AStream;
end;
end;
procedure TIdIOHandlerStream.SetSendStream(AStream: TIdStream);
begin
if AStream <> nil then begin
FSendStream := AStream;
end;
end;
end.