]> Some of my projects - anidbudpclient.git/commitdiff
- Initial, unstable, state machine api
authorAPTX <mail@example.com>
Fri, 31 Jul 2009 20:35:11 +0000 (22:35 +0200)
committerAPTX <mail@example.com>
Sat, 1 Aug 2009 00:07:46 +0000 (02:07 +0200)
anidbudpclient.cpp
anidbudpclient.h
anidbudpclient.pro
anidbudpclient_global.h
logoutcommand.cpp [new file with mode: 0644]
logoutcommand.h [new file with mode: 0644]

index 94be9ca8efc26b60e3d8ddcb85100a21ee007c48..1b1a65ca32778ae414d17650d9e0c8f1322d0549 100644 (file)
@@ -1,9 +1,15 @@
 #include "anidbudpclient.h"
 
+#include <QtStateMachine>
+#include <QtActionState>
+#include <QtHistoryState>
+#include <QtState>
+
 #include <QUdpSocket>
 #include <QTimer>
 
 #include <rawcommand.h>
+#include <logoutcommand.h>
 
 #include <QtDebug>
 
@@ -14,24 +20,18 @@ const int AniDBUdpClient::protocolVersion = PROTOCOL_VERSION;
 AniDBUdpClient::AniDBUdpClient(QObject *parent) : QObject(parent)
 {
 qDebug() << "Api instance init!";
-       m_state = DisconnectedState;
+
        m_error = NoError;
        m_errorString;
        m_idlePolicy = DoNothingIdlePolicy;
-       m_idle = true;
 
        disconnecting = false;
        authCommand = 0;
-       authenticateOnConnect = false;
 
        socket = new QUdpSocket(this);
-       QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readReplies()));
-
-       commandTimer = new QTimer(this);        
-       QObject::connect(commandTimer, SIGNAL(timeout()), this, SLOT(sendNextCommand()));
 
+       commandTimer = new QTimer(this);
        idleTimer = new QTimer(this);
-       QObject::connect(idleTimer, SIGNAL(timeout()), this, SLOT(idleTimeout()));
 
        m_localPort = 9001;
        m_host = "api.anidb.info";
@@ -40,8 +40,89 @@ qDebug() << "Api instance init!";
        authCommand = new AuthCommand(this);
        QObject::connect(authCommand, SIGNAL(replyReady(bool)), this, SLOT(doAuthenticate(bool)));
 
-       commandTimer->setSingleShot(false);
        setFloodInterval(5);
