IdUDPClient.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  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.11 11/12/2004 11:30:20 AM JPMugaas
  18. Expansions for IPv6.
  19. Rev 1.10 11/11/2004 10:25:26 PM JPMugaas
  20. Added OpenProxy and CloseProxy so you can do RecvFrom and SendTo functions
  21. from the UDP client with SOCKS. You must call OpenProxy before using
  22. RecvFrom or SendTo. When you are finished, you must use CloseProxy to close
  23. any connection to the Proxy. Connect and disconnect also call OpenProxy and
  24. CloseProxy.
  25. Rev 1.9 11/10/2004 9:40:42 PM JPMugaas
  26. Timeout error fix. Thanks Bas.
  27. Rev 1.8 11/9/2004 8:18:00 PM JPMugaas
  28. Attempt to add SOCKS support in UDP.
  29. Rev 1.7 11/8/2004 5:03:00 PM JPMugaas
  30. Eliminated Socket property because we probably do not need it after all.
  31. Binding should work just as well. I also made some minor refinements to
  32. Disconnect and Connect.
  33. Rev 1.6 11/7/2004 11:50:36 PM JPMugaas
  34. Fixed a Send method I broke. If FSocket is not assigned, it will call the
  35. inherited SendBuffer method. That should prevent code breakage. The connect
  36. method should be OPTIONAL because UDP may be used for simple one-packet
  37. query/response protocols.
  38. Rev 1.5 11/7/2004 11:33:30 PM JPMugaas
  39. Now uses Connect, Disconnect, Send, and Receive similarly to the TCP Clients.
  40. This should prevent unneeded DNS name to IP address conversions that SendTo
  41. was doing.
  42. Rev 1.4 2004.02.03 4:17:02 PM czhower
  43. For unit name changes.
  44. Rev 1.3 2004.01.21 2:35:40 PM czhower
  45. Removed illegal characters from file.
  46. Rev 1.2 21.1.2004 ã. 12:31:02 DBondzhev
  47. Fix for Indy source. Workaround for dccil bug
  48. now it can be compiled using Compile instead of build
  49. Rev 1.1 10/22/2003 04:41:00 PM JPMugaas
  50. Should compile with some restored functionality. Still not finished.
  51. Rev 1.0 11/13/2002 09:02:16 AM JPMugaas
  52. }
  53. unit IdUDPClient;
  54. interface
  55. {$I IdCompilerDefines.inc}
  56. //Put FPC into Delphi mode
  57. uses
  58. Classes,
  59. IdUDPBase,
  60. IdGlobal,
  61. IdSocketHandle,
  62. IdCustomTransparentProxy;
  63. (*$HPPEMIT '#if defined(_VCL_ALIAS_RECORDS)' *)
  64. (*$HPPEMIT '#if !defined(UNICODE)' *)
  65. (*$HPPEMIT '#pragma alias "@Idudpclient@TIdUDPClient@SetPortA$qqrxus"="@Idudpclient@TIdUDPClient@SetPort$qqrxus"' *)
  66. (*$HPPEMIT '#else' *)
  67. (*$HPPEMIT '#pragma alias "@Idudpclient@TIdUDPClient@SetPortW$qqrxus"="@Idudpclient@TIdUDPClient@SetPort$qqrxus"' *)
  68. (*$HPPEMIT '#endif' *)
  69. (*$HPPEMIT '#endif' *)
  70. // TODO: when compiling with bcc64x, use this pragma instead:
  71. // #pragma comment(linker, "/alternatename:<name1>=<name2>")
  72. type
  73. EIdMustUseOpenProxy = class(EIdUDPException);
  74. TIdUDPClient = class(TIdUDPBase)
  75. protected
  76. FBoundIP: string;
  77. FBoundPort: TIdPort;
  78. FBoundPortMin: TIdPort;
  79. FBoundPortMax: TIdPort;
  80. FProxyOpened : Boolean;
  81. FOnConnected : TNotifyEvent;
  82. FOnDisconnected: TNotifyEvent;
  83. FConnected : Boolean;
  84. {$IFDEF USE_OBJECT_ARC}[Weak]{$ENDIF} FTransparentProxy: TIdCustomTransparentProxy;
  85. FImplicitTransparentProxy: Boolean;
  86. function UseProxy : Boolean;
  87. procedure RaiseUseProxyError;
  88. procedure DoOnConnected; virtual;
  89. procedure DoOnDisconnected; virtual;
  90. procedure InitComponent; override;
  91. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  92. //property methods
  93. procedure SetIPVersion(const AValue: TIdIPVersion); override;
  94. procedure SetHost(const AValue : String); override;
  95. procedure SetPort(const AValue : TIdPort); override;
  96. procedure SetTransparentProxy(AProxy : TIdCustomTransparentProxy);
  97. function GetBinding: TIdSocketHandle; override;
  98. {$IFNDEF TRANSPARENTPROXY_GETTER_BUG}
  99. function GetTransparentProxy: TIdCustomTransparentProxy;
  100. {$ENDIF}
  101. public
  102. destructor Destroy; override;
  103. procedure OpenProxy;
  104. procedure CloseProxy;
  105. procedure Connect; virtual;
  106. procedure Disconnect; virtual;
  107. function Connected: Boolean;
  108. function ReceiveBuffer(var ABuffer : TIdBytes;
  109. const AMSec: Integer = IdTimeoutDefault): Integer; overload; override;
  110. function ReceiveBuffer(var ABuffer : TIdBytes;
  111. var VPeerIP: string; var VPeerPort: TIdPort;
  112. AMSec: Integer = IdTimeoutDefault): integer; overload; override;
  113. function ReceiveBuffer(var ABuffer : TIdBytes;
  114. var VPeerIP: string; var VPeerPort: TIdPort; var VIPVersion: TIdIPVersion;
  115. const AMSec: Integer = IdTimeoutDefault): integer; overload; override;
  116. procedure Send(const AData: string; AByteEncoding: IIdTextEncoding = nil
  117. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  118. ); overload;
  119. procedure SendBuffer(const AHost: string; const APort: TIdPort; const ABuffer : TIdBytes); overload; override;
  120. procedure SendBuffer(const ABuffer: TIdBytes); reintroduce; overload;
  121. procedure SendBuffer(const AHost: string; const APort: TIdPort;
  122. const AIPVersion: TIdIPVersion; const ABuffer: TIdBytes);overload; override;
  123. published
  124. property BoundIP: string read FBoundIP write FBoundIP;
  125. property BoundPort: TIdPort read FBoundPort write FBoundPort default DEF_PORT_ANY;
  126. property BoundPortMin: TIdPort read FBoundPortMin write FBoundPortMin default DEF_PORT_ANY;
  127. property BoundPortMax: TIdPort read FBoundPortMax write FBoundPortMax default DEF_PORT_ANY;
  128. property IPVersion default ID_DEFAULT_IP_VERSION;
  129. property Host;
  130. property Port;
  131. property ReceiveTimeout;
  132. property ReuseSocket;
  133. property TransparentProxy: TIdCustomTransparentProxy read {$IFDEF TRANSPARENTPROXY_GETTER_BUG}FTransparentProxy{$ELSE}GetTransparentProxy{$ENDIF} write SetTransparentProxy;
  134. property OnConnected: TNotifyEvent read FOnConnected write FOnConnected;
  135. property OnDisconnected: TNotifyEvent read FOnDisconnected write FOnDisconnected;
  136. end;
  137. implementation
  138. uses
  139. IdComponent, IdResourceStringsCore, IdSocks, IdStack, IdStackConsts,
  140. SysUtils;
  141. { TIdUDPClient }
  142. procedure TIdUDPClient.CloseProxy;
  143. begin
  144. if UseProxy and FProxyOpened then begin
  145. FTransparentProxy.CloseUDP(Binding);
  146. FProxyOpened := False;
  147. end;
  148. end;
  149. procedure TIdUDPClient.Connect;
  150. var
  151. LIP : String;
  152. // under ARC, convert a weak reference to a strong reference before working with it
  153. LTransparentProxy: TIdCustomTransparentProxy;
  154. begin
  155. if Connected then begin
  156. Disconnect;
  157. end;
  158. LTransparentProxy := FTransparentProxy;
  159. if Assigned(LTransparentProxy) then begin
  160. if LTransparentProxy.Enabled then begin
  161. //we don't use proxy open because we want to pass a peer's hostname and port
  162. //in case a proxy type in the future requires this.
  163. LTransparentProxy.OpenUDP(Binding, Host, Port);
  164. FProxyOpened := True;
  165. FConnected := True;
  166. Exit; //we're done, the transparentProxy takes care of the work.
  167. end;
  168. end;
  169. if FIPVersion = Id_IPv4 then
  170. begin
  171. if not GStack.IsIP(Host) then begin
  172. if Assigned(OnStatus) then begin
  173. {$IFDEF OVERLOADED_OPENARRAY_BUG}DoStatusArr{$ELSE}DoStatus{$ENDIF}(hsResolving, [Host]);
  174. end;
  175. LIP := GStack.ResolveHost(Host, FIPVersion);
  176. end else begin
  177. LIP := Host;
  178. end;
  179. end
  180. else
  181. begin //IPv6
  182. LIP := MakeCanonicalIPv6Address(Host);
  183. if LIP = '' then begin //if MakeCanonicalIPv6Address failed, we have a hostname
  184. if Assigned(OnStatus) then begin
  185. {$IFDEF OVERLOADED_OPENARRAY_BUG}DoStatusArr{$ELSE}DoStatus{$ENDIF}(hsResolving, [Host]);
  186. end;
  187. LIP := GStack.ResolveHost(Host, FIPVersion);
  188. end else begin
  189. LIP := Host;
  190. end;
  191. end;
  192. Binding.SetPeer(LIP, Port, FIPVersion);
  193. Binding.Connect;
  194. {$IFDEF OVERLOADED_OPENARRAY_BUG}DoStatusArr{$ELSE}DoStatus{$ENDIF}(hsConnected, [Host]);
  195. DoOnConnected;
  196. FConnected := True;
  197. end;
  198. function TIdUDPClient.Connected: Boolean;
  199. begin
  200. Result := FConnected;
  201. if Result then begin
  202. Result := Assigned(FBinding);
  203. if Result then begin
  204. Result := FBinding.HandleAllocated;
  205. end;
  206. end;
  207. end;
  208. procedure TIdUDPClient.Disconnect;
  209. begin
  210. if Connected then begin
  211. DoStatus(hsDisconnecting);
  212. if UseProxy and FProxyOpened then begin
  213. CloseProxy;
  214. end;
  215. FBinding.CloseSocket;
  216. DoOnDisconnected;
  217. DoStatus(hsDisconnected);
  218. FConnected := False;
  219. end;
  220. end;
  221. procedure TIdUDPClient.DoOnConnected;
  222. begin
  223. if Assigned(OnConnected) then begin
  224. OnConnected(Self);
  225. end;
  226. end;
  227. procedure TIdUDPClient.DoOnDisconnected;
  228. begin
  229. if Assigned(OnDisconnected) then begin
  230. OnDisconnected(Self);
  231. end;
  232. end;
  233. function TIdUDPClient.GetBinding: TIdSocketHandle;
  234. begin
  235. if FBinding = nil then begin
  236. FBinding := TIdSocketHandle.Create(nil);
  237. end;
  238. if not FBinding.HandleAllocated then begin
  239. FBinding.IPVersion := FIPVersion;
  240. FBinding.AllocateSocket(Id_SOCK_DGRAM);
  241. FBinding.IP := FBoundIP;
  242. FBinding.Port := FBoundPort;
  243. FBinding.ClientPortMin := FBoundPortMin;
  244. FBinding.ClientPortMax := FBoundPortMax;
  245. FBinding.ReuseSocket := FReuseSocket;
  246. FBinding.Bind;
  247. BroadcastEnabledChanged;
  248. end;
  249. Result := FBinding;
  250. end;
  251. {$IFNDEF TRANSPARENTPROXY_GETTER_BUG}
  252. function TIdUDPClient.GetTransparentProxy: TIdCustomTransparentProxy;
  253. var
  254. // under ARC, convert a weak reference to a strong reference before working with it
  255. LTransparentProxy: TIdCustomTransparentProxy;
  256. begin
  257. LTransparentProxy := FTransparentProxy;
  258. // Necessary at design time for Borland SOAP support
  259. // TODO: can we remove this getter and just require the user to link up a
  260. // TransparentProxy component manually at design-time? What problem, if any,
  261. // will this cause for SOAP support?
  262. if LTransparentProxy = nil then begin
  263. LTransparentProxy := TIdSocksInfo.Create(Self); //default
  264. {$IFDEF VCL_6_OR_ABOVE}
  265. if IsDesignTime then begin
  266. LTransparentProxy.SetSubComponent(True);
  267. end;
  268. {$ENDIF}
  269. FTransparentProxy := LTransparentProxy;
  270. FImplicitTransparentProxy := True;
  271. end;
  272. Result := LTransparentProxy;
  273. end;
  274. {$ENDIF}
  275. procedure TIdUDPClient.InitComponent;
  276. begin
  277. inherited InitComponent;
  278. FProxyOpened := False;
  279. FConnected := False;
  280. FBoundPort := DEF_PORT_ANY;
  281. FBoundPortMin := DEF_PORT_ANY;
  282. FBoundPortMax := DEF_PORT_ANY;
  283. end;
  284. // under ARC, all weak references to a freed object get nil'ed automatically
  285. // so this is mostly redundant
  286. procedure TIdUDPClient.Notification(AComponent: TComponent; Operation: TOperation);
  287. begin
  288. if (Operation = opRemove) and (AComponent = FTransparentProxy) then begin
  289. FTransparentProxy := nil;
  290. FImplicitTransparentProxy := False;
  291. end;
  292. inherited Notification(AComponent, Operation);
  293. end;
  294. procedure TIdUDPClient.OpenProxy;
  295. begin
  296. if UseProxy and (not FProxyOpened) then begin
  297. FTransparentProxy.OpenUDP(Binding);
  298. FProxyOpened := True;
  299. end;
  300. end;
  301. function TIdUDPClient.ReceiveBuffer(var ABuffer: TIdBytes;
  302. const AMSec: Integer): Integer;
  303. var
  304. LMSec : Integer;
  305. LHost : String;
  306. LPort : TIdPort;
  307. LIPVersion: TIdIPVersion;
  308. begin
  309. Result := 0;
  310. if AMSec = IdTimeoutDefault then begin
  311. if ReceiveTimeout = 0 then begin
  312. LMSec := IdTimeoutInfinite;
  313. end else begin
  314. LMSec := ReceiveTimeout;
  315. end;
  316. end else begin
  317. LMSec := AMSec;
  318. end;
  319. if UseProxy then begin
  320. if not FProxyOpened then begin
  321. RaiseUseProxyError;
  322. end;
  323. Result := FTransparentProxy.RecvFromUDP(Binding, ABuffer, LHost, LPort, LIPVersion, LMSec);
  324. end else
  325. begin
  326. if Connected then begin
  327. if FBinding.Readable(LMSec) then begin //Select(LMSec) then
  328. Result := FBinding.Receive(ABuffer);
  329. end;
  330. end else begin
  331. Result := inherited ReceiveBuffer(ABuffer, LMSec);
  332. end;
  333. end;
  334. end;
  335. procedure TIdUDPClient.RaiseUseProxyError;
  336. begin
  337. raise EIdMustUseOpenProxy.Create(RSUDPMustUseProxyOpen);
  338. end;
  339. function TIdUDPClient.ReceiveBuffer(var ABuffer: TIdBytes;
  340. var VPeerIP: string; var VPeerPort: TIdPort; AMSec: Integer): integer;
  341. var
  342. VoidIPVersion: TidIPVersion;
  343. begin
  344. Result := ReceiveBuffer(ABuffer, VPeerIP, VPeerPort, VoidIPVersion, AMSec);
  345. end;
  346. procedure TIdUDPClient.Send(const AData: string; AByteEncoding: IIdTextEncoding = nil
  347. {$IFDEF STRING_IS_ANSI}; ASrcEncoding: IIdTextEncoding = nil{$ENDIF}
  348. );
  349. begin
  350. Send(Host, Port, AData, AByteEncoding{$IFDEF STRING_IS_ANSI}, ASrcEncoding{$ENDIF});
  351. end;
  352. procedure TIdUDPClient.SendBuffer(const ABuffer : TIdBytes);
  353. begin
  354. if UseProxy then begin
  355. if not FProxyOpened then begin
  356. RaiseUseProxyError;
  357. end;
  358. FTransparentProxy.SendToUDP(Binding, Host, Port, IPVersion, ABuffer);
  359. end else
  360. begin
  361. if Connected then begin
  362. FBinding.Send(ABuffer, 0, -1);
  363. end else begin
  364. inherited SendBuffer(Host, Port, IPVersion, ABuffer);
  365. end;
  366. end;
  367. end;
  368. procedure TIdUDPClient.SendBuffer(const AHost: string; const APort: TIdPort;
  369. const ABuffer: TIdBytes);
  370. begin
  371. if UseProxy then begin
  372. if not FProxyOpened then begin
  373. RaiseUseProxyError;
  374. end;
  375. FTransparentProxy.SendToUDP(Binding, AHost, APort, IPVersion, ABuffer);
  376. end else begin
  377. inherited SendBuffer(AHost, APort, ABuffer);
  378. end;
  379. end;
  380. procedure TIdUDPClient.SetHost(const AValue: String);
  381. begin
  382. if FHost <> AValue then begin
  383. Disconnect;
  384. end;
  385. inherited SetHost(AValue);
  386. end;
  387. procedure TIdUDPClient.SetIPVersion(const AValue: TIdIPVersion);
  388. begin
  389. if FIPVersion <> AValue then begin
  390. Disconnect;
  391. end;
  392. inherited SetIPVersion(AValue);
  393. end;
  394. procedure TIdUDPClient.SetPort(const AValue: TIdPort);
  395. begin
  396. if FPort <> AValue then begin
  397. Disconnect;
  398. end;
  399. inherited SetPort(AValue);
  400. end;
  401. procedure TIdUDPClient.SetTransparentProxy(AProxy: TIdCustomTransparentProxy);
  402. var
  403. LClass: TIdCustomTransparentProxyClass;
  404. // under ARC, convert a weak reference to a strong reference before working with it
  405. LTransparentProxy: TIdCustomTransparentProxy;
  406. begin
  407. LTransparentProxy := FTransparentProxy;
  408. if LTransparentProxy <> AProxy then
  409. begin
  410. // All this is to preserve the compatibility with old version
  411. // In the case when we have SocksInfo as object created in runtime without owner form it is treated as temporary object
  412. // In the case when the ASocks points to an object with owner it is treated as component on form.
  413. // under ARC, all weak references to a freed object get nil'ed automatically
  414. if Assigned(AProxy) then begin
  415. if not Assigned(AProxy.Owner) then begin
  416. if Assigned(LTransparentProxy) and (not FImplicitTransparentProxy) then begin
  417. {$IFNDEF USE_OBJECT_ARC}
  418. LTransparentProxy.RemoveFreeNotification(Self);
  419. {$ENDIF}
  420. LTransparentProxy := nil;
  421. end;
  422. LClass := TIdCustomTransparentProxyClass(AProxy.ClassType);
  423. if Assigned(LTransparentProxy) and (LTransparentProxy.ClassType <> LClass) then begin
  424. FTransparentProxy := nil;
  425. FImplicitTransparentProxy := False;
  426. IdDisposeAndNil(LTransparentProxy);
  427. end;
  428. if not Assigned(LTransparentProxy) then begin
  429. LTransparentProxy := LClass.Create(Self);
  430. FTransparentProxy := LTransparentProxy;
  431. FImplicitTransparentProxy := True;
  432. end;
  433. LTransparentProxy.Assign(AProxy);
  434. end else begin
  435. if Assigned(LTransparentProxy) then begin
  436. if FImplicitTransparentProxy then begin
  437. FTransparentProxy := nil;
  438. FImplicitTransparentProxy := False;
  439. IdDisposeAndNil(LTransparentProxy);
  440. end else begin
  441. {$IFNDEF USE_OBJECT_ARC}
  442. LTransparentProxy.RemoveFreeNotification(Self);
  443. {$ENDIF}
  444. end;
  445. end;
  446. FTransparentProxy := AProxy;
  447. {$IFNDEF USE_OBJECT_ARC}
  448. AProxy.FreeNotification(Self);
  449. {$ENDIF}
  450. end;
  451. end
  452. else if Assigned(LTransparentProxy) then begin
  453. if FImplicitTransparentProxy then begin
  454. FTransparentProxy := nil;
  455. FImplicitTransparentProxy := False;
  456. IdDisposeAndNil(LTransparentProxy);
  457. end else begin
  458. FTransparentProxy := nil; //remove link
  459. {$IFNDEF USE_OBJECT_ARC}
  460. LTransparentProxy.RemoveFreeNotification(Self);
  461. {$ENDIF}
  462. end;
  463. end;
  464. end;
  465. end;
  466. function TIdUDPClient.UseProxy: Boolean;
  467. var
  468. // under ARC, convert a weak reference to a strong reference before working with it
  469. LTransparentProxy: TIdCustomTransparentProxy;
  470. begin
  471. LTransparentProxy := FTransparentProxy;
  472. Result := Assigned(LTransparentProxy);
  473. if Result then begin
  474. Result := LTransparentProxy.Enabled;
  475. end;
  476. end;
  477. destructor TIdUDPClient.Destroy;
  478. begin
  479. if UseProxy and FProxyOpened then begin
  480. CloseProxy;
  481. end;
  482. if Connected then begin
  483. Disconnect;
  484. end;
  485. inherited Destroy;
  486. end;
  487. function TIdUDPClient.ReceiveBuffer(var ABuffer: TIdBytes;
  488. var VPeerIP: string; var VPeerPort: TIdPort; var VIPVersion: TIdIPVersion;
  489. const AMSec: Integer): integer;
  490. var
  491. LMSec : Integer;
  492. begin
  493. if AMSec = IdTimeoutDefault then begin
  494. if ReceiveTimeout = 0 then begin
  495. LMSec := IdTimeoutInfinite;
  496. end else begin
  497. LMSec := ReceiveTimeout;
  498. end;
  499. end else begin
  500. LMSec := AMSec;
  501. end;
  502. if UseProxy then begin
  503. if not FProxyOpened then begin
  504. RaiseUseProxyError;
  505. end;
  506. Result := FTransparentProxy.RecvFromUDP(Binding, ABuffer, VPeerIP, VPeerPort, VIPVersion, LMSec);
  507. end else begin
  508. Result := inherited ReceiveBuffer(ABuffer, VPeerIP, VPeerPort, VIPVersion, LMSec);
  509. end;
  510. end;
  511. procedure TIdUDPClient.SendBuffer(const AHost: string; const APort: TIdPort;
  512. const AIPVersion: TIdIPVersion; const ABuffer: TIdBytes);
  513. begin
  514. if UseProxy then begin
  515. if not FProxyOpened then begin
  516. RaiseUseProxyError;
  517. end;
  518. FTransparentProxy.SendToUDP(Binding, AHost, APort, AIPVersion, ABuffer);
  519. end else begin
  520. inherited SendBuffer(AHost, APort, AIPVersion, ABuffer);
  521. end;
  522. end;
  523. end.