IdSystatUDPServer.pas 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. procedure InitComponent; override;
  51. published
  52. property OnSystat : TIdUDPSystatEvent read FOnSystat write FOnSystat;
  53. property DefaultPort default IdPORT_SYSTAT;
  54. end;
  55. implementation
  56. uses
  57. SysUtils;
  58. {
  59. According to the "Programming UNIX Sockets in C - Frequently Asked Questions"
  60. This has to do with the maximum size of a datagram on the two machines involved.
  61. This depends on the sytems involved, and the MTU (Maximum Transmission Unit).
  62. According to "UNIX Network Programming", all TCP/IP implementations must support
  63. a minimum IP datagram size of 576 bytes, regardless of the MTU. Assuming a 20
  64. byte IP header and 8 byte UDP header, this leaves 548 bytes as a safe maximum
  65. size for UDP messages. The maximum size is 65516 bytes. Some platforms support
  66. IP fragmentation which will allow datagrams to be broken up (because of MTU
  67. values) and then re-assembled on the other end, but not all implementations
  68. support this.
  69. URL:
  70. http://www.manualy.sk/sock-faq/unix-socket-faq-5.html
  71. }
  72. const Max_UDPPacket = 548;
  73. Max_Line_Len = Max_UDPPacket - 2; //EOL deliniator
  74. { TIdSystatUDPServer }
  75. procedure TIdSystatUDPServer.InitComponent;
  76. begin
  77. inherited;
  78. DefaultPort := IdPORT_SYSTAT;
  79. end;
  80. procedure TIdSystatUDPServer.DoUDPRead(AThread: TIdUDPListenerThread;
  81. const AData: TIdBytes; ABinding: TIdSocketHandle);
  82. var
  83. s, s2 : String;
  84. LResults : TStrings;
  85. i : Integer;
  86. function MaxLenStr(const AStr : String): String;
  87. begin
  88. Result := AStr;
  89. if Length(Result)>Max_Line_Len then
  90. begin
  91. SetLength(Result, Max_Line_Len);
  92. end;
  93. end;
  94. begin
  95. inherited DoUDPRead(AThread, AData, ABinding);
  96. if Assigned(FOnSystat) then
  97. begin
  98. LResults := TStringList.Create;
  99. try
  100. FOnSystat(ABinding, LResults);
  101. s := '';
  102. for i := 0 to LResults.Count - 1 do
  103. begin
  104. {enure that one line will never exceed the maximum packet size }
  105. s2 := s + EOL + MaxLenStr(LResults[i]);
  106. if Length(s2) > Max_UDPPacket then
  107. begin
  108. s := TrimLeft(s);
  109. ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, ToBytes(s), ABinding.IPVersion);
  110. s := MaxLenStr(LResults[i]);
  111. end else
  112. begin
  113. s := s2;
  114. end;
  115. end;
  116. if s <> '' then
  117. begin
  118. s := TrimLeft(s);
  119. ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, ToBytes(s), ABinding.IPVersion);
  120. end;
  121. finally
  122. FreeAndNil(LResults);
  123. end;
  124. end;
  125. end;
  126. end.