#include "mainwindow.h" #include "QUdpSocket" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); m_udpSocket = new QUdpSocket(this); m_udpSocket->bind(QHostAddress::Any, UDP_PORT, QUdpSocket::ShareAddress); connect(m_udpSocket, &QUdpSocket::readyRead, this, &MainWindow::processPendingDatagrams); // Timer just to ask twice (udp) m_timer = new QTimer(this); m_timer->setSingleShot(true); m_timer->setInterval(500); connect(m_timer, &QTimer::timeout, this, &MainWindow::SendRequest); // Send Request on startup on_pbRefresh_clicked(); ui->devices->setIconSize(QSize(48, 48)); ui->devices->setContextMenuPolicy(Qt::CustomContextMenu); ui->comboBox->addItem("default"); ui->comboBox->addItem("192.168.69.10"); // test if (ui->comboBox->currentText() == "default") { ui->ChangeOwner->setDisabled(true); } // //Example items for screenshot: // QListWidgetItem * item = new QListWidgetItem(QIcon(":/res/stm32.png"), "00:80:E1:05:44:21 @ 192.168.0.11 (John // Doe)"); ui->devices->addItem(item); QListWidgetItem * item2 = new QListWidgetItem(QIcon(":/res/rpi.png"), // "E4:5F:01:05:44:21 @ 192.168.0.11 (Jane Doe)"); ui->devices->addItem(item2); QListWidgetItem * item3 = new // QListWidgetItem(QIcon(":/res/unknown.png"), "44:44:44:05:44:21 @ 192.168.0.11 (Juul Doe)"); // ui->devices->addItem(item3); connect(ui->actionAbout_Qt, &QAction::triggered, QApplication::aboutQt); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pbRefresh_clicked() { this->func = 0; SendRequest(); m_timer->start(); } void MainWindow::SendRequest() { int broadcasts_send = 0; int data_send = 0; QUdpSocket udpSocket; QByteArray datagram; if (this->func == 0) { datagram = UDP_REQUEST "v1.0"; // Get all the Network Interface Cards of this Computer QList NICs = QNetworkInterface::allInterfaces(); foreach (QNetworkInterface NIC, NICs) { // Get all the adresses on this NIC QList adresses = NIC.addressEntries(); foreach (QNetworkAddressEntry adress, adresses) { QD << NIC.name() << adress.ip(); // If broadcast adress = null => IPv6 (no support for broadcasts) QHostAddress broadc_addr = adress.broadcast(); if (!broadc_addr.isNull()) { // Send UDP packet udpSocket.writeDatagram(datagram, adress.broadcast(), UDP_PORT); broadcasts_send++; } } } } else if (this->func == 1) { QHostAddress addr(ui->comboBox->currentText()); udpSocket.writeDatagram(this->data, addr, UDP_PORT); data_send++; } if (broadcasts_send == 0 && data_send == 0) { ui->pteLog->appendPlainText( "Warning: no Network Interface Cards or valid IP adresses found (no broadcasts send)"); } else if (data_send != 0) { ui->pteLog->appendPlainText(tr("Info: %1 message sent to %2").arg(data_send).arg(ui->comboBox->currentText())); } else { ui->pteLog->appendPlainText(tr("Info: %1 broadcasts send").arg(broadcasts_send)); } } void MainWindow::processPendingDatagrams() { QByteArray datagram; QHostAddress host; // just get rid of every host in the combobox, not pretty code, i know if (this->func == 0) { for (int i = 1; i < ui->comboBox->count(); i++) { ui->comboBox->removeItem(i); } } while (m_udpSocket->hasPendingDatagrams()) { datagram.resize(int(m_udpSocket->pendingDatagramSize())); m_udpSocket->readDatagram(datagram.data(), datagram.size(), &host); QString msg = QString(datagram).remove(QRegularExpression("\\r|\\n")); processDatagram(msg, host.toString()); } } void MainWindow::processDatagram(QString msg, QString host) { // Append received data to log QString logLine = tr("Van %1: \"%2\"").arg(host).arg(msg); ui->pteLog->appendPlainText(logLine); // We receive our own request. So a check to see if it is the request: if (msg.indexOf(UDP_REQUEST) != -1) { return; // we are done here... } // add new host to select in combobox if (this->func == 0) { ui->comboBox->addItem(host); } // RegEx for MAC adress QRegularExpression macRegExp( "([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})"); QRegularExpressionMatch match = macRegExp.match(msg.toUpper()); if (match.hasMatch()) { QString foundOUI = match.captured(1) % match.captured(2) % match.captured(3); QString foundMAC = match.captured(0); QString imgName = ":/res/unknown.png"; /*grep STMicro oui.txt | grep base 0080E1 (base 16) STMicroelectronics SRL 10E77A (base 16) STMicrolectronics International NV*/ if (foundOUI == "0080E1" || foundOUI == "10E77A") { imgName = ":/res/stm32.png"; } /*grep Raspberry oui.txt | grep base DCA632 (base 16) Raspberry Pi Trading Ltd E45F01 (base 16) Raspberry Pi Trading Ltd B827EB (base 16) Raspberry Pi Foundation*/ if (foundOUI == "DCA632" || foundOUI == "E45F01" || foundOUI == "B827EB") { imgName = ":/res/rpi.png"; } QString needle = UDP_ANS_OWNER; QString owner = "???"; int index = msg.indexOf(needle); if (index != -1) { owner = msg.mid(index + needle.length()); } else { ui->pteLog->appendPlainText("Warning: no OWNER found in message"); } QListWidgetItem* item = searchItem(foundMAC); if (item == nullptr) { item = new QListWidgetItem(); ui->devices->addItem(item); } item->setIcon(QIcon(imgName)); item->setText(tr("%1 @ %2 (%3)").arg(foundMAC).arg(host).arg(owner)); item->setToolTip(tr("Last seen: %1").arg(QTime::currentTime().toString("H:mm:ss.zzz"))); } else { ui->pteLog->appendPlainText("Warning: no MAC found in message"); } } QListWidgetItem* MainWindow::searchItem(QString MAC) { QListWidgetItem* item = nullptr; for (int i = 0; i < ui->devices->count(); i++) { item = ui->devices->item(i); if (item->text().contains(MAC)) { break; } item = nullptr; } return item; } void MainWindow::on_devices_itemDoubleClicked(QListWidgetItem* item) { // Copy the IP to the clipboard QString itemText = item->text(); int start = itemText.indexOf('@') + 2; int end = itemText.indexOf('(') - 1; QString ip = itemText.mid(start, end - start); QClipboard* clipboard = QGuiApplication::clipboard(); clipboard->setText(ip); } void MainWindow::on_devices_customContextMenuRequested(const QPoint& pos) { // create menu QAction copyAction(QIcon(":/res/copy-icon.png"), "Copy IP"); QMenu menu; menu.addAction(©Action); // execute menu QAction* action = menu.exec(ui->devices->mapToGlobal(pos)); if (action == ©Action) { QListWidgetItem* item = ui->devices->itemAt(pos); if (item) { on_devices_itemDoubleClicked(item); } } } void MainWindow::on_actionAbout_triggered() { About ab(this); ab.exec(); } void MainWindow::on_name_textEdited(const QString& arg1) { this->name = arg1; } void MainWindow::on_surname_textEdited(const QString& arg1) { this->surname = arg1; } void MainWindow::on_comboBox_currentIndexChanged(int index) { if (index == 0) { ui->ChangeOwner->setDisabled(true); } else { ui->ChangeOwner->setDisabled(false); } } void MainWindow::on_ChangeOwner_clicked() { this->data = ("func1:name: " + this->name + ", surname: " + this->surname + "").toUtf8(); this->func = 1; SendRequest(); m_timer->start(); }