Skip to content

JacobMitchell088/CS447-Network-Programming-P2

Repository files navigation

CS447 Network Programming P2

Author: Jacob Mitchell
Date: 10/24/25
Description: Distributed File Transfer Protocol (FTP) utilizing the standard socket interface. Based on the classic FTP (RFC 959) to build a federated file network with dynamic data management.

File Structure

P2/
├─ ServerA/
│ ├─ server # compiled binary
│ ├─ server.conf # config (setup for instructor grading)
│ ├─ server.cpp
│ ├─ ftp_session.{h,cpp}
│ ├─ server_utils.{h,cpp}
│ ├─ ftp_codes.{h,cpp}
│ ├─ peer_client.{h,cpp}
│ ├─ peer_manager.{h,cpp}
│ ├─ cidr_utils.{h,cpp}
│ ├─ db/ # jail root for this server’s files
│ └─ Makefile # make

├─ (ServerX, etc...)

Note

db/ is the jail root of each server. ALL paths are evaluated relative to it.

How To Build

  • Run make within correct folder structure

If make file fails, follow steps below:

  • Run g++ in terminal with the following command:
g++ -std=c++20 -pthread server.cpp ftp_session.cpp server_utils.cpp ftp_codes.cpp peer_client.cpp peer_manager.cpp cidr_utils.cpp -o server

How To Run

  • Place the compiled server.exe into a separate ServerA/B/C/Etc folder each with its own db folder filled with its respective data.
  • Execute the ./server followed by a server.conf argument.
./server server.conf
  • Connect to the server using telnet or nc with the appropriate ip and port number. For example,
telnet 127.0.0.1 2121
  • Sign into server with authorization by using:
USER anonymous
  • Navigate to desired files before executing PASV with CWD
  • Enter PASV mode by executing PASV
  • Open a new terminal instance and use telnet or nc again and connect to the displayed ephemeral port forming the data pipe. This port is calculated by (p1 * 256 + p2) For example,
telnet 127.0.0.1 40594

Where 40594 represents the calculated port number.

  • Run LIST to retrieve the linux based information about the current working directory and its content
  • The data pipe connection will then transmit its data and automatically close. You will need to activate PASV once more and reconnect to a new ephemeral port before retrieving more data.

Examples

USER anonymous
CWD ..
250 Requested file action okay, completed.
PASV
227 Entering Passive Mode (127,0,0,1,p1,p2) # where ((p1* 256) + p2) is our ephemeral port
LIST
150 File status okay; about to open data connection.
226 Closing data connection. Requested file action successful.

Where the data transmitted is received within the second connected terminal after connecting to the provided ip and ephemeral port.
Example data connection output for above exectued commands:

drwxr-xr-x 1 local 0 Oct 22 16:30 comp.security
drwxr-xr-x 1 local 0 Oct 22 16:30 news.world

Where a federated listing may look like:

drwxr-xr-x 1 local 0 Oct 22 16:30 comp.security
drwxr-xr-x 1 local 0 Oct 22 16:30 news.world
drwxr-xr-x 1 peer  0 Oct 22 16:35 reddit

Guidelines & Assumptions

  • RFC 959 style control channel all commands/replies are ASCII lines terminated with \r\n.
    • Data path is raw bytes: no CRLF translation on data sockets so files are streamed exactly as stored.
    • Passive mode PASV required before LIST/RETR except for RETR execution on remote file from peer mediated root.
    • One ephemeral data listener at a time. Any CWD invalidates a pending PASV.
  • Federation behavior:
    • Servers auto discover peers within the configured CIDR range supplied within server.conf
    • Each server listens on a base_port, pulled from server.conf for clients and base_port+200 for peer control sessions.
    • At / (root), LIST returns a merged view: local entries + discovered peer entries.
    • When a requested file/dir is remote, the serving server transparently relays the peer’s 227 so the client’s data connection goes directly to the peer.
  • Peer sessions never re-federate: once a server is acting as a peer (receiving USER peer@A), it serves only its local jail. Preventing recursive server calls.
  • Jail enforcement: all resolved paths must stay under db/. Absolute paths are treated relative to jail (/ means db/).
  • Ownership display: listings show only an owner token (local or peer).
  • Directory sizes shown as 0 in listings to match our project’s sample output.
  • One client data transfer socket at a time: data socket opens on PASV, is used by the next LIST/RETR, and is then closed. New transfer requires new PASV.

Supported Commands

Case Insensitive

  • USER <name>: login (accepts anonymous for users and peer@<ip> for server auth
  • PWD / CWD / CDUP: navigate within our jail; returning to / returns to local / ALWAYS
  • PASV: opens ephemeral data listener (local) or relays peer’s 227 (remote)
  • LIST: local list of content when in local namespace. When in a peer directory, relayed to that peer. Or peer mediated when within root / shared filespaces.
  • RETR <path>: streams file bytes. If remote and PASV not yet armed for that peer, server replies with the peer’s 227 first.
  • QUIT: close control connection

Configuration Notes

  • server.conf parameters are fixed for project submission (do not rename keys):
    • PORT — client control listening port
    • PEER_SUBNET — CIDR range for auto discovery (e.g. 192.168.0.0/27 for 32 addresses scanned /28 for 16, etc)
    • PEER_INTERVAL — scan interval ( in seconds)
  • Listener ports:
    • Client listener: PORT
    • Peer listener: PORT + 200
  • Each server MUST have a db/ directory at runtime. (Can assume)

Troubleshooting

  • Ctrl-C slow/unresponsive: Due to the connection sockets and frequent scans / sleeps - sometimes we see a delay in shutting down the server.
  • Cannot connect to PASV port: verify you’re connecting to the IP/port from the most recent 227. Any CWD invalidates previous PASV
  • LIST in remote dir returns 425: call PASV after entering the remote dir so the server can relay the peer’s 227.
  • RETR from / for a remote file returns new PASV: This is the expected behavior. Due to the premature PASV call the server will respond with peer’s 227. Run PASV, connect to that port, then retry RETR.

Known Issues

  • Running RETR within a shared filespace, such as '/', on a remote file before running PASV makes the server automatically enter PASV mode. This is an artifact of my implemented fix of premature PASV on peer mediated space like / -> RETR <remote file> -> should prompt the server to respond with a new PASV port on the corresponding server.
  • User executes CWD into remote server -> server disconnects -> user is left on zombie dir. However, no errors were observed when trying to execute future commands on this zombie dir. Eventually user can return to root dir and continue to perform actions normally.

Future Extensions

  • Test duplicate file/dir names within separate servers.
  • Implement tie breaker functionality / alert when user executes commands on files with same names.
  • Implement full RFC functionality

About

Distributed File Transfer Protocol (FTP) utilizing the standard socket interface. Based on the classic FTP (RFC 959) to build a federated file network with dynamic data management.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors