Files
2023-Webservices_And_Applic…/Applications/Qt-application_for_UDP_broadcast/mainwindow.cpp

259 lines
8.0 KiB
C++

#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<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(&copyAction);
//execute menu
QAction * action = menu.exec(ui->devices->mapToGlobal(pos));
if(action == &copyAction){
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();
}