| 
									
										
										
										
											1991-10-30 11:52:48 +00:00
										 |  |  | # | 
					
						
							|  |  |  | # 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) | 
					
						
							| 
									
										
										
										
											1992-02-11 14:50:22 +00:00
										 |  |  | 			if data[:2] == (loopct+1,curtijd): | 
					
						
							| 
									
										
										
										
											1991-10-30 11:52:48 +00:00
										 |  |  | 			    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) | 
					
						
							| 
									
										
										
										
											1992-02-11 14:50:22 +00:00
										 |  |  | 		elif data[0] == 4: | 
					
						
							| 
									
										
										
										
											1991-10-30 11:52:48 +00:00
										 |  |  | 		    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) |