diff --git a/Makefile b/Makefile index 094f76b..e5d631b 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ CC=g++ CFLAGS=-std=c++17 -Wall -Wextra -O2 -pthread LDFLAGS=-lpcap -pthread TARGET=whatpulse-pcap-service -SOURCES=main.cpp pcapservice.cpp tcpclient.cpp pcapcapturethread.cpp -VERSION=1.0.0 +SOURCES=main.cpp pcapservice.cpp tcpclient.cpp pcapcapturethread.cpp logger.cpp +VERSION=1.0.2 # Default target all: $(TARGET) diff --git a/README.md b/README.md index 89485ab..0834e1b 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ When WhatPulse runs as an AppImage or in other restricted environments, it may n ### Package Manager Installation (Recommended) -Download the latest packages from the [GitHub Releases page](https://github.com/whatpulse/external-pcap-service/releases/latest). +Download the latest packages from the [GitHub Releases page](https://github.com/whatpulse/linux-external-pcap-service). Choose the package format for your Linux distribution: @@ -45,11 +45,11 @@ For automated downloads, use these commands to get the latest release: ```bash # Get latest release info -LATEST_URL=$(curl -s https://api.github.com/repos/whatpulse/external-pcap-service/releases/latest | grep "browser_download_url" | grep "deb" | cut -d '"' -f 4) +LATEST_URL=$(curl -s https://api.github.com/repos/whatpulse/linux-external-pcap-service/releases/latest | grep "browser_download_url" | grep "deb" | cut -d '"' -f 4) wget "$LATEST_URL" # Or browse all releases: -# https://github.com/whatpulse/external-pcap-service/releases +# https://github.com/whatpulse/linux-external-pcap-service/releases ``` ### Build from Source @@ -58,7 +58,7 @@ If packages aren't available for your distribution, or you prefer to build from ```bash # Download and extract source from GitHub releases -# Visit: https://github.com/whatpulse/external-pcap-service/releases +# Visit: https://github.com/whatpulse/linux-external-pcap-service/releases # Download: whatpulse-pcap-service-VERSION-source.tar.gz tar xzf whatpulse-pcap-service-*-source.tar.gz diff --git a/logger.cpp b/logger.cpp new file mode 100644 index 0000000..386ea91 --- /dev/null +++ b/logger.cpp @@ -0,0 +1,182 @@ +/* + * WhatPulse External PCap Service - Logger Implementation + * + * Copyright (c) 2025 WhatPulse. All rights reserved. + * + * Licensed under CC BY-NC 4.0 with additional terms. + * See LICENSE file for complete terms and conditions. + * + * NOTICE: This software integrates with WhatPulse services. Reverse engineering + * the communication protocol or tampering with data transmission is prohibited. + * + * For licensing questions: support@whatpulse.org + */ + +#include "logger.h" +#include +#include +#include + +Logger &Logger::getInstance() +{ + static Logger instance; + return instance; +} + +void Logger::initialize(const std::string &logFile, LogLevel level, bool verbose) +{ + m_level = level; + m_verbose = verbose; + + // Set performance logging intervals based on verbose mode + if (verbose) + { + m_performanceInterval = m_verbosePerformanceInterval; + } + + if (!logFile.empty()) + { + m_logFile.close(); + m_logFile.open(logFile, std::ios::app); + if (!m_logFile.is_open()) + { + std::cerr << "Failed to open log file: " << logFile << std::endl; + return; + } + } + + // Initial log entry + std::stringstream ss; + ss << "Logger initialized - Level: " << levelToString(level) + << ", Verbose: " << (verbose ? "Yes" : "No") + << ", Performance reports every: " << m_performanceInterval.count() << " seconds"; + log(LogLevel::INFO, ss.str()); +} + +void Logger::log(LogLevel level, const std::string &message) +{ + if (level < m_level) + { + return; + } + + std::string logEntry = getCurrentTimestamp() + " [" + levelToString(level) + "] " + message; + + bool isOpen = m_logFile.is_open(); + if (isOpen) + { + m_logFile << logEntry << std::endl; + m_logFile.flush(); + } + if(!isOpen || m_verbose) + { + // Fallback to console if file logging fails + if (level >= LogLevel::ERROR) + { + std::cerr << logEntry << std::endl; + } + else + { + std::cout << logEntry << std::endl; + } + } +} + +void Logger::logPerformance(const std::string &interfaceName, uint64_t packetCount, uint64_t totalBytes, + double seconds, size_t queueSize, bool isConnected) +{ + if (!shouldLogPerformance()) + { + return; + } + + double mbps = (totalBytes * 8.0) / (seconds * 1024 * 1024); + double pps = packetCount / seconds; + + std::stringstream ss; + ss << "PERF [" << interfaceName << "] " + << "Packets: " << packetCount << " (" << std::fixed << std::setprecision(1) << pps << " pps), " + << "Rate: " << std::setprecision(2) << mbps << " Mbps, " + << "Queue: " << queueSize << " packets, " + << "TCP: " << (isConnected ? "Connected" : "Disconnected"); + + log(LogLevel::INFO, ss.str()); +} + +void Logger::logConnectionAttempt(const std::string &host, uint16_t port) +{ + std::stringstream ss; + ss << "TCP: Attempting to connect to " << host << ":" << port; + log(LogLevel::INFO, ss.str()); +} + +void Logger::logConnectionSuccess(const std::string &host, uint16_t port) +{ + std::stringstream ss; + ss << "TCP: Successfully connected to " << host << ":" << port; + log(LogLevel::INFO, ss.str()); +} + +void Logger::logConnectionFailed(const std::string &host, uint16_t port, const std::string &error) +{ + std::stringstream ss; + ss << "TCP: Failed to connect to " << host << ":" << port << " - " << error; + log(LogLevel::WARNING, ss.str()); +} + +void Logger::logDisconnected(const std::string &host, uint16_t port) +{ + std::stringstream ss; + ss << "TCP: Disconnected from " << host << ":" << port; + log(LogLevel::INFO, ss.str()); +} + +void Logger::logSendError(const std::string &error) +{ + std::stringstream ss; + ss << "TCP: Send failed - " << error; + log(LogLevel::WARNING, ss.str()); +} + +std::string Logger::getCurrentTimestamp() +{ + auto now = std::chrono::system_clock::now(); + auto time_t = std::chrono::system_clock::to_time_t(now); + auto milliseconds = std::chrono::duration_cast( + now.time_since_epoch()) % + 1000; + + std::stringstream ss; + ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S"); + ss << "." << std::setfill('0') << std::setw(3) << milliseconds.count(); + + return ss.str(); +} + +std::string Logger::levelToString(LogLevel level) +{ + switch (level) + { + case LogLevel::DEBUG: + return "DEBUG"; + case LogLevel::INFO: + return "INFO"; + case LogLevel::WARNING: + return "WARN"; + case LogLevel::ERROR: + return "ERROR"; + default: + return "UNKNOWN"; + } +} + +bool Logger::shouldLogPerformance() +{ + auto now = std::chrono::steady_clock::now(); + if (now - m_lastPerformanceLog >= m_performanceInterval) + { + m_lastPerformanceLog = now; + return true; + } + return false; +} diff --git a/logger.h b/logger.h new file mode 100644 index 0000000..6af1024 --- /dev/null +++ b/logger.h @@ -0,0 +1,79 @@ +/* + * WhatPulse External PCap Service - Logger Header + * + * Copyright (c) 2025 WhatPulse. All rights reserved. + * + * Licensed under CC BY-NC 4.0 with additional terms. + * See LICENSE file for complete terms and conditions. + * + * NOTICE: This software integrates with WhatPulse services. Reverse engineering + * the communication protocol or tampering with data transmission is prohibited. + * + * For licensing questions: support@whatpulse.org + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +enum class LogLevel +{ + DEBUG = 0, + INFO = 1, + WARNING = 2, + ERROR = 3 +}; + +class Logger +{ +public: + static Logger &getInstance(); + + void initialize(const std::string &logFile, LogLevel level = LogLevel::INFO, bool verbose = false); + void setLevel(LogLevel level) { m_level = level; } + void setVerbose(bool verbose) { m_verbose = verbose; } + + void log(LogLevel level, const std::string &message); + void debug(const std::string &message) { log(LogLevel::DEBUG, message); } + void info(const std::string &message) { log(LogLevel::INFO, message); } + void warning(const std::string &message) { log(LogLevel::WARNING, message); } + void error(const std::string &message) { log(LogLevel::ERROR, message); } + + // Performance logging with throttling + void logPerformance(const std::string &interfaceName, uint64_t packetCount, uint64_t totalBytes, + double seconds, size_t queueSize, bool isConnected); + + // Connection state logging + void logConnectionAttempt(const std::string &host, uint16_t port); + void logConnectionSuccess(const std::string &host, uint16_t port); + void logConnectionFailed(const std::string &host, uint16_t port, const std::string &error); + void logDisconnected(const std::string &host, uint16_t port); + void logSendError(const std::string &error); + +private: + Logger() = default; + std::string getCurrentTimestamp(); + std::string levelToString(LogLevel level); + bool shouldLogPerformance(); + + std::ofstream m_logFile; + std::mutex m_mutex; + LogLevel m_level = LogLevel::INFO; + bool m_verbose = false; + + // Performance logging throttling + std::chrono::steady_clock::time_point m_lastPerformanceLog; + std::chrono::seconds m_performanceInterval{300}; // 5 minutes default + std::chrono::seconds m_verbosePerformanceInterval{10}; // 10 seconds in verbose mode +}; + +// Convenience macros +#define LOG_DEBUG(msg) Logger::getInstance().debug(msg) +#define LOG_INFO(msg) Logger::getInstance().info(msg) +#define LOG_WARNING(msg) Logger::getInstance().warning(msg) +#define LOG_ERROR(msg) Logger::getInstance().error(msg) diff --git a/main.cpp b/main.cpp index b57d1c8..d8300e6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,14 +1,14 @@ /* * WhatPulse External PCap Service - * + * * Copyright (c) 2025 WhatPulse. All rights reserved. - * + * * Licensed under CC BY-NC 4.0 with additional terms. * See LICENSE file for complete terms and conditions. - * + * * NOTICE: This software integrates with WhatPulse services. Reverse engineering * the communication protocol or tampering with data transmission is prohibited. - * + * * For licensing questions: support@whatpulse.org */ @@ -20,31 +20,39 @@ #include #include "pcapservice.h" +#include "logger.h" // Global service instance for signal handler -PcapService* g_service = nullptr; +PcapService *g_service = nullptr; -void printUsage(const char* programName) { +void printUsage(const char *programName) +{ std::cout << "WhatPulse PCap Service v" << PCAP_SERVICE_VERSION << "\n\n"; std::cout << "Usage: " << programName << " [OPTIONS]\n\n"; std::cout << "Options:\n"; std::cout << " -h, --host HOST WhatPulse host to connect to (default: localhost)\n"; std::cout << " -p, --port PORT WhatPulse port to connect to (default: 3499)\n"; std::cout << " -i, --interface IFACE Network interface to monitor (default: all)\n"; - std::cout << " -v, --verbose Enable verbose logging\n"; + std::cout << " -l, --log-file FILE Log file path (default: /var/log/whatpulse-pcap.log)\n"; + std::cout << " -d, --debug Enable debug level logging\n"; + std::cout << " -v, --verbose Enable verbose logging (more frequent reports)\n"; std::cout << " --help Display this help and exit\n"; std::cout << " --version Output version information and exit\n\n"; std::cout << "This service requires root privileges to capture network packets.\n"; + std::cout << "Logs are written to the specified log file. Use console output with empty log file (-l \"\").\n"; } -void printVersion() { +void printVersion() +{ std::cout << "WhatPulse PCap Service v" << PCAP_SERVICE_VERSION << "\n"; std::cout << "External PCap service for WhatPulse network monitoring\n"; } -void signalHandler(int signum) { - std::cout << "\nReceived signal " << signum << ", shutting down gracefully..." << std::endl; - if (g_service) { +void signalHandler(int signum) +{ + LOG_INFO("Received signal " + std::to_string(signum) + ", shutting down gracefully..."); + if (g_service) + { g_service->stop(); } // Exit immediately after stopping the service @@ -56,80 +64,95 @@ int main(int argc, char *argv[]) std::string host = "localhost"; uint16_t port = 3499; std::string interface = ""; + std::string logFile = "/var/log/whatpulse-pcap.log"; bool verbose = false; - + bool debug = false; + // Parse command line arguments static struct option long_options[] = { - {"host", required_argument, 0, 'h'}, - {"port", required_argument, 0, 'p'}, + {"host", required_argument, 0, 'h'}, + {"port", required_argument, 0, 'p'}, {"interface", required_argument, 0, 'i'}, - {"verbose", no_argument, 0, 'v'}, - {"help", no_argument, 0, 1}, - {"version", no_argument, 0, 2}, - {0, 0, 0, 0} - }; - + {"log-file", required_argument, 0, 'l'}, + {"debug", no_argument, 0, 'd'}, + {"verbose", no_argument, 0, 'v'}, + {"help", no_argument, 0, 1}, + {"version", no_argument, 0, 2}, + {0, 0, 0, 0}}; + int c; int option_index = 0; - - while ((c = getopt_long(argc, argv, "h:p:i:v", long_options, &option_index)) != -1) { - switch (c) { - case 'h': - host = optarg; - break; - case 'p': - port = static_cast(std::stoul(optarg)); - break; - case 'i': - interface = optarg; - break; - case 'v': - verbose = true; - break; - case 1: - printUsage(argv[0]); - return 0; - case 2: - printVersion(); - return 0; - case '?': - printUsage(argv[0]); - return 1; - default: - break; + + while ((c = getopt_long(argc, argv, "h:p:i:l:dv", long_options, &option_index)) != -1) + { + switch (c) + { + case 'h': + host = optarg; + break; + case 'p': + port = static_cast(std::stoul(optarg)); + break; + case 'i': + interface = optarg; + break; + case 'l': + logFile = optarg; + break; + case 'd': + debug = true; + break; + case 'v': + verbose = true; + break; + case 1: + printUsage(argv[0]); + return 0; + case 2: + printVersion(); + return 0; + case '?': + printUsage(argv[0]); + return 1; + default: + break; } } - - if (verbose) { - std::cout << "WhatPulse PCap Service starting..." << std::endl; - std::cout << "Target host: " << host << std::endl; - std::cout << "Target port: " << port << std::endl; - std::cout << "Interface: " << (interface.empty() ? "all" : interface) << std::endl; - } - + + // Initialize logging system + LogLevel logLevel = debug ? LogLevel::DEBUG : LogLevel::INFO; + Logger::getInstance().initialize(logFile, logLevel, verbose); + + LOG_INFO("WhatPulse PCap Service v" + std::string(PCAP_SERVICE_VERSION) + " starting..."); + LOG_INFO("Target host: " + host); + LOG_INFO("Target port: " + std::to_string(port)); + LOG_INFO("Interface: " + (interface.empty() ? "all" : interface)); + LOG_INFO("Log level: " + std::string(debug ? "DEBUG" : "INFO")); + LOG_INFO("Verbose mode: " + std::string(verbose ? "enabled" : "disabled")); + // Set up signal handlers for graceful shutdown signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); - + PcapService service; g_service = &service; - - if (!service.initialize(host, port, interface, verbose)) { - std::cerr << "Failed to initialize PCap service" << std::endl; + + if (!service.initialize(host, port, interface, verbose)) + { + LOG_ERROR("Failed to initialize PCap service"); return 1; } - - if (!service.start()) { - std::cerr << "Failed to start PCap service" << std::endl; + + if (!service.start()) + { + LOG_ERROR("Failed to start PCap service"); return 1; } - - if (verbose) { - std::cout << "Service started successfully. Press Ctrl+C to stop." << std::endl; - } - + + LOG_INFO("Service started successfully. Press Ctrl+C to stop."); + // Keep the service running service.run(); - + return 0; } diff --git a/pcapcapturethread.cpp b/pcapcapturethread.cpp index c851823..c90801c 100644 --- a/pcapcapturethread.cpp +++ b/pcapcapturethread.cpp @@ -14,6 +14,7 @@ #include "pcapcapturethread.h" #include "pcapservice.h" +#include "logger.h" #include #include #include @@ -73,10 +74,7 @@ void PcapCaptureThread::run() { char errbuf[PCAP_ERRBUF_SIZE]; - if (m_verbose) - { - std::cout << "Starting capture on interface: " << m_interface << std::endl; - } + LOG_INFO("Starting capture on interface: " + m_interface); // Open pcap handle m_pcapHandle = pcap_open_live(m_interface.c_str(), @@ -87,7 +85,7 @@ void PcapCaptureThread::run() if (!m_pcapHandle) { - std::cerr << "Unable to open interface " << m_interface << ": " << errbuf << std::endl; + LOG_ERROR("Unable to open interface " + m_interface + ": " + std::string(errbuf)); return; } @@ -95,8 +93,7 @@ void PcapCaptureThread::run() struct bpf_program filter; if (pcap_compile(m_pcapHandle, &filter, "tcp or udp", 1, PCAP_NETMASK_UNKNOWN) == -1) { - std::cerr << "Unable to compile filter for interface " << m_interface << ": " - << pcap_geterr(m_pcapHandle) << std::endl; + LOG_ERROR("Unable to compile filter for interface " + m_interface + ": " + std::string(pcap_geterr(m_pcapHandle))); pcap_close(m_pcapHandle); m_pcapHandle = nullptr; return; @@ -104,8 +101,7 @@ void PcapCaptureThread::run() if (pcap_setfilter(m_pcapHandle, &filter) == -1) { - std::cerr << "Unable to set filter for interface " << m_interface << ": " - << pcap_geterr(m_pcapHandle) << std::endl; + LOG_ERROR("Unable to set filter for interface " + m_interface + ": " + std::string(pcap_geterr(m_pcapHandle))); pcap_freecode(&filter); pcap_close(m_pcapHandle); m_pcapHandle = nullptr; @@ -115,10 +111,7 @@ void PcapCaptureThread::run() pcap_freecode(&filter); m_capturing.store(true); - if (m_verbose) - { - std::cout << "Capture started successfully on interface: " << m_interface << std::endl; - } + LOG_INFO("Capture started successfully on interface: " + m_interface); // Start packet capture loop while (!m_shouldStop.load()) @@ -129,8 +122,7 @@ void PcapCaptureThread::run() // Error occurred if (!m_shouldStop.load()) { - std::cerr << "Error in pcap_dispatch for interface " << m_interface << ": " - << pcap_geterr(m_pcapHandle) << std::endl; + LOG_ERROR("Error in pcap_dispatch for interface " + m_interface + ": " + std::string(pcap_geterr(m_pcapHandle))); } break; } @@ -154,10 +146,7 @@ void PcapCaptureThread::run() } } - if (m_verbose) - { - std::cout << "Capture stopped on interface: " << m_interface << std::endl; - } + LOG_INFO("Capture stopped on interface: " + m_interface); } void PcapCaptureThread::packetHandler(u_char *userData, const struct pcap_pkthdr *header, const u_char *packet) diff --git a/pcapservice.cpp b/pcapservice.cpp index 7850c47..d8f5efd 100644 --- a/pcapservice.cpp +++ b/pcapservice.cpp @@ -13,6 +13,7 @@ */ #include "pcapservice.h" +#include "logger.h" #include #include #include @@ -69,7 +70,7 @@ bool PcapService::start() // Check for root privileges (required for pcap) if (geteuid() != 0) { - std::cerr << "PCap service requires root privileges. Please run with sudo." << std::endl; + LOG_ERROR("PCap service requires root privileges. Please run with sudo."); return false; } @@ -87,7 +88,7 @@ bool PcapService::start() if (interfaces.empty()) { - std::cerr << "No suitable network interfaces found for monitoring" << std::endl; + LOG_ERROR("No suitable network interfaces found for monitoring"); return false; } @@ -96,7 +97,7 @@ bool PcapService::start() if (m_captureThreads.empty()) { - std::cerr << "Failed to start any capture threads" << std::endl; + LOG_ERROR("Failed to start any capture threads"); return false; } @@ -158,10 +159,7 @@ void PcapService::stop() m_tcpClient->disconnect(); } - if (m_verbose) - { - std::cout << "PCap service stopped" << std::endl; - } + LOG_INFO("PCap service stopped"); } void PcapService::run() @@ -179,37 +177,44 @@ void PcapService::onPacketCaptured(const PacketData &packet) return; } - if (m_verbose) - { - static uint64_t packetCount = 0; - static uint64_t totalBytes = 0; - static auto lastReport = std::chrono::steady_clock::now(); + // Performance metrics tracking (aggregated across all interfaces) + static uint64_t packetCount = 0; + static uint64_t totalBytes = 0; + static uint64_t droppedPackets = 0; + static auto lastReport = std::chrono::steady_clock::now(); - packetCount++; - totalBytes += packet.dataLength; + packetCount++; + totalBytes += packet.dataLength; - auto now = std::chrono::steady_clock::now(); - auto elapsed = std::chrono::duration_cast(now - lastReport); + auto now = std::chrono::steady_clock::now(); + auto elapsed = std::chrono::duration_cast(now - lastReport); - if (elapsed.count() >= 5) + // Check if we should report performance (handled by Logger class) + if (elapsed.count() >= 60) // Check every minute, Logger will throttle appropriately + { + size_t queueSize; { - // Report every 5 seconds for debugging purposes - double mbps = (totalBytes * 8.0) / (elapsed.count() * 1024 * 1024); - if (LOG_LEVEL_DEBUG) - { - std::cout << "Captured " << packetCount << " packets in " << elapsed.count() - << "s from " << packet.interfaceName << " (rate: " << std::fixed << std::setprecision(2) - << mbps << " Mbps)" << std::endl; - } - lastReport = now; - packetCount = 0; - totalBytes = 0; + std::lock_guard lock(m_queueMutex); + queueSize = m_packetQueue.size(); } + + Logger::getInstance().logPerformance(packet.interfaceName, packetCount, totalBytes, + elapsed.count(), queueSize, m_tcpClient->isConnected()); + + lastReport = now; + packetCount = 0; + totalBytes = 0; } - // Add packet to queue + // Add packet to queue with overflow protection { std::lock_guard lock(m_queueMutex); + if (m_packetQueue.size() > 10000) // Prevent memory overflow + { + droppedPackets++; + LOG_WARNING("Packet queue full, dropping packet. Total dropped: " + std::to_string(droppedPackets)); + return; + } m_packetQueue.push(packet); } m_queueCondition.notify_one(); @@ -217,10 +222,7 @@ void PcapService::onPacketCaptured(const PacketData &packet) void PcapService::networkThreadFunction() { - if (m_verbose) - { - std::cout << "Network thread started" << std::endl; - } + LOG_INFO("Network thread started"); auto lastReconnectAttempt = std::chrono::steady_clock::now(); const auto reconnectInterval = std::chrono::seconds(30); @@ -256,13 +258,13 @@ void PcapService::networkThreadFunction() { sendPacketData(packet); } - else if (m_verbose) + else { static auto lastWarning = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now(); - if (now - lastWarning >= std::chrono::seconds(10)) + if (now - lastWarning >= std::chrono::seconds(60)) // Reduced warning frequency { - std::cout << "Dropping packets - WhatPulse not connected" << std::endl; + LOG_WARNING("Dropping packets - WhatPulse not connected"); lastWarning = now; } } @@ -272,19 +274,11 @@ void PcapService::networkThreadFunction() } } - if (m_verbose) - { - std::cout << "Network thread stopped" << std::endl; - } + LOG_INFO("Network thread stopped"); } void PcapService::connectToWhatPulse() { - if (m_verbose) - { - std::cout << "Connecting to WhatPulse at " << m_host << ":" << m_port << std::endl; - } - m_tcpClient->connect(m_host, m_port); } @@ -350,10 +344,7 @@ void PcapService::sendPacketData(const PacketData &packet) // Send data if (!m_tcpClient->send(data)) { - if (m_verbose) - { - std::cerr << "Failed to send packet data" << std::endl; - } + LOG_DEBUG("Failed to send packet data"); } } @@ -365,10 +356,7 @@ std::vector PcapService::discoverNetworkInterfaces() if (pcap_findalldevs(&devices, errbuf) == -1) { - if (m_verbose) - { - std::cerr << "Error finding network devices: " << errbuf << std::endl; - } + LOG_ERROR("Error finding network devices: " + std::string(errbuf)); return interfaces; } @@ -391,14 +379,11 @@ std::vector PcapService::discoverNetworkInterfaces() std::string(device->description).find("Bluetooth") != std::string::npos || std::string(device->description).find("Adapter for loopback") != std::string::npos))) { - if (m_verbose && deviceName.length() > 0) + if (deviceName.length() > 0) { - std::cout << "Skipping interface: " << deviceName; - if (device->description) - { - std::cout << " (" << device->description << ")"; - } - std::cout << " - not a network interface" << std::endl; + std::string desc = device->description ? std::string(device->description) : ""; + LOG_DEBUG("Skipping interface: " + deviceName + + (desc.empty() ? "" : " (" + desc + ")") + " - not a network interface"); } continue; } @@ -422,23 +407,15 @@ std::vector PcapService::discoverNetworkInterfaces() { interfaces.push_back(deviceName); - if (m_verbose) - { - std::cout << "Found suitable network interface: " << deviceName << std::endl; - if (device->description) - { - std::cout << " Description: " << device->description << std::endl; - } - } + std::string desc = device->description ? std::string(device->description) : ""; + LOG_INFO("Found suitable network interface: " + deviceName + + (desc.empty() ? "" : " (" + desc + ")")); } - else if (m_verbose && deviceName.length() > 0) + else if (deviceName.length() > 0) { - std::cout << "Skipping interface: " << deviceName; - if (device->description) - { - std::cout << " (" << device->description << ")"; - } - std::cout << " - not a recognized network interface pattern" << std::endl; + std::string desc = device->description ? std::string(device->description) : ""; + LOG_DEBUG("Skipping interface: " + deviceName + + (desc.empty() ? "" : " (" + desc + ")") + " - not a recognized network interface pattern"); } } @@ -496,17 +473,11 @@ void PcapService::startCaptureThread(const std::string &interface) { m_captureThreads.push_back(std::move(captureThread)); m_monitoredInterfaces.insert(interface); - if (m_verbose) - { - std::cout << "Started capture thread for new interface: " << interface << std::endl; - } + LOG_INFO("Started capture thread for new interface: " + interface); } else { - if (m_verbose) - { - std::cerr << "Failed to start capture on interface: " << interface << std::endl; - } + LOG_WARNING("Failed to start capture on interface: " + interface); } } @@ -526,19 +497,13 @@ void PcapService::stopCaptureThread(const std::string &interface) m_captureThreads.erase(it, m_captureThreads.end()); m_monitoredInterfaces.erase(interface); - if (m_verbose) - { - std::cout << "Stopped capture thread for interface: " << interface << std::endl; - } + LOG_INFO("Stopped capture thread for interface: " + interface); } } void PcapService::networkMonitorThreadFunction() { - if (m_verbose) - { - std::cout << "Network monitor thread started" << std::endl; - } + LOG_INFO("Network monitor thread started"); const auto checkInterval = std::chrono::seconds(MONITOR_INTERVAL); // Check for interface changes @@ -560,8 +525,5 @@ void PcapService::networkMonitorThreadFunction() } } - if (m_verbose) - { - std::cout << "Network monitor thread stopped" << std::endl; - } + LOG_INFO("Network monitor thread stopped"); } diff --git a/tcpclient.cpp b/tcpclient.cpp index d5ce65a..e3be655 100644 --- a/tcpclient.cpp +++ b/tcpclient.cpp @@ -13,6 +13,7 @@ */ #include "tcpclient.h" +#include "logger.h" #include #include #include @@ -40,14 +41,13 @@ bool TcpClient::connect(const std::string &host, uint16_t port) m_host = host; m_port = port; + Logger::getInstance().logConnectionAttempt(host, port); + // Create socket m_socket = socket(AF_INET, SOCK_STREAM, 0); if (m_socket < 0) { - if (m_verbose) - { - std::cerr << "Failed to create socket: " << strerror(errno) << std::endl; - } + Logger::getInstance().logConnectionFailed(host, port, "Failed to create socket: " + std::string(strerror(errno))); return false; } @@ -55,10 +55,7 @@ bool TcpClient::connect(const std::string &host, uint16_t port) struct hostent *hostInfo = gethostbyname(host.c_str()); if (!hostInfo) { - if (m_verbose) - { - std::cerr << "Failed to resolve hostname: " << host << std::endl; - } + Logger::getInstance().logConnectionFailed(host, port, "Failed to resolve hostname: " + host); close(m_socket); m_socket = -1; return false; @@ -74,20 +71,14 @@ bool TcpClient::connect(const std::string &host, uint16_t port) // Connect if (::connect(m_socket, reinterpret_cast(&serverAddr), sizeof(serverAddr)) < 0) { - if (m_verbose) - { - std::cerr << "Failed to connect to " << host << ":" << port << " - " << strerror(errno) << std::endl; - } + Logger::getInstance().logConnectionFailed(host, port, strerror(errno)); close(m_socket); m_socket = -1; return false; } m_connected = true; - if (m_verbose) - { - std::cout << "Connected to " << host << ":" << port << std::endl; - } + Logger::getInstance().logConnectionSuccess(host, port); return true; } @@ -102,9 +93,9 @@ void TcpClient::disconnect() m_socket = -1; } - if (m_connected && m_verbose) + if (m_connected) { - std::cout << "Disconnected from " << m_host << ":" << m_port << std::endl; + Logger::getInstance().logDisconnected(m_host, m_port); } m_connected = false; @@ -133,10 +124,7 @@ bool TcpClient::send(const std::vector &data) ssize_t sent = ::send(m_socket, dataPtr + totalSent, data.size() - totalSent, 0); if (sent < 0) { - if (m_verbose) - { - std::cerr << "Send failed: " << strerror(errno) << std::endl; - } + Logger::getInstance().logSendError(strerror(errno)); m_connected = false; return false; }