Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/make.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ jobs:
cd ..
fi

- name: Build Lab 7 (Sockets)
run: |
if [ -d "lab7" ]; then
cd lab7
# We call specific targets because our Makefile's 'all' just prints a message
make all
cd ..
fi

- name: Success Notification
run: echo "All laboratories compiled successfully!"

1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The projects focus on low-level system programming in UNIX/Linux environments, u
| [`lab4/`](./lab4) | POSIX Message Queues (IPC) | A "hub and spoke" communication system where multiple independent terminal clients exchange text messages in real-time using `/dev/mqueue`. Features asynchronous I/O managed by duplicating processes via `fork()`. |
| [`lab5/`](./lab5) | POSIX Semaphores & Shared Memory | Implementation of the classic Producer-Consumer problem within a multi-process architecture. Leverages POSIX shared memory for zero-copy data transfer and POSIX semaphores for strict access synchronization, complete with a Manager daemon mitigating starvation via an aging algorithm. |
| [`lab6/`](./lab6) | POSIX Threads, RTOS scheduling | A comprehensive, multithreaded simulation of a mobile robot's internal operating system. POSIX threads (pthreads), complex inter-thread communication, synchronization mechanisms, and Real-Time Operating System (RTOS) scheduling. |
| [`lab7/`](./lab7) | TCP/IP Sockets, Dual-Protocol HTTP Server | An iterative TCP server and client implementation featuring dual-protocol support (HTTP/1.1 and custom text commands). Focuses on network engineering patterns, including modern Linux `accept4()` with `SOCK_CLOEXEC`, graceful shutdown using `sigaction()` to intercept `EINTR`, and live integration testing via a `tmux` automation script. |

## ⚙️ System Requirements

Expand Down
21 changes: 21 additions & 0 deletions lab7/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# --- Build Artifacts ---
bin/
obj/
*.o
*.out

# --- Debug & Temporary Files ---
*.gch
.core
vgcore.*

# --- IDEs and Editors ---
.vscode/
.idea/
*.swp
*.swo
*~

# --- OS specific ---
.DS_Store
Thumbs.db
62 changes: 62 additions & 0 deletions lab7/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# ==============================================================================
# Compiler Configuration
# ==============================================================================
CC = gcc
# -Wall -Wextra: Enable almost all compiler warnings
# -Werror: Treat all warnings as errors (strict code quality control)
# -g: Generate debugging symbols for GDB and Valgrind
# -std=c11: Use the ISO C11 standard
# -D_GNU_SOURCE: Allow Linux-specific solutions (like accept4() function)
# -Iinclude: Look for header files inside the 'include' directory
CFLAGS = -Wall -Wextra -Werror -g -std=c11 -D_GNU_SOURCE -Iinclude

# ==============================================================================
# Directory Structure
# ==============================================================================
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin

# ==============================================================================
# Targets (Executables)
# ==============================================================================
SERVER_TARGET = $(BIN_DIR)/server
CLIENT_TARGET = $(BIN_DIR)/client

# ==============================================================================
# Source and Object Files Mapping
# ==============================================================================
SERVER_SRCS = $(SRC_DIR)/server/main.c
CLIENT_SRCS = $(SRC_DIR)/client/main.c

SERVER_OBJS = $(OBJ_DIR)/server/main.o
CLIENT_OBJS = $(OBJ_DIR)/client/main.o

# ==============================================================================
# Build Rules
# ==============================================================================
.PHONY: all clean

# Default rule to build both the server and the client
all: $(SERVER_TARGET) $(CLIENT_TARGET)

# Rule to link the server executable
$(SERVER_TARGET): $(SERVER_OBJS)
@mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) $(SERVER_OBJS) -o $(SERVER_TARGET)

# Rule to link the client executable
$(CLIENT_TARGET): $(CLIENT_OBJS)
@mkdir -p $(BIN_DIR)
$(CC) $(CFLAGS) $(CLIENT_OBJS) -o $(CLIENT_TARGET)

# Generic pattern rule to compile source files into object files
# Automatically creates the required subdirectories inside obj/
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c $< -o $@

