/
/
/
1#include "qt_icmp/icmp_socket.hpp"
2#include "qt_icmp/icmp_packet.hpp"
3
4#include <sys/socket.h>
5#include <netinet/ip_icmp.h>
6#include <arpa/inet.h>
7#include <unistd.h>
8#include <cstring>
9#include <stdexcept>
10#include <regex>
11#include <QThread>
12#include <QDebug>
13#include <QMutex>
14#include <fcntl.h> // Add this line
15#include <errno.h>
16
17ICMPSocket::ICMPSocket() {
18 sockfd_ = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
19 if (sockfd_ < 0) {
20 throw std::runtime_error("Failed to create raw socket");
21 }
22
23 int flags = fcntl(sockfd_, F_GETFL, 0);
24 fcntl(sockfd_, F_SETFL, flags | O_NONBLOCK);
25}
26
27ICMPSocket::~ICMPSocket() {
28 if (sockfd_ >= 0) {
29 close(sockfd_);
30 }
31}
32
33void ICMPSocket::sendPing(const QString& ipAddress, quint16 id, quint16 sequence) {
34 ICMPPacket packet(id, sequence);
35
36 qDebug() << "sending the ping from socket";
37
38 struct sockaddr_in dest_addr = {};
39 dest_addr.sin_family = AF_INET;
40 if (inet_pton(AF_INET, ipAddress.toStdString().c_str(), &dest_addr.sin_addr) <= 0) {
41 throw std::runtime_error("Invalid IP address");
42 }
43
44 if (sendto(sockfd_, packet.header(), packet.size(), 0,
45 reinterpret_cast<struct sockaddr*>(&dest_addr), sizeof(dest_addr)) < 0) {
46 throw std::runtime_error("Failed to send ICMP packet");
47 }
48}
49
50void ICMPSocket::listenForPackets() {
51 while (!stopRequested) {
52 char buffer[1024];
53 struct sockaddr_in sender_addr;
54 socklen_t addrlen = sizeof(sender_addr);
55
56 ssize_t length = recvfrom(sockfd_, buffer, sizeof(buffer), 0,
57 reinterpret_cast<struct sockaddr*>(&sender_addr), &addrlen);
58
59 if (length >= 0) { // Data received
60 QString receivedIpAddress = inet_ntoa(sender_addr.sin_addr);
61 qDebug() << "Received packet from" << receivedIpAddress;
62 emit pongReceived(receivedIpAddress);
63 } else if (errno != EAGAIN && errno != EWOULDBLOCK) {
64 qWarning() << "recvfrom error:" << strerror(errno);
65 }
66
67 // Check stopRequested flag periodically
68 if (stopRequested) break;
69
70 QThread::msleep(10);
71 }
72}
73
74void ICMPSocket::stopListening() {
75 QMutexLocker locker(&mutex);
76 stopRequested = true;
77 qDebug() << "Stop requested, waking up thread...";
78}