An educational C project that transfers files over TCP, encrypts and decrypts 64-bit blocks in parallel using POSIX threads, and handles multiple clients concurrently.
Security notice: XOR with a repeated key is not secure encryption, and the key is included in the protocol as required by the assignment. This project demonstrates sockets, binary protocols, and concurrency; it must not be used to protect real data. A production system should use TLS or authenticated encryption instead.
- versioned binary protocol with a magic number and response status codes;
- network byte order for both headers and data blocks;
- configurable maximum size for transferred files;
- parallel encryption and decryption over contiguous buffers;
- enforced limit on concurrent connections;
- atomic and unique output file names;
- acknowledgement sent only after the file has been saved successfully;
- strict argument validation and complete error cleanup;
- graceful server shutdown on
SIGINTorSIGTERM; - strict builds, integration tests, and Address/UndefinedBehavior Sanitizers;
- automated GitHub Actions checks on every push and pull request.
The project requires a C11 compiler, POSIX threads, and GNU mkstemps.
Run make help to display all available build targets.
makeThe resulting executables are build/client and build/server.
Start the server with:
build/server <threads> <output_prefix> <max_connections> <port>Send a file with:
build/client <input_file> <key> <threads> <server_ip> <port>Example:
build/server 4 received 8 12345
build/client tests/data/sample1.txt 0x0123456789ABCDEF 4 127.0.0.1 12345The server creates a file such as received_A1b2C3.bin. The output prefix may
include an existing directory. The thread count must be between 1 and 256, the
connection limit between 1 and 1024, and the port between 1 and 65535.
The CLI_P, CLI_KEY, CLI_IP, CLI_PORT, SRV_P, SRV_PREFIX,
SRV_BACKLOG, and SRV_PORT environment variables may override their
respective command-line arguments. The default maximum file size is 1 GiB. It
can be reduced by setting SP_MAX_FILE_SIZE, in bytes, on both the client and
the server.
Each request contains the following fields, in order:
| Field | Size | Description |
|---|---|---|
| magic | 32 bits | 0x53504654 (SPFT) |
| version | 16 bits | protocol version 1 |
| reserved | 16 bits | must be zero |
| length | 64 bits | original file length in bytes |
| key | 64 bits | educational XOR key |
| blocks | variable | encrypted blocks padded to 8 bytes |
All integers use big-endian byte order. The server replies with a 32-bit status code:
| Code | Meaning |
|---|---|
| 0 | success |
| 1 | invalid protocol message |
| 2 | input/output error |
| 3 | file exceeds the configured limit |
| 4 | internal server error |
The server rejects incomplete headers, unsupported protocol versions, and file
sizes above the configured limit. TCP does not preserve message boundaries, so
read_n and write_n handle partial operations and retry calls interrupted by
signals.
Run the integration suite with:
make testRun the same suite with AddressSanitizer and UndefinedBehaviorSanitizer with:
make sanitizeThe suite covers invalid arguments, numeric overflow, empty files, sizes around the 8-byte block boundary, large binary files, malformed protocol messages, server-side output errors, unavailable servers, and concurrent transfers. File integrity is verified by comparing the SHA-256 hashes of all inputs and outputs.
To compile while treating every warning as an error:
make clean
make CFLAGS='-O2 -g -Werror'GitHub Actions automatically performs the strict build, integration tests, and
sanitizer checks for every push and pull request. After a successful push to
main, it also rebuilds the PDF and publishes it in a GitHub release tagged as
report-v<run number>.
The English project report is available as report.pdf. Its LaTeX source is
stored in report/report.tex and can be rebuilt with:
make reportThe generated PDF and intermediate LaTeX files are removed by make clean.
src/client.chandles file reading, parallel encryption, connection setup, and the client side of the protocol;src/server.cimplements the accept loop, concurrency limits, parallel decryption, and file persistence;src/utils.cprovides complete I/O operations, endian conversions, and numeric parsing;include/contains the public APIs and shared protocol types;tests/integration.shprovides end-to-end regression coverage;tests/data/contains sample text and binary input files;.github/workflows/ci.ymldefines the automated CI pipeline.
The client and each server handler use at most
min(requested_threads, block_count) workers, avoiding unnecessary threads for
small files. The server acquires a connection slot before creating a handler,
so the number of connection threads remains bounded.