IdIPMCastBase.pas 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.4 2004.02.03 5:43:52 PM czhower
  18. Name changes
  19. Rev 1.3 1/21/2004 3:11:06 PM JPMugaas
  20. InitComponent
  21. Rev 1.2 10/26/2003 09:11:50 AM JPMugaas
  22. Should now work in NET.
  23. Rev 1.1 2003.10.12 4:03:56 PM czhower
  24. compile todos
  25. Rev 1.0 11/13/2002 07:55:16 AM JPMugaas
  26. }
  27. unit IdIPMCastBase;
  28. interface
  29. {$I IdCompilerDefines.inc}
  30. //here to flip FPC into Delphi mode
  31. uses
  32. {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS}
  33. Classes,
  34. {$ENDIF}
  35. IdComponent, IdException, IdGlobal, IdSocketHandle,
  36. IdStack;
  37. (*$HPPEMIT '#if defined(_VCL_ALIAS_RECORDS)' *)
  38. (*$HPPEMIT '#if !defined(UNICODE)' *)
  39. (*$HPPEMIT '#pragma alias "@Idipmcastbase@TIdIPMCastBase@SetPortA$qqrxi"="@Idipmcastbase@TIdIPMCastBase@SetPort$qqrxi"' *)
  40. (*$HPPEMIT '#else' *)
  41. (*$HPPEMIT '#pragma alias "@Idipmcastbase@TIdIPMCastBase@SetPortW$qqrxi"="@Idipmcastbase@TIdIPMCastBase@SetPort$qqrxi"' *)
  42. (*$HPPEMIT '#endif' *)
  43. (*$HPPEMIT '#endif' *)
  44. // TODO: when compiling with bcc64x, use this pragma instead:
  45. // #pragma comment(linker, "/alternatename:<name1>=<name2>")
  46. const
  47. IPMCastLo = 224;
  48. IPMCastHi = 239;
  49. type
  50. TIdIPMv6Scope = ( IdIPv6MC_InterfaceLocal,
  51. { Interface-Local scope spans only a single interface on a node
  52. and is useful only for loopback transmission of multicast.}
  53. IdIPv6MC_LinkLocal,
  54. { Link-Local multicast scope spans the same topological region as
  55. the corresponding unicast scope. }
  56. IdIPv6MC_AdminLocal,
  57. { Admin-Local scope is the smallest scope that must be
  58. administratively configured, i.e., not automatically derived
  59. from physical connectivity or other, non-multicast-related
  60. configuration.}
  61. IdIPv6MC_SiteLocal,
  62. { Site-Local scope is intended to span a single site. }
  63. IdIPv6MC_OrgLocal,
  64. {Organization-Local scope is intended to span multiple sites
  65. belonging to a single organization.}
  66. IdIPv6MC_Global);
  67. TIdIPMCValidScopes = 0..$F;
  68. TIdIPMCastBase = class(TIdComponent)
  69. protected
  70. FDsgnActive: Boolean;
  71. FMulticastGroup: String;
  72. FPort: Integer;
  73. FIPVersion: TIdIPVersion;
  74. FReuseSocket: TIdReuseSocket;
  75. //
  76. procedure CloseBinding; virtual; abstract;
  77. function GetActive: Boolean; virtual;
  78. function GetBinding: TIdSocketHandle; virtual; abstract;
  79. procedure Loaded; override;
  80. procedure SetActive(const Value: Boolean); virtual;
  81. procedure SetMulticastGroup(const Value: string); virtual;
  82. procedure SetPort(const Value: integer); virtual;
  83. function GetIPVersion: TIdIPVersion; virtual;
  84. procedure SetIPVersion(const AValue: TIdIPVersion); virtual;
  85. //
  86. property Active: Boolean read GetActive write SetActive Default False;
  87. property MulticastGroup: string read FMulticastGroup write SetMulticastGroup;
  88. property Port: Integer read FPort write SetPort;
  89. property IPVersion: TIdIPVersion read GetIPVersion write SetIPVersion default ID_DEFAULT_IP_VERSION;
  90. procedure InitComponent; override;
  91. public
  92. {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS}
  93. constructor Create(AOwner: TComponent); reintroduce; overload;
  94. {$ENDIF}
  95. function IsValidMulticastGroup(const Value: string): Boolean;
  96. {These two items are helper functions that allow you to specify the scope for
  97. a Variable Scope Multicast Addresses. Some are listed in IdAssignedNumbers
  98. as the Id_IPv6MC_V_ constants. You can't use them out of the box in the
  99. MulticastGroup property because you need to specify the scope. This provides
  100. you with more flexibility than you would get with IPv4 multicasting.}
  101. class function SetIPv6AddrScope(const AVarIPv6Addr : String; const AScope : TIdIPMv6Scope ) : String; overload;
  102. class function SetIPv6AddrScope(const AVarIPv6Addr : String; const AScope : TIdIPMCValidScopes): String; overload;
  103. //
  104. property ReuseSocket: TIdReuseSocket read FReuseSocket write FReuseSocket default rsOSDependent;
  105. published
  106. end;
  107. EIdMCastException = Class(EIdException);
  108. EIdMCastNoBindings = class(EIdMCastException);
  109. EIdMCastNotValidAddress = class(EIdMCastException);
  110. EIdMCastReceiveErrorZeroBytes = class(EIdMCastException);
  111. const
  112. DEF_IPv6_MGROUP = 'FF01:0:0:0:0:0:0:1'; {do not localize}
  113. implementation
  114. uses
  115. IdAssignedNumbers,
  116. IdResourceStringsCore,
  117. SysUtils;
  118. { TIdIPMCastBase }
  119. {$IFDEF WORKAROUND_INLINE_CONSTRUCTORS}
  120. constructor TIdIPMCastBase.Create(AOwner: TComponent);
  121. begin
  122. inherited Create(AOwner);
  123. end;
  124. {$ENDIF}
  125. function TIdIPMCastBase.GetIPVersion: TIdIPVersion;
  126. begin
  127. Result := FIPVersion;
  128. end;
  129. procedure TIdIPMCastBase.InitComponent;
  130. begin
  131. inherited InitComponent;
  132. FIPVersion := ID_DEFAULT_IP_VERSION;
  133. FMultiCastGroup := {$IFDEF IdIPv6}DEF_IPv6_MGROUP{$ELSE}Id_IPMC_All_Systems{$ENDIF};
  134. FReuseSocket := rsOSDependent;
  135. end;
  136. function TIdIPMCastBase.GetActive: Boolean;
  137. begin
  138. Result := FDsgnActive;
  139. end;
  140. function TIdIPMCastBase.IsValidMulticastGroup(const Value: string): Boolean;
  141. begin
  142. //just here to prevent a warning from Delphi about an unitialized result
  143. Result := False;
  144. case FIPVersion of
  145. Id_IPv4 : Result := GStack.IsValidIPv4MulticastGroup(Value);
  146. Id_IPv6 : Result := GStack.IsValidIPv6MulticastGroup(Value);
  147. end;
  148. end;
  149. procedure TIdIPMCastBase.Loaded;
  150. begin
  151. inherited Loaded;
  152. if FDsgnActive then begin
  153. FDsgnActive := False;
  154. Active := True;
  155. end;
  156. end;
  157. procedure TIdIPMCastBase.SetActive(const Value: Boolean);
  158. begin
  159. if IsDesignTime or IsLoading then begin
  160. // don't activate at designtime (or during loading of properties) {Do not Localize}
  161. FDsgnActive := Value;
  162. end
  163. else if Active <> Value then begin
  164. if Value then begin
  165. GetBinding;
  166. end else begin
  167. CloseBinding;
  168. end;
  169. end;
  170. end;
  171. class function TIdIPMCastBase.SetIPv6AddrScope(const AVarIPv6Addr: String;
  172. const AScope: TIdIPMv6Scope): String;
  173. begin
  174. case AScope of
  175. IdIPv6MC_InterfaceLocal : Result := SetIPv6AddrScope(AVarIPv6Addr,$1);
  176. IdIPv6MC_LinkLocal : Result := SetIPv6AddrScope(AVarIPv6Addr,$2);
  177. IdIPv6MC_AdminLocal : Result := SetIPv6AddrScope(AVarIPv6Addr,$4);
  178. IdIPv6MC_SiteLocal : Result := SetIPv6AddrScope(AVarIPv6Addr,$5);
  179. IdIPv6MC_OrgLocal : Result := SetIPv6AddrScope(AVarIPv6Addr,$8);
  180. IdIPv6MC_Global : Result := SetIPv6AddrScope(AVarIPv6Addr,$E);
  181. else
  182. Result := AVarIPv6Addr;
  183. end;
  184. end;
  185. class function TIdIPMCastBase.SetIPv6AddrScope(const AVarIPv6Addr: String;
  186. const AScope: TIdIPMCValidScopes): String;
  187. begin
  188. //Replace the X in the Id_IPv6MC_V_ constants with the specified scope
  189. Result := ReplaceOnlyFirst(AVarIPv6Addr, 'X', IntToHex(AScope,1)); {do not localize}
  190. end;
  191. procedure TIdIPMCastBase.SetIPVersion(const AValue: TIdIPVersion);
  192. begin
  193. if AValue <> IPVersion then
  194. begin
  195. Active := False;
  196. FIPVersion := AValue;
  197. if not IsLoading then begin
  198. case AValue of
  199. Id_IPv4: FMulticastGroup := Id_IPMC_All_Systems;
  200. Id_IPv6: FMulticastGroup := DEF_IPv6_MGROUP;
  201. end;
  202. end;
  203. end;
  204. end;
  205. procedure TIdIPMCastBase.SetMulticastGroup(const Value: string);
  206. begin
  207. if FMulticastGroup <> Value then begin
  208. if (not IsLoading) and (not IsValidMulticastGroup(Value)) then begin
  209. raise EIdMCastNotValidAddress.Create(RSIPMCastInvalidMulticastAddress);
  210. end;
  211. Active := False;
  212. FMulticastGroup := Value;
  213. end;
  214. end;
  215. procedure TIdIPMCastBase.SetPort(const Value: integer);
  216. begin
  217. if FPort <> Value then begin
  218. Active := False;
  219. FPort := Value;
  220. end;
  221. end;
  222. end.