+
+       stateMachine = new QtStateMachine(this);
+
+       errorState = new QtState;
+       disconnectedState = new QtState;
+       connectingState = new QtState;
+       connectedState = new QtState;
+       authenticatingState = new QtState(connectedState);
+       authenticatedState = new QtState(connectedState);
+       idleState = new QtState(connectedState);
+       idleTimeoutState = new QtState(connectedState);
+       logoutState = new QtState(connectedState);
+       loggedOutState = new QtState(connectedState);
+       sendState = new QtState(connectedState);
+       waitState = new QtState(connectedState);
+       recieveState = new QtState;
+       recieveFailState = new QtState;
+       connectedHistoryState = connectedState->addHistoryState();
+
+       stateMachine->addState(errorState);
+       stateMachine->addState(disconnectedState);
+       stateMachine->addState(connectingState);
+       stateMachine->addState(connectedState);
+       stateMachine->addState(recieveState);
+       stateMachine->addState(recieveFailState);
+       stateMachine->setInitialState(disconnectedState);
+       stateMachine->setErrorState(errorState);
+
+       connectedState->setInitialState(authenticatingState);
+       connectedHistoryState->setDefaultState(authenticatingState);
+       // ------------- Transitions ---------------------
+
+       connectedState->addTransition(this, SIGNAL(startDisconnecting()), disconnectedState);
+       connectedState->addTransition(socket, SIGNAL(readyRead()), recieveState);
+       connectedState->addTransition(this, SIGNAL(sendFailed()), recieveFailState);
+
+       disconnectedState->addTransition(this, SIGNAL(startConnecting()), connectingState);
+
+       connectingState->addTransition(this, SIGNAL(connected()), connectedState);
+
+       authenticatingState->addTransition(this, SIGNAL(startSending()), sendState);
+       authenticatingState->addTransition(this, SIGNAL(authenticated()), sendState);
+
+       sendState->addTransition(this, SIGNAL(queueEmpty()), idleState);
+       sendState->addTransition(this, SIGNAL(commandSent()), waitState);
+
+       waitState->addTransition(commandTimer, SIGNAL(timeout()), sendState);
+
+       idleState->addTransition(this, SIGNAL(startSending()), sendState);
+       idleState->addTransition(idleTimer, SIGNAL(timeout()), idleTimeoutState);
+
+       idleTimeoutState->addTransition(this, SIGNAL(startLogout()), logoutState);
+
+       logoutState->addTransition(this, SIGNAL(loggedOut()), loggedOutState);
+
+       recieveState->addTransition(this, SIGNAL(authenticated()), sendState);
+       recieveState->addTransition(this, SIGNAL(loggedOut()), loggedOutState);
+
+       recieveState->addTransition(connectedHistoryState);
+
+       recieveFailState->addTransition(connectedHistoryState);
+       // ------------ END Transitions -------------------
+
+       // ------------- Methods ---------------------
+       errorState->invokeMethodOnEntry(this, "enterErrorState");
+       disconnectedState->invokeMethodOnEntry(this, "enterDisconnectedState");
+       connectingState->invokeMethodOnEntry(this, "enterConnectingState");
+       connectedState->invokeMethodOnEntry(this, "enterConnectedState");
+       authenticatingState->invokeMethodOnEntry(this, "enterAuthenticatingState");
+       sendState->invokeMethodOnEntry(this, "enterSendState");
+       waitState->invokeMethodOnEntry(this, "enterWaitState");
+       idleState->invokeMethodOnEntry(this, "enterIdleState");
+       idleState->invokeMethodOnExit(this, "exitIdleState");
+       idleTimeoutState->invokeMethodOnEntry(this, "enterIdleTiemoutState");
+       logoutState->invokeMethodOnEntry(this, "enterLogoutState");
+       loggedOutState->invokeMethodOnEntry(this, "enterLoggedOutState");
+
+       recieveState->invokeMethodOnExit(this, "exitRecieveState");
+       recieveFailState->invokeMethodOnEntry(this, "enterRecieveFailState");
+       // ------------ END Methods -------------------
+
+       stateMachine->start();
 }
 
 AniDBUdpClient::~AniDBUdpClient()
@@ -121,8 +202,7 @@ int AniDBUdpClient::floodInterval() const
 
 void AniDBUdpClient::setFloodInterval(int interval)
 {
-       m_floodInterval = interval;
-       commandTimer->setInterval(m_floodInterval * 1000);
+       m_floodInterval = interval * 1000;
 }
 
 AniDBUdpClient::IdlePolicy AniDBUdpClient::idlePolicy() const
@@ -135,12 +215,6 @@ void AniDBUdpClient::setIdlePolicy(IdlePolicy policy)
        m_idlePolicy = policy;
 }
 
-
-AniDBUdpClient::State AniDBUdpClient::state() const
-{
-       return m_state;
-}
-
 AniDBUdpClient::Error AniDBUdpClient::error() const
 {
        return m_error;
@@ -151,116 +225,70 @@ QString AniDBUdpClient::errorString() const
        return m_errorString;
 }
 
-bool AniDBUdpClient::isIdle()
+void AniDBUdpClient::enterErrorState()
 {
-       return m_idle;
+qDebug() << "Entering Error State";
 }
 
-void AniDBUdpClient::clearCommandQueue()
+void AniDBUdpClient::enterDisconnectedState()
 {
-       // Delete all unsent commands that are managed by the client.
-       while (!commandQueue.empty())
-       {
-               AbstractCommand *cmd = commandQueue.dequeue();
-               if (!cmd->waitForResult())
-               {
-                       // These would be deleted anyway
-                       delete cmd;
-               }
-               else
-               {
-                       // Send CLIENT_DESTROYED to indicate that no real reply will come.
-                       cmd->setRawReply(AbstractCommand::CLIENT_DESTROYED, "", this);
-               }
-       }
+qDebug() << "Entering Disconnected State";
 }
 
