qt/ledset/pcapwin.cpp

166 lines
5.4 KiB
C++
Raw Normal View History

2022-08-25 18:43:03 +08:00
#include "pcapwin.h"
#include <QTextEdit>
#include <QPushButton>
#include <QMessageBox>
#include <QLabel>
#include <QDateTime>
#include <QRadioButton>
#include <QDebug>
2022-12-16 16:16:12 +08:00
PcapWin *PcapWin::newIns(QByteArray &name, QWidget *parent) {
if(name.isEmpty()) return 0;
char errbuf[PCAP_ERRBUF_SIZE]{'\0'};
auto pcapRe = pcap_open_live(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS, 50, errbuf);
if(pcapRe == 0) {
QMessageBox::critical(parent, "Error", QString(tr("打开网卡失败"))+errbuf);
return 0;
}
auto pcapSend = pcap_open_live(name.data(), 65536, 0, 50, errbuf);
if(pcapSend == 0) {
QMessageBox::critical(parent, "Error", QString(tr("打开网卡失败"))+errbuf);
return 0;
}
return new PcapWin(pcapRe, pcapSend, parent);
}
2022-08-25 18:43:03 +08:00
PcapWin::PcapWin(pcap_t *pcapRece, pcap_t *pcapSend, QWidget *parent) : BaseWin{parent}, pcap(pcapSend) {
setWindowModality(Qt::WindowModal);
setAttribute(Qt::WA_DeleteOnClose);
2022-12-16 15:08:53 +08:00
setWindowTitle(tr("网口通信"));
2022-08-25 18:43:03 +08:00
resize(1024, 720);
auto vBox = new QVBoxLayout(center);
vBox->setContentsMargins(0,0,0,0);
vBox->setSpacing(3);
vBox->addLayout(addBtns(new QHBoxLayout()));
auto fdReceive = new QTextEdit;
fdReceive->setFontFamily("Consolas");
fdReceive->setReadOnly(true);
2022-12-16 15:08:53 +08:00
fdReceive->document()->setMaximumBlockCount(200);
2022-08-25 18:43:03 +08:00
auto hBox = new QHBoxLayout;
{
auto vBox = new QVBoxLayout;
auto hBox2 = new QHBoxLayout;
2022-12-16 15:08:53 +08:00
hBox2->addWidget(new QLabel(tr("接收:")));
2022-08-25 18:43:03 +08:00
hBox2->addStretch();
2022-12-16 15:08:53 +08:00
auto fdStart = new QRadioButton(tr("开始"));
2022-08-25 18:43:03 +08:00
fdStart->setChecked(true);
connect(fdStart, &QPushButton::toggled, this, [this](bool checked) {
thd->status = checked ? 0 : 1;
});
hBox2->addWidget(fdStart);
hBox2->addSpacing(20);
2022-12-16 15:08:53 +08:00
auto fdEnd = new QRadioButton(tr("暂停"));
2022-08-25 18:43:03 +08:00
hBox2->addWidget(fdEnd);
hBox2->addStretch();
2022-12-16 15:08:53 +08:00
auto btnClear = new QPushButton(tr("清除"));
2022-08-25 18:43:03 +08:00
btnClear->setMinimumWidth(120);
connect(btnClear, &QPushButton::clicked, fdReceive, &QTextEdit::clear);
hBox2->addWidget(btnClear);
hBox2->addStretch();
vBox->addLayout(hBox2);
vBox->addWidget(fdReceive);
hBox->addLayout(vBox);
}
{
auto wgt = new QWidget;
wgt->setMaximumWidth(400);
auto vBox = new QVBoxLayout(wgt);
vBox->setContentsMargins(0,0,0,0);
vBox->setSpacing(3);
auto hBox2 = new QHBoxLayout;
hBox2->addStretch();
2022-12-16 15:08:53 +08:00
auto btnSend = new QPushButton(tr("发送"));
2022-08-25 18:43:03 +08:00
btnSend->setMinimumWidth(120);
hBox2->addWidget(btnSend);
hBox2->addStretch();
2022-12-16 15:08:53 +08:00
auto btnClear = new QPushButton(tr("清除"));
2022-08-25 18:43:03 +08:00
btnClear->setMinimumWidth(120);
hBox2->addWidget(btnClear);
hBox2->addStretch();
vBox->addLayout(hBox2);
auto fdSend = new QTextEdit;
fdSend->setFontFamily("Consolas");
vBox->addWidget(fdSend);
connect(btnSend, &QPushButton::clicked, this, [this, fdSend] {
auto text = fdSend->toPlainText();
auto len = text.size();
QByteArray bytes;
for(int i=0; i<len; i++) {
auto ch = text[i].toLatin1();
if((ch>='0' && ch<='9') || (ch>='A' && ch<='F') || (ch>='a' && ch<='f')) bytes.append(ch);
}
if(bytes.size() % 2) bytes.append('0');
bytes = QByteArray::fromHex(bytes);
if(pcap_sendpacket(pcap, (u_char*)bytes.data(), bytes.size())) {
2022-12-16 15:08:53 +08:00
QMessageBox::critical(this, "Error", QString(tr("发送失败: "))+pcap_geterr(pcap));
2022-08-25 18:43:03 +08:00
return;
}
});
connect(btnClear, &QPushButton::clicked, fdSend, &QTextEdit::clear);
hBox->addWidget(wgt);
}
vBox->addLayout(hBox);
thd = new PcapThread(pcapRece);
connect(thd, &PcapThread::onMsg, fdReceive, &QTextEdit::append);
thd->start();
}
PcapThread::PcapThread(pcap_t *pcap) : pcap(pcap) {
connect(this, &QThread::finished, this, &QThread::deleteLater);
}
void PcapThread::run() {
pcap_pkthdr *header;
const u_char *data;
int res;
while((res = pcap_next_ex(pcap, &header, &data)) >= 0) {
if(status==2) return;
if(status==1 || res == 0) continue; //超时
if(data[0]!=0x55 || data[1]!=0x55) continue;
QString data_str;
data_str.append(QDateTime::fromSecsSinceEpoch(header->ts.tv_sec).toString("yy-MM-dd HH:mm:ss.")+QString::number(header->ts.tv_usec));
data_str.append(" len:").append(QString::number(header->caplen)).append("/").append(QString::number(header->len)).append("\n");
char line[LINE_LEN + 1];
int l = 0;
for(uint i=0; i<header->caplen; i++) {
data_str.append(QString::asprintf("%.2x ", data[i]));
if(i > 13) {
if(isgraph(data[i]) || data[i] == ' ') line[l] = data[i];
else line[l] = '.';
if(l==15) {
line[16] = 0;
data_str.append(" ").append(line).append("\n");
l = 0;
} else l++;
} else if(i == 13) {
data_str.append("\n");
}
}
line[l] = 0;
data_str.append(" ").append(line).append("\n\n");
emit onMsg(data_str);
}
emit onError(pcap_geterr(pcap));
}