2019-12-01 22:27:00 +03:00
|
|
|
#include "ippdiscovery.h"
|
|
|
|
#define A 1
|
|
|
|
#define PTR 12
|
|
|
|
#define TXT 16
|
|
|
|
#define AAAA 28
|
|
|
|
#define SRV 33
|
|
|
|
|
2020-01-02 23:05:04 +03:00
|
|
|
#define ALL 255 //for querying
|
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
void put_addr(Bytestream& bts, QStringList addr)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < addr.length(); i++)
|
|
|
|
{
|
|
|
|
QString elem = addr[i];
|
|
|
|
bts << (quint8)elem.size() << elem.toStdString();
|
|
|
|
}
|
|
|
|
bts << (quint8)0;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList get_addr(Bytestream& bts)
|
|
|
|
{
|
|
|
|
QStringList addr;
|
|
|
|
while(true)
|
|
|
|
{
|
|
|
|
if(bts.nextU8(0))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if ((bts.peekU8()&0xc0)==0xc0)
|
|
|
|
{
|
|
|
|
quint16 ref = bts.getU16() & 0x0fff;
|
|
|
|
Bytestream tmp = bts;
|
|
|
|
tmp.setPos(ref);
|
|
|
|
addr += get_addr(tmp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string elem;
|
|
|
|
bts/bts.getU8() >> elem;
|
|
|
|
addr.append(QString(elem.c_str()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
IppDiscovery::IppDiscovery() : QStringListModel()
|
|
|
|
{
|
|
|
|
socket = new QUdpSocket(this);
|
|
|
|
connect(socket, SIGNAL(readyRead()),
|
|
|
|
this, SLOT(readPendingDatagrams()));
|
|
|
|
connect(this, SIGNAL(favouritesChanged()),
|
|
|
|
this, SLOT(update()));
|
|
|
|
}
|
|
|
|
|
|
|
|
IppDiscovery::~IppDiscovery() {
|
|
|
|
delete socket;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IppDiscovery::discover() {
|
2020-01-02 23:05:04 +03:00
|
|
|
sendQuery(PTR, {"_ipp","_tcp","local"});
|
|
|
|
}
|
|
|
|
|
2020-01-02 23:28:35 +03:00
|
|
|
void IppDiscovery::reset() {
|
|
|
|
_ipp = QStringList();
|
|
|
|
_rps = QMap<QString,QString>();
|
|
|
|
_ports = QMap<QString,quint16>();
|
|
|
|
_targets = QMap<QString,QString>();
|
|
|
|
|
|
|
|
_AAs = QMultiMap<QString,QString>();
|
|
|
|
_AAAAs = QMultiMap<QString,QString>();
|
|
|
|
|
|
|
|
discover();
|
|
|
|
}
|
|
|
|
|
2020-01-02 23:05:04 +03:00
|
|
|
void IppDiscovery::sendQuery(quint16 qtype, QStringList addr) {
|
|
|
|
qDebug() << "discovering" << qtype << addr;
|
2019-12-01 22:27:00 +03:00
|
|
|
|
|
|
|
Bytestream query;
|
|
|
|
quint16 transactionid = 0;
|
|
|
|
quint16 flags = 0;
|
|
|
|
quint16 questions = 1;
|
|
|
|
|
|
|
|
query << transactionid << flags << questions << (quint16)0 << (quint16)0 << (quint16)0;
|
2020-01-02 23:05:04 +03:00
|
|
|
put_addr(query, addr);
|
|
|
|
query << qtype << (quint16)0x0001;
|
2019-12-01 22:27:00 +03:00
|
|
|
|
|
|
|
QByteArray bytes((char*)(query.raw()), query.size());
|
|
|
|
socket->writeDatagram(bytes, QHostAddress("224.0.0.251"), 5353);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-01-02 23:05:04 +03:00
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
void IppDiscovery::update()
|
|
|
|
{
|
2020-01-02 23:28:35 +03:00
|
|
|
QStringList found;
|
|
|
|
|
2020-01-02 23:05:04 +03:00
|
|
|
for(QStringList::Iterator it = _ipp.begin(); it != _ipp.end(); it++)
|
|
|
|
{
|
|
|
|
quint16 port = _ports[*it];
|
|
|
|
QString target = _targets[*it];
|
|
|
|
QString rp = _rps[*it];
|
|
|
|
|
|
|
|
for(QMultiMap<QString,QString>::Iterator ait = _AAs.begin(); ait != _AAs.end(); ait++)
|
|
|
|
{
|
|
|
|
if(ait.key() == target)
|
|
|
|
{
|
|
|
|
QString ip = ait.value();
|
2020-01-03 18:36:24 +03:00
|
|
|
QString maybePort = port != 631 ? ":"+QString::number(port) : "";
|
|
|
|
QString addr = "ipp://"+ip+maybePort+"/"+rp;
|
2020-01-02 23:28:35 +03:00
|
|
|
if(!found.contains(addr))
|
2020-01-02 23:05:04 +03:00
|
|
|
{
|
2020-01-02 23:28:35 +03:00
|
|
|
found.append(addr);
|
|
|
|
found.sort(Qt::CaseInsensitive);
|
2020-01-02 23:05:04 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-02 23:28:35 +03:00
|
|
|
qDebug() << _favourites << found;
|
|
|
|
this->setStringList(_favourites+found);
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void IppDiscovery::readPendingDatagrams()
|
|
|
|
{
|
|
|
|
while (socket->hasPendingDatagrams()) {
|
|
|
|
|
|
|
|
size_t size = socket->pendingDatagramSize();
|
|
|
|
Bytestream resp(size);
|
|
|
|
QHostAddress sender;
|
|
|
|
quint16 senderPort;
|
|
|
|
|
2020-01-02 23:05:04 +03:00
|
|
|
QStringList ipp_ptrs;
|
2019-12-01 22:27:00 +03:00
|
|
|
|
|
|
|
socket->readDatagram((char*)(resp.raw()), size, &sender, &senderPort);
|
|
|
|
sender = QHostAddress(sender.toIPv4Address());
|
|
|
|
|
|
|
|
quint16 transactionid, flags, questions, answerRRs, authRRs, addRRs;
|
|
|
|
resp >> transactionid >> flags >> questions >> answerRRs >> authRRs >> addRRs;
|
|
|
|
|
|
|
|
for(quint16 i = 0; i < questions; i++)
|
|
|
|
{
|
|
|
|
quint16 qtype, qflags;
|
|
|
|
QString qaddr = get_addr(resp).join('.');
|
|
|
|
resp >> qtype >> qflags;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(quint16 i = 0; i < answerRRs; i++)
|
|
|
|
{
|
|
|
|
quint16 atype, aflags, len;
|
|
|
|
quint32 ttl;
|
|
|
|
|
|
|
|
QString aaddr = get_addr(resp).join('.');
|
|
|
|
resp >> atype >> aflags >> ttl >> len;
|
|
|
|
|
|
|
|
quint16 pos_before = resp.pos();
|
|
|
|
if (atype == PTR)
|
|
|
|
{
|
|
|
|
QString tmpname = get_addr(resp).join(".");
|
2020-01-02 23:05:04 +03:00
|
|
|
if(aaddr.endsWith("_ipp._tcp.local"))
|
|
|
|
{
|
|
|
|
ipp_ptrs.append(tmpname);
|
|
|
|
}
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
else if(atype == TXT)
|
|
|
|
{
|
|
|
|
Bytestream tmp;
|
|
|
|
while(resp.pos() < pos_before+len)
|
|
|
|
{
|
|
|
|
resp/resp.getU8() >> tmp;
|
|
|
|
if(tmp >>= "rp=")
|
|
|
|
{
|
|
|
|
std::string tmprp;
|
|
|
|
tmp/tmp.remaining() >> tmprp;
|
2020-01-02 23:05:04 +03:00
|
|
|
_rps[aaddr] = tmprp.c_str();
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (atype == SRV)
|
|
|
|
{
|
|
|
|
quint16 prio, w, port;
|
|
|
|
resp >> prio >> w >> port;
|
|
|
|
QString target = get_addr(resp).join(".");
|
2020-01-02 23:05:04 +03:00
|
|
|
_ports[aaddr] = port;
|
|
|
|
_targets[aaddr] = target;
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
else if(atype == A)
|
|
|
|
{
|
|
|
|
quint32 addr;
|
|
|
|
resp >> addr;
|
|
|
|
QHostAddress haddr(addr);
|
2020-01-02 23:05:04 +03:00
|
|
|
_AAs.insert(aaddr, haddr.toString());
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
resp += len;
|
|
|
|
}
|
|
|
|
Q_ASSERT(resp.pos() == pos_before+len);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-01-02 23:05:04 +03:00
|
|
|
qDebug() << "new ipp ptrs" << ipp_ptrs;
|
|
|
|
qDebug() << "ipp ptrs" << _ipp;
|
|
|
|
qDebug() << "rps" << _rps;
|
|
|
|
qDebug() << "ports" << _ports;
|
|
|
|
qDebug() << "targets" << _targets;
|
|
|
|
qDebug() << "AAs" << _AAs;
|
|
|
|
qDebug() << "AAAAs" << _AAAAs;
|
2019-12-19 22:12:19 +03:00
|
|
|
|
2020-01-02 23:05:04 +03:00
|
|
|
for(QStringList::Iterator it = ipp_ptrs.begin(); it != ipp_ptrs.end(); it++)
|
2019-12-01 22:27:00 +03:00
|
|
|
{
|
2020-01-02 23:05:04 +03:00
|
|
|
if(!_ipp.contains(*it))
|
2019-12-01 22:27:00 +03:00
|
|
|
{
|
2020-01-02 23:05:04 +03:00
|
|
|
_ipp.append(*it);
|
|
|
|
}
|
|
|
|
if(!_ports.contains(*it) || !_targets.contains(*it) || !_rps.contains(*it))
|
|
|
|
{ // if the PTR doesn't already resolve, ask for everything about it
|
|
|
|
sendQuery(ALL, it->split('.'));
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
}
|
2020-01-02 23:05:04 +03:00
|
|
|
|
2019-12-01 22:27:00 +03:00
|
|
|
}
|
|
|
|
this->update();
|
|
|
|
|
|
|
|
}
|