Revert "update plugin icons (and some minor cleanups)" --> let the author of the...
[enigma2-plugins.git] / elektro / src / ping.py
1 #!/usr/bin/env python\r
2 \r
3 # Derived from ping.c distributed in Linux's netkit. That code is\r
4 # copyright (c) 1989 by The Regents of the University of California.\r
5 # That code is in turn derived from code written by Mike Muuss of the\r
6 # US Army Ballistic Research Laboratory in December, 1983 and\r
7 # placed in the public domain. They have my thanks.\r
8 \r
9 # Bugs are naturally mine. I'd be glad to hear about them. There are\r
10 # certainly word-size dependenceies here.\r
11 \r
12 # Copyright (c) Matthew Dixon Cowles, <http://www.visi.com/~mdc/>.\r
13 # Distributable under the terms of the GNU General Public License\r
14 # version 2. Provided with no warranties of any sort.\r
15 \r
16 # Note that ICMP messages can only be sent from processes running\r
17 # as root.\r
18 \r
19 # Revision history:\r
20 #\r
21 # November 22, 1997\r
22 # Initial hack. Doesn't do much, but rather than try to guess\r
23 # what features I (or others) will want in the future, I've only\r
24 # put in what I need now.\r
25 #\r
26 # December 16, 1997\r
27 # For some reason, the checksum bytes are in the wrong order when\r
28 # this is run under Solaris 2.X for SPARC but it works right under\r
29 # Linux x86. Since I don't know just what's wrong, I'll swap the\r
30 # bytes always and then do an htons().\r
31 #\r
32 # December 4, 2000\r
33 # Changed the struct.pack() calls to pack the checksum and ID as\r
34 # unsigned. My thanks to Jerome Poincheval for the fix.\r
35 #\r
36 \r
37 import os\r
38 from socket import *\r
39 import struct\r
40 import select\r
41 import time\r
42 import sys\r
43 \r
44 # From /usr/include/linux/icmp.h; your milage may vary.\r
45 ICMP_ECHO_REQUEST=8 # Seems to be the same on Solaris.\r
46 \r
47 # I'm not too confident that this is right but testing seems\r
48 # to suggest that it gives the same answers as in_cksum in ping.c\r
49 def checksum(str):\r
50   sum=0\r
51   countTo=(len(str)/2)*2\r
52   count=0\r
53   while count<countTo:\r
54     thisVal=ord(str[count+1])*256+ord(str[count])\r
55     sum=sum+thisVal\r
56     sum=sum & 0xffffffff # Necessary?\r
57     count=count+2\r
58 \r
59   if countTo<len(str):\r
60     sum=sum+ord(str[len(str)-1])\r
61     sum=sum & 0xffffffff # Necessary?\r
62 \r
63   sum=(sum >> 16) + (sum & 0xffff)\r
64   sum=sum+(sum >> 16)\r
65   answer=~sum\r
66   answer=answer & 0xffff\r
67 \r
68   # Swap bytes. Bugger me if I know why.\r
69   answer=answer >> 8 | (answer << 8 & 0xff00)\r
70   \r
71   return answer\r
72 \r
73 def receiveOnePing(mySocket,ID,timeout):\r
74   timeLeft=timeout\r
75   while 1:\r
76     startedSelect=time.time()\r
77     whatReady=select.select([mySocket],[],[],timeLeft)\r
78     howLongInSelect=(time.time()-startedSelect)\r
79     if whatReady[0]==[]: # Timeout\r
80       return None\r
81     timeReceived=time.time()\r
82     recPacket,addr=mySocket.recvfrom(1024)\r
83     icmpHeader=recPacket[20:28]\r
84     type,code,checksum,packetID,sequence=struct.unpack("bbHHh",icmpHeader)\r
85     if packetID==ID:\r
86       bytesInDouble=struct.calcsize("d")\r
87       timeSent=struct.unpack("d",recPacket[28:28+bytesInDouble])[0]\r
88       return timeReceived-timeSent\r
89       \r
90     timeLeft=timeLeft-howLongInSelect\r
91     if timeLeft<=0:\r
92       return None\r
93 \r
94 def sendOnePing(mySocket,destAddr,ID):\r
95   # Header is type (8), code (8), checksum (16), id (16), sequence (16)\r
96   myChecksum=0\r
97   # Make a dummy heder with a 0 checksum.\r
98   header=struct.pack("bbHHh",ICMP_ECHO_REQUEST,0,myChecksum,ID,1)\r
99   bytesInDouble=struct.calcsize("d")\r
100   data=(192-bytesInDouble) * "Q"\r
101   data=struct.pack("d",time.time())+data\r
102   # Calculate the checksum on the data and the dummy header.\r
103   myChecksum=checksum(header+data)\r
104   # Now that we have the right checksum, we put that in. It's just easier\r
105   # to make up a new header than to stuff it into the dummy.\r
106   header=struct.pack("bbHHh",ICMP_ECHO_REQUEST,0,htons(myChecksum),ID,1)\r
107   packet=header+data\r
108   mySocket.sendto(packet,(destAddr,1)) # Don't know about the 1 \r
109   return None\r
110   \r
111 def doOne(destAddr,timeout=10):\r
112   # Returns either the delay (in seconds) or none on timeout.\r
113   icmp=getprotobyname("icmp")\r
114   mySocket=socket(AF_INET,SOCK_RAW,icmp)\r
115   myID=os.getpid() & 0xFFFF\r
116   sendOnePing(mySocket,destAddr,myID)\r
117   delay=receiveOnePing(mySocket,myID,timeout)\r
118   mySocket.close()\r
119   return delay\r
120 \r
121 def main():\r
122   if len(sys.argv)<2:\r
123     print "Usage: %s hostname" % os.path.basename(sys.argv[0])\r
124     sys.exit(1)\r
125 \r
126   dest=gethostbyname(sys.argv[1])\r
127   delay=doOne(dest)\r
128   print delay\r
129   return None\r
130 \r
131 if __name__=='__main__':\r
132   main()\r
133   sys.exit(0)\r
134 \r