feat: Testing environment

- both server and client must specify their directories
This commit is contained in:
minhtrannhat 2023-11-27 14:19:19 -05:00
parent fa544ac1fb
commit d1d5321784
Signed by: minhtrannhat
GPG Key ID: E13CFA85C53F8062
7 changed files with 130 additions and 20 deletions

59
.tmuxinator.yml Normal file
View File

@ -0,0 +1,59 @@
# ./.tmuxinator.yml
name: coen366
root: ~/Desktop/University/Fall2023_Classes/COEN366/project
# Optional tmux socket
# socket_name: foo
# Note that the pre and post options have been deprecated and will be replaced by
# project hooks.
# Project hooks
# Runs on project start, always
# on_project_start: command
# Run on project start, the first time
# on_project_first_start: command
# Run on project start, after the first time
# on_project_restart: command
# Run on project exit ( detaching from tmux session )
# on_project_exit: command
# Run on project stop
# on_project_stop: command
# Runs in each window and pane before window/pane specific commands. Useful for setting up interpreter versions.
# pre_window: rbenv shell 2.0.0-p247
# Pass command line options to tmux. Useful for specifying a different tmux.conf.
# tmux_options: -f ~/.tmux.mac.conf
# Change the command to call tmux. This can be used by derivatives/wrappers like byobu.
# tmux_command: byobu
# Specifies (by name or index) which window will be selected on project startup. If not set, the first window is used.
# startup_window: editor
# Specifies (by index) which pane of the specified window will be selected on project startup. If not set, the first pane is used.
# startup_pane: 1
# Controls whether the tmux session should be attached to automatically. Defaults to true.
# attach: false
windows:
- editor:
root: ~/Desktop/University/Fall2023_Classes/COEN366/project
layout: main-vertical
panes:
- lvim
- test:
layout: main-vertical
root: ~/Desktop/University/Fall2023_Classes/COEN366/project
panes:
- docker-compose up --build --remove-orphans
- sleep 15 && docker exec -it project-ftp_client-1 python client.py --debug 1
- sleep 15 && docker exec -it project-ftp_server-1 python server.py --port_number 12000 --debug 1

View File

@ -5,13 +5,12 @@ FROM python:3.11
EXPOSE 12000 EXPOSE 12000
# Create and set the working directory # Create and set the working directory
WORKDIR /app WORKDIR /client
# Copy the local app files to the container # Copy the local client to the container
COPY ./src/myftp /app RUN mkdir /client_directory
RUN dd if=/dev/urandom of=/client_directory/file_local.txt bs=1024 count=10
RUN dd if=/dev/urandom of=/app/file_local.txt bs=1024 count=10 RUN dd if=/dev/urandom of=/client_directory/image_local.png bs=1024 count=50
RUN dd if=/dev/urandom of=/app/image_local.png bs=1024 count=50
# Start your Python application # Start your Python application
#CMD python client.py --debug 1 #CMD python client.py --debug 1

View File

@ -5,15 +5,12 @@ FROM python:3.11
EXPOSE 12000 EXPOSE 12000
# Create and set the working directory # Create and set the working directory
WORKDIR /app WORKDIR /server
# Copy the local app files to the container
COPY ./src/myftp /app
# Create files with random content in the /server directory # Create files with random content in the /server directory
RUN mkdir /server RUN mkdir /server_directory
RUN dd if=/dev/urandom of=/server/file1.txt bs=1024 count=10 RUN dd if=/dev/urandom of=/server_directory/file_server.txt bs=1024 count=10
RUN dd if=/dev/urandom of=/server/image1.png bs=1024 count=50 RUN dd if=/dev/urandom of=/server_directory/image_server.png bs=1024 count=50
# Start your Python application # Start your Python application
#CMD python server.py --port_number 12000 --debug 1 #CMD python server.py --port_number 12000 --debug 1

View File

