{ $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.