blob: c333e57983ec14296495687a444c97a6f87995be [file] [log] [blame]
Guido van Rossume4bddea1991-10-30 11:52:48 +00001#
2# Module vtime - Keep virtual time between two nodes.
3#
4# We try for synchronised clocks by sending a packet of the for
5# (1,mytime,0) to the other side, and waiting (at most) a second for
6# a reply. This reply has the form (2,mytime,histime), and we can
7# estimate the time difference by defining histime to be exactly half-way
8# between the time we sent our message and got our reply. We send a
9# final (3,mynewtime,histime) message to allow the other side to do the
10# same computations.
11#
12# Note that the protocol suffers heavily from the 2-army problem.
13# It'll have to do until I can read up on time-sync protocols, though.
14#
15from socket import *
16import time
17
18MSGSIZE = 100
19MSGTIMEOUT = 1000
20
21recv_timeout = 'receive timeout'
22bad_connect = 'Bad connection'
23
24def timeavg(a,b):
25 return int((long(a)+b)/2L)
26def tryrecv(s):
27 cnt = 0
28 while 1:
29 if s.avail():
30 return s.recvfrom(MSGSIZE)
31 time.millisleep(100)
32 cnt = cnt + 100
33 if cnt > MSGTIMEOUT:
34 raise recv_timeout
35
36class VTime():
37 def init(self,(client,host,port)):
38 s = socket(AF_INET, SOCK_DGRAM)
39 host = gethostbyname(host)
40 localhost = gethostbyname(gethostname())
41 raddr = (host,port)
42 s.bind((localhost,port))
43 if client:
44 #
45 # We loop here because we want the *second* measurement
46 # for accuracy
47 for loopct in (0,2):
48 curtijd = time.millitimer()
49 check = `(loopct,curtijd,0)`
50 s.sendto(check,raddr)
51 while 1:
52 try:
53 if loopct:
54 data, other = s.recvfrom(MSGSIZE)
55 else:
56 data, other = tryrecv(s)
57 newtijd = time.millitimer()
58 if other <> raddr:
59 print 'Someone else syncing to us: ', other
60 raise bad_connect
61 data = eval(data)
Guido van Rossumf47d0481992-02-11 14:50:22 +000062 if data[:2] == (loopct+1,curtijd):
Guido van Rossume4bddea1991-10-30 11:52:48 +000063 break
64 if data[0] <> 2:
65 print 'Illegal sync reply: ', data
66 raise bad_connect
67 except recv_timeout:
68 curtijd = time.millitimer()
69 check = `(loopct,curtijd,0)`
70 s.sendto(check,raddr)
71 histime = data[2]
72 s.sendto(`(4,newtijd,histime)`,raddr)
73 mytime = timeavg(curtijd,newtijd)
74 #mytime = curtijd
75 self.timediff = histime - mytime
76 else:
77 while 1:
78 data,other = s.recvfrom(MSGSIZE)
79 if other <> raddr:
80 print 'Someone else syncing to us: ', other, ' Wanted ', raddr
81 raise bad_connect
82 data = eval(data)
83 if data[0] in (0,2):
84 curtijd = time.millitimer()
85 s.sendto(`(data[0]+1,data[1],curtijd)`,raddr)
Guido van Rossumf47d0481992-02-11 14:50:22 +000086 elif data[0] == 4:
Guido van Rossume4bddea1991-10-30 11:52:48 +000087 newtijd = time.millitimer()
88 histime = data[1]
89 mytime = timeavg(curtijd,newtijd)
90 #mytime = curtijd
91 self.timediff = histime-mytime
92 break
93 else:
94 print 'Funny data: ', data
95 raise bad_connect
96 return self
97 #
98 def his2mine(self,tijd):
99 return tijd - self.timediff
100 #
101 def mine2his(self, tijd):
102 return tijd + self.timediff
103
104def test(clt, host, port):
105 xx = VTime().init(clt,host,port)
106 print 'Time diff: ', xx.his2mine(0)