IdRawBase.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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.15 7/9/04 4:26:28 PM RLebeau
  18. Removed TIdBytes local variable from Send()
  19. Rev 1.14 09/06/2004 00:28:00 CCostelloe
  20. Kylix 3 patch
  21. Rev 1.13 4/25/2004 7:54:26 AM JPMugaas
  22. Fix for AV.
  23. Rev 1.12 2/8/2004 12:58:42 PM JPMugaas
  24. Should now compile in DotNET.
  25. Rev 1.11 2004.02.03 4:16:48 PM czhower
  26. For unit name changes.
  27. Rev 1.10 2/1/2004 6:10:14 PM JPMugaas
  28. Should compile better.
  29. Rev 1.9 2/1/2004 4:52:34 PM JPMugaas
  30. Removed the rest of the Todo; items.
  31. Rev 1.8 2004.01.20 10:03:30 PM czhower
  32. InitComponent
  33. Rev 1.7 2004.01.02 9:38:46 PM czhower
  34. Removed warning
  35. Rev 1.6 2003.10.24 10:09:54 AM czhower
  36. Compiles
  37. Rev 1.5 2003.10.20 12:03:08 PM czhower
  38. Added IdStackBSDBase to make it compile again.
  39. Rev 1.4 10/19/2003 10:41:12 PM BGooijen
  40. Compiles in DotNet and D7 again
  41. Rev 1.3 10/19/2003 9:34:28 PM BGooijen
  42. SetSocketOption
  43. Rev 1.2 2003.10.11 5:48:58 PM czhower
  44. -VCL fixes for servers
  45. -Chain suport for servers (Super core)
  46. -Scheduler upgrades
  47. -Full yarn support
  48. Rev 1.1 2003.09.30 1:23:00 PM czhower
  49. Stack split for DotNet
  50. Rev 1.0 11/13/2002 08:45:24 AM JPMugaas
  51. }
  52. unit IdRawBase;
  53. interface
  54. {
  55. We need to selectively disable some functionality in DotNET with buffers as
  56. we don't want to impact anything else such as TIdICMPClient.
  57. }
  58. {$I IdCompilerDefines.inc}
  59. uses
  60. Classes,
  61. IdComponent, IdGlobal, IdSocketHandle, IdStack,
  62. {$IFDEF WINDOWS}
  63. IdWship6,
  64. {$ENDIF}
  65. IdStackConsts;
  66. const
  67. Id_TIdRawBase_Port = 0;
  68. Id_TIdRawBase_BufferSize = 8192;
  69. GReceiveTimeout = 0;
  70. GFTTL = 128;
  71. type
  72. TIdRawBase = class(TIdComponent)
  73. protected
  74. FBinding: TIdSocketHandle;
  75. FHost: string;
  76. FPort: TIdPort;
  77. FReceiveTimeout: integer;
  78. FProtocol: TIdSocketProtocol;
  79. FProtocolIPv6 : TIdSocketProtocol;
  80. FTTL: Integer;
  81. FPkt : TIdPacketInfo;
  82. FConnected : Boolean;
  83. //
  84. function GetBinding: TIdSocketHandle;
  85. function GetIPVersion: TIdIPVersion;
  86. //
  87. procedure SetIPVersion(const AValue: TIdIPVersion);
  88. procedure SetTTL(const Value: Integer);
  89. procedure SetHost(const AValue : String); virtual;
  90. //
  91. // TODO: figure out which ReceiveXXX functions we want
  92. //
  93. property IPVersion : TIdIPVersion read GetIPVersion write SetIPVersion;
  94. //
  95. property Port: TIdPort read FPort write FPort default Id_TIdRawBase_Port;
  96. property Protocol: TIdSocketProtocol read FProtocol write FProtocol default Id_IPPROTO_RAW;
  97. property ProtocolIPv6 : TIdSocketProtocol read FProtocolIPv6 write FProtocolIPv6;
  98. property TTL: Integer read FTTL write SetTTL default GFTTL;
  99. public
  100. constructor Create(AOwner: TComponent); override;
  101. destructor Destroy; override;
  102. function ReceiveBuffer(var VBuffer : TIdBytes; ATimeOut: Integer = -1): Integer;
  103. procedure Send(const AData: string; AByteEncoding: IIdTextEncoding = nil); overload; virtual;
  104. procedure Send(const AData: TIdBytes); overload; virtual;
  105. procedure Send(const AHost: string; const APort: TIdPort; const AData: string; AByteEncoding: IIdTextEncoding = nil); overload; virtual;
  106. procedure Send(const AHost: string; const APort: TIdPort; const ABuffer : TIdBytes); overload; virtual;
  107. //
  108. property Binding: TIdSocketHandle read GetBinding;
  109. property ReceiveTimeout: integer read FReceiveTimeout write FReceiveTimeout Default GReceiveTimeout;
  110. published
  111. property Host: string read FHost write SetHost;
  112. end;
  113. implementation
  114. uses
  115. SysUtils;
  116. { TIdRawBase }
  117. constructor TIdRawBase.Create(AOwner: TComponent);
  118. begin
  119. inherited Create(AOwner);
  120. FBinding := TIdSocketHandle.Create(nil);
  121. FBinding.IPVersion := ID_DEFAULT_IP_VERSION;
  122. FPkt := TIdPacketInfo.Create;
  123. ReceiveTimeout := GReceiveTimeout;
  124. FPort := Id_TIdRawBase_Port;
  125. FProtocol := Id_IPPROTO_RAW;
  126. FTTL := GFTTL;
  127. end;
  128. destructor TIdRawBase.Destroy;
  129. begin
  130. FBinding.Free;
  131. FPkt.Free;
  132. inherited Destroy;
  133. end;
  134. function TIdRawBase.GetBinding: TIdSocketHandle;
  135. begin
  136. if not FBinding.HandleAllocated then begin
  137. if FBinding.IPVersion = Id_IPv4 then
  138. begin
  139. FBinding.AllocateSocket(Id_SOCK_RAW, FProtocol);
  140. end else
  141. begin
  142. FBinding.AllocateSocket(Id_SOCK_RAW, FProtocolIPv6);
  143. //indicate we want packet information with RecvMsg WSARecvMsg calls
  144. FBinding.SetSockOpt(Id_SOL_IPv6, Id_IPV6_PKTINFO, 1);
  145. FBinding.SetSockOpt(Id_SOL_IPv6, Id_IPV6_HOPLIMIT, 1);
  146. end;
  147. //set hop limit (or TTL as it was called in IPv4
  148. FBinding.SetTTL(FTTL);
  149. end;
  150. Result := FBinding;
  151. end;
  152. function TIdRawBase.ReceiveBuffer(var VBuffer : TIdBytes; ATimeOut: Integer = -1): Integer;
  153. var
  154. LIP : String;
  155. LPort : TIdPort;
  156. LIPVersion: TIdIPVersion;
  157. begin
  158. Result := 0;
  159. // TODO: pass flags to recv()
  160. if ATimeOut < 0 then
  161. begin
  162. ATimeOut := FReceiveTimeout;
  163. end;
  164. if VBuffer <> nil then
  165. begin
  166. if Binding.Readable(ATimeOut) then begin
  167. if FBinding.IPVersion = Id_IPv4 then
  168. begin
  169. Result := Binding.RecvFrom(VBuffer, LIP, LPort, LIPVersion);
  170. FPkt.Reset;
  171. FPkt.SourceIP := LIP;
  172. FPkt.SourcePort := LPort;
  173. FPkt.SourceIPVersion := LIPVersion;
  174. FPkt.DestIPVersion := LIPVersion;
  175. end else
  176. begin
  177. {
  178. IMPORTANT!!!!
  179. Do NOT call GStack.ReceiveMsg unless it is absolutely necessary.
  180. The reasons are:
  181. 1) WSARecvMsg is only supported on WindowsXP or later. I think Linux
  182. might have a RecvMsg function as well but I'm not sure.
  183. 2) GStack.ReceiveMsg is not supported in the Microsoft NET framework 1.1.
  184. It may be supported in later versions.
  185. For IPv4 and raw sockets, it usually isn't because we get the raw header itself.
  186. For IPv6 and raw sockets, we call this to get information about the destination
  187. IP address and hopefully, the TTL (hop count).
  188. }
  189. Result := GStack.ReceiveMsg(Binding.Handle, VBuffer, FPkt);
  190. end;
  191. end;
  192. end;
  193. end;
  194. procedure TIdRawBase.Send(const AHost: string; const APort: TIdPort; const AData: string;
  195. AByteEncoding: IIdTextEncoding = nil);
  196. begin
  197. Send(AHost, APort, ToBytes(AData, AByteEncoding));
  198. end;
  199. procedure TIdRawBase.Send(const AData: string; AByteEncoding: IIdTextEncoding = nil);
  200. begin
  201. Send(ToBytes(AData, AByteEncoding));
  202. end;
  203. procedure TIdRawBase.Send(const AData: TIdBytes);
  204. begin
  205. Send(Host, Port, AData);
  206. end;
  207. procedure TIdRawBase.Send(const AHost: string; const APort: TIdPort; const ABuffer : TIdBytes);
  208. var
  209. LIP : String;
  210. begin
  211. LIP := GStack.ResolveHost(AHost, FBinding.IPVersion);
  212. Binding.SendTo(LIP, APort, ABuffer, FBinding.IPVersion);
  213. end;
  214. procedure TIdRawBase.SetTTL(const Value: Integer);
  215. begin
  216. if FTTL <> Value then
  217. begin
  218. FTTL := Value;
  219. if FBinding.HandleAllocated then
  220. begin
  221. FBinding.SetTTL(FTTL);
  222. end;
  223. end;
  224. end;
  225. function TIdRawBase.GetIPVersion;
  226. begin
  227. Result := FBinding.IPVersion;
  228. end;
  229. procedure TIdRawBase.SetIPVersion(const AValue: TIdIPVersion);
  230. begin
  231. FBinding.IPVersion := AValue;
  232. end;
  233. procedure TIdRawBase.SetHost(const AValue: String);
  234. begin
  235. FHost := AValue;
  236. end;
  237. end.