Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tidied based on pylint suggestions/proofing #5

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
204 changes: 102 additions & 102 deletions ntpserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
import struct
import time
import Queue
import mutex
import threading
import select

taskQueue = Queue.Queue()
stopFlag = False
TASK_QUEUE = Queue.Queue()
STOP_FLAG = False

def system_to_ntp_time(timestamp):
"""Convert a system time to a NTP time.
Expand All @@ -32,7 +31,7 @@ def _to_int(timestamp):
"""
return int(timestamp)

def _to_frac(timestamp, n=32):
def _to_frac(timestamp, bits=32):
"""Return the fractional part of a timestamp.

Parameters:
Expand All @@ -42,9 +41,9 @@ def _to_frac(timestamp, n=32):
Retuns:
fractional part
"""
return int(abs(timestamp - _to_int(timestamp)) * 2**n)
return int(abs(timestamp - _to_int(timestamp)) * 2**bits)

def _to_time(integ, frac, n=32):
def _to_time(integ, frac, bits=32):
"""Return a timestamp from an integral and fractional part.

Parameters:
Expand All @@ -55,16 +54,16 @@ def _to_time(integ, frac, n=32):
Retuns:
timestamp
"""
return integ + float(frac)/2**n
return integ + float(frac)/2**bits



class NTPException(Exception):
"""Exception raised by this module."""
pass


class NTP:
class NTP(object):
"""Helper class defining constants."""

_SYSTEM_EPOCH = datetime.date(*time.gmtime(0)[0:3])
Expand All @@ -75,16 +74,16 @@ class NTP:
"""delta between system and NTP time"""

REF_ID_TABLE = {
'DNC': "DNC routing protocol",
'NIST': "NIST public modem",
'TSP': "TSP time protocol",
'DTS': "Digital Time Service",
'ATOM': "Atomic clock (calibrated)",
'VLF': "VLF radio (OMEGA, etc)",
'callsign': "Generic radio",
'LORC': "LORAN-C radionavidation",
'GOES': "GOES UHF environment satellite",
'GPS': "GPS UHF satellite positioning",
'DNC': "DNC routing protocol",
'NIST': "NIST public modem",
'TSP': "TSP time protocol",
'DTS': "Digital Time Service",
'ATOM': "Atomic clock (calibrated)",
'VLF': "VLF radio (OMEGA, etc)",
'callsign': "Generic radio",
'LORC': "LORAN-C radionavidation",
'GOES': "GOES UHF environment satellite",
'GPS': "GPS UHF satellite positioning",
}
"""reference identifier table"""

Expand Down Expand Up @@ -114,12 +113,12 @@ class NTP:
}
"""leap indicator table"""

class NTPPacket:
class NTPPacket(object):
"""NTP packet class.

This represents an NTP packet.
"""

_PACKET_FORMAT = "!B B B b 11I"
"""packet format to pack/unpack"""

Expand Down Expand Up @@ -161,7 +160,7 @@ def __init__(self, version=2, mode=3, tx_timestamp=0):
self.tx_timestamp_high = 0
self.tx_timestamp_low = 0
"""tansmit timestamp"""

