From b0e7a31b64758fa79c524d95d66fbb7031144530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Attila=20T=C5=91k=C3=A9s?= Date: Wed, 5 Sep 2012 00:11:24 +0300 Subject: [PATCH] Started the state machine implementation. --- src/smtpclient.cpp | 83 +++++++++++++++++++++++++++++++++++++++++----- src/smtpclient.h | 34 ++++++++++++++----- 2 files changed, 100 insertions(+), 17 deletions(-) diff --git a/src/smtpclient.cpp b/src/smtpclient.cpp index 75a717c..97d62b3 100644 --- a/src/smtpclient.cpp +++ b/src/smtpclient.cpp @@ -25,6 +25,7 @@ /* [1] Constructors and destructors */ SmtpClient::SmtpClient(const QString & host, int port, ConnectionType connectionType) : + state(UnconnectedState), name("localhost"), authMethod(AuthPlain), connectionTimeout(5000), @@ -377,7 +378,6 @@ void SmtpClient::quit() /* [4] Protected methods */ - void SmtpClient::waitForResponse() throw (ResponseTimeoutException) { if (!socket->waitForReadyRead(responseTimeout)) @@ -386,17 +386,70 @@ void SmtpClient::waitForResponse() throw (ResponseTimeoutException) throw ResponseTimeoutException(); } + processResponse(); +} + +void SmtpClient::changeState(ClientState state) { + this->state = state; + + switch (state) + { + case _ELHO_State: + // Service ready. Send ELHO message and chage the state + sendMessage("ELHO " + name); + break; + + case _TLS_State: + // send a request to start TLS handshake + sendMessage("STARTTLS"); + break; + + default: + ; + } + + if (state <= DisconnectingState) { // don't emit for internal signals + emit stateChanged(state); + } +} + +void SmtpClient::processResponse() { // Save the server's response responseText = socket->readAll(); // Extract the respose code from the server's responce (first 3 digits) responseCode = responseText.left(3).toInt(); - if (responseCode / 100 == 4) - emit smtpError(ServerError); + if (responseCode / 100 == 4) { + emit smtpError(ServerError); return; + } - if (responseCode / 100 == 5) - emit smtpError(ClientError); + if (responseCode / 100 == 5) { + emit smtpError(ClientError); return; + } + + switch (state) + { + case ConnectedState: + // Just connected to the server. Wait for 220 (Service ready) + if (responseCode != 220) { + emit smtpError(ServerError); return; + } + changeState(_ELHO_State); + break; + + case _ELHO_State: + // The response code needs to be 250. + if (responseCode != 250) { + emit smtpError(ServerError); return; + } + + changeState((connectionType != TlsConnection) ? ReadyState : _TLS_State); + break; + + default: + ; + } } void SmtpClient::sendMessage(const QString &text) @@ -409,16 +462,28 @@ void SmtpClient::sendMessage(const QString &text) /* [5] Slots for the socket's signals */ -void SmtpClient::socketStateChanged(QAbstractSocket::SocketState state) -{ +void SmtpClient::socketStateChanged(QAbstractSocket::SocketState state) { + switch (state) + { + case QAbstractSocket::ConnectedState: + changeState(ConnectedState); + + break; + case QAbstractSocket::UnconnectedState: + changeState(UnconnectedState); + break; + default: + ; + } } -void SmtpClient::socketError(QAbstractSocket::SocketError socketError) -{ +void SmtpClient::socketError(QAbstractSocket::SocketError socketError) { + emit smtpError(SocketError); } void SmtpClient::socketReadyRead() { + } /* [5] --- */ diff --git a/src/smtpclient.h b/src/smtpclient.h index f4a1472..0ffd57b 100644 --- a/src/smtpclient.h +++ b/src/smtpclient.h @@ -44,7 +44,8 @@ public: ResponseTimeoutError, AuthenticationFailedError, ServerError, // 4xx smtp error - ClientError // 5xx smtp error + ClientError, // 5xx smtp error + SocketError }; enum ConnectionType @@ -54,13 +55,24 @@ public: TlsConnection // STARTTLS }; - enum State { - UnconnectedState, - ConnectingState, - ConnectedState, - AuthenticatingState, - MailSendingState, - DisconnectingState + enum ClientState { + UnconnectedState = 0, + ConnectingState = 1, + ConnectedState = 2, + ReadyState = 3, + AuthenticatingState = 4, + MailSendingState = 5, + DisconnectingState = 6, + + /* Internal States */ + _ELHO_State = 50, + _TLS_State = 51, + + /* Internal Substates */ + _TLS_0_START = 60, + _TLS_1_ENCRYPT = 61, + _TLS_2_ELHO = 62 + }; /* [0] --- */ @@ -126,6 +138,8 @@ protected: /* [4] Protected members */ QTcpSocket *socket; + ClientState state; + bool syncMode; QString host; int port; @@ -149,6 +163,9 @@ protected: /* [5] Protected methods */ + void changeState(ClientState state); + + void processResponse(); void waitForResponse() throw (ResponseTimeoutException); @@ -172,6 +189,7 @@ signals: /* [7] Signals */ void smtpError(SmtpError e); + void stateChanged(ClientState s); /* [7] --- */