feat: Testing environment
- both server and client must specify their directories
This commit is contained in:
parent
fa544ac1fb
commit
d1d5321784
59
.tmuxinator.yml
Normal file
59
.tmuxinator.yml
Normal 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
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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`.
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user