#include "mainwindow.h" #include "ui_mainwindow.h" #include "QUdpSocket" 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(); }