1 /*
2     SPDX-FileCopyrightText: 2015-2019 Krzysztof Nowicki <krissn@op.pl>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "fakeewsserver.h"
8 
9 #include "fakeewsconnection.h"
10 #include "fakeewsserver_debug.h"
11 #include <QRandomGenerator>
12 #include <QThread>
13 
14 const FakeEwsServer::DialogEntry::HttpResponse FakeEwsServer::EmptyResponse = {QString(), 0};
15 
FakeEwsServer(QObject * parent)16 FakeEwsServer::FakeEwsServer(QObject *parent)
17     : QTcpServer(parent)
18     , mPortNumber(0)
19 {
20 }
21 
~FakeEwsServer()22 FakeEwsServer::~FakeEwsServer()
23 {
24     qCInfoNC(EWSFAKE_LOG) << QStringLiteral("Stopping fake EWS server.");
25 }
26 
start()27 bool FakeEwsServer::start()
28 {
29     QMutexLocker lock(&mMutex);
30 
31     int retries = 3;
32     bool ok;
33     auto generator = QRandomGenerator::global();
34     do {
35         mPortNumber = (generator->bounded(10000)) + 10000;
36         qCInfoNC(EWSFAKE_LOG) << QStringLiteral("Starting fake EWS server at 127.0.0.1:%1").arg(mPortNumber);
37         ok = listen(QHostAddress::LocalHost, mPortNumber);
38         if (!ok) {
39             qCWarningNC(EWSFAKE_LOG) << QStringLiteral("Failed to start server");
40         }
41     } while (!ok && --retries);
42 
43     if (ok) {
44         connect(this, &QTcpServer::newConnection, this, &FakeEwsServer::newConnectionReceived);
45     }
46 
47     return ok;
48 }
49 
setDialog(const DialogEntry::List & dialog)50 void FakeEwsServer::setDialog(const DialogEntry::List &dialog)
51 {
52     QMutexLocker lock(&mMutex);
53 
54     mDialog = dialog;
55 }
56 
setDefaultReplyCallback(const DialogEntry::ReplyCallback & defaultReplyCallback)57 void FakeEwsServer::setDefaultReplyCallback(const DialogEntry::ReplyCallback &defaultReplyCallback)
58 {
59     QMutexLocker lock(&mMutex);
60 
61     mDefaultReplyCallback = defaultReplyCallback;
62 }
63 
setOverrideReplyCallback(const DialogEntry::ReplyCallback & overrideReplyCallback)64 void FakeEwsServer::setOverrideReplyCallback(const DialogEntry::ReplyCallback &overrideReplyCallback)
65 {
66     QMutexLocker lock(&mMutex);
67 
68     mOverrideReplyCallback = overrideReplyCallback;
69 }
70 
queueEventsXml(const QStringList & events)71 void FakeEwsServer::queueEventsXml(const QStringList &events)
72 {
73     if (QThread::currentThread() != thread()) {
74         qCWarningNC(EWSFAKE_LOG) << QStringLiteral(
75             "queueEventsXml called from wrong thread "
76             "(called from ") << QThread::currentThread()
77                                  << QStringLiteral(", should be ") << thread() << QStringLiteral(")");
78         return;
79     }
80     mEventQueue += events;
81 
82     if (mStreamingEventsConnection) {
83         mStreamingEventsConnection->sendEvents(mEventQueue);
84         mEventQueue.clear();
85     }
86 }
87 
retrieveEventsXml()88 QStringList FakeEwsServer::retrieveEventsXml()
89 {
90     QStringList events = mEventQueue;
91     mEventQueue.clear();
92     return events;
93 }
94 
newConnectionReceived()95 void FakeEwsServer::newConnectionReceived()
96 {
97     QTcpSocket *sock = nextPendingConnection();
98 
99     auto conn = new FakeEwsConnection(sock, this);
100     connect(conn, &FakeEwsConnection::streamingRequestStarted, this, &FakeEwsServer::streamingConnectionStarted);
101 }
102 
dialog() const103 const FakeEwsServer::DialogEntry::List FakeEwsServer::dialog() const
104 {
105     QMutexLocker lock(&mMutex);
106 
107     return mDialog;
108 }
109 
defaultReplyCallback() const110 const FakeEwsServer::DialogEntry::ReplyCallback FakeEwsServer::defaultReplyCallback() const
111 {
112     QMutexLocker lock(&mMutex);
113 
114     return mDefaultReplyCallback;
115 }
116 
overrideReplyCallback() const117 const FakeEwsServer::DialogEntry::ReplyCallback FakeEwsServer::overrideReplyCallback() const
118 {
119     QMutexLocker lock(&mMutex);
120 
121     return mOverrideReplyCallback;
122 }
123 
streamingConnectionStarted(FakeEwsConnection * conn)124 void FakeEwsServer::streamingConnectionStarted(FakeEwsConnection *conn)
125 {
126     if (mStreamingEventsConnection) {
127         qCWarningNC(EWSFAKE_LOG) << QStringLiteral("Got new streaming connection while existing one is active - terminating existing one");
128         mStreamingEventsConnection->deleteLater();
129     }
130 
131     mStreamingEventsConnection = conn;
132 }
133 
portNumber() const134 ushort FakeEwsServer::portNumber() const
135 {
136     QMutexLocker lock(&mMutex);
137 
138     return mPortNumber;
139 }
140