Changeset View
Standalone View
src/sessionthread.cpp
Show All 15 Lines | 1 | /* | |||
---|---|---|---|---|---|
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | ||
17 | 02110-1301, USA. | 17 | 02110-1301, USA. | ||
18 | */ | 18 | */ | ||
19 | 19 | | |||
20 | #include "sessionthread_p.h" | 20 | #include "sessionthread_p.h" | ||
21 | 21 | | |||
22 | #include <QDebug> | 22 | #include <QDebug> | ||
23 | #include <QThread> | 23 | #include <QThread> | ||
24 | #include <QNetworkProxy> | ||||
24 | 25 | | |||
25 | #include "kimap_debug.h" | 26 | #include "kimap_debug.h" | ||
26 | 27 | | |||
27 | #include "imapstreamparser.h" | 28 | #include "imapstreamparser.h" | ||
28 | #include "response_p.h" | 29 | #include "response_p.h" | ||
29 | 30 | | |||
30 | using namespace KIMAP; | 31 | using namespace KIMAP; | ||
31 | 32 | | |||
32 | Q_DECLARE_METATYPE(KTcpSocket::Error) | 33 | Q_DECLARE_METATYPE(KTcpSocket::Error) | ||
33 | Q_DECLARE_METATYPE(KSslErrorUiData) | 34 | Q_DECLARE_METATYPE(KSslErrorUiData) | ||
34 | static const int _kimap_socketErrorTypeId = qRegisterMetaType<KTcpSocket::Error>(); | 35 | static const int _kimap_socketErrorTypeId = qRegisterMetaType<KTcpSocket::Error>(); | ||
35 | static const int _kimap_sslErrorUiData = qRegisterMetaType<KSslErrorUiData>(); | 36 | static const int _kimap_sslErrorUiData = qRegisterMetaType<KSslErrorUiData>(); | ||
36 | 37 | | |||
37 | SessionThread::SessionThread(const QString &hostName, quint16 port) | 38 | SessionThread::SessionThread(const QString &hostName, quint16 port) | ||
38 | : QObject(), m_hostName(hostName), m_port(port), | 39 | : QObject(), m_hostName(hostName), m_port(port), | ||
39 | m_socket(nullptr), m_stream(nullptr), m_mutex(), | 40 | m_socket(nullptr), m_stream(nullptr), m_mutex(), | ||
40 | m_encryptedMode(false) | 41 | m_encryptedMode(false), | ||
42 | m_useProxy(false) | ||||
41 | { | 43 | { | ||
42 | // Just like the Qt docs now recommend, for event-driven threads: | 44 | // Just like the Qt docs now recommend, for event-driven threads: | ||
43 | // don't derive from QThread, create one directly and move the object to it. | 45 | // don't derive from QThread, create one directly and move the object to it. | ||
44 | QThread *thread = new QThread(); | 46 | QThread *thread = new QThread(); | ||
45 | moveToThread(thread); | 47 | moveToThread(thread); | ||
46 | thread->start(); | 48 | thread->start(); | ||
47 | QMetaObject::invokeMethod(this, &SessionThread::threadInit); | 49 | QMetaObject::invokeMethod(this, &SessionThread::threadInit); | ||
48 | } | 50 | } | ||
49 | 51 | | |||
50 | SessionThread::~SessionThread() | 52 | SessionThread::~SessionThread() | ||
51 | { | 53 | { | ||
52 | QMetaObject::invokeMethod(this, &SessionThread::threadQuit); | 54 | QMetaObject::invokeMethod(this, &SessionThread::threadQuit); | ||
53 | if (!thread()->wait(10 * 1000)) { | 55 | if (!thread()->wait(10 * 1000)) { | ||
54 | qCWarning(KIMAP_LOG) << "Session thread refuses to die, killing harder..."; | 56 | qCWarning(KIMAP_LOG) << "Session thread refuses to die, killing harder..."; | ||
55 | thread()->terminate(); | 57 | thread()->terminate(); | ||
56 | // Make sure to wait until it's done, otherwise it can crash when the pthread callback is called | 58 | // Make sure to wait until it's done, otherwise it can crash when the pthread callback is called | ||
57 | thread()->wait(); | 59 | thread()->wait(); | ||
58 | } | 60 | } | ||
59 | delete thread(); | 61 | delete thread(); | ||
60 | } | 62 | } | ||
61 | 63 | | |||
64 | // Called in primary thread, passes setting to secondary thread | ||||
65 | void SessionThread::setUseNetworkProxy(bool useProxy) | ||||
66 | { | ||||
67 | QMetaObject::invokeMethod(this, [this, useProxy]() { m_useProxy = useProxy; }, Qt::QueuedConnection); | ||||
dvratil: Either make `m_useProxy` an `std::atomic_bool` or make sure `m_useProxy` is accessed from the… | |||||
68 | } | ||||
Unless the socket is disconnected, you should probably force reconnection here to apply the new configuration... dvratil: Unless the socket is disconnected, you should probably force reconnection here to apply the new… | |||||
Is this needed? I've traced the agent and the execution of the SessionThread, and if the account settings are changed in KMail the agent is set offline then online. This means that threadQuit() and threadInit() are called which recreates the socket and reconnects to the server with the new settings. marten: Is this needed? I've traced the agent and the execution of the SessionThread, and if the… | |||||
KIMAP is a generic IMAP library, you shouldn't think about it only in the context of how it's used by KMail/Akonadi. dvratil: KIMAP is a generic IMAP library, you shouldn't think about it only in the context of how it's… | |||||
69 | | ||||
62 | // Called in primary thread | 70 | // Called in primary thread | ||
63 | void SessionThread::sendData(const QByteArray &payload) | 71 | void SessionThread::sendData(const QByteArray &payload) | ||
64 | { | 72 | { | ||
65 | QMutexLocker locker(&m_mutex); | 73 | QMutexLocker locker(&m_mutex); | ||
66 | 74 | | |||
67 | m_dataQueue.enqueue(payload); | 75 | m_dataQueue.enqueue(payload); | ||
68 | QMetaObject::invokeMethod(this, &SessionThread::writeDataQueue); | 76 | QMetaObject::invokeMethod(this, &SessionThread::writeDataQueue); | ||
69 | } | 77 | } | ||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Line(s) | |||||
157 | void SessionThread::reconnect() | 165 | void SessionThread::reconnect() | ||
158 | { | 166 | { | ||
159 | Q_ASSERT(QThread::currentThread() == thread()); | 167 | Q_ASSERT(QThread::currentThread() == thread()); | ||
160 | if (m_socket == nullptr) { // threadQuit already called | 168 | if (m_socket == nullptr) { // threadQuit already called | ||
161 | return; | 169 | return; | ||
162 | } | 170 | } | ||
163 | if (m_socket->state() != SessionSocket::ConnectedState && | 171 | if (m_socket->state() != SessionSocket::ConnectedState && | ||
164 | m_socket->state() != SessionSocket::ConnectingState) { | 172 | m_socket->state() != SessionSocket::ConnectingState) { | ||
173 | | ||||
174 | if (!m_useProxy) { | ||||
175 | qCDebug(KIMAP_LOG) << "Connecting to IMAP server with no proxy"; | ||||
dvratil: Provide more context: "Connecting to IMAP server without a proxy" | |||||
176 | QNetworkProxy proxy; | ||||
177 | proxy.setType(QNetworkProxy::NoProxy); | ||||
178 | m_socket->setProxy(proxy); | ||||
179 | } else { | ||||
180 | qCDebug(KIMAP_LOG) << "Connecting to IMAP server using default system proxy"; | ||||
More context: "Connecting to IMAP server using default system proxy" Shouldn't you also explicitly set the QNetworkProxy here as well? The socket doesn't get recreated on reconnect, so if the option is changed, it wouldn't get reset. dvratil: More context: "Connecting to IMAP server using default system proxy"
Shouldn't you also… | |||||
Set here to make sure, but as above the socket and connection is recreated when the option is changed by the user anyway. marten: Set here to make sure, but as above the socket and connection is recreated when the option is… | |||||
181 | QNetworkProxy proxy; | ||||
182 | proxy.setType(QNetworkProxy::DefaultProxy); | ||||
183 | m_socket->setProxy(proxy); | ||||
184 | } | ||||
185 | | ||||
165 | if (m_encryptedMode) { | 186 | if (m_encryptedMode) { | ||
166 | qCDebug(KIMAP_LOG) << "connectToHostEncrypted" << m_hostName << m_port; | 187 | qCDebug(KIMAP_LOG) << "connectToHostEncrypted" << m_hostName << m_port; | ||
167 | m_socket->connectToHostEncrypted(m_hostName, m_port); | 188 | m_socket->connectToHostEncrypted(m_hostName, m_port); | ||
168 | } else { | 189 | } else { | ||
169 | qCDebug(KIMAP_LOG) << "connectToHost" << m_hostName << m_port; | 190 | qCDebug(KIMAP_LOG) << "connectToHost" << m_hostName << m_port; | ||
170 | m_socket->connectToHost(m_hostName, m_port); | 191 | m_socket->connectToHost(m_hostName, m_port); | ||
171 | } | 192 | } | ||
172 | } | 193 | } | ||
Show All 24 Lines |
Either make m_useProxy an std::atomic_bool or make sure m_useProxy is accessed from the SessionThread's thread (QMetaObject::invokeMethod(this, [this, useProxy]() { m_useProxy = useProxy; }, Qt::QueuedConnection))