-void AniDBUdpClient::connect()
+void AniDBUdpClient::enterConnectingState()
 {
-qDebug() << "Conneting";
-       if (state() == ReconnectingState)
-       {
-               authenticate();
-               return;
-       }
-
-       if (state() != DisconnectedState)
-               return;
-
-       changeState(ConnectingState);
+qDebug() << "Entering Connecting State";
 
        if (!m_hostAddress.isNull())
        {
-               doConnect();
+               if (socket->bind(QHostAddress::Any, m_localPort))
+               {
+qDebug() << "Successful connection";
+                       emit connected();
+               }
+               else
+               {
+                       m_error = BindError;
+                       m_errorString = socket->errorString();
+qDebug() << QString("Bind on Address: %1 port: %2 failed").arg(m_hostAddress.toString()).arg(m_localPort);
+                       emit connectionError();
+               }
                return;
        }
        QHostInfo::lookupHost(m_host, this, SLOT(lookedUp(QHostInfo)));
 }
 
-void AniDBUdpClient::disconnect(bool graceful)
-{
-qDebug() << "Disconneting" << (graceful ? "gracefully" : "");
-       if (graceful)
-       {
-               disconnecting = true;
-               return;
-       }
-       changeState(DisconnectedState);
-}
-
-void AniDBUdpClient::send(AbstractCommand *command)
-{
-       if (state() < ConnectingState)
-               connect();
-
-       enqueueCommand(command);
-}
-
-void AniDBUdpClient::sendRaw(QByteArray command)
-{
-qDebug() << QString("Sending RAW command: %1").arg(command.constData());
-       enqueueCommand(new RawCommand(command));
-}
-
 void AniDBUdpClient::lookedUp(QHostInfo hostInfo)
 {
 qDebug() << "Host lookup finished";
        if (hostInfo.error() != QHostInfo::NoError)
        {
                qDebug() << "Lookup failed:" << hostInfo.errorString();
-               changeState(ErrorState);
                m_error = HostLookupError;
                m_errorString = hostInfo.errorString();
+               emit connectionError();
                return;
        }
        m_hostAddress = hostInfo.addresses()[0];
-       doConnect();
-}
 
+       // TODO
+       enterConnectingState();
+}
 
-void AniDBUdpClient::doConnect()
+void AniDBUdpClient::enterConnectedState()
 {
-       if (socket->bind(QHostAddress::Any, m_localPort))
-       {
-qDebug() << "Successful connection";
-               authenticate();
-       }
-       else
-       {
-               changeState(ErrorState);
-               m_error = BindError;
-               m_errorString = socket->errorString();
-qDebug() << QString("Bind on Address: %1 port: %2 failed").arg(m_hostAddress.toString()).arg(m_localPort);
-       }
+qDebug() << "Entering Connected State";
+       emit connected();
 }
 
-void AniDBUdpClient::authenticate()
+void AniDBUdpClient::enterAuthenticatingState()
 {
+qDebug() << "Entering Authenticating State";
        authCommand->setUser(m_user);
        authCommand->setPass(m_pass);
 
        enqueueCommand(authCommand, true);
-       changeState(ReconnectingState);
+       emit startSending();
 }
 
 void AniDBUdpClient::doAuthenticate(bool success)
@@ -270,86 +298,84 @@ qDebug() << "doAuthenticate init";
        {
 qDebug() << "success!";
                m_sessionId = authCommand->sessionId().toUtf8();
-               changeState(ConnectedState);
+               emit authenticated();
        }
        else
        {
-               changeState(ErrorState);
                m_error = AuthenticationError;
+               emit connectionError();
        }
 
        authenticateOnConnect = false;
 }
 
-void AniDBUdpClient::logout()
+void AniDBUdpClient::enterSendState()
 {
-       if (state() != ConnectedState)
-       // We are not logged in other states, don't try to logout again.
+qDebug() << "Entering Send State";
+       if (commandQueue.isEmpty())
+       {
+               emit queueEmpty();
                return;
-
-       enqueueCommand(new RawCommand("LOGOUT"), true);
-       changeState(ReconnectingState);
-       m_sessionId = "";
+       }
+       sendCommand(commandQueue.dequeue());
+       emit commandSent();
 }
 
