230 lines
8.0 KiB
C++
230 lines
8.0 KiB
C++
#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<QNetworkInterface> NICs = QNetworkInterface::allInterfaces();
|
|
foreach (QNetworkInterface NIC, NICs) {
|
|
// Get all the adresses on this NIC
|
|
QList<QNetworkAddressEntry> 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();
|
|
}
|