KD SOAP API Documentation: KDSoapServer.cpp Source File

| KD SOAP API Documentation 2.2

Loading...
Searching...
No Matches
KDSoapServer.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 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6**
7** SPDX-License-Identifier: MIT
8**
9****************************************************************************/
10#include "KDSoapServer.h"
11#include "KDSoapSocketList_p.h"
12#include "KDSoapThreadPool.h"
13#include <QFile>
14#include <QMutex>
15#ifdef Q_OS_UNIX
16#include <errno.h>
17#include <limits.h>
18#include <sys/resource.h>
19#include <sys/time.h>
20#endif
21
22class KDSoapServer::Private
23{
24public:
25 Private()
26 : m_threadPool(nullptr)
27 , m_mainThreadSocketList(nullptr)
28 , m_use(KDSoapMessage::LiteralUse)
29 , m_logLevel(KDSoapServer::LogNothing)
30 , m_path(QString::fromLatin1("/"))
31 , m_maxConnections(-1)
32 , m_portBeforeSuspend(0)
33 {
34 }
35
36 ~Private()
37 {
38 delete m_mainThreadSocketList;
39 }
40
41 KDSoapThreadPool *m_threadPool;
42 KDSoapSocketList *m_mainThreadSocketList;
43 KDSoapMessage::Use m_use;
44 KDSoapServer::Features m_features;
45
46 QMutex m_logMutex;
47 KDSoapServer::LogLevel m_logLevel;
48 QString m_logFileName;
49 QFile m_logFile;
50
51 QMutex m_serverDataMutex;
52 QString m_wsdlFile;
53 QString m_wsdlPathInUrl;
54 QString m_path;
55 int m_maxConnections;
56
57 QHostAddress m_addressBeforeSuspend;
58 quint16 m_portBeforeSuspend;
59
60#ifndef QT_NO_SSL
61 QSslConfiguration m_sslConfiguration;
62#endif
63};
64
65KDSoapServer::KDSoapServer(QObject *parent)
66 : QTcpServer(parent)
67 , d(new KDSoapServer::Private)
68{
69 // Probably not very useful since we handle them immediately, but cannot hurt.
70 setMaxPendingConnections(1000);
71}
72
73KDSoapServer::~KDSoapServer()
74{
75 delete d;
76}
77
78 void KDSoapServer::incomingConnection(qintptr socketDescriptor)
79{
80 const int max = maxConnections();
81 const int numSockets = numConnectedSockets();
82 if (max > -1 && numSockets >= max) {
83 emit connectionRejected();
84 log(QByteArray("ERROR Too many connections (") + QByteArray::number(numSockets) + "), incoming connection rejected\n");
85 } else if (d->m_threadPool) {
86 // qDebug() << "incomingConnection: using thread pool";
87 d->m_threadPool->handleIncomingConnection(socketDescriptor, this);
88 } else {
89 // qDebug() << "incomingConnection: using main-thread socketlist";
90 if (!d->m_mainThreadSocketList) {
91 d->m_mainThreadSocketList = new KDSoapSocketList(this /*server*/);
92 }
93 d->m_mainThreadSocketList->handleIncomingConnection(socketDescriptor);
94 }
95}
96
97 int KDSoapServer::numConnectedSockets() const
98{
99 if (d->m_threadPool) {
100 return d->m_threadPool->numConnectedSockets(this);
101 } else if (d->m_mainThreadSocketList) {
102 return d->m_mainThreadSocketList->socketCount();
103 } else {
104 return 0;
105 }
106}
107
108 int KDSoapServer::totalConnectionCount() const
109{
110 if (d->m_threadPool) {
111 return d->m_threadPool->totalConnectionCount(this);
112 } else if (d->m_mainThreadSocketList) {
113 return d->m_mainThreadSocketList->totalConnectionCount();
114 } else {
115 return 0;
116 }
117}
118
119 void KDSoapServer::resetTotalConnectionCount()
120{
121 if (d->m_threadPool) {
122 d->m_threadPool->resetTotalConnectionCount(this);
123 } else if (d->m_mainThreadSocketList) {
124 d->m_mainThreadSocketList->resetTotalConnectionCount();
125 }
126}
127
128 void KDSoapServer::setThreadPool(KDSoapThreadPool *threadPool)
129{
130 d->m_threadPool = threadPool;
131}
132
133 KDSoapThreadPool *KDSoapServer::threadPool() const
134{
135 return d->m_threadPool;
136}
137
138 QString KDSoapServer::endPoint() const
139{
140 QMutexLocker lock(&d->m_serverDataMutex);
141 const QHostAddress address = serverAddress();
142 if (address == QHostAddress::Null) {
143 return QString();
144 }
145 const QString addressStr = address == QHostAddress::Any ? QString::fromLatin1("127.0.0.1") : address.toString();
146 return QString::fromLatin1("%1://%2:%3%4")
147 .arg(QString::fromLatin1((d->m_features & Ssl) ? "https" : "http"), addressStr)
148 .arg(serverPort())
149 .arg(d->m_path);
150}
151
152 void KDSoapServer::setUse(KDSoapMessage::Use use)
153{
154 d->m_use = use;
155}
156
157 KDSoapMessage::Use KDSoapServer::use() const
158{
159 return d->m_use;
160}
161
162 void KDSoapServer::setLogLevel(KDSoapServer::LogLevel level)
163{
164 QMutexLocker lock(&d->m_logMutex);
165 d->m_logLevel = level;
166}
167
168 KDSoapServer::LogLevel KDSoapServer::logLevel() const
169{
170 QMutexLocker lock(&d->m_logMutex);
171 return d->m_logLevel;
172}
173
174 void KDSoapServer::setLogFileName(const QString &fileName)
175{
176 QMutexLocker lock(&d->m_logMutex);
177 d->m_logFileName = fileName;
178}
179
180 QString KDSoapServer::logFileName() const
181{
182 QMutexLocker lock(&d->m_logMutex);
183 return d->m_logFileName;
184}
185
186void KDSoapServer::log(const QByteArray &text)
187{
188 if (d->m_logLevel == KDSoapServer::LogNothing) {
189 return;
190 }
191
192 QMutexLocker lock(&d->m_logMutex);
193 if (d->m_logFileName.isEmpty()) {
194 return;
195 }
196 if (!d->m_logFile.isOpen()) {
197 d->m_logFile.setFileName(d->m_logFileName);
198 if (!d->m_logFile.open(QIODevice::Append)) {
199 qCritical("Could not open log file for writing: %s", qPrintable(d->m_logFileName));
200 d->m_logFileName.clear(); // don't retry every time log() is called
201 return;
202 }
203 }
204 d->m_logFile.write(text);
205}
206
207 void KDSoapServer::flushLogFile()
208{
209 if (d->m_logFile.isOpen()) {
210 d->m_logFile.flush();
211 }
212}
213
214 void KDSoapServer::closeLogFile()
215{
216 if (d->m_logFile.isOpen()) {
217 d->m_logFile.close();
218 }
219}
220
221 bool KDSoapServer::setExpectedSocketCount(int sockets)
222{
223 // I hit a system limit when trying to connect more than 1024 sockets in the same process.
224 // strace said: socket(PF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = -1 EMFILE (Too many open files)
225 // Solution: ulimit -n 4096
226 // Or in C code, below.
227
228#ifdef Q_OS_UNIX
229 struct rlimit lim;
230 if (getrlimit(RLIMIT_NOFILE, &lim) != 0) {
231 qDebug() << "error calling getrlimit:" << strerror(errno);
232 return false;
233 }
234 bool changingHardLimit = false;
235 if (sockets > -1) {
236 qDebug() << "Current limit" << lim.rlim_cur << lim.rlim_max;
237 sockets += 20; // we need some file descriptors too
238 if (rlim_t(sockets) <= lim.rlim_cur) {
239 return true; // nothing to do
240 }
241
242 if (rlim_t(sockets) > lim.rlim_max) {
243 // Seems we need to run as root then
244 lim.rlim_max = sockets;
245 qDebug() << "Setting rlim_max to" << sockets;
246 changingHardLimit = true;
247 }
248 }
249#ifdef OPEN_MAX
250 // Mac OSX: setrlimit() no longer accepts "rlim_cur = RLIM_INFINITY" for RLIM_NOFILE. Use "rlim_cur = min(OPEN_MAX, rlim_max)".
251 lim.rlim_cur = qMin(rlim_t(OPEN_MAX), lim.rlim_max);
252#else
253 // Linux: does not define OPEN_MAX anymore, since it's "configurable at runtime".
254 lim.rlim_cur = lim.rlim_max;
255#endif
256 if (setrlimit(RLIMIT_NOFILE, &lim) == 0) {
257 qDebug() << "limit set to" << lim.rlim_cur;
258 } else {
259 if (changingHardLimit) {
260 qDebug() << "WARNING: hard limit is not high enough";
261 }
262 qDebug() << "error calling setrlimit(" << lim.rlim_cur << "," << lim.rlim_max << ") :" << strerror(errno);
263 return false;
264 }
265#else
266 Q_UNUSED(sockets);
267#endif
268 return true;
269}
270
271 void KDSoapServer::suspend()
272{
273 d->m_portBeforeSuspend = serverPort();
274 d->m_addressBeforeSuspend = serverAddress();
275 close();
276
277 // Disconnect connected sockets, otherwise they could still make calls
278 if (d->m_threadPool) {
279 d->m_threadPool->disconnectSockets(this);
280 } else if (d->m_mainThreadSocketList) {
281 d->m_mainThreadSocketList->disconnectAll();
282 }
283}
284
285 void KDSoapServer::resume()
286{
287 if (d->m_portBeforeSuspend == 0) {
288 qWarning("KDSoapServer: resume() called without calling suspend() first");
289 } else {
290 if (!listen(d->m_addressBeforeSuspend, d->m_portBeforeSuspend)) {
291 qWarning("KDSoapServer: failed to listen on %s port %d", qPrintable(d->m_addressBeforeSuspend.toString()), d->m_portBeforeSuspend);
292 }
293 d->m_portBeforeSuspend = 0;
294 }
295}
296
297 void KDSoapServer::setWsdlFile(const QString &file, const QString &pathInUrl)
298{
299 QMutexLocker lock(&d->m_serverDataMutex);
300 d->m_wsdlFile = file;
301 d->m_wsdlPathInUrl = pathInUrl;
302}
303
304 QString KDSoapServer::wsdlFile() const
305{
306 QMutexLocker lock(&d->m_serverDataMutex);
307 return d->m_wsdlFile;
308}
309
310 QString KDSoapServer::wsdlPathInUrl() const
311{
312 QMutexLocker lock(&d->m_serverDataMutex);
313 return d->m_wsdlPathInUrl;
314}
315
316 void KDSoapServer::setPath(const QString &path)
317{
318 QMutexLocker lock(&d->m_serverDataMutex);
319 d->m_path = path;
320}
321
322 QString KDSoapServer::path() const
323{
324 QMutexLocker lock(&d->m_serverDataMutex);
325 return d->m_path;
326}
327
328 void KDSoapServer::setMaxConnections(int sockets)
329{
330 QMutexLocker lock(&d->m_serverDataMutex);
331 d->m_maxConnections = sockets;
332}
333
334 int KDSoapServer::maxConnections() const
335{
336 QMutexLocker lock(&d->m_serverDataMutex);
337 return d->m_maxConnections;
338}
339
340 void KDSoapServer::setFeatures(Features features)
341{
342 QMutexLocker lock(&d->m_serverDataMutex);
343 d->m_features = features;
344}
345
346KDSoapServer::Features KDSoapServer::features() const
347{
348 QMutexLocker lock(&d->m_serverDataMutex);
349 return d->m_features;
350}
351
352#ifndef QT_NO_SSL
353 QSslConfiguration KDSoapServer::sslConfiguration() const
354{
355 return d->m_sslConfiguration;
356}
357
358 void KDSoapServer::setSslConfiguration(const QSslConfiguration &config)
359{
360 d->m_sslConfiguration = config;
361}
362#endif
363
364#include "moc_KDSoapServer.cpp"
KDSoapServer.h
KDSoapSocketList_p.h
KDSoapThreadPool.h
KDSoapMessage
Definition KDSoapMessage.h:29
KDSoapServer
Definition KDSoapServer.h:30
KDSoapServer::numConnectedSockets
int numConnectedSockets() const
Definition KDSoapServer.cpp:97
KDSoapServer::threadPool
KDSoapThreadPool * threadPool() const
Definition KDSoapServer.cpp:133
KDSoapServer::setPath
void setPath(const QString &path)
Definition KDSoapServer.cpp:316
KDSoapServer::setLogFileName
void setLogFileName(const QString &fileName)
Definition KDSoapServer.cpp:174
KDSoapServer::maxConnections
int maxConnections() const
Definition KDSoapServer.cpp:334
KDSoapServer::~KDSoapServer
~KDSoapServer()
Definition KDSoapServer.cpp:73
KDSoapServer::connectionRejected
void connectionRejected()
KDSoapServer::setExpectedSocketCount
static bool setExpectedSocketCount(int sockets)
Definition KDSoapServer.cpp:221
KDSoapServer::setSslConfiguration
void setSslConfiguration(const QSslConfiguration &config)
Definition KDSoapServer.cpp:358
KDSoapServer::setUse
void setUse(KDSoapMessage::Use use)
Definition KDSoapServer.cpp:152
KDSoapServer::KDSoapServer
KDSoapServer(QObject *parent=0)
Definition KDSoapServer.cpp:65
KDSoapServer::use
KDSoapMessage::Use use() const
Definition KDSoapServer.cpp:157
KDSoapServer::setWsdlFile
void setWsdlFile(const QString &file, const QString &pathInUrl)
Definition KDSoapServer.cpp:297
KDSoapServer::LogLevel
LogLevel
Definition KDSoapServer.h:125
KDSoapServer::LogNothing
@ LogNothing
Definition KDSoapServer.h:126
KDSoapServer::resume
void resume()
Definition KDSoapServer.cpp:285
KDSoapServer::Ssl
@ Ssl
HTTPS.
Definition KDSoapServer.h:49
KDSoapServer::incomingConnection
void incomingConnection(qintptr socketDescriptor) override
Definition KDSoapServer.cpp:78
KDSoapServer::sslConfiguration
QSslConfiguration sslConfiguration() const
Definition KDSoapServer.cpp:353
KDSoapServer::setMaxConnections
void setMaxConnections(int sockets)
Definition KDSoapServer.cpp:328
KDSoapServer::wsdlFile
QString wsdlFile() const
Definition KDSoapServer.cpp:304
KDSoapServer::setThreadPool
void setThreadPool(KDSoapThreadPool *threadPool)
Definition KDSoapServer.cpp:128
KDSoapServer::logFileName
QString logFileName() const
Definition KDSoapServer.cpp:180
KDSoapServer::resetTotalConnectionCount
void resetTotalConnectionCount()
Definition KDSoapServer.cpp:119
KDSoapServer::wsdlPathInUrl
QString wsdlPathInUrl() const
Definition KDSoapServer.cpp:310
KDSoapServer::setFeatures
void setFeatures(Features features)
Definition KDSoapServer.cpp:340
KDSoapServer::flushLogFile
void flushLogFile()
Definition KDSoapServer.cpp:207
KDSoapServer::endPoint
QString endPoint() const
Definition KDSoapServer.cpp:138
KDSoapServer::suspend
void suspend()
Definition KDSoapServer.cpp:271
KDSoapServer::logLevel
LogLevel logLevel() const
Definition KDSoapServer.cpp:168
KDSoapServer::path
QString path() const
Definition KDSoapServer.cpp:322
KDSoapServer::features
Features features() const
Definition KDSoapServer.cpp:346
KDSoapServer::totalConnectionCount
int totalConnectionCount() const
Definition KDSoapServer.cpp:108
KDSoapServer::closeLogFile
void closeLogFile()
Definition KDSoapServer.cpp:214
KDSoapServer::setLogLevel
void setLogLevel(LogLevel level)
Definition KDSoapServer.cpp:162
KDSoapSocketList
Definition KDSoapSocketList_p.h:23
KDSoapThreadPool
Definition KDSoapThreadPool.h:27
KDSoapValue::Use
Use
Definition KDSoapValue.h:266
QByteArray
QByteArray::number
QByteArray number(int n, int base)
QFile
QHostAddress
QHostAddress::Null
Null
QHostAddress::toString
QString toString() const const
QIODevice::Append
Append
QMutex
QMutexLocker
QObject
QObject::qobject_cast
T qobject_cast(QObject *object)
QSslConfiguration
QString
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QTcpServer
QTcpServer::close
void close()
QTcpServer::listen
bool listen(const QHostAddress &address, quint16 port)
QTcpServer::serverAddress
QHostAddress serverAddress() const const
QTcpServer::serverPort
quint16 serverPort() const const
QTcpServer::setMaxPendingConnections
void setMaxPendingConnections(int numConnections)
QTcpServer::socketDescriptor
qintptr socketDescriptor() const const

© 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 on Sun Jan 7 2024 11:47:36 for KD SOAP API Documentation by doxygen 1.9.8