www.pudn.com > indy10.0.52_source.rar > IdUDPBase.pas


{ $HDR$} 
{**********************************************************************} 
{ Unit archived using Team Coherence                                   } 
{ Team Coherence is Copyright 2002 by Quality Software Components      } 
{                                                                      } 
{ For further information / comments, visit our WEB site at            } 
{ http://www.TeamCoherence.com                                         } 
{**********************************************************************} 
{} 
{ $Log:  12016: IdUDPBase.pas  
{ 
{   Rev 1.14    11/11/04 12:05:32 PM  RLebeau 
{ Updated ReceiveBuffer() to set AMSec to IdTimeoutInfinite when the 
{ ReceiveTimeout property is 0 
} 
{ 
{   Rev 1.13    11/7/2004 11:33:30 PM  JPMugaas 
{ Now uses Connect, Disconnect, Send, and Receive similarly to the TCP Clients. 
{  This should prevent unneeded DNS name to IP address conversions that SendTo 
{ was doing. 
} 
{ 
{   Rev 1.12    7/21/04 3:33:10 PM  RLebeau 
{ Updated TIdUDPBase.ReceiveString() to use new BytesToString() parameters 
} 
{ 
{   Rev 1.11    09/06/2004 00:29:56  CCostelloe 
{ Kylix 3 patch 
} 
{ 
{   Rev 1.10    2004.02.03 4:17:00 PM  czhower 
{ For unit name changes. 
} 
{ 
{   Rev 1.9    21.1.2004 ã. 12:31:00  DBondzhev 
{ Fix for Indy source. Workaround for dccil bug 
{ now it can be compiled using Compile instead of build 
} 
{ 
{   Rev 1.7    10/26/2003 12:30:18 PM  BGooijen 
{ DotNet 
} 
{ 
{   Rev 1.6    10/24/2003 5:18:36 PM  BGooijen 
{ Removed boolean shortcutting from .GetActive 
} 
{ 
{   Rev 1.5    10/22/2003 04:40:58 PM  JPMugaas 
{ Should compile with some restored functionality.  Still not finished. 
} 
{ 
{   Rev 1.4    10/19/2003 9:34:30 PM  BGooijen 
{ SetSocketOption 
} 
{ 
{   Rev 1.3    2003.10.11 9:58:48 PM  czhower 
{ Started on some todos 
} 
{ 
{   Rev 1.2    2003.10.11 5:52:10 PM  czhower 
{ -VCL fixes for servers 
{ -Chain suport for servers (Super core) 
{ -Scheduler upgrades 
{ -Full yarn support 
} 
{ 
{   Rev 1.1    2003.09.30 1:23:08 PM  czhower 
{ Stack split for DotNet 
} 
{ 
{   Rev 1.0    11/13/2002 09:02:06 AM  JPMugaas 
} 
unit IdUDPBase; 
 
interface 
 
uses 
  Classes, 
  IdComponent, IdGlobal, IdException, IdSocketHandle; 
 
const 
  ID_UDP_BUFFERSIZE = 8192; 
 
type 
  TIdUDPBase = class(TIdComponent) 
  protected 
    FBinding: TIdSocketHandle; 
    FBufferSize: Integer; 
    FDsgnActive: Boolean; 
    FHost: String; 
    FPort: Integer; 
    FReceiveTimeout: Integer; 
    FIPVersion: TIdIPVersion; 
    // 
    FBroadcastEnabled: Boolean; 
    procedure BroadcastEnabledChanged; dynamic; 
    procedure CloseBinding; virtual; 
    function GetActive: Boolean; virtual; 
    procedure InitComponent; override; 
    procedure SetActive(const Value: Boolean); 
    procedure SetBroadcastFlag( 
      AEnabled: Boolean; 
      ABinding: TIdSocketHandle = nil 
      ); 
    procedure SetBroadcastEnabled(AValue: Boolean); 
    function GetBinding: TIdSocketHandle; virtual; 
    procedure Loaded; override; 
 
    function GetIPVersion: TIdIPVersion;  virtual; 
    procedure SetIPVersion(const AValue: TIdIPVersion); virtual; 
 
    function GetHost : String; virtual; 
    procedure SetHost(const AValue : String); virtual; 
 
    function GetPort : Integer; virtual; 
    procedure SetPort(const AValue : Integer); virtual; 
 
    property Host: string read GetHost write SetHost; 
    property Port: Integer read GetPort write SetPort; 
  public 
    destructor Destroy; override; 
    // 
    property Binding: TIdSocketHandle read GetBinding; 
    procedure Broadcast(const AData: string; const APort: integer); 
    function ReceiveBuffer(var ABuffer : TIdBytes; 
      var VPeerIP: string; var VPeerPort: integer; 
      AMSec: Integer = IdTimeoutDefault): integer; overload; virtual; 
 
    function ReceiveString(const AMSec: Integer = IdTimeoutDefault): string; overload; 
    function ReceiveString(var VPeerIP: string; var VPeerPort: integer; 
     const AMSec: Integer = IdTimeoutDefault): string;  overload; 
    function ReceiveBuffer(var ABuffer : TIdBytes; 
     const AMSec: Integer = IdTimeoutDefault): Integer; overload;  virtual; 
    procedure Send(AHost: string; const APort: Integer; const AData: string); 
    procedure SendBuffer(AHost: string; const APort: Integer; const ABuffer : TIdBytes); virtual; 
    // 
    property ReceiveTimeout: Integer read FReceiveTimeout write FReceiveTimeout default IdTimeoutInfinite; 
  published 
    property Active: Boolean read GetActive write SetActive Default False; 
    property BufferSize: Integer read FBufferSize write FBufferSize default ID_UDP_BUFFERSIZE; 
    property BroadcastEnabled: Boolean read FBroadcastEnabled 
     write SetBroadcastEnabled Default False; 
    property IPVersion: TIdIPVersion read GetIPVersion write SetIPVersion default ID_DEFAULT_IP_VERSION; 
  end; 
  EIdUDPException = Class(EIdException); 
  EIdUDPReceiveErrorZeroBytes = class(EIdUDPException); 
 
implementation 
 
uses 
  IdStackConsts, IdStack, 
  SysUtils; 
 
{ TIdUDPBase } 
 
procedure TIdUDPBase.Broadcast(const AData: string; const APort: integer); 
begin 
  SetBroadcastFlag(True); 
  Send('255.255.255.255', APort, AData);    {Do not Localize} 
  BroadcastEnabledChanged; 
end; 
 
procedure TIdUDPBase.BroadcastEnabledChanged; 
begin 
  SetBroadcastFlag(BroadcastEnabled); 
end; 
 
procedure TIdUDPBase.CloseBinding; 
begin 
  FreeAndNil(FBinding); 
end; 
 
destructor TIdUDPBase.Destroy; 
begin 
  Active := False; 
  inherited; 
end; 
 
function TIdUDPBase.GetActive: Boolean; 
begin 
  Result := FDsgnActive; 
  if not Result then begin 
    if Assigned(FBinding) then begin 
      if FBinding.HandleAllocated then begin 
        result:=true; 
      end; 
    end; 
  end; 
end; 
 
function TIdUDPBase.GetBinding: TIdSocketHandle; 
begin 
  if FBinding = nil then begin 
    FBinding := TIdSocketHandle.Create(nil); 
  end; 
  if not FBinding.HandleAllocated then begin 
{$IFDEF LINUX} 
    FBinding.AllocateSocket(Integer(Id_SOCK_DGRAM)); 
{$ELSE} 
    FBinding.AllocateSocket(Id_SOCK_DGRAM); 
{$ENDIF} 
    BroadcastEnabledChanged; 
  end; 
  Result := FBinding; 
end; 
 
function TIdUDPBase.GetHost: String; 
begin 
  Result := FHost; 
end; 
 
function TIdUDPBase.GetIPVersion: TIdIPVersion; 
begin 
  Result := FIPVersion; 
end; 
 
function TIdUDPBase.GetPort: Integer; 
begin 
  Result := FPort; 
end; 
 
procedure TIdUDPBase.InitComponent; 
begin 
  inherited; 
  BufferSize := ID_UDP_BUFFERSIZE; 
  FReceiveTimeout := IdTimeoutInfinite; 
  FIPVersion := ID_DEFAULT_IP_VERSION; 
end; 
 
procedure TIdUDPBase.Loaded; 
var 
  b: Boolean; 
begin 
  inherited; 
  b := FDsgnActive; 
  FDsgnActive := False; 
  Active := b; 
end; 
 
function TIdUDPBase.ReceiveBuffer(var ABuffer : TIdBytes; 
  const AMSec: Integer = IdTimeoutDefault): Integer; 
var 
  VoidIP: string; 
  VoidPort: Integer; 
begin 
  Result := ReceiveBuffer(ABuffer,  VoidIP, VoidPort, AMSec); 
end; 
 
function TIdUDPBase.ReceiveBuffer(var ABuffer : TIdBytes; 
  var VPeerIP: string; var VPeerPort: integer; 
  AMSec: Integer = IdTimeoutDefault): integer; 
begin 
  if AMSec = IdTimeoutDefault then begin 
    if ReceiveTimeOut = 0 then begin 
      AMSec := IdTimeoutInfinite; 
    end else begin 
      AMSec := ReceiveTimeOut; 
    end; 
  end; 
  if not Binding.Readable(AMSec) then begin 
    Result := 0; 
    VPeerIP := '';    {Do not Localize} 
    VPeerPort := 0; 
    Exit; 
  end; 
  Result := Binding.RecvFrom(ABuffer,VPeerIP, VPeerPort); 
 // (GStack as TIdStackBSDBase).CheckForSocketError(Result); 
end; 
 
function TIdUDPBase.ReceiveString(var VPeerIP: string; var VPeerPort: integer; 
  const AMSec: Integer = IdTimeoutDefault): string; 
var 
  i: Integer; 
  LBuffer : TIdBytes; 
begin 
  SetLength(LBuffer, BufferSize); 
  i := ReceiveBuffer(LBuffer, VPeerIP, VPeerPort, AMSec); 
  Result := BytesToString(LBuffer, 0, i); 
end; 
 
function TIdUDPBase.ReceiveString(const AMSec: Integer): string; 
var 
  VoidIP: string; 
  VoidPort: Integer; 
begin 
  Result := ReceiveString(VoidIP, VoidPort, AMSec); 
end; 
 
procedure TIdUDPBase.Send(AHost: string; const APort: Integer; const AData: string); 
begin 
  SendBuffer(AHost, APort, ToBytes(AData)); 
end; 
 
procedure TIdUDPBase.SendBuffer(AHost: string; const APort: Integer; const ABuffer : TIdBytes); 
begin 
  AHost := GStack.ResolveHost(AHost); 
  Binding.SendTo(AHost, APort, ABuffer); 
end; 
 
procedure TIdUDPBase.SetActive(const Value: Boolean); 
begin 
  if (Active <> Value) then begin 
    if not ((csDesigning in ComponentState) or (csLoading in ComponentState)) then begin 
      if Value then begin 
        GetBinding; 
      end 
      else begin 
        CloseBinding; 
      end; 
    end 
    else begin  // don't activate at designtime (or during loading of properties)    {Do not Localize} 
      FDsgnActive := Value; 
    end; 
  end; 
end; 
 
procedure TIdUDPBase.SetBroadcastEnabled(AValue: Boolean); 
begin 
  if FBroadCastEnabled <> AValue then begin 
    FBroadcastEnabled := AValue; 
    if Active then begin 
      BroadcastEnabledChanged; 
    end; 
  end; 
end; 
 
procedure TIdUDPBase.SetBroadcastFlag( 
  AEnabled: Boolean; 
  ABinding: TIdSocketHandle = nil 
  ); 
begin 
  if ABinding = nil then begin 
    ABinding := Binding; 
  end; 
  GStack.SetSocketOption(ABinding.Handle,Id_SOL_SOCKET, Id_SO_BROADCAST, iif(AEnabled,1,0)); 
end; 
 
procedure TIdUDPBase.SetHost(const AValue: String); 
begin 
  FHost := Avalue; 
end; 
 
procedure TIdUDPBase.SetIPVersion(const AValue: TIdIPVersion); 
begin 
  FIPVersion := AValue; 
end; 
 
procedure TIdUDPBase.SetPort(const AValue: Integer); 
begin 
  FPort := AValue; 
end; 
 
end.