257 lines
7.4 KiB
Plaintext
257 lines
7.4 KiB
Plaintext
|
{
|
||
|
$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.10 3/10/2005 12:00:46 AM JPMugaas
|
||
|
Minor problem Craig Peterson had noted in an E-Mail to me.
|
||
|
|
||
|
Rev 1.9 11/30/04 6:19:12 PM RLebeau
|
||
|
Promoted the TIdConnectionIntercept.Intercept property from protected to
|
||
|
published
|
||
|
|
||
|
Rev 1.8 2004.02.03 4:16:44 PM czhower
|
||
|
For unit name changes.
|
||
|
|
||
|
Rev 1.7 2004.01.20 10:03:24 PM czhower
|
||
|
InitComponent
|
||
|
|
||
|
Rev 1.6 5/12/2003 12:33:32 AM GGrieve
|
||
|
add Data from BlockCipher descendent
|
||
|
|
||
|
Rev 1.5 2003.10.14 1:26:48 PM czhower
|
||
|
Uupdates + Intercept support
|
||
|
|
||
|
Rev 1.4 2003.10.11 5:48:16 PM czhower
|
||
|
-VCL fixes for servers
|
||
|
-Chain suport for servers (Super core)
|
||
|
-Scheduler upgrades
|
||
|
-Full yarn support
|
||
|
|
||
|
Rev 1.3 10/5/2003 3:20:46 PM BGooijen
|
||
|
.net
|
||
|
|
||
|
Rev 1.2 2003.10.01 1:12:34 AM czhower
|
||
|
.Net
|
||
|
|
||
|
Rev 1.1 3/5/2003 10:59:48 PM BGooijen
|
||
|
Fixed (i know, the SendBuffer looks bad)
|
||
|
|
||
|
Rev 1.0 11/13/2002 08:44:42 AM JPMugaas
|
||
|
|
||
|
2002-03-01 - Andrew P.Rybin
|
||
|
- Nested Intercept support (ex: ->logging->compression->encryption)
|
||
|
|
||
|
2002-04-09 - Chuck Smith
|
||
|
- set ABuffer.Position := 0; in OnSend/OnReceive for Nested Stream send/receive
|
||
|
}
|
||
|
|
||
|
unit IdIntercept;
|
||
|
|
||
|
interface
|
||
|
|
||
|
{$I IdCompilerDefines.inc}
|
||
|
//here only to put FPC in Delphi mode
|
||
|
|
||
|
uses
|
||
|
Classes,
|
||
|
IdGlobal, IdBaseComponent, IdBuffer, IdException;
|
||
|
|
||
|
type
|
||
|
EIdInterceptCircularLink = class(EIdException);
|
||
|
TIdConnectionIntercept = class;
|
||
|
TIdInterceptNotifyEvent = procedure(ASender: TIdConnectionIntercept) of object;
|
||
|
TIdInterceptStreamEvent = procedure(ASender: TIdConnectionIntercept; var ABuffer: TIdBytes) of object;
|
||
|
|
||
|
TIdConnectionIntercept = class(TIdBaseComponent)
|
||
|
protected
|
||
|
FConnection: TComponent;
|
||
|
{$IFDEF USE_OBJECT_ARC}[Weak]{$ENDIF} FIntercept: TIdConnectionIntercept;
|
||
|
FIsClient: Boolean;
|
||
|
{$IFDEF USE_OBJECT_ARC}
|
||
|
// When ARC is enabled, object references MUST be valid objects.
|
||
|
// It is common for users to store non-object values, though, so
|
||
|
// we will provide separate properties for those purposes
|
||
|
//
|
||
|
// TODO; use TValue instead of separating them
|
||
|
//
|
||
|
FDataObject: TObject;
|
||
|
FDataValue: PtrInt;
|
||
|
{$ELSE}
|
||
|
FData: TObject;
|
||
|
{$ENDIF}
|
||
|
|
||
|
FOnConnect: TIdInterceptNotifyEvent;
|
||
|
FOnDisconnect: TIdInterceptNotifyEvent;
|
||
|
FOnReceive: TIdInterceptStreamEvent;
|
||
|
FOnSend: TIdInterceptStreamEvent;
|
||
|
//
|
||
|
procedure InitComponent; override;
|
||
|
{$IFNDEF USE_OBJECT_ARC}
|
||
|
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
|
||
|
{$ENDIF}
|
||
|
procedure SetIntercept(AValue: TIdConnectionIntercept);
|
||
|
//
|
||
|
public
|
||
|
procedure Connect(AConnection: TComponent); virtual;
|
||
|
procedure Disconnect; virtual;
|
||
|
procedure Receive(var VBuffer: TIdBytes); virtual;
|
||
|
procedure Send(var VBuffer: TIdBytes); virtual;
|
||
|
//
|
||
|
property Connection: TComponent read FConnection;
|
||
|
property IsClient: Boolean read FIsClient;
|
||
|
|
||
|
// user can use this to keep context
|
||
|
{$IFDEF USE_OBJECT_ARC}
|
||
|
property DataObject: TObject read FDataObject write FDataObject;
|
||
|
property DataValue: PtrInt read FDataValue write FDataValue;
|
||
|
{$ELSE}
|
||
|
property Data: TObject read FData write FData;
|
||
|
{$ENDIF}
|
||
|
published
|
||
|
property Intercept: TIdConnectionIntercept read FIntercept write SetIntercept;
|
||
|
property OnConnect: TIdInterceptNotifyEvent read FOnConnect write FOnConnect;
|
||
|
property OnDisconnect: TIdInterceptNotifyEvent read FOnDisconnect write FOnDisconnect;
|
||
|
property OnReceive: TIdInterceptStreamEvent read FOnReceive write FOnReceive;
|
||
|
property OnSend: TIdInterceptStreamEvent read FOnSend write FOnSend;
|
||
|
end;
|
||
|
|
||
|
TIdServerIntercept = class(TIdBaseComponent)
|
||
|
public
|
||
|
procedure Init; virtual; abstract;
|
||
|
function Accept(AConnection: TComponent): TIdConnectionIntercept; virtual; abstract;
|
||
|
end;
|
||
|
|
||
|
implementation
|
||
|
uses
|
||
|
IdResourceStringsCore;
|
||
|
|
||
|
{ TIdIntercept }
|
||
|
|
||
|
procedure TIdConnectionIntercept.Disconnect;
|
||
|
var
|
||
|
// under ARC, convert a weak reference to a strong reference before working with it
|
||
|
LIntercept: TIdConnectionIntercept;
|
||
|
begin
|
||
|
LIntercept := Intercept;
|
||
|
if LIntercept <> nil then begin
|
||
|
LIntercept.Disconnect;
|
||
|
end;
|
||
|
if Assigned(OnDisconnect) then begin
|
||
|
OnDisconnect(Self);
|
||
|
end;
|
||
|
FConnection := nil;
|
||
|
end;
|
||
|
|
||
|
procedure TIdConnectionIntercept.Connect(AConnection: TComponent);
|
||
|
var
|
||
|
// under ARC, convert a weak reference to a strong reference before working with it
|
||
|
LIntercept: TIdConnectionIntercept;
|
||
|
begin
|
||
|
FConnection := AConnection;
|
||
|
if Assigned(OnConnect) then begin
|
||
|
OnConnect(Self);
|
||
|
end;
|
||
|
LIntercept := Intercept;
|
||
|
if LIntercept <> nil then begin
|
||
|
LIntercept.Connect(AConnection);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdConnectionIntercept.Receive(var VBuffer: TIdBytes);
|
||
|
var
|
||
|
// under ARC, convert a weak reference to a strong reference before working with it
|
||
|
LIntercept: TIdConnectionIntercept;
|
||
|
begin
|
||
|
LIntercept := Intercept;
|
||
|
if LIntercept <> nil then begin
|
||
|
LIntercept.Receive(VBuffer);
|
||
|
end;
|
||
|
if Assigned(OnReceive) then begin
|
||
|
OnReceive(Self, VBuffer);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdConnectionIntercept.Send(var VBuffer: TIdBytes);
|
||
|
var
|
||
|
// under ARC, convert a weak reference to a strong reference before working with it
|
||
|
LIntercept: TIdConnectionIntercept;
|
||
|
begin
|
||
|
if Assigned(OnSend) then begin
|
||
|
OnSend(Self, VBuffer);
|
||
|
end;
|
||
|
LIntercept := Intercept;
|
||
|
if LIntercept <> nil then begin
|
||
|
LIntercept.Send(VBuffer);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdConnectionIntercept.SetIntercept(AValue: TIdConnectionIntercept);
|
||
|
var
|
||
|
// under ARC, convert a weak reference to a strong reference before working with it
|
||
|
LIntercept: TIdConnectionIntercept;
|
||
|
LNextValue: TIdConnectionIntercept;
|
||
|
begin
|
||
|
LIntercept := FIntercept;
|
||
|
if LIntercept <> AValue then
|
||
|
begin
|
||
|
LNextValue := AValue;
|
||
|
while Assigned(LNextValue) do begin
|
||
|
if LNextValue = Self then begin //recursion
|
||
|
raise EIdInterceptCircularLink.CreateFmt(RSInterceptCircularLink, [ClassName]);
|
||
|
end;
|
||
|
LNextValue := LNextValue.Intercept;
|
||
|
end;
|
||
|
|
||
|
// under ARC, all weak references to a freed object get nil'ed automatically
|
||
|
|
||
|
{$IFNDEF USE_OBJECT_ARC}
|
||
|
// remove self from the Intercept's free notification list {Do not Localize}
|
||
|
if Assigned(LIntercept) then begin
|
||
|
LIntercept.RemoveFreeNotification(Self);
|
||
|
end;
|
||
|
{$ENDIF}
|
||
|
|
||
|
FIntercept := AValue;
|
||
|
|
||
|
{$IFNDEF USE_OBJECT_ARC}
|
||
|
// add self to the Intercept's free notification list {Do not Localize}
|
||
|
if Assigned(AValue) then begin
|
||
|
AValue.FreeNotification(Self);
|
||
|
end;
|
||
|
{$ENDIF}
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
// under ARC, all weak references to a freed object get nil'ed automatically
|
||
|
{$IFNDEF USE_OBJECT_ARC}
|
||
|
procedure TIdConnectionIntercept.Notification(AComponent: TComponent; Operation: TOperation);
|
||
|
begin
|
||
|
if (Operation = opRemove) and (AComponent = Intercept) then begin
|
||
|
FIntercept := nil;
|
||
|
end;
|
||
|
inherited Notification(AComponent, OPeration);
|
||
|
end;
|
||
|
{$ENDIF}
|
||
|
|
||
|
procedure TIdConnectionIntercept.InitComponent;
|
||
|
begin
|
||
|
inherited InitComponent;
|
||
|
FIsClient := True;
|
||
|
end;
|
||
|
|
||
|
end.
|