def to_data(self):
"""Convert this NTPPacket to a buffer that can be sent over a socket.

Expand All @@ -173,23 +172,23 @@ def to_data(self):
"""
try:
packed = struct.pack(NTPPacket._PACKET_FORMAT,
(self.leap << 6 | self.version << 3 | self.mode),
self.stratum,
self.poll,
self.precision,
_to_int(self.root_delay) << 16 | _to_frac(self.root_delay, 16),
_to_int(self.root_dispersion) << 16 |
_to_frac(self.root_dispersion, 16),
self.ref_id,
_to_int(self.ref_timestamp),
_to_frac(self.ref_timestamp),
#Change by lichen, avoid loss of precision
self.orig_timestamp_high,
self.orig_timestamp_low,
_to_int(self.recv_timestamp),
_to_frac(self.recv_timestamp),
_to_int(self.tx_timestamp),
_to_frac(self.tx_timestamp))
(self.leap << 6 | self.version << 3 | self.mode),
self.stratum,
self.poll,
self.precision,
_to_int(self.root_delay) << 16 | _to_frac(self.root_delay, 16),
_to_int(self.root_dispersion) << 16 |
_to_frac(self.root_dispersion, 16),
self.ref_id,
_to_int(self.ref_timestamp),
_to_frac(self.ref_timestamp),
#Change by lichen, avoid loss of precision
self.orig_timestamp_high,
self.orig_timestamp_low,
_to_int(self.recv_timestamp),
_to_frac(self.recv_timestamp),
_to_int(self.tx_timestamp),
_to_frac(self.tx_timestamp))
except struct.error:
raise NTPException("Invalid NTP packet fields.")
return packed
Expand All @@ -206,7 +205,7 @@ def from_data(self, data):
"""
try:
unpacked = struct.unpack(NTPPacket._PACKET_FORMAT,
data[0:struct.calcsize(NTPPacket._PACKET_FORMAT)])
data[0:struct.calcsize(NTPPacket._PACKET_FORMAT)])
except struct.error:
raise NTPException("Invalid NTP packet.")

Expand All @@ -228,88 +227,89 @@ def from_data(self, data):
self.tx_timestamp_high = unpacked[13]
self.tx_timestamp_low = unpacked[14]

def GetTxTimeStamp(self):
return (self.tx_timestamp_high,self.tx_timestamp_low)
def get_tx_time_stamp(self):
return (self.tx_timestamp_high, self.tx_timestamp_low)

def SetOriginTimeStamp(self,high,low):
def set_origin_time_stamp(self, high, low):
self.orig_timestamp_high = high
self.orig_timestamp_low = low


class RecvThread(threading.Thread):
def __init__(self,socket):
def __init__(self, my_socket):
threading.Thread.__init__(self)
self.socket = socket
self.my_socket = my_socket
def run(self):
global taskQueue,stopFlag
global TASK_QUEUE, STOP_FLAG
while True:
if stopFlag == True:
if STOP_FLAG is True:
print "RecvThread Ended"
break
rlist,wlist,elist = select.select([self.socket],[],[],1);
rlist, _, _ = select.select([self.my_socket], [], [], 1)
if len(rlist) != 0:
print "Received %d packets" % len(rlist)
for tempSocket in rlist:
for temp_socket in rlist:
try:
data,addr = tempSocket.recvfrom(1024)
recvTimestamp = recvTimestamp = system_to_ntp_time(time.time())
taskQueue.put((data,addr,recvTimestamp))
except socket.error,msg:
print msg;
data, addr = temp_socket.recvfrom(1024)
recv_timestamp = recv_timestamp = system_to_ntp_time(time.time())
TASK_QUEUE.put((data, addr, recv_timestamp))
except socket.error, msg:
print msg

class WorkThread(threading.Thread):
def __init__(self,socket):
def __init__(self, my_socket):
threading.Thread.__init__(self)
self.socket = socket
self.my_socket = my_socket
def run(self):
global taskQueue,stopFlag
global TASK_QUEUE, STOP_FLAG
while True:
if stopFlag == True:
if STOP_FLAG is True:
print "WorkThread Ended"
break
try:
data,addr,recvTimestamp = taskQueue.get(timeout=1)
recvPacket = NTPPacket()
recvPacket.from_data(data)
timeStamp_high,timeStamp_low = recvPacket.GetTxTimeStamp()
sendPacket = NTPPacket(version=3,mode=4)
sendPacket.stratum = 2
sendPacket.poll = 10
'''
sendPacket.precision = 0xfa
sendPacket.root_delay = 0x0bfa
sendPacket.root_dispersion = 0x0aa7
sendPacket.ref_id = 0x808a8c2c
'''
sendPacket.ref_timestamp = recvTimestamp-5
sendPacket.SetOriginTimeStamp(timeStamp_high,timeStamp_low)
sendPacket.recv_timestamp = recvTimestamp
sendPacket.tx_timestamp = system_to_ntp_time(time.time())
socket.sendto(sendPacket.to_data(),addr)
print "Sended to %s:%d" % (addr[0],addr[1])
data, addr, recv_timestamp = TASK_QUEUE.get(timeout=1)
recv_packet = NTPPacket()
recv_packet.from_data(data)
time_stamp_high, time_stamp_low = recv_packet.get_tx_time_stamp()
send_packet = NTPPacket(version=3, mode=4)
send_packet.stratum = 2
send_packet.poll = 10
# send_packet.precision = 0xfa
# send_packet.root_delay = 0x0bfa
# send_packet.root_dispersion = 0x0aa7
# send_packet.ref_id = 0x808a8c2c
send_packet.ref_timestamp = recv_timestamp-5
send_packet.set_origin_time_stamp(time_stamp_high, time_stamp_low)
send_packet.recv_timestamp = recv_timestamp
send_packet.tx_timestamp = system_to_ntp_time(time.time())
self.my_socket.sendto(send_packet.to_data(), addr)
print "Sended to %s:%d" % (addr[0], addr[1])
except Queue.Empty:
continue


listenIp = "0.0.0.0"
listenPort = 123
socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
socket.bind((listenIp,listenPort))
print "local socket: ", socket.getsockname();
recvThread = RecvThread(socket)
recvThread.start()
workThread = WorkThread(socket)
workThread.start()

while True:
try:
time.sleep(0.5)
except KeyboardInterrupt:
print "Exiting..."
stopFlag = True
recvThread.join()
workThread.join()
#socket.close()
print "Exited"
break


def main():
global STOP_FLAG
listen_ip = "0.0.0.0"
listen_port = 123
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
listen_socket.bind((listen_ip, listen_port))
print "local socket: ", listen_socket.getsockname()
recv_thread = RecvThread(listen_socket)
recv_thread.start()
work_thread = WorkThread(listen_socket)
work_thread.start()

while True:
try:
time.sleep(0.5)
except KeyboardInterrupt:
print "Exiting..."
STOP_FLAG = True
recv_thread.join()
work_thread.join()
#listen_socket.close()
print "Exited"
break

if __name__ == '__main__':
main()