{"id":18915932,"url":"https://github.com/christosgalano/dir-clone-server","last_synced_at":"2025-06-15T07:03:46.806Z","repository":{"id":142612524,"uuid":"503879823","full_name":"christosgalano/Dir-Clone-Server","owner":"christosgalano","description":"An FTP-like server utilizing socket and thread programming with synchronization.","archived":false,"fork":false,"pushed_at":"2022-09-20T07:45:38.000Z","size":21,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-15T07:03:42.670Z","etag":null,"topics":["c","client-server","socket-programming","synchronization","thread","threading"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/christosgalano.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-06-15T18:28:17.000Z","updated_at":"2023-01-13T12:46:10.000Z","dependencies_parsed_at":null,"dependency_job_id":"0b9ffcd0-102e-47d6-b5f4-cea7634cdafa","html_url":"https://github.com/christosgalano/Dir-Clone-Server","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/christosgalano/Dir-Clone-Server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christosgalano%2FDir-Clone-Server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christosgalano%2FDir-Clone-Server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christosgalano%2FDir-Clone-Server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christosgalano%2FDir-Clone-Server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/christosgalano","download_url":"https://codeload.github.com/christosgalano/Dir-Clone-Server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/christosgalano%2FDir-Clone-Server/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259935589,"owners_count":22934384,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","client-server","socket-programming","synchronization","thread","threading"],"created_at":"2024-11-08T10:17:46.930Z","updated_at":"2025-06-15T07:03:46.799Z","avatar_url":"https://github.com/christosgalano.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Directory Clone Server\n\nAn FTP-like server utilizing socket and thread programming with synchronization. A client makes a request to the server providing the server's directory to be cloned into results. A server can handle requests from multiple clients.\n\n## Build and run instructions\n\n- Run `make` to the executables\n- Run `make clean` to clean the bin and the results folders\n\n## Implementation details\n\nThe code contains pretty detailed comments, so what follows is an analysis of the main implementation decisions that were taken:\n\n### Server logic\n\n- Parse the arguments and make sure that they are correct\n- Create queue of given size and initialize mutex and condition variables\n- Create workers thread pool of given size with a routine called 'process'\n- Create socket, bind it to specified port (use INADDR_ANY) and set the option to reuse it\n- Repeatedly:\n  - Listen for a new connection\n  - Accept a connection\n  - Create its corresponding communication thread with a routine called 'client_communication'\n\n### Communication thread logic\n\n- Detach thread\n- Read the directory, if it is not valid send 'INVALID DIR', close fd and exit\n- Find the number of files inside the directory, if even one directory - nested or not - cannot be opened send 'COULD NOT OPEN DIR/S', close fd and exit\n- Send the number of files and wait for response ('NF READ')\n- Send the block size and wait for response ('BS READ')\n- Create and initialize client's mutex (each client has its own mutex)\n- For each file inside the directory, wait for queue to be non-full and then insert its file info into the queue\n- Exit\n\n### Worker logic\n\n- Detach thread\n- Repeatedly:\n  - Wait for queue to be non-empty\n  - Get first non-empty item of queue\n  - Send file's content\n  - Destroy file info\n\n### Client logic\n\n- Parse the arguments and make sure they are correct\n- Create socket, bind it to specified port (use server_ip) and connect to it\n- Send directory to clone, if directory is not valid exit\n- Read number of files the directory contains, if some directory couldn't be opened exit\n- Create directory clone inside 'results'\n- Send response ('NF READ')\n- Read block size and send response ('BS READ')\n- While there are files that remain to be received:\n  - Receive file path and file size, create file and write to it the received content\n  - Send remaining files\n- Exit\n\n## General notes\n\n- Only the content of regular files is transferred - no pipes, links and hidden files\n- If the requested directory is not valid the server sends 'INVALID DIR' to the client\n- If the server does not have permissions to open the requested directory or any nested directory inside it, it sends 'COULD NOT OPEN DIR/S' to the client\n- If an error occurs inside a communication thread the server closes the fd and exits the thread but does not terminate\n- The requested directory must begin with '/'and have length \u003e 1 (we ask for the dir to begin with '/' so that we can properly create a dir clone inside the results)\n- The directories cloned are stored inside the results directory\n- Each client has its own mutex, because only one worker must be able to sent a file to the client at any time - a different approach would be to have a mutex for all the clients\n- The heap data from the queue and workers allocations do not get freed from the server process, that is because if the server receives a SIGINT signal it is difficult to handle that signal properly due to the usage of threads\n- The contents of the queue (file_info objects) do get freed from the worker thread that process each one\n- The dynamically allocated client mutex does get freed when all the files have been sent to the client\n- The order in which the printed messages appear is not necessarily an indicator of the execution order\n\n## Important note\n\n- Client sends acknowledgement messages to the server after receiving different type of information (number of files, block size, file path, file size, content). This approach is used because we cannot safely assume that the write/read procedures to/from the socket from the server/client are going to be perfectly synchronized every time. For example it is possible that the client is having a small delay before reading from the socket the file path and the server proceeds normally, sending the file path and then the file size without waiting for a client's response. Then when the client reads from the socket, the buffer is going to contain both the file path and the file size but the client cannot be sure of the that. So instead of parsing each time the buffer with several cases taken into consideration, we opt to send an acknowledgement message (much like a tcp handshake).\n\n---\n\n## Communication Protocol Server-Client\n\n```mermaid\nsequenceDiagram\n    participant S as Server\n    participant C as Client\n    C--\u003e\u003eS: Directory's path\n    S-\u003e\u003eC: Number of files in given dir\n    C--\u003e\u003eS: NF READ\n    S-\u003e\u003eC: Block size\n    C--\u003e\u003eS: BS READ\n    Note left of S: File 1\n    S-\u003e\u003eC: File path\n    C--\u003e\u003eS: FP READ\n    S-\u003e\u003eC: File size\n    C--\u003e\u003eS: FS READ\n    S-\u003e\u003eC: File content\n    C--\u003e\u003eS: Number of files remaining\n    Note left of S: ... File N\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristosgalano%2Fdir-clone-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchristosgalano%2Fdir-clone-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchristosgalano%2Fdir-clone-server/lists"}