@ -8,13 +8,13 @@ Zero. Only python standard libs were used.
### Client ### Client
You can run `python3 src/myftp/client.py` to start the client or `python3 src/myftp/client.py --debug 1` for debugging purposes. You can run `python3 src/myftp/client.py --directory <insert valid directory that you have read/write permissions>` to start the client or `python3 src/myftp/client.py --debug 1 --directory <insert valid directory that you have read/write permissions>` for debugging purposes.
### Server ### Server
By default, the server IP address or hostname or server name will be `0.0.0.0` (meaning it will bind to all interfaces). The `--port_number` flag, if not specified will be by default `12000`. By default, the server IP address or hostname or server name will be `0.0.0.0` (meaning it will bind to all interfaces). The `--port_number` flag, if not specified will be by default `12000`.
You can run `python3 src/myftp/server.py` to start the server or `python3 src/myftp/server.py --ip_addr <insert ip addr of the server> --port_number <insert port number here> --debug 1` for debugging purposes and to specify the port number. You can run `python3 src/myftp/server.py --directory <insert valid directory that you have read/write permissions>` to start the server or `python3 src/myftp/server.py --ip_addr <insert ip addr of the server> --port_number <insert port number here> --debug 1 --directory <insert valid directory that you have read/write permissions>` for debugging purposes and to specify the port number.
## Testing with Docker ## Testing with Docker
@ -29,7 +29,7 @@ You can run `python3 src/myftp/server.py` to start the server or `python3 src/my
- Wait 10 seconds. - Wait 10 seconds.
- 2 containers will be created on the same network `mynetwork`. Their respective IP addresses will be printed to stdout. - 2 containers will be created on the same network `mynetwork`. Their respective IP addresses will be printed to stdout.
- Open two terminal windows: one for each of server and client. - Open two terminal windows: one for each of server and client.
- Run the server with `docker exec -it project-ftp_server_1 python server.py <insert any flags here>`. - Run the server with `docker exec -it project-ftp_server_1 python server.py --directory /server_directory <insert any other flags here>`.
- Run the client with `docker exec -it project-ftp_client_1 python client.py <insert any flags here>`. - Run the client with `docker exec -it project-ftp_client_1 python client.py --directory /client_directory <insert any flags here>`.
- For the client, when asked to put in the ip address and port number of the server, you can put in `ftp_server 12000` or adjust to your chosen port number. The IP address is resolved by Docker so ftp_server can not be changed. - For the client, when asked to put in the ip address and port number of the server, you can put in `ftp_server 12000` or adjust to your chosen port number. The IP address is resolved by Docker so ftp_server can not be changed.
- Tear down everything with `docker-compose down`. - Tear down everything with `docker-compose down`.

View File

@ -5,6 +5,8 @@ services:
build: build:
context: . context: .
dockerfile: Dockerfile.server dockerfile: Dockerfile.server
volumes:
- ./src/myftp:/server:ro
networks: networks:
- mynetwork - mynetwork
command: command:
@ -22,6 +24,8 @@ services:
dockerfile: Dockerfile.client dockerfile: Dockerfile.client
networks: networks:
- mynetwork - mynetwork
volumes:
- ./src/myftp:/client:ro
command: command:
- sh - sh
- -c - -c

View File

@ -1,6 +1,7 @@
from socket import socket, AF_INET, SOCK_DGRAM from socket import socket, AF_INET, SOCK_DGRAM
from typing import Tuple from typing import Tuple
from argparse import ArgumentParser from argparse import ArgumentParser
import os
# 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]
@ -19,12 +20,13 @@ class UDPClient:
if not self.pong_received: if not self.pong_received:
return return
client_socket = socket(AF_INET, SOCK_DGRAM) client_socket = None # shutup the variableNotBound warning
client_socket.connect((self.server_name, self.server_port))
while True: while True:
try: try:
client_socket = socket(AF_INET, SOCK_DGRAM)
client_socket.connect((self.server_name, self.server_port))
# get command from user # get command from user
while (command := input(f"myftp> - {self.mode} - : ")) not in [ while (command := input(f"myftp> - {self.mode} - : ")) not in [
"put", "put",
@ -117,6 +119,20 @@ def get_address_input() -> Address:
) )
def check_directory(path):
if os.path.exists(path):
if os.path.isdir(path):
if os.access(path, os.R_OK) and os.access(path, os.W_OK):
return True
else:
print(f"Error: The directory '{path}' is not readable or writable.")
else:
print(f"Error: '{path}' is not a directory.")
else:
print(f"Error: The directory '{path}' does not exist.")
return False
def init(): def init():
arg_parser = ArgumentParser(description="A FTP client written in Python") arg_parser = ArgumentParser(description="A FTP client written in Python")
@ -129,6 +145,10 @@ def init():
help="Enable or disable the flag (0 or 1)", help="Enable or disable the flag (0 or 1)",
) )
arg_parser.add_argument(
"--directory", required=True, type=str, help="Path to the client directory"
)
args = arg_parser.parse_args() args = arg_parser.parse_args()
while ( while (
@ -136,6 +156,12 @@ def init():
) not in {"1", "2"}: ) not in {"1", "2"}:
print("myftp>Invalid choice. Press 1 for TCP, Press 2 for UDP") print("myftp>Invalid choice. Press 1 for TCP, Press 2 for UDP")
if not check_directory(args.directory):
print(
f"The directory '{args.directory}' does not exists or is not readable/writable."
)
return
# UDP client selected here # UDP client selected here
if protocol_selection == "2": if protocol_selection == "2":
user_supplied_address = get_address_input() user_supplied_address = get_address_input()

View File

@ -1,5 +1,6 @@
from socket import socket, AF_INET, SOCK_DGRAM from socket import socket, AF_INET, SOCK_DGRAM
from argparse import ArgumentParser from argparse import ArgumentParser
import os
class UDPServer: class UDPServer:
@ -48,6 +49,20 @@ class UDPServer:
print(f"myftp> - {self.mode} - Closed the server socket\n") print(f"myftp> - {self.mode} - Closed the server socket\n")
def check_directory(path):
if os.path.exists(path):
if os.path.isdir(path):
if os.access(path, os.R_OK) and os.access(path, os.W_OK):
return True
else:
print(f"Error: The directory '{path}' is not readable or writable.")
else:
print(f"Error: '{path}' is not a directory.")
else:
print(f"Error: The directory '{path}' does not exist.")
return False
def init(): def init():
parser = ArgumentParser(description="A FTP server written in Python") parser = ArgumentParser(description="A FTP server written in Python")
@ -59,6 +74,10 @@ def init():
help="Port number for the server. Default = 12000", help="Port number for the server. Default = 12000",
) )
parser.add_argument(
"--directory", required=True, type=str, help="Path to the server directory"
)
parser.add_argument( parser.add_argument(
"--ip_addr", "--ip_addr",
default="0.0.0.0", default="0.0.0.0",
@ -82,6 +101,12 @@ def init():
) not in {"1", "2"}: ) not in {"1", "2"}:
print("myftp>Invalid choice. Press 1 for TCP, Press 2 for UDP") print("myftp>Invalid choice. Press 1 for TCP, Press 2 for UDP")
if not check_directory(args.directory):
print(
f"The directory '{args.directory}' does not exists or is not readable/writable."
)
return
# UDP client selected here # UDP client selected here
if protocol_selection == "2": if protocol_selection == "2":
udp_server = UDPServer(args.ip_addr, args.port_number, args.debug) udp_server = UDPServer(args.ip_addr, args.port_number, args.debug)