blob: c333e57983ec14296495687a444c97a6f87995be [file] [log] [blame]
#
# 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)