unit uROIndyTCPChannel; {----------------------------------------------------------------------------} { RemObjects SDK Library - Indy Components } { } { compiler: Delphi 5 and up, Kylix 2 and up } { platform: Win32, Linux } { } { (c)opyright RemObjects Software. all rights reserved. } { } { Using this code requires a valid license of the RemObjects SDK } { which can be obtained at http://www.remobjects.com. } {----------------------------------------------------------------------------} {$I RemObjects.inc} interface uses {$IFDEF REMOBJECTS_TRIAL}uROTrial,{$ENDIF} Classes, uROClient, IdBaseComponent, uROClientIntf, IdTCPClient; type {$IFDEF RemObjects_INDY10} TIdTCPClientBaseClass = TIdTCPClientCustom; TIdIndy10HackClient = class(TIdTCPClientCustom) public property Port; property Host; end; {$ELSE} TIdTCPClientBaseClass = TIdTcpClient; TIdIndy10HackClient = TIdTcpClient; {$ENDIF} { TROCustomIndyTCPChannel } TROCustomIndyTCPChannel = class(TROTransportChannel, IROTransport, IROTCPTransport) private fIndyClient : TIdTCPClientBaseClass; fKeepAlive: boolean; fDisableNagle: boolean; function GetHost: string; function GetPort: integer; procedure SetHost(const Value: string); procedure SetPort(const Value: integer); protected procedure IntDispatch(aRequest, aResponse : TStream); override; procedure IntSetServerLocator(aServerLocator : TROServerLocator); override; function CreateIndyClient: TIdTCPClientBaseClass; virtual; {$IFDEF DESIGNTIME} {$IFDEF MSWINDOWS} procedure NoIndyAtDesigntime; {$ENDIF MSWINDOWS} {$ENDIF DESIGNTIME} { IROTransport } function GetTransportObject : TObject; override; { IROTCPTransport } function GetClientAddress : string; public constructor Create(aOwner : TComponent); override; property Port : integer read GetPort write SetPort; property Host : string read GetHost write SetHost; property DisableNagle : boolean read fDisableNagle write fDisableNagle default FALSE; property IndyClient : TIdTCPClientBaseClass read fIndyClient; property KeepAlive : boolean read fKeepAlive write fKeepAlive default false; published property SynchronizedProbing; property OnSendStream; property OnReceiveStream; property ServerLocators; property DispatchOptions; property OnServerLocatorAssignment; property ProbeServers; property ProbeFrequency; property OnBeforeProbingServers; property OnAfterProbingServers; property OnBeforeProbingServer; property OnAfterProbingServer; property OnLoginNeeded; end; { TROIndyTCPChannel } TROIndyTCPChannel = class(TROCustomIndyTCPChannel, IROTransport, IROTCPTransport) private protected published property Port; property Host; property DisableNagle; property IndyClient; property KeepAlive; end; implementation uses {$IFDEF RemObjects_INDY10}IdStreamVCL, {$ENDIF} SysUtils, uRORes, uROClasses, idstackconsts; { TROCustomIndyTCPChannel } constructor TROCustomIndyTCPChannel.Create(aOwner: TComponent); begin inherited; fIndyClient := CreateIndyClient; fIndyClient.Name := 'InternalIndyClient'; {$IFDEF DELPHI6UP} fIndyClient.SetSubComponent(TRUE); {$ENDIF} end; function TROCustomIndyTCPChannel.CreateIndyClient: TIdTCPClientBaseClass; begin result := TIdTCPClient.Create(Self); TIdTCPClient(result).Port := 8090; TIdTCPClient(result).Host := '127.0.0.1'; end; function TROCustomIndyTCPChannel.GetClientAddress: string; begin {$IFDEF REMOBJECTS_INDY8} if IndyClient.Binding <> nil then Result := IndyClient.Binding.PeerIP else Result := ''; {$ELSE} if (IndyClient.Socket <> nil) and (IndyClient.Socket.Binding <> nil) then Result := IndyClient.Socket.Binding.PeerIP else Result := ''; {$ENDIF} end; function TROCustomIndyTCPChannel.GetTransportObject: TObject; begin result := Self; end; procedure TROCustomIndyTCPChannel.IntSetServerLocator( aServerLocator: TROServerLocator); begin Host := aServerLocator.Host; Port := aServerLocator.Port; end; procedure TROCustomIndyTCPChannel.IntDispatch(aRequest, aResponse: TStream); {$IFDEF RemObjects_INDY10A} var lStream: TIdStreamVCL; {$ENDIF} begin {$IFDEF DESIGNTIME} {$IFDEF MSWINDOWS} NoIndyAtDesigntime(); {$ENDIF MSWINDOWS} {$ENDIF DESIGNTIME} try if not IndyClient.Connected then begin IndyClient.Connect; if DisableNagle then begin {$IFDEF RemObjects_INDY8} IndyClient.Binding.SetSockOpt(Id_IPPROTO_TCP, Id_TCP_NODELAY, PChar(@Id_SO_True), SizeOf(Id_SO_True)); {$ELSE} {$IFDEF RemObjects_INDY9} IndyClient.Socket.Binding.SetSockOpt(Id_IPPROTO_TCP, Id_TCP_NODELAY, PChar(@Id_SO_True), SizeOf(Id_SO_True)); {$ELSE} IndyClient.Socket.Binding.SetSockOpt(Id_IPPROTO_TCP, Id_TCP_NODELAY, Id_SO_True); {$ENDIF} {$ENDIF} end; end; {$IFDEF RemObjects_INDY10A} lStream := TIdStreamVCL.Create(aRequest, false); lStream.Position := 0; try IndyClient.IOHandler.Write(lStream, lStream.Size, TRUE); finally FreeAndNil(lStream); end; lStream := TIdStreamVCL.Create(aResponse, false); try IndyClient.IOHandler.ReadStream(lStream); finally FreeAndNil(lStream); end; {$ELSE} aRequest.Position := 0; {$IFDEF RemObjects_INDY10B} IndyClient.IOHandler.Write(aRequest, aRequest.Size, TRUE); IndyClient.IOHandler.ReadStream(aResponse); {$ELSE} IndyClient.WriteStream(aRequest, TRUE, TRUE); IndyClient.ReadStream(aResponse); {$ENDIF} {$ENDIF} finally if not KeepAlive then IndyClient.Disconnect; end; end; {$IFDEF DESIGNTIME} {$IFDEF MSWINDOWS} procedure TROCustomIndyTCPChannel.NoIndyAtDesigntime; begin {$IFNDEF RemObjects_INDY_DESIGNTIME_FIX} if csDesigning in ComponentState then raise EROIDEProblem.Create('We''re sorry, but the '+ClassName+' cannot be used inside the Delphi IDE at designtime.'#13#13+ 'This is due to a Indy issue and outside of our control.'#13#13+ 'Please use TROWinInetHttpChannel instead.'#13#13#13+ 'If your version if Indy is patched to fix this problem, please set the'#13+ '"RemObjects_INDY_DESIGNTIME_FIX" define in RemObjects.inc and rebuild the package.'); {$ENDIF RemObjects_INDY_DESIGNTIME_FIX} end; {$ENDIF MSWINDOWS} {$ENDIF DESIGNTIME} function TROCustomIndyTCPChannel.GetHost: string; begin result := TIdIndy10HackClient(IndyClient).Host; end; function TROCustomIndyTCPChannel.GetPort: integer; begin result := TIdIndy10HackClient(IndyClient).Port; end; procedure TROCustomIndyTCPChannel.SetHost(const Value: string); begin TIdIndy10HackClient(IndyClient).Host := Value; end; procedure TROCustomIndyTCPChannel.SetPort(const Value: integer); begin TIdIndy10HackClient(IndyClient).Port := Value; end; initialization RegisterTransportChannelClass(TROIndyTCPChannel); finalization UnRegisterTransportChannelClass(TROIndyTCPChannel); end.