/
/
/
1#include "qt_icmp/icmp_wrapper.hpp"
2#include "qt_icmp/icmp_socket.hpp"
3
4#include <QDebug>
5#include <QCoreApplication>
6#include <netinet/ip_icmp.h>
7#include <arpa/inet.h>
8#include <stdexcept>
9#include <regex>
10
11#include <QThread>
12#include <QEventLoop>
13#include <QTimer>
14
15#include <QTextStream>
16#include <cstdio>
17
18ICMPWrapper::ICMPWrapper(QObject *parent) : QObject(parent) {}
19
20// Overloaded method that accepts an integer IP address
21bool ICMPWrapper::pingHost(const quint32& ipAddressInt) {
22 QString ipAddress = convertIntToIPAddress(ipAddressInt);
23 return pingHost(ipAddress);
24}
25
26bool ICMPWrapper::pingHost(const QString& ipAddress) {
27 if (!isValidIPAddress(ipAddress)) {
28 qWarning() << "Invalid IP address format:" << ipAddress;
29 return false;
30 }
31
32 try {
33 ICMPSocket socket;
34 quint16 id = static_cast<quint16>(QCoreApplication::applicationPid());
35 quint16 sequence = 1; // Increment this for subsequent pings
36
37 // Create an event loop and timer for timeout handling
38 QEventLoop loop;
39 QTimer timeoutTimer;
40
41 // Variable to store the pong response status
42 bool pongReceived = false;
43
44 // Connect the pongReceived signal to update the status and quit the loop
45 connect(&socket, &ICMPSocket::pongReceived, [&loop, &pongReceived]() {
46 pongReceived = true;
47 qDebug() << "Pong received";
48 loop.quit(); // Quit the event loop when pong is received
49 });
50
51 // Connect the timeout timer to quit the loop on timeout
52 connect(&timeoutTimer, &QTimer::timeout, [&loop]() {
53 qWarning() << "Ping timeout reached";
54 loop.quit(); // Quit the event loop on timeout
55 });
56
57 // Start the timeout timer
58 timeoutTimer.setSingleShot(true);
59 timeoutTimer.start(2000); // Timeout after 2000 ms (2 seconds)
60
61 // Start the packet listening in a separate thread
62 QThread packetThread;
63 connect(&packetThread, &QThread::started, [&socket]() {
64 socket.listenForPackets(); // This method should keep running
65 });
66
67 packetThread.start();
68
69 // Send the ping
70 socket.sendPing(ipAddress, id, sequence);
71 qDebug() << "Ping sent to" << ipAddress;
72
73 // Wait for response or timeout
74 loop.exec();
75
76 // Clean up
77 socket.stopListening(); // Request the thread to stop
78 packetThread.quit();
79 packetThread.wait();
80
81 // Return the result based on pong received status
82 return pongReceived;
83 } catch (const std::exception& e) {
84 qWarning() << "Error while pinging:" << e.what();
85 return false;
86 }
87}
88
89// Helper method to convert an int to an IP address string
90QString ICMPWrapper::convertIntToIPAddress(quint32 ipAddressInt) {
91 struct in_addr ipAddrStruct;
92 ipAddrStruct.s_addr = htonl(ipAddressInt); // Ensure correct byte order
93 return QString(inet_ntoa(ipAddrStruct)); // Convert to QString
94}
95
96// Helper method to validate IP address string using regex
97bool ICMPWrapper::isValidIPAddress(const QString& ipAddress) {
98 const std::regex ipPattern(
99 R"(^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$)"
100 );
101 return std::regex_match(ipAddress.toStdString(), ipPattern);
102}
103