02-25-2009, 11:43 PM
Function Ping
Tested on Vista and XP. Should also work on 2000.
;/
function# $dest [&TTL] [timeout]
;Sends an ICMP echo request to an internet or network computer.
;It is called "ping", and is used to see if we can connect to a computer, and how quickly.
;Returns roundtrip time, in milliseconds. If cannot connect, returns 0. Does not throw errors.
;Uses the same Windows API functions as ping.exe.
;Note that some ICMP packets may be lost. Then the function returns 0. Call it several times to make more reliable. Don't ping too frequently.
;If you will use this function in a dialog, you should call it in other thread.
;dest - ip (eg "123.456.78.90"), or web server address (eg "www.qweryzxcv.com"), or network computer name, or "" for this computer. The function returns 0 if dest is invalid or cannot be resolved.
;TTL - receives TTL. Default: 0.
;timeout - timeout in milliseconds. Default: 1000. The function returns 0 if not connected during that time.
;EXAMPLE
;str dest="www.google.com"
;int t ttl
;t=Ping(dest ttl)
;if(t) out "Ping %s: bytes=32 time=%i TTL=%i" dest t ttl
;else out "Ping %s: failed" dest
type IP_OPTION_INFORMATION !Ttl !Tos !Flags !OptionsSize !*OptionsData
type ICMP_ECHO_REPLY Address Status RoundTripTime @DataSize @Reserved !*Data IP_OPTION_INFORMATION'Options
int+ __icmp_ev; if(!__icmp_ev) __icmp_ev=1; SetEnvVar "icmp_dll" iif(_winver=0x500 "icmp" "iphlpapi")
dll- "%icmp_dll%" #IcmpCreateFile
dll- "%icmp_dll%" #IcmpCloseHandle IcmpHandle
dll- "%icmp_dll%" #IcmpSendEcho2 IcmpHandle Event ApcRoutine !*ApcContext #DestinationAddress !*RequestData @RequestSize IP_OPTION_INFORMATION*RequestOptions !*ReplyBuffer ReplySize Timeout
int ipa=inet_addr(dest)
if(ipa=INADDR_NONE)
,if(!GetIpAddress(dest _s)) ret
,ipa=inet_addr(_s)
str sd.RandomString(32 32)
str rb.all(8*sizeof(ICMP_ECHO_REPLY)+sd.len 2 0)
ICMP_ECHO_REPLY& r=rb
;------------------
;!!rem
;workaround to QM version < 2.3.0.8 bug: possible random exceptions when delayloading dll functions from multiple threads simultaneously
lock
_i=&IcmpCreateFile+&IcmpCloseHandle+&IcmpSendEcho2
lock-
;------------------
int h=IcmpCreateFile
if(IcmpSendEcho2(h 0 0 0 ipa sd sd.len 0 rb rb.len iif(timeout timeout 1000)) and (!r.Status or r.Status=11000))
,int t=r.RoundTripTime; if(!t) t=1
,if(&TTL) TTL=r.Options.Ttl
IcmpCloseHandle h
ret t
Tested on Vista and XP. Should also work on 2000.