added test case and fixed incomplete data

This commit is contained in:
Arturo Hernandez
2018-07-20 19:47:36 -04:00
parent ff7b4902c2
commit 46560b4511
2 changed files with 164 additions and 135 deletions

View File

@@ -958,88 +958,6 @@ class ZK(object):
else:
if self.verbose: print ("can't read/find finger")
return None
#-----------------------------------------------------------------
if not cmd_response.get('status'):
return None #("can't get user template")
#else
if cmd_response.get('code') == const.CMD_DATA: # less than 1024!!!
resp = self.__data[:-1]
if self.tcp:
if resp[-6:] == b'\x00\x00\x00\x00\x00\x00': # padding? bug?
resp = resp[:-6]
if self.verbose: print("tcp too small!")
return Finger(uid, temp_id, 1, resp)
if cmd_response.get('code') == const.CMD_PREPARE_DATA:
data = []
bytes = self.__get_data_size() #TODO: check with size
size = bytes
if self.tcp:
data_recv = self.__sock.recv(bytes + 32)
tcp_length = self.__test_tcp_top(data_recv)
if tcp_length == 0:
print ("Incorrect tcp packet")
return None
recieved = len(data_recv)
if self.verbose: print ("recieved {}, size {} rec {}".format(recieved, size, data_recv.encode('hex'))) #todo python3
tcp_length = unpack('<HHI', data_recv[:8])[2] #bytes+8
if tcp_length < (bytes + 8):
if self.verbose: print ("request chunk too big!")
response = unpack('HHHH', data_recv[8:16])[0]
if recieved >= (bytes + 32): #complete
if response == const.CMD_DATA:
resp = data_recv[16:bytes+16][:size-1] # no ack?
if resp[-6:] == b'\x00\x00\x00\x00\x00\x00': # padding? bug?
if self.verbose: print ("cutting from",len(resp))
resp = resp[:-6]
if self.verbose: print ("resp len1", len(resp))
return Finger(uid, temp_id, 1, resp) #mistery
else:
if self.verbose: print("broken packet!!!")
return None #broken
else: # incomplete
if self.verbose: print ("try incomplete")
data.append(data_recv[16:]) # w/o tcp and header
bytes -= recieved-16
while bytes>0: #jic
data_recv = self.__sock.recv(bytes) #ideal limit?
recieved = len(data_recv)
if self.verbose: print ("partial recv {}".format(recieved))
data.append(data_recv) # w/o tcp and header
bytes -= recieved
data_recv = self.__sock.recv(16)
response = unpack('<4H', data_recv[8:16])[0]
if response == const.CMD_ACK_OK:
resp = b''.join(data)[:size-1] # testing
if resp[-6:] == b'\x00\x00\x00\x00\x00\x00':
resp = resp[:-6]
if self.verbose: print ("resp len2", len(resp))
return Finger(uid, temp_id, 1, resp)
#data_recv[bytes+16:].encode('hex') #included CMD_ACK_OK
if self.verbose: print("bad response %s" % data_recv)
if self.verbose: print(data)
return None
#else udp
size = bytes
while True: #limitado por respuesta no por tamaño
data_recv = self.__sock.recv(response_size)
response = unpack('<4H', data_recv[:8])[0]
if self.verbose: print("# packet response is: {}".format(response))
if response == const.CMD_DATA:
data.append(data_recv[8:]) #header turncated
bytes -= 1024
elif response == const.CMD_ACK_OK:
break #without problem.
else:
#truncado! continuar?
if self.verbose: print("broken!")
break
if self.verbose: print("still needs %s" % bytes)
data = b''.join(data)[:-1]
if data[-6:] == b'\x00\x00\x00\x00\x00\x00': # padding? bug?
data = data[:-6]
#uid 32 fing 03, starts with 4d-9b-53-53-32-31
#CMD_USERTEMP_RRQ desn't need [:-1]
return Finger(uid, temp_id, 1, data)
def get_templates(self):
""" return array of all fingers """
@@ -1073,7 +991,7 @@ class ZK(object):
users = []
max_uid = 0
userdata, size = self.read_with_buffer(const.CMD_USERTEMP_RRQ, const.FCT_USER)
if self.verbose: print("user size %i" % size)
if self.verbose: print("user size {} (= {})".format(size, len(userdata)))
if size <= 4:
print("WRN: missing user data")# debug
return []
@@ -1342,6 +1260,73 @@ class ZK(object):
else:
raise ZKErrorResponse("can't clear data")
def __recieve_tcp_data(self, data_recv, size):
""" data_recv, raw tcp packet
must analyze tcp_length
must return data, broken
"""
data = []
tcp_length = self.__test_tcp_top(data_recv) # tcp header
if self.verbose: print ("tcp_length {}, size {}".format(tcp_length, size))
if tcp_length <= 0:
if self.verbose: print ("Incorrect tcp packet")
return None, b""
if (tcp_length - 8) < size: #broken on smaller DATAs
if self.verbose: print ("tcp length too small... retrying")
resp, bh = self.__recieve_tcp_data(data_recv, tcp_length - 8)
data.append(resp)
size -= len(resp)
if self.verbose: print ("new tcp DATA packet to fill misssing {}".format(size))
data_recv = bh + self.__sock.recv(size) #ideal limit?
resp, bh = self.__recieve_tcp_data(data_recv, size)
data.append(resp)
if self.verbose: print ("for misssing {} recieved {} with extra {}".format(size, len(resp), len(bh)))
return b''.join(data), bh
recieved = len(data_recv)
if self.verbose: print ("recieved {}, size {}".format(recieved, size))
#if (tcp_length - 16) > (recieved - 16): #broken first DATA
# #reparse as more data packets?
# if self.verbose: print ("trying".format(recieved, size))
# _data, bh = self.__recieve_tcp_data(data_recv, tcp_length-16)
#analize first response
response = unpack('HHHH', data_recv[8:16])[0]
if recieved >= (size + 32): #complete with ACK_OK included
if response == const.CMD_DATA:
resp = data_recv[16 : size + 16] # no ack?
if self.verbose: print ("resp complete len {}".format(len(resp)))
return resp, data_recv[size + 16:]
else:
if self.verbose: print("incorrect response!!! {}".format(response))
return None, b"" #broken
else: # response DATA incomplete (or missing ACK_OK)
if self.verbose: print ("try DATA incomplete (actual valid {})".format(recieved-16))
data.append(data_recv[16 : size + 16 ]) # w/o DATA tcp and header
size -= recieved - 16 # w/o DATA tcp and header
broken_header = b""
if size < 0: #broken ack header?
broken_header = data_recv[size:]
if self.verbose: print ("broken", (broken_header).encode('hex')) #TODO python3
if size > 0: #need raw data to complete
data_recv = self.__recieve_raw_data(size)
data.append(data_recv) # w/o tcp and header
return b''.join(data), broken_header
#get cmd_ack_ok on __rchunk
def __recieve_raw_data(self, size):
""" partial data ? """
data = []
if self.verbose: print ("expecting {} bytes raw data".format(size))
while size > 0:
data_recv = self.__sock.recv(size) #ideal limit?
recieved = len(data_recv)
if self.verbose: print ("partial recv {}".format(recieved))
data.append(data_recv) # w/o tcp and header
size -= recieved
if self.verbose: print ("still need {}".format(size))
return b''.join(data)
def __recieve_chunk(self):
""" recieve a chunk """
if self.__response == const.CMD_DATA: # less than 1024!!!
@@ -1350,61 +1335,36 @@ class ZK(object):
elif self.__response == const.CMD_PREPARE_DATA:
data = []
size = self.__get_data_size()
if self.verbose: print ("recieve chunk:data size is", size)
if self.verbose: print ("recieve chunk: prepare data size is {}".format(size))
if self.tcp:
if len(self.__data)>=(8+size): #prepare data with actual data! should be 8+size+32
if len(self.__data) >= (8 + size): #prepare data with actual data! should be 8+size+32
data_recv = self.__data[8:] # test, maybe -32
else:
data_recv = self.__sock.recv(size + 32)
tcp_length = self.__test_tcp_top(data_recv)
if tcp_length == 0:
print ("Incorrect tcp packet")
return None
recieved = len(data_recv)
if self.verbose: print ("recieved {}, size {}".format(recieved, size))
if tcp_length < (size + 8):
if self.verbose: print ("request chunk too big!")
response = unpack('HHHH', data_recv[8:16])[0]
if recieved >= (size + 32): #complete with ACK_OK included
if response == const.CMD_DATA:
resp = data_recv[16 : size + 16] # no ack?
if self.verbose: print ("resp complete len", len(resp))
return resp
else:
if self.verbose: print("broken packet!!! {}".format(response))
return None #broken
else: # incomplete
if self.verbose: print ("try incomplete (actual valid {})".format(recieved-16))
data.append(data_recv[16 : size+ 16 ]) # w/o DATA tcp and header
size -= recieved-16 # w/o DATA tcp and header
broken_header = b""
if size < 0: #broken ack header?
broken_header = data_recv[size:]
if self.verbose: print ("broken", (broken_header).encode('hex')) #TODO python3
while size>0: #jic
if self.verbose: print ("still need {}".format(size))
data_recv = self.__sock.recv(size) #ideal limit?
recieved = len(data_recv)
if self.verbose: print ("partial recv {}".format(recieved))
data.append(data_recv) # w/o tcp and header
size -= recieved
#get cmd_ack_ok
data_recv = self.__sock.recv(size + 32) #could have two commands
resp, broken_header = self.__recieve_tcp_data(data_recv, size)
data.append(resp)
# get CMD_ACK_OK
if len(broken_header) < 16:
data_recv = broken_header + self.__sock.recv(16)
#could be broken
if len(data_recv) < 16:
print ("trying to complete broken ACK %s /16" % len(data_recv))
if self.verbose: print (data_recv.encode('hex')) #todo python3
data_recv += self.__sock.recv(16 - len(data_recv)) #TODO: CHECK HERE_!
if not self.__test_tcp_top(data_recv):
if self.verbose: print ("invalid tcp ACK OK")
return None #b''.join(data) # incomplete?
response = unpack('HHHH', data_recv[8:16])[0]
if response == const.CMD_ACK_OK:
return b''.join(data)
#data_recv[bytes+16:].encode('hex') #included CMD_ACK_OK
if self.verbose: print("bad response %s" % data_recv)
if self.verbose: print (data)
return None
else:
data_recv = broken_header
#could be broken
if len(data_recv) < 16:
print ("trying to complete broken ACK %s /16" % len(data_recv))
if self.verbose: print (data_recv.encode('hex')) #todo python3
data_recv += self.__sock.recv(16 - len(data_recv)) #TODO: CHECK HERE_!
if not self.__test_tcp_top(data_recv):
if self.verbose: print ("invalid chunk tcp ACK OK")
return None #b''.join(data) # incomplete?
response = unpack('HHHH', data_recv[8:16])[0]
if response == const.CMD_ACK_OK:
if self.verbose: print ("chunk tcp ACK OK!")
return b''.join(data)
if self.verbose: print("bad response %s" % data_recv)
if self.verbose: print (codecs.encode(data,'hex'))
return None
return resp
#else udp
while True: #limitado por respuesta no por tamaño
data_recv = self.__sock.recv(1024+8)
@@ -1459,10 +1419,12 @@ class ZK(object):
#direct!!! small!!!
size = len(self.__data)
return self.__data, size
#else ACK_OK with size
size = unpack('I', self.__data[1:5])[0] # extra info???
if self.verbose: print ("size fill be %i" % size)
remain = size % MAX_CHUNK
packets = (size-remain) // MAX_CHUNK # should be size /16k
if self.verbose: print ("rwb: #{} packets of max {} bytes, and extra {} bytes remain".format(packets, MAX_CHUNK, remain))
for _wlk in range(packets):
data.append(self.__read_chunk(start,MAX_CHUNK))
start += MAX_CHUNK