restemplate/indy/Protocols/IdSystatUDPServer.pas

151 lines
3.9 KiB
Plaintext

{
$Project$
$Workfile$
$Revision$
$DateUTC$
$Id$
This file is part of the Indy (Internet Direct) project, and is offered
under the dual-licensing agreement described on the Indy website.
(http://www.indyproject.org/)
Copyright:
(c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
}
{
$Log$
}
{
Rev 1.5 10/26/2004 10:49:20 PM JPMugaas
Updated ref.
Rev 1.4 2004.02.03 5:44:30 PM czhower
Name changes
Rev 1.3 1/21/2004 4:04:08 PM JPMugaas
InitComponent
Rev 1.2 10/24/2003 02:54:58 PM JPMugaas
These should now work with the new code.
Rev 1.1 2003.10.24 10:38:30 AM czhower
UDP Server todos
Rev 1.0 11/13/2002 08:02:44 AM JPMugaas
}
unit IdSystatUDPServer;
{
Indy Systat Client TIdSystatUDPServer
Copyright (C) 2002 Winshoes Working Group
Original author J. Peter Mugaas
2002-August-13
Based on RFC 866
Note that this protocol is officially called Active User.
}
interface
{$i IdCompilerDefines.inc}
uses
Classes,
IdAssignedNumbers, IdGlobal, IdSocketHandle, IdUDPBase, IdUDPServer;
type
TIdUDPSystatEvent = procedure (ABinding: TIdSocketHandle; AResults : TStrings) of object;
type
TIdSystatUDPServer = class(TIdUDPServer)
protected
FOnSystat : TIdUDPSystatEvent;
procedure DoUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); override;
procedure InitComponent; override;
published
property OnSystat : TIdUDPSystatEvent read FOnSystat write FOnSystat;
property DefaultPort default IdPORT_SYSTAT;
end;
implementation
uses
SysUtils;
{
According to the "Programming UNIX Sockets in C - Frequently Asked Questions"
This has to do with the maximum size of a datagram on the two machines involved.
This depends on the sytems involved, and the MTU (Maximum Transmission Unit).
According to "UNIX Network Programming", all TCP/IP implementations must support
a minimum IP datagram size of 576 bytes, regardless of the MTU. Assuming a 20
byte IP header and 8 byte UDP header, this leaves 548 bytes as a safe maximum
size for UDP messages. The maximum size is 65516 bytes. Some platforms support
IP fragmentation which will allow datagrams to be broken up (because of MTU
values) and then re-assembled on the other end, but not all implementations
support this.
URL:
http://www.manualy.sk/sock-faq/unix-socket-faq-5.html
}
const Max_UDPPacket = 548;
Max_Line_Len = Max_UDPPacket - 2; //EOL deliniator
{ TIdSystatUDPServer }
procedure TIdSystatUDPServer.InitComponent;
begin
inherited;
DefaultPort := IdPORT_SYSTAT;
end;
procedure TIdSystatUDPServer.DoUDPRead(AThread: TIdUDPListenerThread;
const AData: TIdBytes; ABinding: TIdSocketHandle);
var
s, s2 : String;
LResults : TStrings;
i : Integer;
function MaxLenStr(const AStr : String): String;
begin
Result := AStr;
if Length(Result)>Max_Line_Len then
begin
SetLength(Result, Max_Line_Len);
end;
end;
begin
inherited DoUDPRead(AThread, AData, ABinding);
if Assigned(FOnSystat) then
begin
LResults := TStringList.Create;
try
FOnSystat(ABinding, LResults);
s := '';
for i := 0 to LResults.Count - 1 do
begin
{enure that one line will never exceed the maximum packet size }
s2 := s + EOL + MaxLenStr(LResults[i]);
if Length(s2) > Max_UDPPacket then
begin
s := TrimLeft(s);
ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, ToBytes(s), ABinding.IPVersion);
s := MaxLenStr(LResults[i]);
end else
begin
s := s2;
end;
end;
if s <> '' then
begin
s := TrimLeft(s);
ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, ToBytes(s), ABinding.IPVersion);
end;
finally
FreeAndNil(LResults);
end;
end;
end;
end.