IdIPMCastServer.pas 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10223: IdIPMCastServer.pas
  11. {
  12. { Rev 1.0 2002.11.12 10:43:20 PM czhower
  13. }
  14. unit IdIPMCastServer;
  15. {
  16. History:
  17. Date By Description
  18. ---------- ---------- --------------------------------------------------
  19. 2001-10-16 DSiders Modified TIdIPMCastServer.MulticastBuffer to
  20. validate the AHost argument to the method instead
  21. of the MulticastGroup property.
  22. ??? Dr. Harley J. Mackenzie Initial revision.
  23. }
  24. interface
  25. uses
  26. Classes,
  27. IdIPMCastBase, IdComponent, IdSocketHandle;
  28. const
  29. DEF_IMP_LOOPBACK = True;
  30. DEF_IMP_TTL = 1;
  31. type
  32. TIdIPMCastServer = class(TIdIPMCastBase)
  33. protected
  34. FBinding: TIdSocketHandle;
  35. FBoundIP: String;
  36. FBoundPort: Integer;
  37. FLoopback: Boolean;
  38. FTimeToLive: Byte;
  39. //
  40. procedure CloseBinding; override;
  41. function GetActive: Boolean; override;
  42. function GetBinding: TIdSocketHandle; override;
  43. procedure Loaded; override;
  44. procedure MulticastBuffer(AHost: string; const APort: Integer; var ABuffer; const AByteCount: integer);
  45. procedure SetLoopback(const AValue: Boolean); virtual;
  46. procedure SetLoopbackOption(InBinding: TIdSocketHandle; const Value: Boolean); virtual;
  47. procedure SetTTL(const Value: Byte); virtual;
  48. procedure SetTTLOption(InBinding: TIdSocketHandle; const Value: Byte); virtual;
  49. public
  50. constructor Create(AOwner: TComponent); override;
  51. procedure Send(AData: string);
  52. procedure SendBuffer(var ABuffer; const AByteCount: integer);
  53. destructor Destroy; override;
  54. //
  55. property Binding: TIdSocketHandle read GetBinding;
  56. published
  57. property Active;
  58. property BoundIP: String read FBoundIP write FBoundIP;
  59. property BoundPort: Integer read FBoundPort write FBoundPort;
  60. property Loopback: Boolean read FLoopback write SetLoopback default DEF_IMP_LOOPBACK;
  61. property MulticastGroup;
  62. property Port;
  63. property TimeToLive: Byte read FTimeToLive write SetTTL default DEF_IMP_TTL;
  64. end;
  65. implementation
  66. { TIdIPMCastServer }
  67. uses
  68. IdResourceStrings, IdStack, IdStackConsts, IdGlobal, SysUtils;
  69. constructor TIdIPMCastServer.Create(AOwner: TComponent);
  70. begin
  71. inherited Create(AOwner);
  72. FLoopback := DEF_IMP_LOOPBACK;
  73. FTimeToLive := DEF_IMP_TTL;
  74. end;
  75. procedure TIdIPMCastServer.CloseBinding;
  76. var
  77. Multicast: TMultiCast;
  78. begin
  79. Multicast.IMRMultiAddr := GStack.StringToTInAddr(FMulticastGroup);
  80. Multicast.IMRInterface.S_addr := Id_INADDR_ANY;
  81. FBinding.SetSockOpt(Id_IPPROTO_IP, Id_IP_DROP_MEMBERSHIP, pchar(@Multicast), SizeOf(Multicast));
  82. FreeAndNil(FBinding);
  83. end;
  84. function TIdIPMCastServer.GetActive: Boolean;
  85. begin
  86. Result := inherited GetActive or (Assigned(FBinding) and FBinding.HandleAllocated);
  87. end;
  88. function TIdIPMCastServer.GetBinding: TIdSocketHandle;
  89. var
  90. Multicast: TMultiCast;
  91. begin
  92. if not Assigned(FBinding) then begin
  93. FBinding := TIdSocketHandle.Create(nil);
  94. end;
  95. if not FBinding.HandleAllocated then begin
  96. FBinding.AllocateSocket(Id_SOCK_DGRAM);
  97. FBinding.IP := FBoundIP;
  98. FBinding.Port := FBoundPort;
  99. FBinding.Bind;
  100. Multicast.IMRMultiAddr := GStack.StringToTInAddr(FMulticastGroup);
  101. Multicast.IMRInterface.S_addr := Id_INADDR_ANY;
  102. FBinding.SetSockOpt(Id_IPPROTO_IP, Id_IP_ADD_MEMBERSHIP, pchar(@Multicast), SizeOf(Multicast));
  103. SetTTLOption(FBinding, FTimeToLive);
  104. SetLoopbackOption(FBinding, FLoopback);
  105. end;
  106. Result := FBinding;
  107. end;
  108. procedure TIdIPMCastServer.Loaded;
  109. var
  110. b: Boolean;
  111. begin
  112. inherited Loaded;
  113. b := FDsgnActive;
  114. FDsgnActive := False;
  115. Active := b;
  116. end;
  117. procedure TIdIPMCastServer.MulticastBuffer(AHost: string; const APort: Integer; var ABuffer; const AByteCount: integer);
  118. begin
  119. // DS - if not IsValidMulticastGroup(FMulticastGroup) then
  120. if not IsValidMulticastGroup(AHost) then
  121. raise EIdMCastNotValidAddress.Create(RSIPMCastInvalidMulticastAddress);
  122. Binding.SendTo(AHost, APort, ABuffer, AByteCount);
  123. end;
  124. procedure TIdIPMCastServer.Send(AData: string);
  125. begin
  126. MulticastBuffer(FMulticastGroup, FPort, PChar(AData)^, Length(AData));
  127. end;
  128. procedure TIdIPMCastServer.SendBuffer(var ABuffer; const AByteCount: integer);
  129. begin
  130. MulticastBuffer(FMulticastGroup, FPort, ABuffer, AByteCount);
  131. end;
  132. procedure TIdIPMCastServer.SetLoopback(const AValue: Boolean);
  133. var
  134. LThisLoopback: Integer;
  135. begin
  136. if FLoopback <> AValue then begin
  137. FLoopback := AValue;
  138. SetLoopbackOption(FBinding, AValue);
  139. end;
  140. end;
  141. procedure TIdIPMCastServer.SetLoopbackOption(InBinding: TIdSocketHandle; const Value: Boolean);
  142. var
  143. LThisLoopback: Integer;
  144. begin
  145. if Assigned(InBinding) and InBinding.HandleAllocated then begin
  146. LThisLoopback := iif(Value, 1, 0);
  147. InBinding.SetSockOpt(Id_IPPROTO_IP, Id_IP_MULTICAST_LOOP, PChar(@LThisLoopback), SizeOf(LThisLoopback));
  148. end;
  149. end;
  150. procedure TIdIPMCastServer.SetTTL(const Value: Byte);
  151. begin
  152. if (FTimeToLive <> Value) then begin
  153. FTimeToLive := Value;
  154. SetTTLOption(FBinding, Value);
  155. end;
  156. end;
  157. procedure TIdIPMCastServer.SetTTLOption(InBinding: TIdSocketHandle; const Value: Byte);
  158. var
  159. LThisTTL: Integer;
  160. begin
  161. if Assigned(InBinding) and InBinding.HandleAllocated then begin
  162. LThisTTL := Value;
  163. InBinding.SetSockOpt(Id_IPPROTO_IP, Id_IP_MULTICAST_TTL, PChar(@LThisTTL), SizeOf(LThisTTL));
  164. end;
  165. end;
  166. destructor TIdIPMCastServer.Destroy;
  167. begin
  168. Active := False;
  169. inherited Destroy;
  170. end;
  171. end.