-void AniDBUdpClient::enqueueCommand(AbstractCommand *command, bool first)
+void AniDBUdpClient::enterWaitState()
 {
-       if (first)
-       {
-               commandQueue.push_front(command);
-       }
-       else
-       {
-               commandQueue.enqueue(command);
-       }
-
-       leaveIdleState();
+qDebug() << "Entering Wait State";
+       commandTimer->start(m_floodInterval);
 }
 
-void AniDBUdpClient::sendNextCommand()
+void AniDBUdpClient::enterIdleState()
 {
-       if (commandQueue.isEmpty())
+qDebug() << "Entering Idle State";
+       switch (m_idlePolicy)
        {
-               enterIdleState();
-               return;
+               case KeepAliveIdlePolicy:
+                       idleTimer->start(UDP_API_INACTIVITY_LOGOUT * 1000);
+               break;
+               case LogoutIdlePolicy:
+                       emit startLogout();
+               break;
+               default:
+               break;
        }
-
-       sendCommand(commandQueue.dequeue());
 }
 
-void AniDBUdpClient::sendCommand(AbstractCommand *command)
+void AniDBUdpClient::exitIdleState()
 {
-       Command cmdPair = command->rawCommand();
-       QByteArray datagram = buildCmd(cmdPair.first, cmdPair.second);
-
-       QByteArray commandId = nextCommandId();
-
-       datagram += datagram.contains(" ") ? "&" : " ";
-       datagram += "tag=" + commandId;
-
-       if (m_sessionId.length())
-               datagram += "&s=" + m_sessionId;
+qDebug() << "Exiting Idle State";
+       idleTimer->stop();
+}
 
-       if (command->waitForResult())
-       {
-               sentCommands[commandId] = command;
-       }
-       else
+void AniDBUdpClient::enterIdleTiemoutState()
+{
+qDebug() << "Entering IdleTiemout State";
+       switch (m_idlePolicy)
        {
-               command->deleteLater();
+               case KeepAliveIdlePolicy:
+               default:
+               break;
        }
+}
 
-qDebug() << QString("SENDING datagram:\n\t%1\nto: %2 ([%3]:%4)")
-               .arg(datagram.constData())
-               .arg(m_host)
-               .arg(m_hostAddress.toString())
-               .arg(m_hostPort);
+void AniDBUdpClient::enterLogoutState()
+{
+qDebug() << "Entering Logout State";
+       enqueueCommand(new LogoutCommand);
+       emit startSending();
+}
 
-       socket->writeDatagram(datagram, m_hostAddress, m_hostPort);
+void AniDBUdpClient::enterLoggedOutState()
+{
+qDebug() << "Entering LoggedOut State";
+       m_sessionId = "";
 }
 
