IdSystatUDPServer.pas 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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.5 10/26/2004 10:49:20 PM JPMugaas
  18. Updated ref.
  19. Rev 1.4 2004.02.03 5:44:30 PM czhower
  20. Name changes
  21. Rev 1.3 1/21/2004 4:04:08 PM JPMugaas
  22. InitComponent
  23. Rev 1.2 10/24/2003 02:54:58 PM JPMugaas
  24. These should now work with the new code.
  25. Rev 1.1 2003.10.24 10:38:30 AM czhower
  26. UDP Server todos
  27. Rev 1.0 11/13/2002 08:02:44 AM JPMugaas
  28. }
  29. unit IdSystatUDPServer;
  30. {
  31. Indy Systat Client TIdSystatUDPServer
  32. Copyright (C) 2002 Winshoes Working Group
  33. Original author J. Peter Mugaas
  34. 2002-August-13
  35. Based on RFC 866
  36. Note that this protocol is officially called Active User.
  37. }
  38. interface
  39. {$i IdCompilerDefines.inc}
  40. uses
  41. Classes,
  42. IdAssignedNumbers, IdGlobal, IdSocketHandle, IdUDPServer;
  43. type
  44. TIdUDPSystatEvent = procedure (ABinding: TIdSocketHandle; AResults : TStrings) of object;
  45. type
  46. TIdSystatUDPServer = class(TIdUDPServer)
  47. protected
  48. FOnSystat : TIdUDPSystatEvent;
  49. procedure DoUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); override;
  50. public
  51. constructor Create(AOwner: TComponent); override;
  52. published
  53. property OnSystat : TIdUDPSystatEvent read FOnSystat write FOnSystat;
  54. property DefaultPort default IdPORT_SYSTAT;
  55. end;
  56. implementation
  57. uses
  58. SysUtils;
  59. {
  60. According to the "Programming UNIX Sockets in C - Frequently Asked Questions"
  61. This has to do with the maximum size of a datagram on the two machines involved.
  62. This depends on the sytems involved, and the MTU (Maximum Transmission Unit).
  63. According to "UNIX Network Programming", all TCP/IP implementations must support
  64. a minimum IP datagram size of 576 bytes, regardless of the MTU. Assuming a 20
  65. byte IP header and 8 byte UDP header, this leaves 548 bytes as a safe maximum
  66. size for UDP messages. The maximum size is 65516 bytes. Some platforms support
  67. IP fragmentation which will allow datagrams to be broken up (because of MTU
  68. values) and then re-assembled on the other end, but not all implementations
  69. support this.
  70. URL:
  71. http://www.manualy.sk/sock-faq/unix-socket-faq-5.html
  72. }
  73. const
  74. Max_UDPPacket = 548;
  75. Max_Line_Len = Max_UDPPacket - 2; //EOL deliniator
  76. { TIdSystatUDPServer }
  77. constructor TIdSystatUDPServer.Create(AOwner: TComponent);
  78. begin
  79. inherited Create(AOwner);
  80. DefaultPort := IdPORT_SYSTAT;
  81. end;
  82. procedure TIdSystatUDPServer.DoUDPRead(AThread: TIdUDPListenerThread;
  83. const AData: TIdBytes; ABinding: TIdSocketHandle);
  84. var
  85. s, s2 : String;
  86. LResults : TStrings;
  87. i : Integer;
  88. function MaxLenStr(const AStr : String): String;
  89. begin
  90. Result := AStr;
  91. if Length(Result)>Max_Line_Len then
  92. begin
  93. SetLength(Result, Max_Line_Len);
  94. end;
  95. end;
  96. begin
  97. inherited DoUDPRead(AThread, AData, ABinding);
  98. if Assigned(FOnSystat) then
  99. begin
  100. LResults := TStringList.Create;
  101. try
  102. FOnSystat(ABinding, LResults);
  103. s := '';
  104. for i := 0 to LResults.Count - 1 do
  105. begin
  106. {enure that one line will never exceed the maximum packet size }
  107. s2 := s + EOL + MaxLenStr(LResults[i]);
  108. if Length(s2) > Max_UDPPacket then
  109. begin
  110. s := TrimLeft(s);
  111. ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, ToBytes(s), ABinding.IPVersion);
  112. s := MaxLenStr(LResults[i]);
  113. end else
  114. begin
  115. s := s2;
  116. end;
  117. end;
  118. if s <> '' then
  119. begin
  120. s := TrimLeft(s);
  121. ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, ToBytes(s), ABinding.IPVersion);
  122. end;
  123. finally
  124. LResults.Free;
  125. end;
  126. end;
  127. end;
  128. end.