; PING
;
; Program for Proteus
;
; (C) 2003-2004 Simone Zanella Productions
;
; This program pings a remote address, displaying response times, until the user presses Esc on the
; keyboard.
#!proteus -z -j
!include "win32.prt"
!include "socket.prt"
IF LT(ARGC, 5)
CONSOLELN "Syntax: " ARGV(1) " " ARGV(2) " address"
ABORT 0
FI
NetAddr = ARGV(5)
CONSOLELN "NETADDR: " NetAddr
HSock = W32SOCKET(AF_INET, SOCK_RAW, IPPROTO_ICMP)
IF EQ(HSock, -1)
CONSOLELN "Unable to create socket."
ABORT 0
FI
IF EQ(W32SETSOCKOPT(HSock, SOL_SOCKET, SO_RCVTIMEO, 1000), -1)
CONSOLELN "Unable to set receive timeout."
ABORT 0
FI
IF EQ(W32SETSOCKOPT(HSock, SOL_SOCKET, SO_SNDTIMEO, 1000), -1)
CONSOLELN "Unable to set transmission timeout."
ABORT 0
FI
Name = NetAddr
Alias = ""
Type = 0
Addresses = ""
; Try to resolve address
Result = W32GETHOSTBYNAME(@Name, @Alias, @Type, @Addresses)
IF EQ(Result, 0)
NetAddr = TOKEN(Addresses, 1, "\t")
FI
; RAW header:
; IcmpHeader:
; BYTE i_type (ECHO = 8)
; BYTE i_code (= 0)
; WORD i_cksum (= 0)
; WORD i_id (= ID of current process)
; WORD i_seq (= 0)
; DWORD timestamp (= Tick Count)
; CONSOLELN "PROCID: " W32GETPROCESSID()
; CONSOLELN "TICKCOUNT: " W32GETTICKCOUNT()
SEQ = 0
WHILE 1
; Wait 1 second
SLEEP(1)
; Check if user pressed Esc; if so, then exit
IF KBDHIT()
IF EQ(GETCH(0), 27)
BREAK
FI
FI
; Send echo request (RAW packet)
Buffer = CHR(8) CHR(0) CHR(0) CHR(0) Word2String(W32GETPROCESSID()) Word2String(SEQ) \
LongWord2String(W32GETTICKCOUNT()) REPLICATE("E", SUB(44, 12))
Buffer = LEFT(Buffer, 2) Word2String(CheckSum(Buffer)) RESTFROM(Buffer, 5)
Result = W32SENDTO(HSock, Buffer, 0, AF_INET, 0, NetAddr)
IF EQ(Result, -1)
CONSOLELN "Unable to send packet."
CONTINUE
FI
; Receive reply packet, with timeout
Buffer = REPLICATE(" ", 1024)
Address = ""
Port = 0
Family = 0
Result = W32RECVFROM(HSock, @Buffer, 0, @Family, @Port, @Address)
IF EQ(Result, -1)
CONSOLELN "Unable to receive packet."
CONSOLELN "SOCKERR: " W32LASTSOCKETERR()
CONTINUE
FI
; Analizza il pacchetto ricevuto
L = MUL(NAND(ASC(LEFT(Buffer,1)), 0xF), 4)
NewBuf = RESTFROM(Buffer, INC(L))
IF NEQ(ASC(SUBSTR(NewBuf, 1, 1)), 0)
CONSOLELN "Non-echo type."
CONTINUE
FI
IF NEQ(String2Word(SUBSTR(NewBuf, 5, 2)), W32GETPROCESSID())
CONSOLELN "Wrong destination."
CONTINUE
FI
; Display ping result
CONSOLELN PFORMAT("d", STRLEN(Buffer)) " bytes from " NetAddr " seq = " \
PFORMAT("d", String2Word(SUBSTR(NewBuf, 7, 2))) " time = " \
SUB(W32GETTICKCOUNT(), String2LongWord(SUBSTR(NewBuf, 9, 4)))
INC(@SEQ)
LOOP
; Close socket opened
W32SHUTDOWN(HSock, SD_BOTH)
W32CLOSESOCKET(HSock)
HSock = -1
ABORT 0
FUNCTION CheckSum(s)
l = STRLEN(s)
chk = 0
x = 1
WHILE GT(l, 1)
ADD(@chk, ASC(SUBSTR(s, x, 1)), MUL(ASC(SUBSTR(s, INC(x), 1)), 256))
SUB(@l, 2)
ADD(@x, 2)
LOOP
IF l
ADD(@chk, ASC(SUBSTR(s, x, 1)))
FI
chk = ADD(SHIFTRT(chk, 16), NAND(chk, 0xFFFF))
ADD(@chk, SHIFTRT(chk, 16))
RETURN NAND(NNOT(chk), 0xFFFF)
FUNCTION String2Word(s)
RETURN NOR( ASC(LEFT(s, 1)), SHIFTLT(ASC(SUBSTR(s, 2, 1)), 8) )
FUNCTION Word2String(n)
RETURN CHR(NAND(n, 0xFF)) CHR(NAND(SHIFTRT(n, 8), 0xFF))
FUNCTION String2LongWord(s)
RETURN NOR(ASC(LEFT(s, 1)), \
SHIFTLT(ASC(SUBSTR(s, 2, 1)), 8), \
SHIFTLT(ASC(SUBSTR(s, 3, 1)), 16), \
SHIFTLT(ASC(SUBSTR(s, 4, 1)), 24))
FUNCTION LongWord2String(n)
RETURN CHR(NAND(n, 0xFF)) CHR(NAND(SHIFTRT(n, 8), 0xFF)) CHR(NAND(SHIFTRT(n, 16), 0xFF)) \
CHR(NAND(SHIFTRT(n, 24), 0xFF))