IdRawBase.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. IdComponent, IdGlobal, IdSocketHandle, IdStack,
  61. {$IFDEF WINDOWS}
  62. IdWship6,
  63. {$ENDIF}
  64. IdStackConsts;
  65. const
  66. Id_TIdRawBase_Port = 0;
  67. Id_TIdRawBase_BufferSize = 8192;
  68. GReceiveTimeout = 0;
  69. GFTTL = 128;
  70. type
  71. TIdRawBase = class(TIdComponent)
  72. protected
  73. FBinding: TIdSocketHandle;
  74. FHost: string;
  75. FPort: TIdPort;
  76. FReceiveTimeout: integer;
  77. FProtocol: TIdSocketProtocol;
  78. FProtocolIPv6 : TIdSocketProtocol;
  79. FTTL: Integer;
  80. FPkt : TIdPacketInfo;
  81. FConnected : Boolean;
  82. //
  83. function GetBinding: TIdSocketHandle;
  84. function GetIPVersion: TIdIPVersion;
  85. //
  86. procedure InitComponent; override;
  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. destructor Destroy; override;
  101. function ReceiveBuffer(var VBuffer : TIdBytes; ATimeOut: Integer = -1): Integer;
  102. procedure Send(const AData: string; AByteEncoding: IIdTextEncoding = nil
  103. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  104. ); overload; virtual;
  105. procedure Send(const AData: TIdBytes); overload; virtual;
  106. procedure Send(const AHost: string; const APort: TIdPort; const AData: string;
  107. AByteEncoding: IIdTextEncoding = nil
  108. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  109. ); overload; virtual;
  110. procedure Send(const AHost: string; const APort: TIdPort; const ABuffer : TIdBytes); overload; virtual;
  111. //
  112. property Binding: TIdSocketHandle read GetBinding;
  113. property ReceiveTimeout: integer read FReceiveTimeout write FReceiveTimeout Default GReceiveTimeout;
  114. published
  115. property Host: string read FHost write SetHost;
  116. end;
  117. implementation
  118. uses
  119. SysUtils;
  120. { TIdRawBase }
  121. destructor TIdRawBase.Destroy;
  122. begin
  123. FreeAndNil(FBinding);
  124. FreeAndNil(FPkt);
  125. inherited Destroy;
  126. end;
  127. function TIdRawBase.GetBinding: TIdSocketHandle;
  128. begin
  129. if not FBinding.HandleAllocated then begin
  130. if FBinding.IPVersion = Id_IPv4 then
  131. begin
  132. FBinding.AllocateSocket(Id_SOCK_RAW, FProtocol);
  133. end else
  134. begin
  135. FBinding.AllocateSocket(Id_SOCK_RAW, FProtocolIPv6);
  136. {$IFDEF DOTNET}
  137. {$IFDEF DOTNET_2_OR_ABOVE}
  138. {
  139. Microsoft NET Framework 1.1 may actually have the packetinfo option but that
  140. will not do you any good because you need a RecvMsg function which is not
  141. in NET 1.1. NET 2.0 does have a RecvMsg function, BTW.
  142. }
  143. //indicate we want packet information with RecvMsg calls
  144. FBinding.SetSockOpt(Id_SOL_IPv6, Id_IPV6_PKTINFO, 1);
  145. {$ENDIF}
  146. {$ELSE}
  147. //indicate we want packet information with RecvMsg WSARecvMsg calls
  148. FBinding.SetSockOpt(Id_SOL_IPv6, Id_IPV6_PKTINFO, 1);
  149. FBinding.SetSockOpt(Id_SOL_IPv6, Id_IPV6_HOPLIMIT, 1);
  150. {$ENDIF}
  151. end;
  152. //set hop limit (or TTL as it was called in IPv4
  153. FBinding.SetTTL(FTTL);
  154. end;
  155. Result := FBinding;
  156. end;
  157. function TIdRawBase.ReceiveBuffer(var VBuffer : TIdBytes; ATimeOut: Integer = -1): Integer;
  158. var
  159. LIP : String;
  160. LPort : TIdPort;
  161. LIPVersion: TIdIPVersion;
  162. begin
  163. Result := 0;
  164. // TODO: pass flags to recv()
  165. if ATimeOut < 0 then
  166. begin
  167. ATimeOut := FReceiveTimeout;
  168. end;
  169. if Length(VBuffer) > 0 then
  170. begin
  171. if Binding.Readable(ATimeOut) then begin
  172. if FBinding.IPVersion = Id_IPv4 then
  173. begin
  174. Result := Binding.RecvFrom(VBuffer, LIP, LPort, LIPVersion);
  175. FPkt.Reset;
  176. FPkt.SourceIP := LIP;
  177. FPkt.SourcePort := LPort;
  178. FPkt.SourceIPVersion := LIPVersion;
  179. FPkt.DestIPVersion := LIPVersion;
  180. end else
  181. begin
  182. {
  183. IMPORTANT!!!!
  184. Do NOT call GStack.ReceiveMsg unless it is absolutely necessary.
  185. The reasons are:
  186. 1) WSARecvMsg is only supported on WindowsXP or later. I think Linux
  187. might have a RecvMsg function as well but I'm not sure.
  188. 2) GStack.ReceiveMsg is not supported in the Microsoft NET framework 1.1.
  189. It may be supported in later versions.
  190. For IPv4 and raw sockets, it usually isn't because we get the raw header itself.
  191. For IPv6 and raw sockets, we call this to get information about the destination
  192. IP address and hopefully, the TTL (hop count).
  193. }
  194. Result := GStack.ReceiveMsg(Binding.Handle, VBuffer, FPkt);
  195. end;
  196. end;
  197. end;
  198. end;
  199. procedure TIdRawBase.Send(const AHost: string; const APort: TIdPort; const AData: string;
  200. AByteEncoding: IIdTextEncoding = nil
  201. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  202. );
  203. begin
  204. Send(AHost, APort, ToBytes(AData, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF}));
  205. end;
  206. procedure TIdRawBase.Send(const AData: string;
  207. AByteEncoding: IIdTextEncoding = nil
  208. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  209. );
  210. begin
  211. Send(ToBytes(AData, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF}));
  212. end;
  213. procedure TIdRawBase.Send(const AData: TIdBytes);
  214. begin
  215. Send(Host, Port, AData);
  216. end;
  217. procedure TIdRawBase.Send(const AHost: string; const APort: TIdPort; const ABuffer : TIdBytes);
  218. var
  219. LIP : String;
  220. begin
  221. LIP := GStack.ResolveHost(AHost, FBinding.IPVersion);
  222. Binding.SendTo(LIP, APort, ABuffer, FBinding.IPVersion);
  223. end;
  224. procedure TIdRawBase.SetTTL(const Value: Integer);
  225. begin
  226. if FTTL <> Value then
  227. begin
  228. FTTL := Value;
  229. if FBinding.HandleAllocated then
  230. begin
  231. FBinding.SetTTL(FTTL);
  232. end;
  233. end;
  234. end;
  235. procedure TIdRawBase.InitComponent;
  236. begin
  237. inherited InitComponent;
  238. FBinding := TIdSocketHandle.Create(nil);
  239. FBinding.IPVersion := ID_DEFAULT_IP_VERSION;
  240. FPkt := TIdPacketInfo.Create;
  241. ReceiveTimeout := GReceiveTimeout;
  242. FPort := Id_TIdRawBase_Port;
  243. FProtocol := Id_IPPROTO_RAW;
  244. FTTL := GFTTL;
  245. end;
  246. function TIdRawBase.GetIPVersion;
  247. begin
  248. Result := FBinding.IPVersion;
  249. end;
  250. procedure TIdRawBase.SetIPVersion(const AValue: TIdIPVersion);
  251. begin
  252. FBinding.IPVersion := AValue;
  253. end;
  254. procedure TIdRawBase.SetHost(const AValue: String);
  255. begin
  256. FHost := AValue;
  257. end;
  258. end.