Started the state machine implementation.

This commit is contained in:
Attila Tőkés 2012-09-05 00:11:24 +03:00 committed by Attila
parent 04b7054aa9
commit b0e7a31b64
2 changed files with 100 additions and 17 deletions

View File

@ -25,6 +25,7 @@
/* [1] Constructors and destructors */ /* [1] Constructors and destructors */
SmtpClient::SmtpClient(const QString & host, int port, ConnectionType connectionType) : SmtpClient::SmtpClient(const QString & host, int port, ConnectionType connectionType) :
state(UnconnectedState),
name("localhost"), name("localhost"),
authMethod(AuthPlain), authMethod(AuthPlain),
connectionTimeout(5000), connectionTimeout(5000),
@ -377,7 +378,6 @@ void SmtpClient::quit()
/* [4] Protected methods */ /* [4] Protected methods */
void SmtpClient::waitForResponse() throw (ResponseTimeoutException) void SmtpClient::waitForResponse() throw (ResponseTimeoutException)
{ {
if (!socket->waitForReadyRead(responseTimeout)) if (!socket->waitForReadyRead(responseTimeout))
@ -386,17 +386,70 @@ void SmtpClient::waitForResponse() throw (ResponseTimeoutException)
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 // Save the server's response
responseText = socket->readAll(); responseText = socket->readAll();
// Extract the respose code from the server's responce (first 3 digits) // Extract the respose code from the server's responce (first 3 digits)
responseCode = responseText.left(3).toInt(); responseCode = responseText.left(3).toInt();
if (responseCode / 100 == 4) if (responseCode / 100 == 4) {
emit smtpError(ServerError); emit smtpError(ServerError); return;
}
if (responseCode / 100 == 5) if (responseCode / 100 == 5) {
emit smtpError(ClientError); 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) void SmtpClient::sendMessage(const QString &text)
@ -409,16 +462,28 @@ void SmtpClient::sendMessage(const QString &text)
/* [5] Slots for the socket's signals */ /* [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() void SmtpClient::socketReadyRead()
{ {
} }
/* [5] --- */ /* [5] --- */

View File

@ -44,7 +44,8 @@ public:
ResponseTimeoutError, ResponseTimeoutError,
AuthenticationFailedError, AuthenticationFailedError,
ServerError, // 4xx smtp error ServerError, // 4xx smtp error
ClientError // 5xx smtp error ClientError, // 5xx smtp error
SocketError
}; };
enum ConnectionType enum ConnectionType
@ -54,13 +55,24 @@ public:
TlsConnection // STARTTLS TlsConnection // STARTTLS
}; };
enum State { enum ClientState {
UnconnectedState, UnconnectedState = 0,
ConnectingState, ConnectingState = 1,
ConnectedState, ConnectedState = 2,
AuthenticatingState, ReadyState = 3,
MailSendingState, AuthenticatingState = 4,
DisconnectingState 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] --- */ /* [0] --- */
@ -126,6 +138,8 @@ protected:
/* [4] Protected members */ /* [4] Protected members */
QTcpSocket *socket; QTcpSocket *socket;
ClientState state;
bool syncMode;
QString host; QString host;
int port; int port;
@ -149,6 +163,9 @@ protected:
/* [5] Protected methods */ /* [5] Protected methods */
void changeState(ClientState state);
void processResponse();
void waitForResponse() throw (ResponseTimeoutException); void waitForResponse() throw (ResponseTimeoutException);
@ -172,6 +189,7 @@ signals:
/* [7] Signals */ /* [7] Signals */
void smtpError(SmtpError e); void smtpError(SmtpError e);
void stateChanged(ClientState s);
/* [7] --- */ /* [7] --- */