440 lines
13 KiB
Plaintext
440 lines
13 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.28 12/2/2004 4:23:54 PM JPMugaas
|
||
|
Adjusted for changes in Core.
|
||
|
|
||
|
Rev 1.27 11/15/04 11:32:22 AM RLebeau
|
||
|
Changed OutboundConnect() to assign the TIdTcpClient.ConnectTimeout property
|
||
|
instead of the IOHandler.ConnectTimeout property.
|
||
|
|
||
|
Rev 1.26 10/6/2004 10:22:12 PM BGooijen
|
||
|
Removed PEVerify errors in this unit
|
||
|
|
||
|
Rev 1.25 8/2/04 5:55:00 PM RLebeau
|
||
|
Updated TIdMappedPortContext.OutboundConnect() with ConnectTimeout property
|
||
|
change.
|
||
|
|
||
|
Rev 1.24 3/1/04 7:17:02 PM RLebeau
|
||
|
Minor correction to previous change
|
||
|
|
||
|
Rev 1.23 3/1/04 7:14:34 PM RLebeau
|
||
|
Updated TIdMappedPortContext.OutboundConnect() to call CreateIOHandler()
|
||
|
before attempting to use the outbound client's IOHandler property.
|
||
|
|
||
|
Rev 1.22 2004.02.03 5:43:58 PM czhower
|
||
|
Name changes
|
||
|
|
||
|
Rev 1.21 2/1/2004 4:23:32 AM JPMugaas
|
||
|
Should now compile in DotNET.
|
||
|
|
||
|
Rev 1.20 1/21/2004 3:11:30 PM JPMugaas
|
||
|
InitComponent
|
||
|
|
||
|
Rev 1.19 12/14/03 7:16:20 PM RLebeau
|
||
|
Typo fixes when accessing OutboudClient.IOHandler
|
||
|
|
||
|
Rev 1.18 2003.11.29 10:19:04 AM czhower
|
||
|
Updated for core change to InputBuffer.
|
||
|
|
||
|
Rev 1.17 2003.10.21 9:13:10 PM czhower
|
||
|
Now compiles.
|
||
|
|
||
|
Rev 1.16 10/19/2003 5:25:10 PM DSiders
|
||
|
Added localization comments.
|
||
|
|
||
|
Rev 1.15 2003.10.18 9:42:10 PM czhower
|
||
|
Boatload of bug fixes to command handlers.
|
||
|
|
||
|
Rev 1.14 2003.10.12 4:04:00 PM czhower
|
||
|
compile todos
|
||
|
|
||
|
Rev 1.13 9/19/2003 03:30:06 PM JPMugaas
|
||
|
Now should compile again.
|
||
|
|
||
|
Rev 1.12 04.06.2003 14:09:28 ARybin
|
||
|
updated for new IoHandler behavior
|
||
|
|
||
|
Rev 1.11 3/6/2003 5:08:46 PM SGrobety
|
||
|
Updated the read buffer methodes to fit the new core (InputBuffer ->
|
||
|
InputBufferAsString + call to CheckForDataOnSource)
|
||
|
|
||
|
Rev 1.10 28.05.2003 17:35:34 ARybin
|
||
|
right bug fix
|
||
|
|
||
|
Rev 1.9 28.05.2003 16:55:30 ARybin
|
||
|
bug fix
|
||
|
|
||
|
Rev 1.8 5/26/2003 12:23:46 PM JPMugaas
|
||
|
|
||
|
Rev 1.7 4/3/2003 7:26:10 PM BGooijen
|
||
|
Re-enabled .ConnectTimeout and .Connect
|
||
|
|
||
|
Rev 1.6 3/21/2003 11:45:36 AM JPMugaas
|
||
|
Added OnBeforeConnect method so the TIdMappedPort component is more flexible.
|
||
|
|
||
|
Rev 1.5 2/24/2003 09:14:38 PM JPMugaas
|
||
|
|
||
|
Rev 1.4 1/20/2003 1:15:32 PM BGooijen
|
||
|
Changed to TIdTCPServer / TIdCmdTCPServer classes
|
||
|
|
||
|
Rev 1.3 1/17/2003 06:45:12 PM JPMugaas
|
||
|
Now compiles with new framework.
|
||
|
|
||
|
Rev 1.2 1-8-2003 22:20:40 BGooijen
|
||
|
these compile (TIdContext)
|
||
|
|
||
|
Rev 1.1 12/7/2002 06:43:10 PM JPMugaas
|
||
|
These should now compile except for Socks server. IPVersion has to be a
|
||
|
property someplace for that.
|
||
|
|
||
|
Rev 1.0 11/13/2002 07:56:42 AM JPMugaas
|
||
|
|
||
|
2001-12-xx - Andrew P.Rybin
|
||
|
-new architecture
|
||
|
|
||
|
2002-02-02 - Andrew P.Rybin
|
||
|
-DoDisconnect fix
|
||
|
}
|
||
|
|
||
|
unit IdMappedPortTCP;
|
||
|
|
||
|
interface
|
||
|
|
||
|
{$i IdCompilerDefines.inc}
|
||
|
|
||
|
uses
|
||
|
Classes,
|
||
|
IdAssignedNumbers,
|
||
|
IdContext,
|
||
|
IdCustomTCPServer,
|
||
|
IdGlobal, IdStack, IdTCPConnection, IdTCPServer, IdYarn, SysUtils;
|
||
|
|
||
|
type
|
||
|
TIdMappedPortTCP = class;
|
||
|
|
||
|
TIdMappedPortContext = class(TIdServerContext)
|
||
|
protected
|
||
|
FOutboundClient: TIdTCPConnection;//was TIdTCPClient
|
||
|
FReadList: TIdSocketList;
|
||
|
FDataAvailList: TIdSocketList;
|
||
|
FConnectTimeOut: Integer;
|
||
|
FNetData: TIdBytes;
|
||
|
FServer : TIdMappedPortTCP;
|
||
|
//
|
||
|
procedure CheckForData(DoRead: Boolean); virtual;
|
||
|
procedure HandleLocalClientData; virtual;
|
||
|
procedure HandleOutboundClientData; virtual;
|
||
|
procedure OutboundConnect; virtual;
|
||
|
public
|
||
|
constructor Create(
|
||
|
AConnection: TIdTCPConnection;
|
||
|
AYarn: TIdYarn;
|
||
|
AList: TIdContextThreadList = nil
|
||
|
); override;
|
||
|
destructor Destroy; override;
|
||
|
//
|
||
|
property Server : TIdMappedPortTCP Read FServer write FServer;
|
||
|
property ConnectTimeOut: Integer read FConnectTimeOut write FConnectTimeOut default IdTimeoutDefault;
|
||
|
property NetData: TIdBytes read FNetData write FNetData;
|
||
|
property OutboundClient: TIdTCPConnection read FOutboundClient write FOutboundClient;
|
||
|
end;//TIdMappedPortContext
|
||
|
|
||
|
TIdMappedPortTCP = class(TIdCustomTCPServer)
|
||
|
protected
|
||
|
FMappedHost: string;
|
||
|
FMappedPort: TIdPort;
|
||
|
FOnBeforeConnect: TIdServerThreadEvent;
|
||
|
|
||
|
//AThread.Connection.Server & AThread.OutboundClient
|
||
|
FOnOutboundConnect: TIdServerThreadEvent;
|
||
|
FOnOutboundData: TIdServerThreadEvent;
|
||
|
FOnOutboundDisConnect: TIdServerThreadEvent;
|
||
|
//
|
||
|
procedure ContextCreated(AContext:TIdContext); override;
|
||
|
procedure DoBeforeConnect(AContext: TIdContext); virtual;
|
||
|
procedure DoConnect(AContext: TIdContext); override;
|
||
|
function DoExecute(AContext: TIdContext): boolean; override;
|
||
|
procedure DoDisconnect(AContext: TIdContext); override; //DoLocalClientDisconnect
|
||
|
procedure DoLocalClientConnect(AContext: TIdContext); virtual;
|
||
|
procedure DoLocalClientData(AContext: TIdContext); virtual;//APR: bServer
|
||
|
|
||
|
procedure DoOutboundClientConnect(AContext: TIdContext); virtual;
|
||
|
procedure DoOutboundClientData(AContext: TIdContext); virtual;
|
||
|
procedure DoOutboundDisconnect(AContext: TIdContext); virtual;
|
||
|
function GetOnConnect: TIdServerThreadEvent;
|
||
|
function GetOnExecute: TIdServerThreadEvent;
|
||
|
procedure SetOnConnect(const Value: TIdServerThreadEvent);
|
||
|
procedure SetOnExecute(const Value: TIdServerThreadEvent);
|
||
|
function GetOnDisconnect: TIdServerThreadEvent;
|
||
|
procedure SetOnDisconnect(const Value: TIdServerThreadEvent);
|
||
|
procedure InitComponent; override;
|
||
|
published
|
||
|
property OnBeforeConnect: TIdServerThreadEvent read FOnBeforeConnect write FOnBeforeConnect;
|
||
|
property MappedHost: String read FMappedHost write FMappedHost;
|
||
|
property MappedPort: TIdPort read FMappedPort write FMappedPort;
|
||
|
//
|
||
|
property OnConnect: TIdServerThreadEvent read GetOnConnect write SetOnConnect; //OnLocalClientConnect
|
||
|
property OnOutboundConnect: TIdServerThreadEvent read FOnOutboundConnect write FOnOutboundConnect;
|
||
|
|
||
|
property OnExecute: TIdServerThreadEvent read GetOnExecute write SetOnExecute;//OnLocalClientData
|
||
|
property OnOutboundData: TIdServerThreadEvent read FOnOutboundData write FOnOutboundData;
|
||
|
|
||
|
property OnDisconnect: TIdServerThreadEvent read GetOnDisconnect write SetOnDisconnect;//OnLocalClientDisconnect
|
||
|
property OnOutboundDisconnect: TIdServerThreadEvent read FOnOutboundDisconnect write FOnOutboundDisconnect;
|
||
|
End;//TIdMappedPortTCP
|
||
|
|
||
|
Implementation
|
||
|
|
||
|
uses
|
||
|
IdException,
|
||
|
IdIOHandler, IdIOHandlerSocket, IdResourceStrings,IdStackConsts, IdTCPClient;
|
||
|
|
||
|
procedure TIdMappedPortTCP.InitComponent;
|
||
|
begin
|
||
|
inherited InitComponent;
|
||
|
FContextClass := TIdMappedPortContext;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.ContextCreated(AContext: TIdContext);
|
||
|
begin
|
||
|
TIdMappedPortContext(AContext).Server := Self;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.DoBeforeConnect(AContext: TIdContext);
|
||
|
begin
|
||
|
if Assigned(FOnBeforeConnect) then begin
|
||
|
FOnBeforeConnect(AContext);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.DoLocalClientConnect(AContext: TIdContext);
|
||
|
begin
|
||
|
if Assigned(FOnConnect) then begin
|
||
|
FOnConnect(AContext);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.DoOutboundClientConnect(AContext: TIdContext);
|
||
|
begin
|
||
|
if Assigned(FOnOutboundConnect) then begin
|
||
|
FOnOutboundConnect(AContext);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.DoLocalClientData(AContext: TIdContext);
|
||
|
begin
|
||
|
if Assigned(FOnExecute) then begin
|
||
|
FOnExecute(AContext);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.DoOutboundClientData(AContext: TIdContext);
|
||
|
begin
|
||
|
if Assigned(FOnOutboundData) then begin
|
||
|
FOnOutboundData(AContext);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.DoDisconnect(AContext: TIdContext);
|
||
|
begin
|
||
|
inherited DoDisconnect(AContext);
|
||
|
//check for loop
|
||
|
if Assigned(TIdMappedPortContext(AContext).FOutboundClient) and
|
||
|
TIdMappedPortContext(AContext).FOutboundClient.Connected then
|
||
|
begin
|
||
|
TIdMappedPortContext(AContext).FOutboundClient.Disconnect;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.DoOutboundDisconnect(AContext: TIdContext);
|
||
|
begin
|
||
|
if Assigned(FOnOutboundDisconnect) then begin
|
||
|
FOnOutboundDisconnect(AContext);
|
||
|
end;
|
||
|
AContext.Connection.Disconnect; //disconnect local
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.DoConnect(AContext: TIdContext);
|
||
|
var
|
||
|
LContext: TIdMappedPortContext;
|
||
|
begin
|
||
|
DoBeforeConnect(AContext);
|
||
|
|
||
|
LContext := TIdMappedPortContext(AContext);
|
||
|
|
||
|
//WARNING: Check TIdTCPServer.DoConnect and synchronize code. Don't call inherited!=> OnConnect in OutboundConnect {Do not Localize}
|
||
|
LContext.OutboundConnect;
|
||
|
|
||
|
//cache
|
||
|
LContext.FReadList.Clear;
|
||
|
LContext.FReadList.Add(AContext.Connection.Socket.Binding.Handle);
|
||
|
LContext.FReadList.Add(LContext.FOutboundClient.Socket.Binding.Handle);
|
||
|
end;
|
||
|
|
||
|
function TIdMappedPortTCP.DoExecute(AContext: TIdContext): Boolean;
|
||
|
var
|
||
|
LContext: TIdMappedPortContext;
|
||
|
begin
|
||
|
LContext := TIdMappedPortContext(AContext);
|
||
|
try
|
||
|
LContext.CheckForData(True);
|
||
|
finally
|
||
|
if not LContext.FOutboundClient.Connected then begin
|
||
|
Result := False;
|
||
|
DoOutboundDisconnect(AContext); //&Connection.Disconnect
|
||
|
end else begin;
|
||
|
Result := AContext.Connection.Connected;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TIdMappedPortTCP.GetOnConnect: TIdServerThreadEvent;
|
||
|
begin
|
||
|
Result := FOnConnect;
|
||
|
end;
|
||
|
|
||
|
function TIdMappedPortTCP.GetOnExecute: TIdServerThreadEvent;
|
||
|
begin
|
||
|
Result := FOnExecute;
|
||
|
end;
|
||
|
|
||
|
function TIdMappedPortTCP.GetOnDisconnect: TIdServerThreadEvent;
|
||
|
begin
|
||
|
Result := FOnDisconnect;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.SetOnConnect(const Value: TIdServerThreadEvent);
|
||
|
begin
|
||
|
FOnConnect := Value;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.SetOnExecute(const Value: TIdServerThreadEvent);
|
||
|
begin
|
||
|
FOnExecute := Value;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortTCP.SetOnDisconnect(const Value: TIdServerThreadEvent);
|
||
|
begin
|
||
|
FOnDisconnect := Value;
|
||
|
end;
|
||
|
|
||
|
|
||
|
{ TIdMappedPortContext }
|
||
|
|
||
|
constructor TIdMappedPortContext.Create(
|
||
|
AConnection: TIdTCPConnection;
|
||
|
AYarn: TIdYarn;
|
||
|
AList: TIdContextThreadList = nil
|
||
|
);
|
||
|
begin
|
||
|
inherited Create(AConnection, AYarn, AList);
|
||
|
FReadList := TIdSocketList.CreateSocketList;
|
||
|
FDataAvailList := TIdSocketList.CreateSocketList;
|
||
|
FConnectTimeOut := IdTimeoutDefault;
|
||
|
end;
|
||
|
|
||
|
destructor TIdMappedPortContext.Destroy;
|
||
|
begin
|
||
|
FreeAndNil(FOutboundClient);
|
||
|
FreeAndNIL(FReadList);
|
||
|
FreeAndNIL(FDataAvailList);
|
||
|
inherited Destroy;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortContext.CheckForData(DoRead: Boolean);
|
||
|
begin
|
||
|
if DoRead and Connection.IOHandler.InputBufferIsEmpty and FOutboundClient.IOHandler.InputBufferIsEmpty then
|
||
|
begin
|
||
|
if FReadList.SelectReadList(FDataAvailList, IdTimeoutInfinite) then
|
||
|
begin
|
||
|
//1.LConnectionHandle
|
||
|
if FDataAvailList.ContainsSocket(Connection.Socket.Binding.Handle) then
|
||
|
begin
|
||
|
// TODO: WSAECONNRESET (Exception [EIdSocketError] Socket Error # 10054 Connection reset by peer)
|
||
|
Connection.IOHandler.CheckForDataOnSource(0);
|
||
|
end;
|
||
|
//2.LOutBoundHandle
|
||
|
if FDataAvailList.ContainsSocket(FOutboundClient.Socket.Binding.Handle) then
|
||
|
begin
|
||
|
FOutboundClient.IOHandler.CheckForDataOnSource(0);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
if not Connection.IOHandler.InputBufferIsEmpty then
|
||
|
begin
|
||
|
HandleLocalClientData;
|
||
|
end;
|
||
|
if not FOutboundClient.IOHandler.InputBufferIsEmpty then
|
||
|
begin
|
||
|
HandleOutboundClientData;
|
||
|
end;
|
||
|
Connection.IOHandler.CheckForDisconnect;
|
||
|
FOutboundClient.IOHandler.CheckForDisconnect;
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortContext.HandleLocalClientData;
|
||
|
begin
|
||
|
SetLength(FNetData, 0);
|
||
|
Connection.IOHandler.InputBuffer.ExtractToBytes(FNetData);
|
||
|
Server.DoLocalClientData(Self);
|
||
|
FOutboundClient.IOHandler.Write(FNetData);
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortContext.HandleOutboundClientData;
|
||
|
begin
|
||
|
SetLength(FNetData, 0);
|
||
|
FOutboundClient.IOHandler.InputBuffer.ExtractToBytes(FNetData);
|
||
|
Server.DoOutboundClientData(Self);
|
||
|
Connection.IOHandler.Write(FNetData);
|
||
|
end;
|
||
|
|
||
|
procedure TIdMappedPortContext.OutboundConnect;
|
||
|
var
|
||
|
LServer: TIdMappedPortTCP;
|
||
|
LClient: TIdTCPClient;
|
||
|
begin
|
||
|
FOutboundClient := TIdTCPClient.Create(nil);
|
||
|
LServer := TIdMappedPortTCP(Server);
|
||
|
try
|
||
|
LClient := TIdTCPClient(FOutboundClient);
|
||
|
|
||
|
LClient.Port := LServer.MappedPort;
|
||
|
LClient.Host := LServer.MappedHost;
|
||
|
|
||
|
LServer.DoLocalClientConnect(Self);
|
||
|
|
||
|
LClient.ConnectTimeout := FConnectTimeOut;
|
||
|
LClient.Connect;
|
||
|
|
||
|
LServer.DoOutboundClientConnect(Self);
|
||
|
|
||
|
//APR: buffer can contain data from prev (users) read op.
|
||
|
CheckForData(False);
|
||
|
except
|
||
|
on E: Exception do
|
||
|
begin
|
||
|
DoException(E);// DONE: Handle connect failures
|
||
|
Connection.Disconnect; //req IdTcpServer with "Stop this thread if we were disconnected"
|
||
|
raise;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
end.
|