feat(udp): help functionality finished
- Added res-code to client.py - Improved client error handling
This commit is contained in:
parent
236853828f
commit
d369b8e1b1
@ -19,11 +19,20 @@ summary_command_pattern: Pattern = re.compile(r"^summary\s+[^\s]+$")
|
|||||||
change_command_pattern: Pattern = re.compile(r"^change\s+[^\s]+\s+[^\s]+$")
|
change_command_pattern: Pattern = re.compile(r"^change\s+[^\s]+\s+[^\s]+$")
|
||||||
|
|
||||||
# opcodes
|
# opcodes
|
||||||
put_request_opcode = "000"
|
put_request_opcode:str = "000"
|
||||||
get_request_opcode = "001"
|
get_request_opcode:str = "001"
|
||||||
change_request_opcode = "010"
|
change_request_opcode: str = "010"
|
||||||
summary_request_opcode = "011"
|
summary_request_opcode: str = "011"
|
||||||
help_requrest_opcode = "100"
|
help_requrest_opcode: str = "100"
|
||||||
|
|
||||||
|
# Res-code
|
||||||
|
correct_put_and_change_request_rescode: str = "000"
|
||||||
|
correct_get_request_rescode: str = "001"
|
||||||
|
correct_summary_request_rescode: str = "010"
|
||||||
|
file_not_error_rescode: str = "011"
|
||||||
|
unknown_request_rescode: str = "100"
|
||||||
|
unsuccessful_change_rescode: str = "101"
|
||||||
|
help_rescode: str = "110"
|
||||||
|
|
||||||
# custome type to represent the hostname(server name) and the server port
|
# custome type to represent the hostname(server name) and the server port
|
||||||
Address = Tuple[str, int]
|
Address = Tuple[str, int]
|
||||||
@ -64,7 +73,10 @@ class UDPClient:
|
|||||||
|
|
||||||
# help
|
# help
|
||||||
elif command == "help":
|
elif command == "help":
|
||||||
continue
|
request_payload: str = help_requrest_opcode + "00000"
|
||||||
|
print(
|
||||||
|
f"myftp> - {self.mode} - : asking for help from the server"
|
||||||
|
) if self.debug else None
|
||||||
|
|
||||||
# get command handling
|
# get command handling
|
||||||
elif get_command_pattern.match(command):
|
elif get_command_pattern.match(command):
|
||||||
@ -87,7 +99,7 @@ class UDPClient:
|
|||||||
f"myftp> - {self.mode} - : summary file {filename} from the server"
|
f"myftp> - {self.mode} - : summary file {filename} from the server"
|
||||||
) if self.debug else None
|
) if self.debug else None
|
||||||
|
|
||||||
# summary command handling
|
# change command handling
|
||||||
elif change_command_pattern.match(command):
|
elif change_command_pattern.match(command):
|
||||||
_, old_filename, new_filename = command.split()
|
_, old_filename, new_filename = command.split()
|
||||||
print(
|
print(
|
||||||
@ -100,9 +112,10 @@ class UDPClient:
|
|||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
client_socket.send(command.encode())
|
client_socket.send(request_payload.encode("utf-8"))
|
||||||
modified_message = client_socket.recv(2048)
|
modified_message = client_socket.recv(2048)[1:]
|
||||||
print(modified_message.decode())
|
print(modified_message.decode())
|
||||||
|
client_socket.close() # type: ignore
|
||||||
|
|
||||||
except ConnectionRefusedError:
|
except ConnectionRefusedError:
|
||||||
print(
|
print(
|
||||||
@ -112,8 +125,6 @@ class UDPClient:
|
|||||||
print(
|
print(
|
||||||
f"myftp> - {self.mode} - {error} happened."
|
f"myftp> - {self.mode} - {error} happened."
|
||||||
)
|
)
|
||||||
finally:
|
|
||||||
client_socket.close() # type: ignore
|
|
||||||
|
|
||||||
# ping pong UDP
|
# ping pong UDP
|
||||||
def check_udp_server(self):
|
def check_udp_server(self):
|
||||||
@ -170,9 +181,7 @@ def get_address_input() -> Address:
|
|||||||
|
|
||||||
# Ensure there are exactly two parts
|
# Ensure there are exactly two parts
|
||||||
if len(input_parts) != 2:
|
if len(input_parts) != 2:
|
||||||
raise ValueError(
|
raise ValueError
|
||||||
"myftp>Invalid input. Please enter a servername/hostname/ip address as a string and the port number as an integer separated by a space."
|
|
||||||
)
|
|
||||||
|
|
||||||
# Extract the values and create the tuple
|
# Extract the values and create the tuple
|
||||||
string_part, int_part = input_parts
|
string_part, int_part = input_parts
|
||||||
@ -183,7 +192,7 @@ def get_address_input() -> Address:
|
|||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(
|
print(
|
||||||
f"Error: {e}. Invalid input. Please enter a servername/hostname/ip address as a string and the port number as an integer separated by a space."
|
f"Error: Invalid input. Please enter a servername/hostname/ip address as a string and the port number as an integer separated by a space."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,13 @@ unknown_request_rescode: str = "100"
|
|||||||
unsuccessful_change_rescode: str = "101"
|
unsuccessful_change_rescode: str = "101"
|
||||||
help_rescode: str = "110"
|
help_rescode: str = "110"
|
||||||
|
|
||||||
|
# opcodes
|
||||||
|
put_request_opcode: str = "000"
|
||||||
|
get_request_opcode: str = "001"
|
||||||
|
change_request_opcode: str = "010"
|
||||||
|
summary_request_opcode: str = "011"
|
||||||
|
help_requrest_opcode: str = "100"
|
||||||
|
|
||||||
|
|
||||||
class UDPServer:
|
class UDPServer:
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -41,33 +48,45 @@ class UDPServer:
|
|||||||
try:
|
try:
|
||||||
while not shut_down:
|
while not shut_down:
|
||||||
message, clientAddress = self.server_socket.recvfrom(2048)
|
message, clientAddress = self.server_socket.recvfrom(2048)
|
||||||
message_in_utf8 = message.decode()
|
request_payload = message.decode()
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f"myftp> - {self.mode} - received message from client at {clientAddress}: {message_in_utf8}"
|
f"myftp> - {self.mode} - received message from client at {clientAddress}: {request_payload}"
|
||||||
) if self.debug else None
|
) if self.debug else None
|
||||||
|
|
||||||
# check for connectivity
|
# check for connectivity
|
||||||
if message_in_utf8 == "ping":
|
if request_payload == "ping":
|
||||||
response_message = "pong"
|
self.server_socket.sendto("pong".encode(), clientAddress)
|
||||||
|
continue
|
||||||
|
|
||||||
# list files available on server
|
# list files available on server
|
||||||
elif message_in_utf8 == "list":
|
elif request_payload == "list":
|
||||||
encoded_message = pickle.dumps(
|
encoded_message = pickle.dumps(
|
||||||
get_files_in_directory(self.directory_path)
|
get_files_in_directory(self.directory_path)
|
||||||
)
|
)
|
||||||
self.server_socket.sendto(encoded_message, clientAddress)
|
self.server_socket.sendto(encoded_message, clientAddress)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# help request handling
|
||||||
|
elif request_payload == help_requrest_opcode + "00000":
|
||||||
|
print(
|
||||||
|
f"myftp> - {self.mode} - received help request"
|
||||||
|
) if self.debug else None
|
||||||
|
rescode = help_rescode
|
||||||
|
response_data_string = "get,put,summary,change,help,bye"
|
||||||
|
|
||||||
else:
|
else:
|
||||||
response_message = message_in_utf8.upper()
|
# handle unrecognized request here
|
||||||
|
pass
|
||||||
|
|
||||||
|
payload: bytes = self.build_res_payload(rescode, response_data_string)
|
||||||
|
|
||||||
|
self.server_socket.sendto(payload, clientAddress)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f"myftp> - {self.mode} - sent message to client at {clientAddress}: {response_message}"
|
f"myftp> - {self.mode} - sent message to client at {clientAddress}: {payload}"
|
||||||
) if self.debug else None
|
) if self.debug else None
|
||||||
|
|
||||||
self.server_socket.sendto(response_message.encode(), clientAddress)
|
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
shut_down = True
|
shut_down = True
|
||||||
self.server_socket.close()
|
self.server_socket.close()
|
||||||
@ -76,6 +95,40 @@ class UDPServer:
|
|||||||
finally:
|
finally:
|
||||||
print(f"myftp> - {self.mode} - Closed the server socket\n")
|
print(f"myftp> - {self.mode} - Closed the server socket\n")
|
||||||
|
|
||||||
|
# assembling the payload to send back to the client
|
||||||
|
def build_res_payload(self,
|
||||||
|
rescode: str,
|
||||||
|
response_data_string: str) -> bytes:
|
||||||
|
|
||||||
|
bytes_response_data = response_data_string.encode("utf-8")
|
||||||
|
|
||||||
|
data_len = len(bytes_response_data)
|
||||||
|
|
||||||
|
print(f"myftp> - {self.mode} - Rescode {rescode}") if self.debug else None
|
||||||
|
print(f"myftp> - {self.mode} - Length of data {data_len}") if self.debug else None
|
||||||
|
print(f"myftp> - {self.mode} - Data {response_data_string}") if self.debug else None
|
||||||
|
|
||||||
|
# convert to binary
|
||||||
|
try:
|
||||||
|
# pad the length of data to make sure it is always 5 bits
|
||||||
|
# i.e "010" -> "00010"
|
||||||
|
binary_data_len: str = bin(data_len).zfill(5)
|
||||||
|
|
||||||
|
print(f"myftp> - {self.mode} - binary_data_len {binary_data_len[2:]}") if self.debug else None
|
||||||
|
|
||||||
|
# create the first byte
|
||||||
|
# since binary_data_len is of the format 0b00100, we have to remove the first two characters 0b
|
||||||
|
first_byte: bytes = bytes([int(rescode + binary_data_len[2:], 2)])
|
||||||
|
|
||||||
|
print(f"myftp> - {self.mode} - First byte assembled for rescode {rescode}: {bin(int.from_bytes(first_byte, byteorder='big'))[2:]}") if self.debug else None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(e)
|
||||||
|
|
||||||
|
res_payload = first_byte + bytes_response_data
|
||||||
|
|
||||||
|
return res_payload
|
||||||
|
|
||||||
|
|
||||||
def get_files_in_directory(directory_path: str) -> list[str]:
|
def get_files_in_directory(directory_path: str) -> list[str]:
|
||||||
file_list = []
|
file_list = []
|
||||||
|
Loading…
x
Reference in New Issue
Block a user