Programma di esempio PING.PRT |
; PING
;
; Programma per Proteus
;
; (C) 2003 Simone Zanella Productions
;
; Questo programma invia ping ad un indirizzo remoto, visualizzando i tempi di risposta, finché l'utente non
; preme Esc sulla tastiera.
#!proteus -z -j
!include "win32.prt"
!include "socket.prt"
IF LT(ARGC, 5)
CONSOLELN "Sintassi: " ARGV(1) " " ARGV(2) " indirizzo"
ABORT 0
FI
NetAddr = ARGV(5)
CONSOLELN "NETADDR: " NetAddr
HSock = W32SOCKET(AF_INET, SOCK_RAW, IPPROTO_ICMP)
IF EQ(HSock, -1)
CONSOLELN "Impossibile creare il socket."
ABORT 0
FI
IF EQ(W32SETSOCKOPT(HSock, SOL_SOCKET, SO_RCVTIMEO, 1000), -1)
CONSOLELN "Impossibile impostare il timeout di ricezione."
ABORT 0
FI
IF EQ(W32SETSOCKOPT(HSock, SOL_SOCKET, SO_SNDTIMEO, 1000), -1)
CONSOLELN "Impossibile impostare il timeout di trasmissione."
ABORT 0
FI
Nome = NetAddr
Alias = ""
Tipo = 0
Indirizzi = ""
; Prova a risolvere l'indirizzo
Result = W32GETHOSTBYNAME(@Nome, @Alias, @Tipo, @Indirizzi)
IF EQ(Result, 0)
NetAddr = TOKEN(Indirizzi, 1, "\t")
FI
; Formato dell'intestazione RAW:
; IcmpHeader:
; BYTE i_type (ECHO = 8)
; BYTE i_code (= 0)
; WORD i_cksum (= 0)
; WORD i_id (= ID del processo corrente)
; WORD i_seq (= 0)
; DWORD timestamp (= Tick Count)
; CONSOLELN "PROCID: " W32GETPROCESSID()
; CONSOLELN "TICKCOUNT: " W32GETTICKCOUNT()
SEQ = 0
WHILE 1
; Attende un secondo
SLEEP(1)
; Verifica che l'utente non abbia premuto Esc, nel caso esce
IF KBDHIT()
IF EQ(GETCH(0), 27)
BREAK
FI
FI
; Invia la richiesta di echo (pacchetto in formato RAW)
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 "Impossibile inviare il pacchetto."
CONTINUE
FI
; Riceve il pacchetto di risposta, con timeout
Buffer = REPLICATE(" ", 1024)
Indirizzo = ""
Porta = 0
Famiglia = 0
Result = W32RECVFROM(HSock, @Buffer, 0, @Famiglia, @Porta, @Indirizzo)
IF EQ(Result, -1)
CONSOLELN "Impossibile ricevere il pacchetto."
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 "Tipo non-echo."
CONTINUE
FI
IF NEQ(String2Word(SUBSTR(NewBuf, 5, 2)), W32GETPROCESSID())
CONSOLELN "Destinatario errato."
CONTINUE
FI
; Mostra l'esito del ping
CONSOLELN PFORMAT("d", STRLEN(Buffer)) " bytes da " NetAddr " seq = " \
PFORMAT("d", String2Word(SUBSTR(NewBuf, 7, 2))) " tempo = " \
SUB(W32GETTICKCOUNT(), String2LongWord(SUBSTR(NewBuf, 9, 4)))
INC(@SEQ)
LOOP
; Chiude in modo corretto il socket aperto
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))