home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 December / Chip_2001-12_cd1.bin / zkuste / delphi / unity / d23456 / SYNAPSE.ZIP / source / lib / PINGsend.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-09-23  |  6.1 KB  |  216 lines

  1. {==============================================================================|
  2. | Project : Delphree - Synapse                                   | 002.001.002 |
  3. |==============================================================================|
  4. | Content: PING sender                                                         |
  5. |==============================================================================|
  6. | The contents of this file are subject to the Mozilla Public License Ver. 1.1 |
  7. | (the "License"); you may not use this file except in compliance with the     |
  8. | License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ |
  9. |                                                                              |
  10. | Software distributed under the License is distributed on an "AS IS" basis,   |
  11. | WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
  12. | the specific language governing rights and limitations under the License.    |
  13. |==============================================================================|
  14. | The Original Code is Synapse Delphi Library.                                 |
  15. |==============================================================================|
  16. | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
  17. | Portions created by Lukas Gebauer are Copyright (c)2000,2001.                |
  18. | All Rights Reserved.                                                         |
  19. |==============================================================================|
  20. | Contributor(s):                                                              |
  21. |==============================================================================|
  22. | History: see HISTORY.HTM from distribution package                           |
  23. |          (Found at URL: http://www.ararat.cz/synapse/)                       |
  24. |==============================================================================}
  25.  
  26. {
  27. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  28. See 'winsock2.txt' file in distribute package!
  29. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  30. }
  31.  
  32. {$Q-}
  33. {$WEAKPACKAGEUNIT ON}
  34.  
  35. unit PINGsend;
  36.  
  37. interface
  38.  
  39. uses
  40. {$IFDEF LINUX}
  41.   Libc,
  42. {$ELSE}
  43.   Windows,
  44. {$ENDIF}
  45.   SysUtils,
  46.   synsock, blcksock, SynaUtil;
  47.  
  48. const
  49.   ICMP_ECHO = 8;
  50.   ICMP_ECHOREPLY = 0;
  51.  
  52. type
  53.   TIcmpEchoHeader = record
  54.     i_type: Byte;
  55.     i_code: Byte;
  56.     i_checkSum: Word;
  57.     i_Id: Word;
  58.     i_seq: Word;
  59.     TimeStamp: ULONG;
  60.   end;
  61.  
  62.   TPINGSend = class(TObject)
  63.   private
  64.     FSock: TICMPBlockSocket;
  65.     FBuffer: string;
  66.     FSeq: Integer;
  67.     FId: Integer;
  68.     FTimeout: Integer;
  69.     FPacketSize: Integer;
  70.     FPingTime: Integer;
  71.     function Checksum: Integer;
  72.     function GetTick: Cardinal;
  73.     function ReadPacket: Boolean;
  74.   public
  75.     function Ping(const Host: string): Boolean;
  76.     constructor Create;
  77.     destructor Destroy; override;
  78.   published
  79.     property Timeout: Integer read FTimeout Write FTimeout;
  80.     property PacketSize: Integer read FPacketSize Write FPacketSize;
  81.     property PingTime: Integer read FPingTime;
  82.     property Sock: TICMPBlockSocket read FSock;
  83.   end;
  84.  
  85. function PingHost(const Host: string): Integer;
  86.  
  87. implementation
  88.  
  89. {==============================================================================}
  90.  
  91. constructor TPINGSend.Create;
  92. begin
  93.   inherited Create;
  94.   FSock := TICMPBlockSocket.Create;
  95.   FSock.CreateSocket;
  96.   FTimeout := 5000;
  97.   FPacketSize := 32;
  98.   FSeq := 0;
  99.   Randomize;
  100. end;
  101.  
  102. destructor TPINGSend.Destroy;
  103. begin
  104.   FSock.Free;
  105.   inherited Destroy;
  106. end;
  107.  
  108. function TPINGSend.ReadPacket: Boolean;
  109. begin
  110.   FBuffer := FSock.RecvPacket(Ftimeout);
  111.   Result := FSock.LastError = 0;
  112. end;
  113.  
  114. function TPINGSend.Ping(const Host: string): Boolean;
  115. var
  116.   IPHeadPtr: ^TIPHeader;
  117.   IpHdrLen: Integer;
  118.   IcmpEchoHeaderPtr: ^TICMPEchoHeader;
  119.   n: Integer;
  120.   t: Boolean;
  121. begin
  122.   Result := False;
  123.   FSock.Connect(Host, '0');
  124.   FBuffer := StringOfChar(#0, SizeOf(TICMPEchoHeader) + FPacketSize);
  125.   IcmpEchoHeaderPtr := Pointer(FBuffer);
  126.   with IcmpEchoHeaderPtr^ do
  127.   begin
  128.     i_type := ICMP_ECHO;
  129.     i_code := 0;
  130.     i_CheckSum := 0;
  131.     FId := Random(32767);
  132.     i_Id := FId;
  133.     TimeStamp := GetTick;
  134.     Inc(FSeq);
  135.     i_Seq := FSeq;
  136.     for n := Succ(SizeOf(TIcmpEchoHeader)) to Length(FBuffer) do
  137.       FBuffer[n] := #$55;
  138.     i_CheckSum := CheckSum;
  139.   end;
  140.   FSock.SendString(FBuffer);
  141.   repeat
  142.     t := ReadPacket;
  143.     if not t then
  144.       break;
  145.     IPHeadPtr := Pointer(FBuffer);
  146.     IpHdrLen := (IPHeadPtr^.VerLen and $0F) * 4;
  147.     IcmpEchoHeaderPtr := @FBuffer[IpHdrLen + 1];
  148.   until IcmpEchoHeaderPtr^.i_type <> ICMP_ECHO;
  149.   //it discard sometimes possible 'echoes' of previosly sended packet...
  150.   if t then
  151.     if (IcmpEchoHeaderPtr^.i_type = ICMP_ECHOREPLY) then
  152.       if (IcmpEchoHeaderPtr^.i_id = FId) then
  153.       begin
  154.         FPingTime := GetTick - IcmpEchoHeaderPtr^.TimeStamp;
  155.         Result := True;
  156.       end;
  157. end;
  158.  
  159. function TPINGSend.Checksum: Integer;
  160. type
  161.   TWordArray = array[0..0] of Word;
  162. var
  163.   WordArr: ^TWordArray;
  164.   CkSum: DWORD;
  165.   Num, Remain: Integer;
  166.   n: Integer;
  167. begin
  168.   Num := Length(FBuffer) div 2;
  169.   Remain := Length(FBuffer) mod 2;
  170.   WordArr := Pointer(FBuffer);
  171.   CkSum := 0;
  172.   for n := 0 to Num - 1 do
  173.     CkSum := CkSum + WordArr^[n];
  174.   if Remain <> 0 then
  175.     CkSum := CkSum + Ord(FBuffer[Length(FBuffer)]);
  176.   CkSum := (CkSum shr 16) + (CkSum and $FFFF);
  177.   CkSum := CkSum + (CkSum shr 16);
  178.   Result := Word(not CkSum);
  179. end;
  180.  
  181. {$IFDEF LINUX}
  182.  
  183. function TPINGSend.GetTick: Cardinal;
  184. var
  185.   Stamp: TTimeStamp;
  186. begin
  187.   Stamp := DateTimeToTimeStamp(Now);
  188.   Result := Stamp.Time;
  189. end;
  190.  
  191. {$ELSE}
  192.  
  193. function TPINGSend.GetTick: Cardinal;
  194. begin
  195.   Result := Windows.GetTickCount;
  196. end;
  197.  
  198. {$ENDIF}
  199.  
  200. {==============================================================================}
  201.  
  202. function PingHost(const Host: string): Integer;
  203. begin
  204.   with TPINGSend.Create do
  205.   try
  206.     if Ping(Host) then
  207.       Result := PingTime
  208.     else
  209.       Result := -1;
  210.   finally
  211.     Free;
  212.   end;
  213. end;
  214.  
  215. end.
  216.