virtual Command rawCommand() const;
+ /**
+ If it's false the client takes ownership of the request!
+ **/
virtual bool waitForResult() const;
virtual bool requiresSession() const;
};
+#define REPLY_DEFINITION_HELPER_INTERNAL(name, constructor) \
+friend class Client; \
+public: \
+typedef name##Command CommandType; \
+private: \
+CommandType m_command; \
+Client *m_client; \
+name##Reply(const CommandType command, const QByteArray &id, Client *client, QObject *parent) : m_command(command), m_client(client), AbstractReply(id, client, parent) {constructor} \
+inline const CommandType &command() const { return m_command; }
+
#define REPLY_DEFINITION_HELPER(name) \
- friend class Client; \
- public: \
- typedef name##Command CommandType; \
- private: \
- CommandType m_command; \
- Client *m_client; \
- name##Reply(const CommandType command, const QByteArray &id, Client *client, QObject *parent) : m_command(command), m_client(client), AbstractReply(id, client, parent) {m_commandPtr = &m_command;} \
- inline const CommandType &command() const { return m_command; }
+ REPLY_DEFINITION_HELPER_INTERNAL(name, m_commandPtr = &m_command;)
#define REPLY_DEFINITION_HELPER2(name) \
- friend class Client; \
- public: \
- typedef name##Command CommandType; \
- private: \
- CommandType m_command; \
- Client *m_client; \
- name##Reply(const CommandType command, const QByteArray &id, Client *client, QObject *parent) : m_command(command), m_client(client), AbstractReply(id, client, parent) {m_commandPtr = &m_command; init();} \
- inline const CommandType &command() const { return m_command; }
+ REPLY_DEFINITION_HELPER_INTERNAL(name, m_commandPtr = &m_command; init();)
class ANIDBUDPCLIENTSHARED_EXPORT AbstractReply : public QObject
{
qDebug() << "Api instance init!";
authReply = 0;
+ uptimeReply = 0;
m_error = NoError;
m_idlePolicy = DoNothingIdlePolicy;
Client::~Client()
{
- disconnect();
- clearCommandQueue();
-
foreach (CommandData *cmd, sentCommands)
{
- if (!cmd->command->command().waitForResult())
- {
- // Send CLIENT_DESTROYED to indicate that no real reply will come.
- cmd->command->setRawReply(CLIENT_DESTROYED, "");
- }
+ // Send CLIENT_DESTROYED to indicate that no real reply will come.
+ cmd->command->setRawReply(CLIENT_DESTROYED, "");
}
+ sentCommands.clear();
+
+ clearCommandQueue();
if (!m_sessionId.isEmpty())
{
while (commandTimer->isActive())
QCoreApplication::processEvents();
- sendCommand(createReply(LogoutCommand()), true);
+ logout(true);
socket->waitForBytesWritten(5);
}
+ disconnect();
+ if (authReply)
+ {
+ delete authReply;
+ authReply = 0;
+ }
+ if (uptimeReply)
+ {
+ delete uptimeReply;
+ uptimeReply = 0;
+ }
}
QString Client::host() const
idleTimer->start(UDP_API_INACTIVITY_UPDATE * 1000);
break;
case ImmediateLogoutIdlePolicy:
- enqueueControlCommand(logoutReply);
+ logout(true);
break;
default:
break;
case LOGIN_FIRST:
case INVALID_SESSION:
qDebug() << "LOGIN FIRST required, authing";
- m_sessionId = "";
+ m_sessionId.clear();
if (controlCommand)
enqueueControlCommand(cmd);
else
goto continueLoop;
break;
case LOGGED_OUT:
- m_sessionId = "";
+ m_sessionId.clear();
break;
case BANNED:
m_error = BannedError;
reply = reply.mid(10);
cmd->setRawReply(replyCode, reply);
+
+ // Delete if command is owned by the client.
+ if (!cmd->command().waitForResult())
+ delete cmd;
continueLoop:
;
}
AbstractReply *reply = commandQueue.dequeue();
if (!reply->command().waitForResult())
{
- // These would be deleted anyway
+ // These are owned by the client
delete reply;
}
else
AbstractReply *reply = commandQueue.dequeue();
if (!reply->command().waitForResult())
{
- // These would be deleted anyway
+ // These are owned by the client
delete reply;
}
else
void Client::logout()
{
- if (!m_sessionId.isEmpty())
- enqueueControlCommand(logoutReply);
+ logout(false);
+}
+
+void Client::logout(bool force)
+{
+ if (m_sessionId.isEmpty())
+ return;
+ enqueueControlCommand(createReply(LogoutCommand()), force);
}
void Client::commandTimeout(const QByteArray &commandId)
void enqueueControlCommand(AbstractReply *command, bool first = false);
void sendCommand(AbstractReply *command, bool controlCommand = false);
+ void logout(bool force);
QByteArray buildCmd(const QString &cmd, const QVariantMap &args);
QByteArray nextCommandId(int len = 5);
AuthCommand authCommand;
AuthReply *authReply;
- LogoutReply *logoutReply;
UptimeReply *uptimeReply;
static Client *m_instance;
File::~File()
{
+ if (markReply)
+ {
+ delete markReply;
+ markReply = 0;
+ }
if (fileReply)
{
delete fileReply;
return true;
}
-bool File::markWatched(bool watched)
+bool File::markWatched()
{
- if (m_markingState != Success)
+ if (m_markingState == Success)
return true;
if (m_hashingState != Success)
actionsQueue.enqueue(Hashing);
+ if (m_addingState != Success)
+ actionsQueue.enqueue(Adding);
+
+ actionsQueue.enqueue(MarkingWatched);
+
if (notWorking) work();
- return watched;
+ return true;
}
void File::finishMarking(bool success)
{
- Q_UNUSED(success);
+ if (!success)
+ {
+ updateStatus(MarkingWatched, Failure);
+ return;
+ }
+ updateStatus(MarkingWatched, Success);
}
void File::work()
if (actionsQueue.isEmpty())
{
emit statusUpdate(All, Finished);
+ emit finished();
notWorking = true;
return;
}
work();
return;
}
+ MyListAddCommand markCommand(0);
+ if (addReply->lid())
+ markCommand = MyListAddCommand(addReply->lid());
+ else
+ markCommand = MyListAddCommand(m_ed2k, size(), true);
+ markCommand.setViewed(true);
+
+ if (markReply) markReply->deleteLater();
+ markReply = Client::instance()->send(markCommand);
+ connect(markReply, SIGNAL(replyReady(bool)), this, SLOT(finishMarking(bool)));
+
+ updateStatus(MarkingWatched, InProgress);
}
void File::init()
hashResult = 0;
fileReply = 0;
addReply = 0;
+ markReply = 0;
m_hashingState = m_renamingState = m_addingState = m_markingState = NotStarted;
notWorking = true;
void hash();
bool rename();
bool addToMyList();
- bool markWatched(bool watched = true);
+ bool markWatched();
signals:
void statusUpdate(AniDBUdpClient::File::Action action, AniDBUdpClient::File::ActionState state);
+ void finished();
private slots:
void finishHashing();
HashResult *hashResult;
FileReply *fileReply;
MyListAddReply *addReply;
+ MyListAddReply *markReply;
};
{
}
+bool UptimeCommand::waitForResult() const
+{
+ return true;
+}
+
Command UptimeCommand::rawCommand() const
{
Command command;
typedef UptimeReply ReplyType;
UptimeCommand();
+ bool waitForResult() const;
Command rawCommand() const;
};