# Rule to clean up all build artifacts
clean:
@echo "Cleaning up build artifacts..."
rm -rf $(OBJ_DIR) $(BIN_DIR)
133 changes: 133 additions & 0 deletions lab7/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Iterative TCP Server and Client with HTTP Support

A C-based network application implementing an iterative TCP server with dual-protocol parsing capability (standard HTTP/1.1 and a custom text-based protocol) alongside a dedicated client and a TMUX-driven test automation harness. Built specifically for Linux/WSL2 environments utilizing modern POSIX and jądra system systems mechanisms.

## Project Overview

The project consists of two primary applications communicating over TCP/IPv4:

1. **The Server (`server`)**:
- Operates as an iterative network listener on port `9000` across all available interfaces (`INADDR_ANY`).
- Maintains an internal state variable: `REQUEST_COUNTER` (initialized at 0).
- Dynamically parses incoming stream data:
- **HTTP GET/POST Requests**: Increments the counter by 1 and replies with a valid HTTP/1.1 200 OK plain-text response containing the string `"Liczba pobrań strony: %d"`.
- **Custom "ZADANIE <NUMBER>" Command**: Increments the counter by the specified integer value and responds immediately with the raw string payload (omitting HTTP headers).
- Implements robust system engineering patterns including graceful shutdown handling (`SIGINT`), socket resource preservation (`SO_REUSEADDR`), and leak prevention (`SOCK_CLOEXEC`).

2. **The Client (`client`)**:
- A command-line network utility accepting three arguments: Server IPv4, Port, and a Number.
- Formats the command as `"ZADANIE <NUMBER>"`, establishes a reliable TCP connection, transmits the payload, prints the raw server response, and exits cleanly.

## Key Architectural Highlights

- **Modern Network Extensions**: Utilizes Linux-specific `accept4()` with `SOCK_CLOEXEC` to prevent descriptor leakage across process forks.
- **Graceful Shutdown Hook**: Replaces standard unsafe signal routines with a POSIX-compliant `sigaction()` structure. Interrupted blocking calls (returning `EINTR`) are gracefully intercepted to allow systematic garbage collection of network descriptors.
- **Signal Resilience**: Uses `MSG_NOSIGNAL` on data transmissions (`send()`) to mask `SIGPIPE` generation, securing the process against unexpected client socket dropouts.
- **Byte Order Integrity**: Enforces structural conversion between Host Byte Order (Little-Endian) and Network Byte Order (Big-Endian) using `htons()` and `htonl()` wrappers.

## Project Structure

```text
.
├── Makefile # Strict compilation definition file
├── bin/ # Compiled production binaries (server, client)
├── obj/ # Temporary translation object files (.o)
├── include/ # Universal project header declarations
├── scripts/ # Production-ready shell scripts
│ └── test_automation.sh # Complete TMUX automation deployment harness
└── src/ # Implementation source files
├── client/
│ └── main.c # Client source entry point
└── server/
└── main.c # Server source entry point
```

## Prerequisites

* **Operating System**: Linux kernel 2.6.28+ or WSL2 (Windows Subsystem for Linux).
* **Toolchain**: `gcc` compiler supporting the ISO C11 standard and `GNU make`.
* **System Diagnostics**: `tmux` (required for automated sequence monitoring), `iproute2` (`ss`), and `netcat` (`nc`).

To install dependencies on Debian/Ubuntu-based environments:

```bash
sudo apt update && sudo apt install build-essential tmux iproute2 netcat-openbsd -y
```

## Compilation

The project uses `GNU Make` with strict error policing (`-Wall -Wextra -Werror`). Any compiler warnings will abort the compilation pipeline to enforce code reliability.

To compile both target binaries:

```bash
make
```

To purge object layers and binaries:

```bash
make clean
```

## Execution and Usage

### Manual Operations

1. **Initialize the Listener Node**:
```bash
./bin/server
```


2. **Execute a Custom Client Call**:
```bash
./bin/client 127.0.0.1 9000 42
```



### Interface Diagnostics

* **Web Browser Validation**: Point any standard web browser to `http://127.0.0.1:9000`. The browser will submit a speculative `GET` sequence, advancing the server state machine and outputting the counter.
* **Raw Diagnostic Injection via Netcat**:
```bash
echo -n "ZADANIE 10" | nc 127.0.0.1 9000
```


