feat(udp): put command completed
This commit is contained in:
parent
ae1d34da2a
commit
73b4e06d02
@ -4,7 +4,7 @@
|
||||
|
||||
|
||||
from socket import socket, AF_INET, SOCK_DGRAM
|
||||
from typing import Pattern, Tuple
|
||||
from typing import Pattern, Tuple, Optional
|
||||
from argparse import ArgumentParser
|
||||
import traceback
|
||||
import os
|
||||
@ -30,7 +30,7 @@ unknown_request_opcode: int = 0b101
|
||||
rescode_dict: dict[int, str] = {
|
||||
0b011: "File Not Found Error",
|
||||
0b100: "Unknown Request",
|
||||
0b101: "Change Unsuccessful Error",
|
||||
0b101: "Change/Put Unsuccessful Error",
|
||||
0b000: "Put/Change Request Successful",
|
||||
0b001: "Get Request Successful",
|
||||
0b010: "Summary Request Successful",
|
||||
@ -87,7 +87,7 @@ class Client:
|
||||
|
||||
first_byte = (get_request_opcode << 5) + len(filename)
|
||||
|
||||
second_byte_to_n_byte: bytes = filename.encode("ascii")
|
||||
second_byte_to_n_byte = filename.encode("ascii")
|
||||
|
||||
print(
|
||||
f"myftp> - {self.protocol} - Getting file {filename} from the server"
|
||||
@ -96,6 +96,11 @@ class Client:
|
||||
# put command handling
|
||||
elif put_command_pattern.match(command):
|
||||
command_name, filename = command.split(" ", 1)
|
||||
|
||||
first_byte, second_byte_to_n_byte, data = self.put_payload_handling(
|
||||
filename
|
||||
)
|
||||
|
||||
print(
|
||||
f"myftp> - {self.protocol} - Putting file {filename} into the server"
|
||||
) if self.debug else None
|
||||
@ -120,9 +125,16 @@ class Client:
|
||||
first_byte: int = unknown_request_opcode << 5
|
||||
|
||||
# get or put case
|
||||
if command_name == "get" or command_name == "put":
|
||||
if command_name == "get":
|
||||
payload = first_byte.to_bytes(1, "big") + second_byte_to_n_byte # type: ignore
|
||||
|
||||
elif command_name == "put":
|
||||
payload = (
|
||||
first_byte.to_bytes(1, "big") + second_byte_to_n_byte + data # type: ignore
|
||||
if second_byte_to_n_byte is not None and data is not None # type: ignore
|
||||
else first_byte.to_bytes(1, "big") # type: ignore
|
||||
)
|
||||
|
||||
elif command_name == "summary":
|
||||
pass
|
||||
|
||||
@ -189,19 +201,50 @@ class Client:
|
||||
|
||||
# successful rescodes
|
||||
else:
|
||||
# help rescode and successful change or put rescode
|
||||
if rescode == 0b110:
|
||||
print(f"myftp> - {self.protocol} - {response_data.decode('ascii')}")
|
||||
else:
|
||||
elif rescode == 0b000:
|
||||
print(f"myftp> - {self.protocol} - {rescode_dict[rescode]}")
|
||||
# get rescode
|
||||
elif rescode == 0b001:
|
||||
self.handle_get_response_from_server(filename_length, response_data)
|
||||
|
||||
def put_payload_handling(
|
||||
self, filename: str
|
||||
) -> Tuple[int, Optional[bytes], Optional[bytes]]:
|
||||
"""
|
||||
Assemble the pay load to put the file onto server
|
||||
|
||||
Return first_byte, second_byte_to_n_byte and data if successful
|
||||
Or (None, None, None) if file not found
|
||||
"""
|
||||
try:
|
||||
with open(os.path.join(self.directory_path, filename), "rb") as file:
|
||||
content = file.read()
|
||||
content_length = len(content)
|
||||
|
||||
first_byte = (put_request_opcode << 5) + len(filename)
|
||||
|
||||
second_byte_to_n_byte = filename.encode(
|
||||
"ascii"
|
||||
) + content_length.to_bytes(4, "big")
|
||||
|
||||
data = content
|
||||
|
||||
return (first_byte, second_byte_to_n_byte, data)
|
||||
|
||||
except FileNotFoundError:
|
||||
return ((put_request_opcode << 5), None, None)
|
||||
|
||||
def handle_get_response_from_server(
|
||||
self, filename_length: int, response_data: bytes
|
||||
):
|
||||
"""
|
||||
response_data is
|
||||
file name (filename_length bytes) +
|
||||
file size (4 bytes) +
|
||||
file content (rest of the bytes)
|
||||
Response_data is
|
||||
File name (filename_length bytes) +
|
||||
File size (4 bytes) +
|
||||
File content (rest of the bytes)
|
||||
"""
|
||||
try:
|
||||
filename = response_data[:filename_length].decode("ascii")
|
||||
|
@ -6,6 +6,7 @@
|
||||
from socket import socket, AF_INET, SOCK_DGRAM
|
||||
from argparse import ArgumentParser
|
||||
from typing import Optional, Tuple
|
||||
import traceback
|
||||
import os
|
||||
|
||||
# Res-codes
|
||||
@ -68,7 +69,9 @@ class Server:
|
||||
|
||||
first_byte = bytes([req_payload[0]])
|
||||
|
||||
request_type, filename_length = self.decode_first_byte(first_byte)
|
||||
request_type, filename_length_in_bytes = self.decode_first_byte(
|
||||
first_byte
|
||||
)
|
||||
|
||||
print(
|
||||
f"myftp> - {self.protocol} - Received message from client at {clientAddress}: {req_payload}"
|
||||
@ -83,7 +86,7 @@ class Server:
|
||||
rescode = rescode_success_dict["help_rescode"]
|
||||
response_data = "get,put,summary,change,help,bye".encode("ascii")
|
||||
filename = None
|
||||
filename_length = None
|
||||
filename_length_in_bytes = None
|
||||
|
||||
elif request_type == "get":
|
||||
pre_payload = self.process_get_req(req_payload[1:])
|
||||
@ -95,24 +98,41 @@ class Server:
|
||||
):
|
||||
rescode = rescode_success_dict["correct_get_request_rescode"]
|
||||
filename = pre_payload[0]
|
||||
filename_length = pre_payload[2]
|
||||
filename_length_in_bytes = pre_payload[2]
|
||||
response_data = pre_payload[1]
|
||||
|
||||
else:
|
||||
rescode = rescode_fail_dict["file_not_error_rescode"]
|
||||
filename_length = None
|
||||
filename_length_in_bytes = None
|
||||
filename = None
|
||||
response_data = None
|
||||
|
||||
elif request_type == "put":
|
||||
# put request failed since there wasnt a file sent from client
|
||||
if filename_length_in_bytes == 0:
|
||||
rescode = rescode_fail_dict["unsuccessful_change_rescode"]
|
||||
filename_length_in_bytes = None
|
||||
filename = None
|
||||
response_data = None
|
||||
|
||||
# put request success
|
||||
else:
|
||||
rescode = self.process_put_req(
|
||||
filename_length_in_bytes, req_payload[1:]
|
||||
)
|
||||
filename_length_in_bytes = None
|
||||
filename = None
|
||||
response_data = None
|
||||
|
||||
elif request_type == "unknown":
|
||||
rescode = rescode_fail_dict["unknown_request_rescode"]
|
||||
filename_length = None
|
||||
filename_length_in_bytes = None
|
||||
filename = None
|
||||
response_data = None
|
||||
|
||||
res_payload: bytes = self.build_res_payload(
|
||||
rescode=rescode, # type: ignore
|
||||
filename_length=filename_length,
|
||||
filename_length=filename_length_in_bytes,
|
||||
filename=filename, # type: ignore
|
||||
response_data=response_data, # type:ignore
|
||||
)
|
||||
@ -154,6 +174,38 @@ class Server:
|
||||
|
||||
return request_type, filename_length_in_bytes
|
||||
|
||||
def process_put_req(self, filename_length: int, req_payload: bytes) -> int:
|
||||
"""
|
||||
Reconstruct file put by client
|
||||
"""
|
||||
filename = req_payload[:filename_length].decode("ascii")
|
||||
filesize = int.from_bytes(
|
||||
req_payload[filename_length : filename_length + 4], "big"
|
||||
)
|
||||
file_content = req_payload[filename_length + 4 :]
|
||||
|
||||
print(
|
||||
f"myftp> - {self.protocol} - Reconstructing the file {filename} of size {filesize} bytes on the server after the client finished sending"
|
||||
)
|
||||
|
||||
try:
|
||||
with open(os.path.join(self.directory_path, filename), "wb") as file:
|
||||
file.write(file_content)
|
||||
|
||||
print(
|
||||
f"myftp> - {self.protocol} - File {filename} uploaded successfully"
|
||||
)
|
||||
|
||||
return rescode_success_dict["correct_put_and_change_request_rescode"]
|
||||
|
||||
except Exception as error:
|
||||
traceback_info = traceback.format_exc()
|
||||
|
||||
print(f"myftp> - {self.protocol} - {error} happened.")
|
||||
|
||||
print(traceback_info)
|
||||
return rescode_fail_dict["unsuccessful_change_rescode"]
|
||||
|
||||
def process_get_req(
|
||||
self, second_byte_to_byte_n: bytes
|
||||
) -> Tuple[Optional[str], Optional[bytes], Optional[int]]:
|
||||
@ -219,6 +271,7 @@ class Server:
|
||||
if filename is None:
|
||||
second_byte_to_FL_plus_five = None
|
||||
else:
|
||||
# get case
|
||||
second_byte_to_FL_plus_five = (
|
||||
filename.encode() + len(response_data).to_bytes(4, "big")
|
||||
if response_data is not None
|
||||
|
Loading…
x
Reference in New Issue
Block a user