add outdated warning to pyth*n

This commit is contained in:
Mystikfluu
2023-05-30 16:01:30 +02:00
parent 2474c62b5b
commit 85386d11fb
3 changed files with 5 additions and 1 deletions
+171
View File
@@ -0,0 +1,171 @@
print("###WARNING### This client is outdated and can only be used with server.py")
timeout = 0.5
local_server = False
serverAddressPort = ("213.47.107.152", 1337)
if local_server:
serverAddressPort[0] = "127.0.0.1"
possible_value = input("Enter a value: ")
filename = possible_value if (filename := possible_value) else "data.bin"
import socket, struct, select, time, math
import hashlib
#convert bps to Kbps, Mbps, Gbps if they are >= 1000
def convert_to_highest_speed(bps):
if bps < 1000:
return f'{round(bps,2)}bps'
elif bps < 1000**2:
return f'{round(bps/1000,2)}Kbps'
elif bps < 1000**3:
return f'{round(bps/1000**2,2)}Mbps'
elif bps < 1000**4:
return f'{round(bps/1000**3,2)}Gbps'
max_frame_payload=1016 #508 is the minimum size for routers to "understand" udp packets, but we can possibly send more data
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)
ready = select.select([UDPClientSocket], [], [], timeout)
if not ready[0]:
print("Server not responding")
exit()
msgFromServer = UDPClientSocket.recvfrom(max_frame_payload)[0]
msg = struct.unpack(f'!IHQ', msgFromServer)
last_packet_size = msg[1]
if msg[2] != sum(byte for byte in message.encode('utf-8')):
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) == 65:
serverhash = struct.unpack("64sx", datareceived)[0]
continue
if len(datareceived) != max_frame_payload:
print("\n[WARNING] bad packet: wrong size",len(datareceived))
continue
seq,checksum,data = struct.unpack(f"{header}{max_payload}s", datareceived)
if data_packets[seq] != None:
print("\n[INFO] 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("\n[WARNING] bad packet: checksum mismatch",seq)
print(checksum.hex(),hashlib.sha3_512(data).digest()[:16].hex())
print(data.hex())
continue
#print(seq)
#print(data)
#data = deflate.gzip_decompress(data)
data_packets[seq] = data
packets -= 1
else:
#collect packets that were not received and send them in n messages
#where n is the minimum amount of messages needed to request all packets
msg = message
lost_packets = []
for i in range(len(data_packets)):
if data_packets[i] == None:
lost_packets.append(i)
#split lost_packets into groups of size 508-msg.length bytes
current_packets = []
for i in range(len(lost_packets)):
if len(str(lost_packets[i])) + len(msg) + 1 > max_frame_payload:
current_packets.append(msg)
msg = message
msg += f"/{lost_packets[i]}"
if len(lost_packets) > 0:
timeout *= 2 #increase timeout to relieve internet connection and server
current_packets.append(msg)
for msg in current_packets:
UDPClientSocket.sendto(str.encode(msg), serverAddressPort)
#print(f'requested lost packets {msg}')
if serverhash == None:
UDPClientSocket.sendto(str.encode(f"{message}:"), serverAddressPort)
download_speed = (total_packets - packets)/(time.time()-time_started if (time.time()-time_started)!=0 else 1)*max_payload
print(f'{total_packets - packets}/{total_packets} | {round((total_packets - packets)/total_packets*100,2)}% | {convert_to_highest_speed(download_speed)}'+'\t'*5, end='\r')
print("finished transfer" + "\t"*5, end='\r')
for packet in data_packets:
sha512.update(packet)
sha512 = sha512.hexdigest()
total_data = b''.join(data_packets)
if sha512 != serverhash.hex():
print('sha512: %s' % sha512)
print('server sha512: %s' % serverhash.hex())
print(f'hash mismatch, writing corrupt file to disk: {filename}.corrupt')
with open("received/"+filename+".corrupt", 'wb') as f:
f.write(total_data)
exit()
with open("received/"+filename, 'wb') as f:
f.write(total_data)
print(f'{filename} generated with size {len(total_data)} bytes')
+9
View File
@@ -0,0 +1,9 @@
import secrets
rndsize = 488*500+5
rndbytes = secrets.token_bytes(rndsize)
open('files/data.bin', 'wb').write(rndbytes)
print('data.bin generated with size %d bytes' % rndsize)
+112
View File
@@ -0,0 +1,112 @@
print("###WARNING### This server is outdated and can only be used with client.py")
import socket, struct, os, select, math, hashlib, re#, brotli
max_frame_payload=508 #1016 #508 is the minimum size for routers to "understand" udp packets, but we can possibly send more data
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.-_ ]+:")
def send_missing_packet(filename, address, msgpart):
with open(filename, 'rb') as f:
#part = int(message.decode().split('/')[1])
part = int(msgpart)
#print(f'part {part} | msgpart {msgpart}')
f.seek(part*max_payload)
data = f.read(max_payload)
#data = deflate.gzip_compress(data, 12)
checksum = hashlib.sha3_512(data).digest()[:16]
data = struct.pack(f"{header}{max_payload}s", part, checksum, data)
UDPServerSocket.sendto(data, address)
while True:
ready = select.select([UDPServerSocket], [], [], 0.1)
if ready[0]:
try:
bytesAddressPair = UDPServerSocket.recvfrom(max_frame_payload)
except:
continue
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
for msgpart in message.decode().split('/')[1:]:
send_missing_packet(filename, address, msgpart) #extracted from loop for clarity
print(f'sent lost packets {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("64sx", 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)
filename_checksum = sum(message)
tosend = struct.pack(f'!IHQ', file_len, last_packet_size, filename_checksum)
UDPServerSocket.sendto(tosend, address)
sha512 = hashlib.sha512()
try:
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
checkhash = hashlib.sha3_512(fdata).digest()[:16]
data = struct.pack(f"{header}{max_payload}s", i, checkhash, fdata)
#print("sending data",fdata)
UDPServerSocket.sendto(data, address)
print(f'{i+1}/{file_len}', end='\r')
UDPServerSocket.sendto(struct.pack("64sx", sha512.digest()), address)
except:
pass
print(' '*100,end='\r')