File indexing completed on 2024-06-23 05:27:54

0001 /*
0002     SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include <atomic>
0008 #include <csignal>
0009 #include <iomanip>
0010 #include <iostream>
0011 #include <thread>
0012 
0013 #include <getopt.h>
0014 
0015 #include "Accumulator.h"
0016 #include "Capture.h"
0017 #include "ConnectionMapping.h"
0018 #include "Packet.h"
0019 #include "TimeStamps.h"
0020 
0021 static std::atomic_bool g_running{false};
0022 
0023 int main(int argc, char **argv)
0024 {
0025     static struct option long_options[] = {
0026         {"help", 0, nullptr, 'h'},
0027         {"stats", 0, nullptr, 's'},
0028         {nullptr, 0, nullptr, 0},
0029     };
0030 
0031     auto statsRequested = false;
0032     auto optionIndex = 0;
0033     auto option = -1;
0034     while ((option = getopt_long(argc, argv, "", long_options, &optionIndex)) != -1) {
0035         switch (option) {
0036         case 's':
0037             statsRequested = true;
0038             break;
0039         default:
0040             std::cerr << "Usage: " << argv[0] << " [options]\n";
0041             std::cerr << "This is a helper application for tracking per-process network usage.\n";
0042             std::cerr << "\n";
0043             std::cerr << "Options:\n";
0044             std::cerr << "  --stats     Print packet capture statistics.\n";
0045             std::cerr << "  --help      Display this help.\n";
0046             return 0;
0047         }
0048     }
0049 
0050     auto mapping = std::make_shared<ConnectionMapping>();
0051 
0052     auto capture = std::make_shared<Capture>();
0053     if (!capture->start()) {
0054         std::cerr << capture->lastError() << std::endl;
0055         return 1;
0056     }
0057 
0058     auto accumulator = std::make_shared<Accumulator>(capture, mapping);
0059 
0060     signal(SIGINT, [](int) {
0061         g_running = false;
0062     });
0063     signal(SIGTERM, [](int) {
0064         g_running = false;
0065     });
0066 
0067     g_running = true;
0068     while (g_running) {
0069         auto data = accumulator->data();
0070         auto timeStamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
0071 
0072         if (statsRequested != 0) {
0073             capture->reportStatistics();
0074         }
0075 
0076         if (data.empty()) {
0077             std::cout << std::put_time(std::localtime(&timeStamp), "%T") << std::endl;
0078         } else {
0079             for (auto itr = data.begin(); itr != data.end(); ++itr) {
0080                 std::cout << std::put_time(std::localtime(&timeStamp), "%T");
0081                 std::cout << "|PID|" << (*itr).first << "|IN|" << (*itr).second.first << "|OUT|" << (*itr).second.second;
0082                 std::cout << std::endl;
0083             }
0084         }
0085 
0086         std::this_thread::sleep_for(std::chrono::seconds(1));
0087     }
0088 
0089     return 0;
0090 }