KD SOAP API Documentation  2.1
KDSoapClientThread.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Soap project.
4 **
5 ** SPDX-FileCopyrightText: 2010-2022 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: MIT
8 **
9 ****************************************************************************/
10 
11 #include "KDSoapClientInterface.h"
13 #include "KDSoapClientThread_p.h"
14 #include "KDSoapPendingCall.h"
16 #include "KDSoapPendingCall_p.h"
17 #include <QAuthenticator>
18 #include <QBuffer>
19 #include <QDebug>
20 #include <QEventLoop>
21 #include <QNetworkProxy>
22 #include <QNetworkRequest>
23 
25  : QThread(parent)
26  , m_stopThread(false)
27 {
28 }
29 
30 // Called by the main thread
32 {
33  // On hindsight, it would have been simpler to use signal/slots
34  // to communicate with secondary thread (turning this class
35  // into a simple QObject with a QThread internally)
36 
37  QMutexLocker locker(&m_mutex);
38  m_queue.append(taskData);
39  m_queueNotEmpty.wakeOne();
40 }
41 
43 {
44  QNetworkAccessManager accessManager;
45  // Use own QEventLoop so its slot quit() is executed in this thread
46  // (using QThread::exec/quit would try to call QThread::quit() in main thread,
47  // which is blocked on semaphore)
48  QEventLoop eventLoop;
49 
50  while (true) {
51  QMutexLocker locker(&m_mutex);
52  while (!m_stopThread && m_queue.isEmpty()) {
53  m_queueNotEmpty.wait(&m_mutex);
54  }
55  if (m_stopThread) {
56  break;
57  }
58  KDSoapThreadTaskData *taskData = m_queue.dequeue();
59  locker.unlock();
60 
61  KDSoapThreadTask task(taskData); // must be created here, so that it's in the right thread
62  connect(&task, &KDSoapThreadTask::taskDone, &eventLoop, &QEventLoop::quit);
63  connect(&accessManager, &QNetworkAccessManager::authenticationRequired, &task, &KDSoapThreadTask::slotAuthenticationRequired);
64  task.process(accessManager);
65 
66  // Process events until the task tells us the handling of that task is finished
67  eventLoop.exec();
68  }
69 }
70 
71 void KDSoapThreadTask::process(QNetworkAccessManager &accessManager)
72 {
73  // Can't use m_iface->asyncCall, it would use the accessmanager from the main thread
74  // KDSoapPendingCall pendingCall = m_iface->asyncCall(m_method, m_message, m_action);
75 
76  // Headers should be always qualified
77  for (KDSoapMessage &header : m_data->m_headers) {
78  header.setQualified(true);
79  }
80 
81  QNetworkCookieJar *jar = m_data->m_iface->d->accessManager()->cookieJar();
82  accessManager.setCookieJar(jar);
83 
84  accessManager.setProxy(m_data->m_iface->d->accessManager()->proxy());
85 
86  QBuffer *buffer = m_data->m_iface->d->prepareRequestBuffer(m_data->m_method,
87  m_data->m_message,
88  m_data->m_action,
89  m_data->m_headers);
90  QNetworkRequest request = m_data->m_iface->d->prepareRequest(m_data->m_method, m_data->m_action);
91  QNetworkReply *reply = accessManager.post(request, buffer);
92  m_data->m_iface->d->setupReply(reply);
93  maybeDebugRequest(buffer->data(), reply->request(), reply);
94  KDSoapPendingCall pendingCall(reply, buffer);
95  pendingCall.d->soapVersion = m_data->m_iface->d->m_version;
96 
97  KDSoapPendingCallWatcher *watcher = new KDSoapPendingCallWatcher(pendingCall, this);
98  connect(watcher, &KDSoapPendingCallWatcher::finished, this, &KDSoapThreadTask::slotFinished);
99 }
100 
101 void KDSoapThreadTask::slotFinished(KDSoapPendingCallWatcher *watcher)
102 {
103  m_data->m_response = watcher->returnMessage();
104  m_data->m_responseHeaders = watcher->returnHeaders();
105  m_data->m_semaphore.release();
106  // Helgrind bug: says this races with main thread. Looks like it's confused by QSharedDataPointer
107  // qDebug() << m_data->m_returnArguments.value();
108  watcher->deleteLater();
109 
110  emit taskDone();
111 }
112 
114 {
115  QMutexLocker locker(&m_mutex);
116  m_stopThread = true;
117  m_queueNotEmpty.wakeAll();
118 }
119 
120 void KDSoapThreadTask::slotAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
121 {
122  m_data->m_authentication.handleAuthenticationRequired(reply, authenticator);
123 }
void maybeDebugRequest(const QByteArray &data, const QNetworkRequest &request, QNetworkReply *reply)
void setupReply(QNetworkReply *reply)
QNetworkRequest prepareRequest(const QString &method, const QString &action)
QNetworkAccessManager * accessManager()
QBuffer * prepareRequestBuffer(const QString &method, const KDSoapMessage &message, const QString &soapAction, const KDSoapHeaders &headers)
KDSoapClientThread(QObject *parent=nullptr)
virtual void run() override
void enqueue(KDSoapThreadTaskData *taskData)
void finished(KDSoapPendingCallWatcher *self)
KDSoapHeaders returnHeaders() const
KDSoapMessage returnMessage() const
KDSoapAuthentication m_authentication
KDSoapHeaders m_responseHeaders
KDSoapClientInterface * m_iface
void slotAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
void process(QNetworkAccessManager &accessManager)
void setQualified(bool qualified)

© 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