* **Socket Allocation Tracking**: Check socket listening states via `ss`:
```bash
ss -tulpn | grep 9000
```



## Automated Evaluation Environment

The repository includes an automated integration test suite located within `scripts/test_automation.sh`.

This shell script dynamically:

1. Validates the filesystem topology and existence of compiled targets.
2. Initializes a detached background `tmux` instance.
3. Automatically maps directory contexts to mitigate jądra system defaults.
4. Spawns the server block on Pane 0, inserts a calculated polling threshold, splits the matrix horizontally, and queues up programmatic `client` executions on Pane 1.
5. Injects automated text sequences, handles real-time visual output, signals a system `SIGINT` interruption vector to trigger the server's internal resource destructor, and attaches to the live buffer.

To execute the automation framework:

```bash
chmod +x scripts/test_automation.sh
./scripts/test_automation.sh
```

## Memory Allocation Profile

The application has been audited under binary translation tools (`Valgrind Memcheck`) to confirm absence of heap fragmentation, descriptor pollution, or memory leaks.

```bash
valgrind --leak-check=full ./bin/server
```

Expected execution signature: `All heap blocks were freed -- no leaks are possible`.
71 changes: 71 additions & 0 deletions lab7/scripts/test_automation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/bin/bash

# ==============================================================================
# BULLETPROOF TMUX Automation Script for Socket Server/Client Testing
# ==============================================================================

SESSION_NAME="socket_test_session"

# Calculate the absolute path of the project root
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"

# Change the working directory of this script execution to the project root
cd "$PROJECT_ROOT" || exit 1

# Ensure tmux is installed in WSL2
if ! command -v tmux &> /dev/null; then
echo "Error: tmux is not installed. Please run 'sudo apt install tmux' first."
exit 1
fi

# Ensure the binaries exist before running the automation
if [ ! -f "./bin/server" ] || [ ! -f "./bin/client" ]; then
echo "Error: Binaries not found. Please build the project using 'make' first."
exit 1
fi

echo "Starting automated test architecture in: $PROJECT_ROOT"

# 1. Start a new detached tmux session
tmux new-session -d -s "$SESSION_NAME" -n "Main"

# 2. FORCE Pane 0 (Server) to change directory to project root via explicit send-keys
# This overrides any global shell settings or .bashrc profiles
tmux send-keys -t "$SESSION_NAME:Main.0" "cd \"$PROJECT_ROOT\"" C-m
tmux send-keys -t "$SESSION_NAME:Main.0" "./bin/server" C-m

# 3. Give the server a moment to bind to port 9000
sleep 1.5

# 4. Split the current window horizontally to create Pane 1 (Client)
tmux split-window -h -t "$SESSION_NAME:Main"

# 5. Run the client automation in the BACKGROUND.
(
sleep 2.0

# FORCE Pane 1 (Client) to change directory to project root before sending commands
tmux send-keys -t "$SESSION_NAME:Main.1" "cd \"$PROJECT_ROOT\"" C-m
sleep 0.5

echo "-> Sending Request 1 (Value: 10) via client..."
tmux send-keys -t "$SESSION_NAME:Main.1" "./bin/client 127.0.0.1 9000 10" C-m
sleep 2.0

echo "-> Sending Request 2 (Value: 50) via client..."
tmux send-keys -t "$SESSION_NAME:Main.1" "./bin/client 127.0.0.1 9000 50" C-m
sleep 2.0

echo "-> Sending Request 3 (Value: 15) via client..."
tmux send-keys -t "$SESSION_NAME:Main.1" "./bin/client 127.0.0.1 9000 15" C-m
sleep 3.0

# Trigger graceful shutdown of the server (sending SIGINT via Ctrl+C)
echo "-> Triggering graceful server shutdown (sending SIGINT)..."
tmux send-keys -t "$SESSION_NAME:Main.0" C-c
) &

# 6. Immediately attach to the tmux session so the user can watch the live show
echo "Attaching to tmux session... Watch the automation live!"
tmux attach-session -t "$SESSION_NAME"
Loading
Loading