MailTransport

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

KDE's Doxygen guidelines are available online.