-void AniDBUdpClient::readReplies()
+void AniDBUdpClient::exitRecieveState()
 {
+qDebug() << "Entering Recieve State";
        while (socket->hasPendingDatagrams())
        {
                char data[UDP_DATAGRAM_MAXIMUM_SIZE];
@@ -406,66 +432,135 @@ qDebug() << QString("Sending reply to command with id: %1").arg(commandId.constD
                AbstractCommand *cmd = sentCommands.take(commandId);
 
                // Requeue command and reauthenticate if not logged in.
-               if (replyCode == AbstractCommand::LOGIN_FIRST
-                       || replyCode == AbstractCommand::INVALID_SESSION)
+               switch (replyCode)
                {
+                       case AbstractCommand::LOGIN_FIRST:
+                       case AbstractCommand::INVALID_SESSION:
 qDebug() << "LOGIN FIRST required, authing";
                                enqueueCommand(cmd);
-                               authenticate();
-                       continue;
+                               emit startAuthentication();
+                               goto continueLoop;
+                       break;
+                       case AbstractCommand::LOGGED_OUT:
+                               emit loggedOut();
+                       break;
+                       default:
+                       break;
                }
                // tag + space + replyCode + space = 5 + 1 + 3 + 1
                reply = reply.mid(10);
 
                cmd->setRawReply(replyCode, reply, this);
+continueLoop:
+               ;
        }
 }
 
-void AniDBUdpClient::enterIdleState()
+void AniDBUdpClient::enterRecieveFailState()
 {
-       if (m_idle)
-               return;
-qDebug() << "Entering idle state";
-       m_idle = true;
+qDebug() << "Entering RecieveFail State";
+}
 
-       switch (m_idlePolicy)
+// -------------------------------------------------------------------------------------
+
+void AniDBUdpClient::clearCommandQueue()
+{
+       // Delete all unsent commands that are managed by the client.
+       while (!commandQueue.empty())
        {
-               case DoNothingIdlePolicy:
-               case KeepAliveIdlePolicy:
-                       commandTimer->stop();
-                       idleTimer->start();
-               break;
-               case LogoutIdlePolicy:
-               default:
-                       idleTimeout();
-               break;
+               AbstractCommand *cmd = commandQueue.dequeue();
+               if (!cmd->waitForResult())
+               {
+                       // These would be deleted anyway
+                       delete cmd;
+               }
+               else
+               {
+                       // Send CLIENT_DESTROYED to indicate that no real reply will come.
+                       cmd->setRawReply(AbstractCommand::CLIENT_DESTROYED, "", this);
+               }
        }
+}
 
+void AniDBUdpClient::connect()
+{
+qDebug() << "Conneting";
+       emit startConnecting();
 }
 
-void AniDBUdpClient::leaveIdleState()
+void AniDBUdpClient::disconnect(bool graceful)
 {
-       // Don't do anything untill connected!
-       if (state() < ReconnectingState)
+qDebug() << "Disconneting" << (graceful ? "gracefully" : "");
+       if (graceful)
+       {
+               disconnecting = true;
                return;
+       }
+       emit startDisconnecting();
+}
 
-       if (!m_idle)
-               return;
-qDebug() << "Leaving idle state";
-       m_idle = false;
+void AniDBUdpClient::send(AbstractCommand *command)
+{
+       connect();
 
-       idleTimer->stop();
+       enqueueCommand(command);
+}
+
+void AniDBUdpClient::sendRaw(QByteArray command)
+{
+qDebug() << QString("Sending RAW command: %1").arg(command.constData());
+       enqueueCommand(new RawCommand(command));
+}
 
-       // Do not wait for the timer floodInterval seconds for the first command.
-       sendNextCommand();
-       commandTimer->start();
+void AniDBUdpClient::logout()
+{
+       emit startLogout();
 }
 
-void AniDBUdpClient::idleTimeout()
+void AniDBUdpClient::enqueueCommand(AbstractCommand *command, bool first)
 {
-       logout();
+       if (first)
+       {
+               commandQueue.push_front(command);
+       }
+       else
+       {
+               commandQueue.enqueue(command);
+       }
+
+       emit startSending();
 }
 
+void AniDBUdpClient::sendCommand(AbstractCommand *command)
+{
+       Command cmdPair = command->rawCommand();
+       QByteArray datagram = buildCmd(cmdPair.first, cmdPair.second);
+
+       QByteArray commandId = nextCommandId();
+
+       datagram += datagram.contains(" ") ? "&" : " ";
+       datagram += "tag=" + commandId;
+
+       if (m_sessionId.length())
+               datagram += "&s=" + m_sessionId;
+
+       if (command->waitForResult())
+       {
+               sentCommands[commandId] = command;
+       }
+       else
+       {
+               command->deleteLater();
+       }
+
+qDebug() << QString("SENDING datagram:\n\t%1\nto: %2 ([%3]:%4)")
+               .arg(datagram.constData())
+               .arg(m_host)
+               .arg(m_hostAddress.toString())
+               .arg(m_hostPort);
+
+       socket->writeDatagram(datagram, m_hostAddress, m_hostPort);
+}
 
 QByteArray AniDBUdpClient::buildCmd(const QString &cmd, const QVariantMap &args)
 {
@@ -478,7 +573,7 @@ QByteArray AniDBUdpClient::buildCmd(const QString &cmd, const QVariantMap &args)
                        continue;
                }
 
-               // The string version of bool is "true" or "false", but hte API expects 1 or 0
+               // The string version of bool is "true" or "false", but the API expects 1 or 0
                QString value;
                if (it.value().type() == QVariant::Bool)
                {
@@ -497,51 +592,6 @@ QByteArray AniDBUdpClient::buildCmd(const QString &cmd, const QVariantMap &args)
        return result.toUtf8();
 }
 
-void AniDBUdpClient::changeState(State newState)
-{
-       if (newState == m_state)
-               return;
-
-       State oldState = m_state;
-
-       // BEFORE statechange
-       switch(newState)
-       {
-               case DisconnectedState:
-
-                       if (m_sessionId.length())
-                               logout();
-
-                       socket->close();
-                       m_sessionId = "";
-                       emit disconnected();
-//             break;
-               case ErrorState:
-                       commandTimer->stop();
-               break;
-               default:
-               break;
-       }
-
-       m_state = newState;
-
-       // AFTER statechange
-       switch (newState)
-       {
-               case ReconnectingState:
-                       leaveIdleState();
-               break;
-               case ConnectedState:
-                       emit connected();
-               break;
-               default:
-               break;
-       }
-
-qDebug() << "State changed from" << oldState << "to" << newState;
-       emit stateChanged(newState, oldState);
-}
-
 QByteArray AniDBUdpClient::nextCommandId(int len)
 {
        static const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
index 7a7da46dab7aa8a4478649006b256519d0796fdb..10e0e33ac70642eb1c72f78a4adcc4131bfd2878 100644 (file)
 
 #include "authcommand.h"
 
+class QtStateMachine;
+class QtState;
+class QtHistoryState;
+
+
 class QUdpSocket;
 class QTimer;
 
@@ -33,9 +38,7 @@ class ANIDBUDPCLIENTSHARED_EXPORT AniDBUdpClient : public QObject
          Send commands in \interval seconds intervals
        */
        Q_PROPERTY(int floodInterval READ floodInterval WRITE setFloodInterval);
-
        Q_PROPERTY(IdlePolicy idlePolicy READ idlePolicy WRITE setIdlePolicy);
-       Q_PROPERTY(State state READ state);
        Q_PROPERTY(Error error READ error);
        Q_PROPERTY(QString errorString READ errorString);
 
@@ -44,15 +47,6 @@ public:
        static const int clientVersion;
        static const int protocolVersion;
 
-       enum State
-       {
-               ErrorState = -1,
-               DisconnectedState,
-               ConnectingState,
-               ReconnectingState,
-               ConnectedState,
-       };
-
        enum Error
        {
                NoError,
@@ -96,12 +90,9 @@ public:
        IdlePolicy idlePolicy() const;
        void setIdlePolicy(IdlePolicy policy);
 
-       State state() const;
        Error error() const;
        QString errorString() const;
 
-       bool isIdle();
-
        // ---------------- END Properties ----------------
 
        void clearCommandQueue();
@@ -115,43 +106,63 @@ public slots:
        */
        void disconnect(bool graceful = false);
 
-       void authenticate();
-
        void send(AbstractCommand *command);
        void sendRaw(QByteArray command);
 
 signals:
+
+       void startConnecting();
        void connected();
+       void startDisconnecting();
        void disconnected();
 
-       void pong();
-       void uptime();
-       
-       void stateChanged(State newState, State oldState);
+       void startAuthentication();
+       void authenticated();
+       void authenticationFailure();
+
+       void startSending();
+       void commandSent();
+       void queueEmpty();
+
+       void replyRecieved();
+       void sendFailed();
+
+       void connectionError();
+       void notLoggedInError();
+
+       void startLogout();
+       void loggedOut();
 
 private slots:
+       void enterErrorState();
+       void enterDisconnectedState();
+
+       void enterConnectingState();
        void lookedUp(QHostInfo hostInfo);
-       void doConnect();
-       void doAuthenticate(bool success);
 
-       void logout();
+       void enterConnectedState();
 
+       void enterAuthenticatingState();
+       void doAuthenticate(bool success);
 
-       void enqueueCommand(AbstractCommand *command, bool first = false);
-       void sendNextCommand();
-       void sendCommand(AbstractCommand *command);
+       void enterSendState();
+       void enterWaitState();
+       void enterIdleState();
+       void exitIdleState();
+       void enterIdleTiemoutState();
+       void enterLogoutState();
+       void enterLoggedOutState();
 
-       void readReplies();
+       void exitRecieveState();
+       void enterRecieveFailState();
 
-       void enterIdleState();
-       void leaveIdleState();
+       void logout();
 
-       void idleTimeout();
+       void enqueueCommand(AbstractCommand *command, bool first = false);
+       void sendCommand(AbstractCommand *command);
 
 private:
        QByteArray buildCmd(const QString &cmd, const QVariantMap &args);
-
-       void changeState(State newState);
        QByteArray nextCommandId(int len = 5);
 
        QTimer *commandTimer;
@@ -182,12 +193,10 @@ private:
 
        // Misc params
        IdlePolicy m_idlePolicy;
-       State m_state;
        Error m_error;
        QString m_errorString;
 
        bool disconnecting;
-       bool m_idle;
 
        AuthCommand *authCommand;
        bool authenticateOnConnect;
@@ -195,6 +204,26 @@ private:
 
        static const int UDP_DATAGRAM_MAXIMUM_SIZE = 1400;
        static const int UDP_API_INACTIVITY_LOGOUT = 30 * 60;
+
+       QtStateMachine *stateMachine;
+       QtState *errorState;
+       QtState *disconnectedState;
+       QtState *connectingState;
+       QtState *connectedState;
+       QtState *authenticatingState;
+       QtState *authenticatedState;
+       QtState *logoutState;
+       QtState *loggedOutState;
+
+       QtState *idleState;
+       QtState *idleTimeoutState;
+       QtState *sendState;
+       QtState *waitState;
+
+       QtState *recieveState;
+       QtState *recieveFailState;
+
+       QtHistoryState *connectedHistoryState;
 };
 
 #endif // ANIDBUDPCLIENT_H
index 6ad72ce14ff7337a0286157b8f19fea5c84b247c..c3f0267cf78b40a61ec58b680a10fb43a842172d 100644 (file)
@@ -5,13 +5,13 @@ QT += network
 QT -= gui
 TEMPLATE = lib
 TARGET = anidbudpclient
-static {
-       message(anidbpudpclinet: Static build)
-       DESTDIR = ../../build-static
+static { 
+    message(anidbpudpclinet: Static build)
+    DESTDIR = ../../build-static
 }
-!static {
-       message(anidbpudpclinet: Dynamic build)
-       DESTDIR = ../../build
+!static { 
+    message(anidbpudpclinet: Dynamic build)
+    DESTDIR = ../../build
 }
 INCLUDEPATH += $$PWD
 DEPENDPATH += $$PWD
@@ -21,12 +21,13 @@ SOURCES += anidbudpclient.cpp \
     abstractcommand.cpp \
     authcommand.cpp \
     rawcommand.cpp \
-    mylistaddcommand.cpp
+    mylistaddcommand.cpp \
+    logoutcommand.cpp
 HEADERS += anidbudpclient.h \
     anidbudpclient_global.h \
     abstractcommand.h \
     authcommand.h \
     rawcommand.h \
-    mylistaddcommand.h
-
+    mylistaddcommand.h \
+    logoutcommand.h
 include(../../lib/qtstatemachine/src/qtstatemachine.pri)
index a0a429ae539e47e888e9f8f6efd71e4d4b811a30..2f39cdac9bbb37c24367ba5b8d8bb5b1518fa621 100644 (file)
@@ -4,7 +4,7 @@
 #include <QtCore/qglobal.h>
 
 #define CLIENT_NAME "anidbudpclient"
-#define CLIENT_VERSION 0x000001
+#define CLIENT_VERSION 0x000002
 #define PROTOCOL_VERSION 3
 
 #if defined(ANIDBUDPCLIENT_LIBRARY)
diff --git a/logoutcommand.cpp b/logoutcommand.cpp
new file mode 100644 (file)
index 0000000..10039b6
--- /dev/null
@@ -0,0 +1,13 @@
+#include "logoutcommand.h"
+
+LogoutCommand::LogoutCommand()
+{
+}
+
+Command LogoutCommand::rawCommand() const
+{
+       Command command;
+       command.first = "LOGOUT";
+
+       return command;
+}
diff --git a/logoutcommand.h b/logoutcommand.h
new file mode 100644 (file)
index 0000000..250a1af
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef LOGOUTCOMMAND_H
+#define LOGOUTCOMMAND_H
+
+#include "abstractcommand.h"
+
+class ANIDBUDPCLIENTSHARED_EXPORT LogoutCommand : public AbstractCommand
+{
+       Q_OBJECT
+public:
+       LogoutCommand();
+       Command rawCommand() const;
+};
+
+#endif // LOGOUTCOMMAND_H