This guide covers how to set up a development environment and contribute to the Simple TFTP Daemon project.
- Development Environment
- Project Structure
- Building from Source
- Code Style and Standards
- Testing
- Debugging
- Contributing
- Release Process
- Operating System: Linux, macOS 12.0+, or Windows 10+
- Compiler: C++17 compatible compiler
- CMake: Version 3.16 or higher
- Git: Version 2.20 or higher
- Build Tools: Make, Ninja, or equivalent
# Ubuntu/Debian
sudo apt update
sudo apt install build-essential cmake git pkg-config
# CentOS/RHEL/Fedora
sudo yum groupinstall "Development Tools"
sudo yum install cmake3 git
# or
sudo dnf groupinstall "Development Tools"
sudo dnf install cmake git# Install Homebrew if not already installed
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Install dependencies
brew install cmake pkg-config git- Visual Studio: Install Visual Studio 2019 or later with C++ development tools
- CMake: Install CMake 3.16+ from cmake.org
- Git: Install Git for Windows
- jsoncpp: For JSON configuration parsing
- Google Test: For unit testing
- clang-format: For code formatting
- valgrind: For memory leak detection (Linux)
simple-tftpd/
├── cmake/ # CMake configuration files
├── config/ # Configuration files and examples
├── docs/ # Documentation
├── include/ # Header files
│ └── simple_tftpd/ # Public API headers
├── scripts/ # Build and utility scripts
├── src/ # Source files
│ ├── core/ # Core TFTP functionality
│ ├── utils/ # Utility classes
│ ├── tests/ # Test suite
│ └── examples/ # Example programs
├── tools/ # Development tools
├── CMakeLists.txt # Main CMake file
├── Makefile # Build convenience targets
└── README.md # Project overview
Contains all public header files:
platform.hpp- Platform abstraction layerlogger.hpp- Logging systemtftp_config.hpp- Configuration managementtftp_packet.hpp- TFTP packet handlingtftp_connection.hpp- Connection managementtftp_server.hpp- Main server class
Core TFTP implementation:
tftp_server.cpp- Main server implementationtftp_connection.cpp- Connection handlingtftp_packet.cpp- Packet parsing and creation
Utility classes:
logger.cpp- Logging implementationconfig_parser.cpp- Configuration parsing
Test suite:
test_main.cpp- Test entry pointtest_helpers.cpp- Test utilities
- Setup Guide - Set up your development environment
- Build Guide - Build commands and reference
- Continue reading this guide for development workflow
See Build Guide for complete build instructions.
# Clone repository
git clone https://github.com/SimpleDaemons/simple-tftpd.git
cd simple-tftpd
# Create build directory
mkdir build && cd build
# Configure and build Production version
cmake -DBUILD_VERSION=production ..
make -j$(nproc) # Linux/macOS# Production version
cmake -DBUILD_VERSION=production ..
# Enterprise version
cmake -DBUILD_VERSION=enterprise ..
# Datacenter version
cmake -DBUILD_VERSION=datacenter ..# Full build process
./scripts/build-macos.sh --all
# Clean build
./scripts/build-macos.sh --clean --test
# Debug build
./scripts/build-macos.sh --debug# Full build process
./scripts/build-linux.sh --all
# Custom options
./scripts/build-linux.sh --clean --install- Install C/C++ extension
- Open project folder
- Configure
c_cpp_properties.json:
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/src"
],
"defines": [],
"compilerPath": "/usr/bin/g++",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}- Open project folder
- CLion will automatically detect CMake project
- Configure build options in CMake settings
- Open project folder
- Use CMake integration
- Configure build settings in CMakeSettings.json
- Language: C++17
- Compiler: GCC 7+, Clang 5+, MSVC 2017+
- Platform: Cross-platform (Linux, macOS, Windows)
// PascalCase for class names
class TftpServer;
class TftpConnection;
// PascalCase for enums
enum class TftpOpcode;
enum class LogLevel;// camelCase for methods
void startServer();
bool isValidPacket();
std::string getStatus();// camelCase for variables
std::string serverName;
int connectionCount;
// Underscore suffix for member variables
class TftpServer {
private:
std::string server_name_;
int connection_count_;
};// UPPER_SNAKE_CASE for constants
constexpr size_t MAX_PACKET_SIZE = 512;
constexpr port_t DEFAULT_PORT = 69;# Format all source files
make format
# Check formatting without changes
make check-style# .clang-format
BasedOnStyle: Google
IndentWidth: 4
TabWidth: 4
UseTab: Never
ColumnLimit: 120
AccessModifierOffset: -4
NamespaceIndentation: None/**
* @brief TFTP server main class
*
* This class manages the main TFTP server functionality including:
* - Listening for incoming connections
* - Managing multiple TFTP connections
* - User authentication and authorization
* - Virtual host support
* - SSL/TLS support
*/
class TftpServer {
public:
/**
* @brief Start the TFTP server
* @return true if started successfully, false otherwise
*/
bool start();
/**
* @brief Stop the TFTP server
*/
void stop();
};bool TftpServer::start() {
// Check if server is already running
if (running_.load()) {
logger_->warning("Server is already running");
return false;
}
// Initialize network components
if (!initializeNetwork()) {
logger_->error("Failed to initialize network");
return false;
}
// Start listener thread
startListenerThread();
running_.store(true);
logger_->info("TFTP server started successfully");
return true;
}# Build and run tests
make test
# Run tests from build directory
cd build
make test
# Run specific test
./bin/simple-tftpd-tests --gtest_filter=TftpPacketTest*#include <gtest/gtest.h>
#include "simple_tftpd/tftp_packet.hpp"
class TftpPacketTest : public ::testing::Test {
protected:
void SetUp() override {
// Setup test data
}
void TearDown() override {
// Cleanup test data
}
};
TEST_F(TftpPacketTest, CreateValidPacket) {
TftpPacket packet(TftpOpcode::RRQ);
EXPECT_EQ(packet.getOpcode(), TftpOpcode::RRQ);
EXPECT_TRUE(packet.isValid());
}
TEST_F(TftpPacketTest, ParseInvalidData) {
uint8_t invalid_data[] = {0x00}; // Too short
TftpPacket packet(invalid_data, 1);
EXPECT_FALSE(packet.isValid());
}- Unit Tests: Test individual classes and methods
- Integration Tests: Test component interactions
- Performance Tests: Test performance characteristics
- Memory Tests: Test memory management
# Generate coverage report
cmake -DENABLE_COVERAGE=ON ..
make
make coverage
# View coverage report
open coverage/index.html# Create debug build
cmake -DCMAKE_BUILD_TYPE=Debug ..
make
# Run with debugger
gdb ./bin/simple-tftpd// Enable debug logging
logger_->debug("Processing packet: " + packet.getTypeString());
// Log with context
logger_->info("Connection established from " + client_addr + ":" + std::to_string(client_port));
// Error logging with details
logger_->error("Failed to send packet: " + std::string(strerror(errno)));# Memory leak detection
valgrind --leak-check=full --show-leak-kinds=all ./bin/simple-tftpd
# Memory error detection
valgrind --tool=memcheck ./bin/simple-tftpd# Build with AddressSanitizer
cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_SANITIZER=address ..
make# Set breakpoints
(gdb) break TftpServer::start
(gdb) break tftp_connection.cpp:45
# Run with arguments
(gdb) run start --config test.conf
# Inspect variables
(gdb) print server_name_
(gdb) print *config_- Fork the repository
- Create a feature branch
- Make your changes
- Test your changes
- Commit with clear messages
- Push to your fork
- Create a pull request
type(scope): brief description
Detailed description of changes
- Bullet point of change 1
- Bullet point of change 2
Fixes #123
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changesrefactor: Code refactoringtest: Test additions/changeschore: Build/tool changes
feat(server): add IPv6 support
- Implement IPv6 socket binding
- Add IPv6 configuration options
- Update network initialization logic
Closes #45
fix(packet): resolve memory leak in packet parsing
- Fix memory allocation in TftpPacket constructor
- Add proper cleanup in destructor
- Update unit tests to verify fix
Fixes #67
- Self-review: Test your changes thoroughly
- Pull request: Create detailed PR description
- Review: Address feedback from maintainers
- Merge: Changes merged after approval
- All new code must include tests
- Existing tests must pass
- Code coverage should not decrease
- Performance tests for new features
- Semantic Versioning: MAJOR.MINOR.PATCH
- Development: 0.x.x versions
- Stable: 1.0.0 and above
- All tests pass
- Documentation updated
- Changelog updated
- Version numbers updated
- Release notes prepared
- Binaries built and tested
- GitHub release created
# Create release build
cmake -DCMAKE_BUILD_TYPE=Release ..
make
# Create packages
make package
# Install to staging area
make install DESTDIR=staging- Issues: Report bugs or request features
- Discussions: Ask questions and share ideas
- Wiki: Development tips and tricks
- Code Review: Get feedback on your changes
- API Reference - Complete API documentation
- Architecture Overview - System design details
- Testing Guide - Testing best practices
- Contributing Guidelines - Contribution guidelines
After setting up your development environment:
- API Reference - Learn the codebase
- Architecture Overview - Understand the design
- Testing Guide - Write effective tests
- Examples - See practical implementations
For development support:
- Check this documentation first
- Search existing GitHub issues
- Create a new issue with:
- Development environment details
- Complete error messages
- Steps to reproduce
- Proposed solution or question