KD SOAP API Documentation  2.1
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-2022 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->socketIPv4 = new QUdpSocket(this);
35  connect(d->socketIPv4, &QIODevice::readyRead, d, &KDSoapUdpClientPrivate::readyRead);
36  d->socketIPv6 = new QUdpSocket(this);
37  connect(d->socketIPv6, &QIODevice::readyRead, d, &KDSoapUdpClientPrivate::readyRead);
38 }
39 
41 {
42  delete d_ptr;
43 }
44 
45 bool KDSoapUdpClient::bind(quint16 port, QAbstractSocket::BindMode mode)
46 {
47  Q_D(KDSoapUdpClient);
48  const QHostAddress AnyIPv4(QLatin1String("0.0.0.0"));
49  bool rc = true;
50  // Workaround for lack of dual stack sockets in Qt4
51  // Qt5 supports binding to QHostAddress::Any, which will listen on both IPv4 and IPv6 interfaces.
52  // TODO: use a single socket now that we dropped Qt4 support
53  rc = d->socketIPv4->bind(AnyIPv4, port, mode) && rc;
54  rc = d->socketIPv6->bind(QHostAddress::AnyIPv6, port, mode) && rc;
55  return rc;
56 }
57 
59 {
60  Q_D(KDSoapUdpClient);
61  d->soapVersion = version;
62 }
63 
64 bool KDSoapUdpClient::sendMessage(const KDSoapMessage &message, const KDSoapHeaders &headers, const QHostAddress &address, quint16 port)
65 {
66  Q_D(KDSoapUdpClient);
67  KDSoapMessageWriter msgWriter;
68  msgWriter.setVersion(d->soapVersion);
69  const QByteArray data = msgWriter.messageToXml(message, QString(), headers, QMap<QString, KDSoapMessage>());
70 
71  if (isMulticastAddress(address)) {
72  bool anySuccess = false;
73  const auto &allInterfaces = QNetworkInterface::allInterfaces();
74  for (const auto &iface : allInterfaces) {
75  if (iface.flags().testFlag(QNetworkInterface::IsUp) && iface.flags().testFlag(QNetworkInterface::CanMulticast)) {
76  // qDebug() << "Sending multicast to" << iface.name() << address << ":" << data;
77  if (address.protocol() == QAbstractSocket::IPv4Protocol) {
78  d->socketIPv4->setMulticastInterface(iface);
79  qint64 writtenSize = d->socketIPv4->writeDatagram(data, address, port);
80  anySuccess = anySuccess || (writtenSize == data.size());
81  } else if (address.protocol() == QAbstractSocket::IPv6Protocol) {
82  d->socketIPv6->setMulticastInterface(iface);
83  qint64 writtenSize = d->socketIPv6->writeDatagram(data, address, port);
84  anySuccess = anySuccess || (writtenSize == data.size());
85  }
86  }
87  }
88  return anySuccess;
89  } else {
90  // qDebug() << "Sending to" << address << ":" << data;
91  if (address.protocol() == QAbstractSocket::IPv4Protocol) {
92  qint64 writtenSize = d->socketIPv4->writeDatagram(data, address, port);
93  return writtenSize == data.size();
94  } else if (address.protocol() == QAbstractSocket::IPv6Protocol) {
95  qint64 writtenSize = d->socketIPv6->writeDatagram(data, address, port);
96  return writtenSize == data.size();
97  }
98  }
99  return false;
100 }
101 
103 {
104  QUdpSocket *socket = qobject_cast<QUdpSocket *>(sender());
105  while (socket->hasPendingDatagrams()) {
106  qint64 size = socket->pendingDatagramSize();
107 
108  QByteArray buffer;
109  buffer.resize(size);
110  QHostAddress senderAddress;
111  quint16 senderPort;
112  socket->readDatagram(buffer.data(), buffer.size(), &senderAddress, &senderPort);
113 
114  receivedDatagram(buffer, senderAddress, senderPort);
115  }
116 }
117 
118 void KDSoapUdpClientPrivate::receivedDatagram(const QByteArray &messageData, const QHostAddress &senderAddress, quint16 senderPort)
119 {
120  Q_Q(KDSoapUdpClient);
121  // qDebug() << "Received datagram from:" << senderAddress << "data:" << QString::fromUtf8(messageData);
122 
123  KDSoapMessage replyMessage;
124  KDSoapHeaders replyHeaders;
125 
126  KDSoapMessageReader reader;
127  reader.xmlToMessage(messageData, &replyMessage, 0, &replyHeaders, soapVersion);
128 
129  emit q->receivedMessage(replyMessage, replyHeaders, senderAddress, senderPort);
130 }
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-2022 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 on Tue Jun 13 2023 12:18:34 for KD SOAP API Documentation by doxygen 1.9.1