KD SOAP API Documentation 2.1
Loading...
Searching...
No Matches
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-2023 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"
17#include <QNetworkInterface>
18
19static 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{
34 d->socketIPv4 = new QUdpSocket(this);
36 d->socketIPv6 = new QUdpSocket(this);
38}
39
41{
42 delete d_ptr;
43}
44
46{
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{
61 d->soapVersion = version;
62}
63
64bool KDSoapUdpClient::sendMessage(const KDSoapMessage &message, const KDSoapHeaders &headers, const QHostAddress &address, quint16 port)
65{
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{
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
118void KDSoapUdpClientPrivate::receivedDatagram(const QByteArray &messageData, const QHostAddress &senderAddress, quint16 senderPort)
119{
121 // qDebug() << "Received datagram from:" << senderAddress << "data:" << QString::fromUtf8(messageData);
122
123 KDSoapMessage replyMessage;
124 KDSoapHeaders replyHeaders;
125
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
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)
char * data()
void resize(int size)
int size() const const
bool isInSubnet(const QHostAddress &subnet, int netmask) const const
QAbstractSocket::NetworkLayerProtocol protocol() const const
void readyRead()
QList< QNetworkInterface > allInterfaces()
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
QObject * sender() const const
bool hasPendingDatagrams() const const
qint64 pendingDatagramSize() const const
qint64 readDatagram(char *data, qint64 maxSize, QHostAddress *address, quint16 *port)

© 2010-2023 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 Dec 26 2023 00:00:25 for KD SOAP API Documentation by doxygen 1.9.8