init
This commit is contained in:
commit
320ad23b29
129
client.py
Normal file
129
client.py
Normal file
@ -0,0 +1,129 @@
|
||||
timeout = 1
|
||||
serverAddressPort = ("213.47.107.152", 1337)
|
||||
|
||||
possible_value = input("Enter a value: ")
|
||||
filename = possible_value if (filename := possible_value) else "data.bin"
|
||||
|
||||
import socket, struct, select, time, math
|
||||
|
||||
import hashlib
|
||||
|
||||
#import brotli #pip install brotlipy
|
||||
|
||||
max_frame_payload=508
|
||||
header = "!L16s"
|
||||
header_size = struct.calcsize(header)
|
||||
max_payload = max_frame_payload - header_size
|
||||
|
||||
UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
|
||||
|
||||
|
||||
message = filename
|
||||
|
||||
|
||||
UDPClientSocket.sendto(str.encode(message), serverAddressPort)
|
||||
|
||||
msgFromServer = UDPClientSocket.recvfrom(max_frame_payload)[0]
|
||||
|
||||
msg = struct.unpack(f'!LH{len(message)}s', msgFromServer)
|
||||
|
||||
last_packet_size = msg[1]
|
||||
|
||||
if msg[2] != str.encode(message):
|
||||
print('Server error: wrong file name')
|
||||
exit()
|
||||
|
||||
total_packets = msg[0]
|
||||
|
||||
packets = msg[0]
|
||||
|
||||
print(f'Packets to receive: {packets}')
|
||||
|
||||
total_data = b''
|
||||
|
||||
data_packets = []
|
||||
for i in range(packets):
|
||||
data_packets.append(None)
|
||||
|
||||
sha512 = hashlib.sha512()
|
||||
|
||||
serverhash = None
|
||||
|
||||
time_started = time.time()
|
||||
|
||||
while packets > 0 or serverhash == None:
|
||||
|
||||
ready = select.select([UDPClientSocket], [], [], timeout)
|
||||
|
||||
if ready[0]:
|
||||
|
||||
datareceived = UDPClientSocket.recvfrom(max_frame_payload)[0]
|
||||
if len(datareceived) == 64:
|
||||
serverhash = struct.unpack("64s", datareceived)[0]
|
||||
continue
|
||||
if len(datareceived) != max_frame_payload:
|
||||
print("\nerror bad packet: wrong size",len(datareceived))
|
||||
continue
|
||||
|
||||
|
||||
seq,checksum,data = struct.unpack(f"{header}{max_payload}s", datareceived)
|
||||
if data_packets[seq] != None:
|
||||
print("\nerror bad packet: received multiple times",seq)
|
||||
continue
|
||||
|
||||
#check if packet is last packet and cut data to last packet size
|
||||
if seq == total_packets-1:
|
||||
#print("len before cut",len(data))
|
||||
data = data[:last_packet_size]
|
||||
# print("len after cut",len(data))
|
||||
|
||||
#check if packet is corrupted
|
||||
if checksum.hex() != hashlib.sha3_512(data).digest()[:16].hex():
|
||||
print("\nerror bad packet: checksum mismatch",seq)
|
||||
print(checksum.hex(),hashlib.sha3_512(data).digest()[:16].hex())
|
||||
print(data.hex())
|
||||
continue
|
||||
|
||||
data_packets[seq] = data
|
||||
|
||||
packets -= 1
|
||||
else:
|
||||
#collect packets that were not received and send them in one message
|
||||
for i in range(len(data_packets)):
|
||||
if data_packets[i] == None:
|
||||
#print("requesting packet", i)
|
||||
UDPClientSocket.sendto(str.encode(f"{message}/{i}"), serverAddressPort)
|
||||
|
||||
if serverhash == None:
|
||||
UDPClientSocket.sendto(str.encode(f"{message}:"), serverAddressPort)
|
||||
print(f'{total_packets - packets}/{total_packets} | {math.floor((total_packets - packets)/(time.time()-time_started if (time.time()-time_started)!=0 else 1)*max_payload)}Bps'+'\t'*10, end='\r')
|
||||
|
||||
|
||||
|
||||
print("finished transfer", end='\r')
|
||||
|
||||
for packet in data_packets:
|
||||
sha512.update(packet)
|
||||
|
||||
sha512 = sha512.hexdigest()
|
||||
|
||||
print('sha512: %s' % sha512)
|
||||
|
||||
print('server sha512: %s' % serverhash.hex())
|
||||
|
||||
if sha512 != serverhash.hex():
|
||||
print('hash mismatch')
|
||||
with open("received/"+filename+".corrupt", 'wb') as f:
|
||||
f.write(total_data)
|
||||
exit()
|
||||
|
||||
total_data = b''.join(data_packets)
|
||||
|
||||
with open("received/"+filename, 'wb') as f:
|
||||
f.write(total_data)
|
||||
|
||||
print(f'{filename} generated with size {len(total_data)} bytes')
|
||||
|
||||
|
||||
|
||||
|
9
generate_data.py
Normal file
9
generate_data.py
Normal file
@ -0,0 +1,9 @@
|
||||
import secrets
|
||||
|
||||
rndsize = 488*50_000
|
||||
|
||||
rndbytes = secrets.token_bytes(rndsize)
|
||||
|
||||
open('files/data.bin', 'wb').write(rndbytes)
|
||||
|
||||
print('data.bin generated with size %d bytes' % rndsize)
|
92
server.py
Normal file
92
server.py
Normal file
@ -0,0 +1,92 @@
|
||||
import socket, struct, os, select, math, hashlib, re#, brotli
|
||||
|
||||
max_frame_payload=508
|
||||
header = "!L16s"
|
||||
header_size = struct.calcsize(header)
|
||||
max_payload = max_frame_payload - header_size
|
||||
|
||||
localport = 1337
|
||||
localip = '0.0.0.0'
|
||||
|
||||
|
||||
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
|
||||
|
||||
UDPServerSocket.bind((localip, localport))
|
||||
UDPServerSocket.setblocking(0)
|
||||
|
||||
print("UDP server up and listening")
|
||||
|
||||
packet_request_format = re.compile("[a-zA-Z0-9.-_ ]+/[0-9]+")
|
||||
hash_request_format = re.compile("[a-zA-Z0-9.-_ ]+:")
|
||||
|
||||
while True:
|
||||
|
||||
ready = select.select([UDPServerSocket], [], [], 0.1)
|
||||
|
||||
if ready[0]:
|
||||
|
||||
bytesAddressPair = UDPServerSocket.recvfrom(max_frame_payload)
|
||||
|
||||
message = bytesAddressPair[0]
|
||||
|
||||
if ".." in message.decode():
|
||||
continue
|
||||
|
||||
address = bytesAddressPair[1]
|
||||
|
||||
if re.match(packet_request_format, message.decode()):
|
||||
filename = "./files/"+message.decode().split('/')[0]
|
||||
if not os.path.isfile(filename):
|
||||
continue
|
||||
with open(filename, 'rb') as f:
|
||||
part = int(message.decode().split('/')[1])
|
||||
f.seek(part*max_payload)
|
||||
data = f.read(max_payload)
|
||||
checksum = hashlib.sha3_512(data).digest()[:16]
|
||||
data = struct.pack(f"{header}{max_payload}s", part, checksum, data)
|
||||
UDPServerSocket.sendto(data, address)
|
||||
print(f'sent lost packet {message.decode()}')
|
||||
continue
|
||||
|
||||
if re.match(hash_request_format, message.decode()):
|
||||
print("hash request")
|
||||
filename = "./files/"+message.decode().split(':')[0]
|
||||
if not os.path.isfile(filename):
|
||||
continue
|
||||
sha512 = hashlib.sha1()
|
||||
with open(filename, 'rb') as f:
|
||||
data = f.read(max_payload)
|
||||
sha512.update(data)
|
||||
UDPServerSocket.sendto(struct.pack("64s", sha512.digest()), address)
|
||||
continue
|
||||
|
||||
filename = "./files/"+message.decode()
|
||||
if not os.path.isfile(filename):
|
||||
continue
|
||||
file_len = math.ceil(os.path.getsize(filename)/max_payload)
|
||||
|
||||
#calculate last packet size
|
||||
last_packet_size = os.path.getsize(filename) % max_payload
|
||||
if last_packet_size == 0:
|
||||
last_packet_size = max_payload # if last packet is full, set size to max
|
||||
#print(max_payload,last_packet_size)
|
||||
|
||||
tosend = struct.pack(f'!LH{len(message.decode())}s', file_len, last_packet_size, message)
|
||||
|
||||
UDPServerSocket.sendto(tosend, address)
|
||||
|
||||
sha512 = hashlib.sha512()
|
||||
|
||||
with open(filename, 'rb') as f:
|
||||
for i in range(file_len):
|
||||
fdata = f.read(max_payload)
|
||||
sha512.update(fdata)
|
||||
#if i == 5: #simulate lost packet
|
||||
# continue
|
||||
checksum = hashlib.sha3_512(fdata).digest()[:16]
|
||||
data = struct.pack(f"{header}{max_payload}s", i, checksum, fdata)
|
||||
#print("sending data",fdata)
|
||||
UDPServerSocket.sendto(data, address)
|
||||
print(f'{i+1}/{file_len}', end='\r')
|
||||
UDPServerSocket.sendto(struct.pack("64s", sha512.digest()), address)
|
||||
print(' '*100,end='\r')
|
Loading…
x
Reference in New Issue
Block a user