107 lines
2.8 KiB
Python
Executable File
107 lines
2.8 KiB
Python
Executable File
#
|
|
# Module vtime - Keep virtual time between two nodes.
|
|
#
|
|
# We try for synchronised clocks by sending a packet of the for
|
|
# (1,mytime,0) to the other side, and waiting (at most) a second for
|
|
# a reply. This reply has the form (2,mytime,histime), and we can
|
|
# estimate the time difference by defining histime to be exactly half-way
|
|
# between the time we sent our message and got our reply. We send a
|
|
# final (3,mynewtime,histime) message to allow the other side to do the
|
|
# same computations.
|
|
#
|
|
# Note that the protocol suffers heavily from the 2-army problem.
|
|
# It'll have to do until I can read up on time-sync protocols, though.
|
|
#
|
|
from socket import *
|
|
import time
|
|
|
|
MSGSIZE = 100
|
|
MSGTIMEOUT = 1000
|
|
|
|
recv_timeout = 'receive timeout'
|
|
bad_connect = 'Bad connection'
|
|
|
|
def timeavg(a,b):
|
|
return int((long(a)+b)/2L)
|
|
def tryrecv(s):
|
|
cnt = 0
|
|
while 1:
|
|
if s.avail():
|
|
return s.recvfrom(MSGSIZE)
|
|
time.millisleep(100)
|
|
cnt = cnt + 100
|
|
if cnt > MSGTIMEOUT:
|
|
raise recv_timeout
|
|
|
|
class VTime():
|
|
def init(self,(client,host,port)):
|
|
s = socket(AF_INET, SOCK_DGRAM)
|
|
host = gethostbyname(host)
|
|
localhost = gethostbyname(gethostname())
|
|
raddr = (host,port)
|
|
s.bind((localhost,port))
|
|
if client:
|
|
#
|
|
# We loop here because we want the *second* measurement
|
|
# for accuracy
|
|
for loopct in (0,2):
|
|
curtijd = time.millitimer()
|
|
check = `(loopct,curtijd,0)`
|
|
s.sendto(check,raddr)
|
|
while 1:
|
|
try:
|
|
if loopct:
|
|
data, other = s.recvfrom(MSGSIZE)
|
|
else:
|
|
data, other = tryrecv(s)
|
|
newtijd = time.millitimer()
|
|
if other <> raddr:
|
|
print 'Someone else syncing to us: ', other
|
|
raise bad_connect
|
|
data = eval(data)
|
|
if data[:2] == (loopct+1,curtijd):
|
|
break
|
|
if data[0] <> 2:
|
|
print 'Illegal sync reply: ', data
|
|
raise bad_connect
|
|
except recv_timeout:
|
|
curtijd = time.millitimer()
|
|
check = `(loopct,curtijd,0)`
|
|
s.sendto(check,raddr)
|
|
histime = data[2]
|
|
s.sendto(`(4,newtijd,histime)`,raddr)
|
|
mytime = timeavg(curtijd,newtijd)
|
|
#mytime = curtijd
|
|
self.timediff = histime - mytime
|
|
else:
|
|
while 1:
|
|
data,other = s.recvfrom(MSGSIZE)
|
|
if other <> raddr:
|
|
print 'Someone else syncing to us: ', other, ' Wanted ', raddr
|
|
raise bad_connect
|
|
data = eval(data)
|
|
if data[0] in (0,2):
|
|
curtijd = time.millitimer()
|
|
s.sendto(`(data[0]+1,data[1],curtijd)`,raddr)
|
|
elif data[0] == 4:
|
|
newtijd = time.millitimer()
|
|
histime = data[1]
|
|
mytime = timeavg(curtijd,newtijd)
|
|
#mytime = curtijd
|
|
self.timediff = histime-mytime
|
|
break
|
|
else:
|
|
print 'Funny data: ', data
|
|
raise bad_connect
|
|
return self
|
|
#
|
|
def his2mine(self,tijd):
|
|
return tijd - self.timediff
|
|
#
|
|
def mine2his(self, tijd):
|
|
return tijd + self.timediff
|
|
|
|
def test(clt, host, port):
|
|
xx = VTime().init(clt,host,port)
|
|
print 'Time diff: ', xx.his2mine(0)
|