synapse/pingsend.pas
geby 18bbf79351 Release 21
git-svn-id: https://svn.code.sf.net/p/synalist/code/trunk@45 7c85be65-684b-0410-a082-b2ed4fbef004
2008-04-24 06:59:26 +00:00

211 lines
6.2 KiB
ObjectPascal

{==============================================================================|
| Project : Delphree - Synapse | 002.000.000 |
|==============================================================================|
| Content: PING sender |
|==============================================================================|
| The contents of this file are subject to the Mozilla Public License Ver. 1.0 |
| (the "License"); you may not use this file except in compliance with the |
| License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ |
| |
| Software distributed under the License is distributed on an "AS IS" basis, |
| WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
| the specific language governing rights and limitations under the License. |
|==============================================================================|
| The Original Code is Synapse Delphi Library. |
|==============================================================================|
| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
| Portions created by Lukas Gebauer are Copyright (c)2000. |
| All Rights Reserved. |
|==============================================================================|
| Contributor(s): |
|==============================================================================|
| History: see HISTORY.HTM from distribution package |
| (Found at URL: http://www.ararat.cz/synapse/) |
|==============================================================================}
{
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Remember, this unit work only on Linux or Windows with Winsock2!
(on Win98 and WinNT 4.0 or higher)
If you must use this unit on Win95, download W�nsock2 from Microsoft
and distribute it with your application!
In spite of I use Winsock level version 1.1, RAW sockets work in this level only
if Winsock2 is installed on your computer!!!
On WinNT standardly RAW sockets work if program is running under user with
administrators provilegies. To use RAW sockets under another users, you must
create the following registry variable and set its value to DWORD 1:
HKLM\System\CurrentControlSet\Services\Afd\Parameters\DisableRawSecurity
After you change the registry, you need to restart your computer!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
unit PINGsend;
interface
uses
{$IFDEF LINUX}
libc,
{$ELSE}
windows,
{$ENDIF}
synsock, SysUtils, blcksck2, Synautil;
const
ICMP_ECHO=8;
ICMP_ECHOREPLY=0;
type
TIcmpEchoHeader = Record
i_type : Byte;
i_code : Byte;
i_checkSum : Word;
i_Id : Word;
i_seq : Word;
TimeStamp : ULong;
End;
TPINGSend=class(TObject)
private
Sock:TICMPBlockSocket;
Buffer:string;
seq:integer;
id:integer;
function checksum:integer;
function GetTick:cardinal;
public
timeout:integer;
PacketSize:integer;
PingTime:integer;
function ping(host:string):Boolean;
constructor Create;
destructor Destroy; override;
end;
function PingHost(host:string):integer;
implementation
{==============================================================================}
{TPINGSend.Create}
Constructor TPINGSend.Create;
begin
inherited Create;
sock:=TICMPBlockSocket.create;
sock.CreateSocket;
timeout:=5000;
packetsize:=32;
seq:=0;
end;
{TPINGSend.Destroy}
Destructor TPINGSend.Destroy;
begin
Sock.free;
inherited destroy;
end;
{TPINGSend.ping}
function TPINGSend.ping(host:string):Boolean;
var
PIPHeader:^TIPHeader;
IpHdrLen:Integer;
PIcmpEchoHeader:^TICMPEchoHeader;
n,x:integer;
begin
Result:=False;
sock.connect(host,'0');
Buffer:=StringOfChar(#0,SizeOf(TICMPEchoHeader)+packetSize);
PIcmpEchoHeader := Pointer(Buffer);
With PIcmpEchoHeader^ Do Begin
i_type:=ICMP_ECHO;
i_code:=0;
i_CheckSum:=0;
id:=Random(32767);
i_Id:=id;
TimeStamp:=GetTick;
Inc(Seq);
i_Seq:=Seq;
for n:=Succ(SizeOf(TicmpEchoHeader)) to Length(Buffer) do
Buffer[n]:=#$55;
i_CheckSum:=CheckSum;
end;
sock.sendString(Buffer);
if sock.canread(timeout)
then begin
x:=sock.waitingdata;
setlength(Buffer,x);
sock.recvbuffer(Pointer(Buffer),x);
PIpHeader:=Pointer(Buffer);
IpHdrLen:=(PIpHeader^.VerLen and $0F)*4;
PIcmpEchoHeader:=@Buffer[IpHdrLen+1];
if (PIcmpEchoHeader^.i_type=ICMP_ECHOREPLY)
// Linux return from localhost ECHO instead ECHOREPLY???
or (PIcmpEchoHeader^.i_type=ICMP_ECHO) then
if (PIcmpEchoHeader^.i_id=id) then
begin
PingTime:=GetTick-PIcmpEchoHeader^.TimeStamp;
Result:=True;
end;
end;
end;
{TPINGSend.checksum}
function TPINGSend.checksum:integer;
type
tWordArray=Array[0..0] Of Word;
var
PWordArray:^TWordArray;
CkSum:Dword;
Num,Remain:Integer;
n:Integer;
begin
Num:=length(Buffer) div 2;
Remain:=length(Buffer) mod 2;
PWordArray:=Pointer(Buffer);
CkSum := 0;
for n:=0 to Num-1 do
CkSum:=CkSum+PWordArray^[n];
if Remain<>0 then
CkSum:=CkSum+ord(Buffer[Length(Buffer)]);
CkSum:=(CkSum shr 16)+(CkSum and $FFFF);
CkSum:=CkSum+(CkSum shr 16);
Result:=Word(not CkSum);
end;
{TPINGSend.GetTick}
function TPINGSend.GetTick:cardinal;
begin
{$IFDEF LINUX}
result:=clock div (CLOCKS_PER_SEC div 1000);
{$ELSE}
result:=windows.GetTickCount;
{$ENDIF}
end;
{==============================================================================}
function PingHost(host:string):integer;
var
ping:TPINGSend;
begin
ping:=TPINGSend.Create;
try
if ping.ping(host)
then Result:=ping.pingtime
else Result:=-1;
finally
ping.Free;
end;
end;
end.