KD SOAP API Documentation  2.2
KDSoapUdpClient.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Soap project.
4 **
5 ** SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: MIT
8 **
9 ****************************************************************************/
10 
11 #include "KDSoapUdpClient.h"
12 #include "KDSoapUdpClient_p.h"
13 
14 #include "KDSoapMessage.h"
15 #include "KDSoapMessageReader_p.h"
16 #include "KDSoapMessageWriter_p.h"
17 #include <QNetworkInterface>
18 
19 static bool isMulticastAddress(const QHostAddress &address)
20 {
21  if (address.protocol() == QAbstractSocket::IPv4Protocol) {
22  return address.isInSubnet(QHostAddress(QLatin1String("224.0.0.0")), 4);
23  } else if (address.protocol() == QAbstractSocket::IPv6Protocol) {
24  return address.isInSubnet(QHostAddress(QLatin1String("ff00::")), 8);
25  }
26  return false;
27 }
28 
30  : QObject(parent)
31  , d_ptr(new KDSoapUdpClientPrivate(this))
32 {
33  Q_D(KDSoapUdpClient);
34  d->socket = new QUdpSocket(this);
35  connect(d->socket, &QIODevice::readyRead, d, &KDSoapUdpClientPrivate::readyRead);
36 }
37 
39 {
40  delete d_ptr;
41 }
42 
43 bool KDSoapUdpClient::bind(quint16 port, QAbstractSocket::BindMode mode)
44 {
45  Q_D(KDSoapUdpClient);
46  const bool rc = d->socket->bind(QHostAddress::Any, port, mode);
47  if (!rc) {
48  qWarning() << "KDSoapUdpClient: failed to bind on port" << port << "mode" << mode << ":" << d->socket->errorString();
49  }
50  return rc;
51 }
52 
54 {
55  Q_D(KDSoapUdpClient);
56  d->soapVersion = version;
57 }
58 
59 bool KDSoapUdpClient::sendMessage(const KDSoapMessage &message, const KDSoapHeaders &headers, const QHostAddress &address, quint16 port)
60 {
61  Q_D(KDSoapUdpClient);
62  KDSoapMessageWriter msgWriter;
63  msgWriter.setVersion(d->soapVersion);
64  const QByteArray data = msgWriter.messageToXml(message, QString(), headers, QMap<QString, KDSoapMessage>());
65 
66  if (isMulticastAddress(address)) {
67  bool anySuccess = false;
68  const auto &allInterfaces = QNetworkInterface::allInterfaces();
69  for (const auto &iface : allInterfaces) {
70  if (iface.flags().testFlag(QNetworkInterface::IsUp) && iface.flags().testFlag(QNetworkInterface::CanMulticast)) {
71  // qDebug() << "Sending multicast to" << iface.name() << address << ":" << data;
72  d->socket->setMulticastInterface(iface);
73  const qint64 writtenSize = d->socket->writeDatagram(data, address, port);
74  anySuccess = anySuccess || (writtenSize == data.size());
75  }
76  }
77  return anySuccess;
78  } else {
79  // qDebug() << "Sending to" << address << ":" << data;
80  const qint64 writtenSize = d->socket->writeDatagram(data, address, port);
81  return writtenSize == data.size();
82  }
83 }
84 
86 {
87  QUdpSocket *socket = qobject_cast<QUdpSocket *>(sender());
88  while (socket->hasPendingDatagrams()) {
89  qint64 size = socket->pendingDatagramSize();
90 
91  QByteArray buffer;
92  buffer.resize(size);
93  QHostAddress senderAddress;
94  quint16 senderPort;
95  socket->readDatagram(buffer.data(), buffer.size(), &senderAddress, &senderPort);
96 
97  receivedDatagram(buffer, senderAddress, senderPort);
98  }
99 }
100 
101 void KDSoapUdpClientPrivate::receivedDatagram(const QByteArray &messageData, const QHostAddress &senderAddress, quint16 senderPort)
102 {
103  Q_Q(KDSoapUdpClient);
104  // qDebug() << "Received datagram from:" << senderAddress << "data:" << QString::fromUtf8(messageData);
105 
106  KDSoapMessage replyMessage;
107  KDSoapHeaders replyHeaders;
108 
109  KDSoapMessageReader reader;
110  reader.xmlToMessage(messageData, &replyMessage, 0, &replyHeaders, soapVersion);
111 
112  emit q->receivedMessage(replyMessage, replyHeaders, senderAddress, senderPort);
113 }
static bool isMulticastAddress(const QHostAddress &address)
XmlError xmlToMessage(const QByteArray &data, KDSoapMessage *pParsedMessage, QString *pMessageNamespace, KDSoapHeaders *pRequestHeaders, KDSoap::SoapVersion soapVersion) const
QByteArray messageToXml(const KDSoapMessage &message, const QString &method, const KDSoapHeaders &headers, const QMap< QString, KDSoapMessage > &persistentHeaders, const KDSoapAuthentication &authentication=KDSoapAuthentication()) const
void setVersion(KDSoap::SoapVersion version)
KDSoap::SoapVersion soapVersion
void receivedDatagram(const QByteArray &messageData, const QHostAddress &senderAddress, quint16 senderPort)
KDSoapUdpClient provides an interface for implementing a SOAP-over-UDP client.
void setSoapVersion(KDSoap::SoapVersion version)
bool bind(quint16 port=0, QAbstractSocket::BindMode mode=QAbstractSocket::DefaultForPlatform)
bool sendMessage(const KDSoapMessage &message, const KDSoapHeaders &headers, const QHostAddress &address, quint16 port)
KDSoapUdpClient(QObject *parent=nullptr)

© 2010-2024 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-soap/
Generated by doxygen 1.9.1