MailTransport

socket.cpp
1/*
2 SPDX-FileCopyrightText: 2006-2007 KovoKs <info@kovoks.nl>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7// Uncomment the next line for full comm debug
8// #define comm_debug
9
10// Own
11#include "socket.h"
12using namespace Qt::Literals::StringLiterals;
13
14// Qt
15#include <QByteArray>
16#include <QNetworkProxy>
17// KDE
18#include "mailtransport_debug.h"
19
20using namespace MailTransport;
21
22namespace MailTransport
23{
24class SocketPrivate
25{
26public:
27 SocketPrivate(Socket *s);
28 Socket *const q;
29 QSslSocket *socket = nullptr;
30 QString server;
31 QString protocol;
32 int port = 0;
33 bool secure = false;
34
35 // slots
36 void slotConnected();
37 void slotStateChanged(QAbstractSocket::SocketState state);
38 void slotModeChanged(QSslSocket::SslMode state);
39 void slotSocketRead();
40 void slotSslErrors(const QList<QSslError> &errors);
41
42private:
43 QString m_msg;
44};
45}
46
47SocketPrivate::SocketPrivate(Socket *s)
48 : q(s)
49{
50}
51
52void SocketPrivate::slotConnected()
53{
54 qCDebug(MAILTRANSPORT_LOG);
55
56 if (!secure) {
57 qCDebug(MAILTRANSPORT_LOG) << "normal connect";
58 Q_EMIT q->connected();
59 } else {
60 qCDebug(MAILTRANSPORT_LOG) << "encrypted connect";
61 socket->startClientEncryption();
62 }
63}
64
65void SocketPrivate::slotStateChanged(QAbstractSocket::SocketState state)
66{
67#ifdef comm_debug
68 qCDebug(MAILTRANSPORT_LOG) << "State is now:" << (int)state;
69#endif
71 Q_EMIT q->failed();
72 }
73}
74
75void SocketPrivate::slotModeChanged(QSslSocket::SslMode state)
76{
77#ifdef comm_debug
78 qCDebug(MAILTRANSPORT_LOG) << "Mode is now:" << state;
79#endif
80 if (state == QSslSocket::SslClientMode) {
81 Q_EMIT q->tlsDone();
82 }
83}
84
85void SocketPrivate::slotSocketRead()
86{
87 qCDebug(MAILTRANSPORT_LOG);
88
89 if (!socket) {
90 return;
91 }
92
93 m_msg += QLatin1StringView(socket->readAll());
94
95 if (!m_msg.endsWith(QLatin1Char('\n'))) {
96 return;
97 }
98
99#ifdef comm_debug
100 qCDebug(MAILTRANSPORT_LOG) << socket->isEncrypted() << m_msg.trimmed();
101#endif
102
103 Q_EMIT q->data(m_msg);
104 m_msg.clear();
105}
106
107void SocketPrivate::slotSslErrors(const QList<QSslError> &)
108{
109 qCDebug(MAILTRANSPORT_LOG);
110 /* We can safely ignore the errors, we are only interested in the
111 capabilities. We're not sending auth info. */
112 socket->ignoreSslErrors();
113 Q_EMIT q->connected();
114}
115
116// ------------------ end private ---------------------------//
117
119 : QObject(parent)
120 , d(new SocketPrivate(this))
121{
122 qCDebug(MAILTRANSPORT_LOG);
123}
124
126{
127 qCDebug(MAILTRANSPORT_LOG);
128}
129
131{
132 qCDebug(MAILTRANSPORT_LOG) << "Connecting to:" << d->server << ":" << d->port;
133
134#ifdef comm_debug
135 // qCDebug(MAILTRANSPORT_LOG) << d->protocol;
136#endif
137
138 if (d->socket) {
139 return;
140 }
141
142 d->socket = new QSslSocket(this);
143 d->socket->setProxy(QNetworkProxy::DefaultProxy);
144 d->socket->connectToHost(d->server, d->port);
145
146 d->socket->setProtocol(QSsl::AnyProtocol);
147
148 connect(d->socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SLOT(slotStateChanged(QAbstractSocket::SocketState)));
149 connect(d->socket, SIGNAL(modeChanged(QSslSocket::SslMode)), SLOT(slotModeChanged(QSslSocket::SslMode)));
150 connect(d->socket, SIGNAL(connected()), SLOT(slotConnected()));
151 connect(d->socket, SIGNAL(readyRead()), SLOT(slotSocketRead()));
152 connect(d->socket, &QSslSocket::encrypted, this, &Socket::connected);
153 connect(d->socket, SIGNAL(sslErrors(QList<QSslError>)), SLOT(slotSslErrors(QList<QSslError>)));
154}
155
156void Socket::write(const QString &text)
157{
158 // qCDebug(MAILTRANSPORT_LOG);
159 // Eat things in the queue when there is no connection. We need
160 // to get a connection first don't we...
161 if (!d->socket || !available()) {
162 return;
163 }
164
165 QByteArray cs = (text + "\r\n"_L1).toLatin1();
166
167#ifdef comm_debug
168 qCDebug(MAILTRANSPORT_LOG) << "C :" << cs;
169#endif
170
171 d->socket->write(cs.data(), cs.size());
172}
173
175{
176 // qCDebug(MAILTRANSPORT_LOG);
177 bool ok = d->socket && d->socket->state() == QAbstractSocket::ConnectedState;
178 return ok;
179}
180
182{
183 qCDebug(MAILTRANSPORT_LOG) << objectName();
184 d->socket->setProtocol(QSsl::TlsV1_2OrLater);
185 d->socket->startClientEncryption();
186}
187
188void Socket::setProtocol(const QString &proto)
189{
190 d->protocol = proto;
191}
192
193void Socket::setServer(const QString &server)
194{
195 d->server = server;
196}
197
198void Socket::setPort(int port)
199{
200 d->port = port;
201}
202
203int Socket::port() const
204{
205 return d->port;
206}
207
208void Socket::setSecure(bool what)
209{
210 d->secure = what;
211}
212
213#include "moc_socket.cpp"
Responsible for communicating with the server, it's designed to work with the ServerTest class.
Definition socket.h:26
void connected()
emitted when there is a connection (ready to send something).
Socket(QObject *parent)
Constructor, it will not auto connect.
Definition socket.cpp:118
void setServer(const QString &server)
set the server to use
Definition socket.cpp:193
void setPort(int port)
set the port to use.
Definition socket.cpp:198
virtual void reconnect()
Existing connection will be closed and a new connection will be made.
Definition socket.cpp:130
void failed()
emitted when not connected.
int port() const
returns the used port.
Definition socket.cpp:203
void data(const QString &)
emits the incoming data
virtual bool available()
Definition socket.cpp:174
void setSecure(bool what)
this will be a secure connection
Definition socket.cpp:208
void setProtocol(const QString &proto)
set the protocol to use
Definition socket.cpp:188
virtual void write(const QString &text)
Write text to the socket.
Definition socket.cpp:156
~Socket() override
Destructor.
Definition socket.cpp:125
void tlsDone()
emitted when startShake() is completed.
void startTLS()
If you want to start TLS encryption, call this.
Definition socket.cpp:181
char * data()
qsizetype size() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void clear()
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
QString trimmed() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Aug 30 2024 11:51:06 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.