// ===
-AbstractReply::AbstractReply(const QByteArray &id, Client *client, QObject *parent) : QObject(parent)
+AbstractReply::AbstractReply(const QByteArray &id, QObject *parent) : QObject(parent)
{
m_replyCode = UNKNOWN_REPLY;
m_id = id;
- m_client = client;
m_commandPtr = 0;
m_controlCommand = false;
}
};
#define REPLY_DEFINITION_HELPER_INTERNAL(name, constructor) \
+friend class ClientInterface; \
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) : AbstractReply(id, client, parent), m_command(command), m_client(client) {constructor} \
+name##Reply(const CommandType command, const QByteArray &id, QObject *parent) : AbstractReply(id, parent), m_command(command) {constructor} \
inline const CommandType &command() const { return m_command; }
#define REPLY_DEFINITION_HELPER(name) \
public:
typedef AbstractCommand CommandType;
- AbstractReply(const QByteArray &id, Client *client, QObject *parent = 0);
+ AbstractReply(const QByteArray &id, QObject *parent = 0);
virtual ~AbstractReply();
const CommandType &command() const;
QDateTime m_timeSent;
bool m_controlCommand;
- Client *m_client;
-
AbstractCommand *m_commandPtr;
AbstractCommand m_command;
};
hashconsumer.cpp \\r
clientsentcommandsmodel.cpp \\r
clientqueuedcommandsmodel.cpp \\r
- filerenamedelegate.cpp\r
+ filerenamedelegate.cpp \\r
+ clientinterface.cpp\r
\r
HEADERS += client.h \\r
anidbudpclient_global.h \\r
circularbuffer.h \\r
clientsentcommandsmodel.h \\r
clientqueuedcommandsmodel.h \\r
- filerenamedelegate.h\r
+ filerenamedelegate.h \\r
+ clientinterface.h\r
\r
CONV_HEADERS += include/AniDBUdpClient/Client \\r
include/AniDBUdpClient/AbstractCommand \\r
include/AniDBUdpClient/ClientQueuedCommandsModel \\r
include/AniDBUdpClient/FileRenameDelegate\r
\r
+# proxy files\r
+\r
+CONFIG += qxt\r
+QXT *= network\r
+\r
+HEADERS += proxyclient.h \\r
+ proxyserver.h \\r
+\r
+SOURCES += proxyclient.cpp \\r
+ proxyserver.cpp \\r
+\r
+CONV_HEADERS += include/AniDBUdpClient/ProxyClient \\r
+ include/AniDBUdpClient/ProxyServer\r
+\r
# RenameParser Files\r
\r
HEADERS += renameparser/renameengine.h \\r
const int Client::clientVersion = CLIENT_VERSION;
const int Client::protocolVersion = PROTOCOL_VERSION;
-Client::Client(QObject *parent) : QObject(parent)
+Client::Client(QObject *parent) : ClientInterface(parent)
{
qDebug() << "Api instance init!";
authReply = 0;
uptimeReply = 0;
- m_error = NoError;
m_idlePolicy = DoNothingIdlePolicy;
disconnecting = false;
replyTimeoutTimer->setSingleShot(true);
QObject::connect(replyTimeoutTimer, SIGNAL(timeout()), this, SLOT(commandTimeout()));
- m_localPort = 9001;
- m_host = "api.anidb.info";
- m_hostPort = 9000;
-
setFloodInterval(3);
stateMachine = new QStateMachine(this);
}
}
-QString Client::host() const
-{
- return m_host;
-}
-
-void Client::setHost(const QString &host, quint16 port)
-{
- m_host = host;
- if (port)
- m_hostPort = port;
- m_hostAddress = QHostAddress();
-}
-
-quint16 Client::hostPort() const
-{
- return m_hostPort;
-}
-
-void Client::setHostPort(quint16 port)
-{
- m_hostPort = port;
-}
-
-quint16 Client::localPort() const
-{
- return m_localPort;
-}
-
-void Client::setLocalPort(quint16 port)
-{
- m_localPort = port;
-}
-
QString Client::user() const
{
return authCommand.user();
m_idlePolicy = policy;
}
-Error Client::error() const
-{
- return m_error;
-}
-
-QString Client::errorString() const
-{
- return m_errorString;
-}
-
// ------------------------------------------------------------------------------
void Client::enterErrorState()
if (cmd) cancel(cmd);
}
-QByteArray Client::buildCmd(const QString &cmd, const QVariantMap &args)
-{
- QString result = cmd;
- for (QVariantMap::const_iterator it = args.constBegin(); it != args.constEnd(); ++it)
- {
- if (!it.value().canConvert(QVariant::String))
- {
- qWarning("Passed value cannot be converted to string!");
- continue;
- }
-
- // The string version of bool is "true" or "false", but the API expects 1 or 0
- QString value;
- if (it.value().type() == QVariant::Bool)
- {
- value = it.value().toBool() ? "1" : "0";
- }
- else
- {
- value = it.value().toString();
- }
-
- if (it == args.constBegin())
- result += QString(" %1=%2").arg(it.key(), value);
- else
- result += QString("&%1=%2").arg(it.key(), value);
- }
- return result.toUtf8();
-}
-
-QByteArray Client::nextCommandId(int len)
-{
- static const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
- static const int numChars = sizeof(chars) - 1;
-
- QByteArray result(len, '-');
- while (len--)
- result[len] = chars[qrand() % numChars];
-
-qDebug() << QString("Generated id %1").arg(result.constData());
- return result;
-}
-
Client *Client::m_instance = 0;
// TODO, figure out why GCC can't export it like it could before, because this doesn't work in other compilers.
#define ANIDBUDPCLIENT_H
#include "anidbudpclient_global.h"
-#include <QObject>
+#include "clientinterface.h"
#include <QQueue>
#include <QTimer>
-#include <QHostAddress>
-#include <QHostInfo>
-#include <QVariantMap>
#include "authcommand.h"
class LogoutReply;
class UptimeReply;
-class ANIDBUDPCLIENTSHARED_EXPORT Client : public QObject
+class ANIDBUDPCLIENTSHARED_EXPORT Client : public ClientInterface
{
friend class AbstractReply;
friend class ClientQueuedCommandsModel;
Q_OBJECT
Q_ENUMS(AniDBUdpClient::State AniDBUdpClient::Error AniDBUdpClient::IdlePolicy AniDBUdpClient::ReplyCode);
- Q_PROPERTY(QString host READ host WRITE setHost);
- Q_PROPERTY(quint16 hostPort READ hostPort WRITE setHostPort);
- Q_PROPERTY(quint16 localPort READ localPort WRITE setLocalPort);
-
- Q_PROPERTY(QString user READ user WRITE setUser);
- Q_PROPERTY(QString pass READ pass WRITE setPass);
-
/*
- Send commands in \interval seconds intervals
+ Send commands in interval seconds intervals
*/
- Q_PROPERTY(int floodInterval READ floodInterval WRITE setFloodInterval);
- Q_PROPERTY(IdlePolicy idlePolicy READ idlePolicy WRITE setIdlePolicy);
- Q_PROPERTY(Error error READ error);
- Q_PROPERTY(QString errorString READ errorString);
+ Q_PROPERTY(int floodInterval READ floodInterval WRITE setFloodInterval)
+ Q_PROPERTY(IdlePolicy idlePolicy READ idlePolicy WRITE setIdlePolicy)
+ Q_PROPERTY(Error error READ error)
public:
static const QByteArray clientName;
public:
// ------------------ Properties ------------------
- QString host() const;
- void setHost(const QString &host, quint16 port = 0);
- quint16 hostPort() const;
- void setHostPort(quint16 port);
- quint16 localPort() const;
- void setLocalPort(quint16 port);
-
QString user() const;
void setUser(const QString &user);
QString pass() const;
IdlePolicy idlePolicy() const;
void setIdlePolicy(IdlePolicy policy);
- Error error() const;
- QString errorString() const;
-
// ---------------- END Properties ----------------
void clearCommandQueue();
public slots:
void connect();
-
- /*
- Disconnect from host.
- If \graceful is true send all enququed messages first.
- */
void disconnect(bool graceful = false);
public:
return reply;
}
-private:
+protected:
template<typename T> typename T::ReplyType *createReply(const T &command, QObject *parent = 0)
{
- return new typename T::ReplyType(command, nextCommandId(), this, parent);
+ return new typename T::ReplyType(command, nextCommandId(), parent);
}
+
public slots:
void send(AbstractReply *reply);
void replyRecieved();
void sendFailed();
- void connectionError();
-
void model_queuedCommandAdded(int index);
void model_queuedCommandRemoved(int index);
void model_sentCommandAdded(int index);
void logout(bool force);
- QByteArray buildCmd(const QString &cmd, const QVariantMap &args);
- QByteArray nextCommandId(int len = 5);
-
QTimer *commandTimer;
QTimer *idleTimer;
QTimer *replyTimeoutTimer;
QUdpSocket *socket;
-
- // Connection params
- QString m_host;
- QHostAddress m_hostAddress;
- quint16 m_hostPort;
- quint16 m_localPort;
-
int m_floodInterval;
QByteArray m_sessionId;
// Misc params
IdlePolicy m_idlePolicy;
Error m_error;
- QString m_errorString;
bool disconnecting;
bool authenticatingStarted;
--- /dev/null
+#include "clientinterface.h"
+
+namespace AniDBUdpClient {
+
+ClientInterface::ClientInterface(QObject *parent) :
+ QObject(parent), m_error(NoError)
+{
+ m_localPort = 9001;
+ m_host = "api.anidb.info";
+ m_hostPort = 9000;
+}
+
+QString ClientInterface::host() const
+{
+ return m_host;
+}
+
+void ClientInterface::setHost(const QString &host, quint16 port)
+{
+ m_host = host;
+ if (port)
+ m_hostPort = port;
+ m_hostAddress = QHostAddress();
+}
+
+quint16 ClientInterface::hostPort() const
+{
+ return m_hostPort;
+}
+
+void ClientInterface::setHostPort(quint16 port)
+{
+ m_hostPort = port;
+}
+
+quint16 ClientInterface::localPort() const
+{
+ return m_localPort;
+}
+
+void ClientInterface::setLocalPort(quint16 port)
+{
+ m_localPort = port;
+}
+
+Error ClientInterface::error() const
+{
+ return m_error;
+}
+
+QString ClientInterface::errorString() const
+{
+ return m_errorString;
+}
+
+QByteArray ClientInterface::nextCommandId(int len)
+{
+ static const char chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
+ static const int numChars = sizeof(chars) - 1;
+
+ QByteArray result(len, '-');
+ while (len--)
+ result[len] = chars[qrand() % numChars];
+
+qDebug() << QString("Generated id %1").arg(result.constData());
+ return result;
+}
+
+QByteArray ClientInterface::buildCmd(const QString &cmd, const QVariantMap &args)
+{
+ QString result = cmd;
+ for (QVariantMap::const_iterator it = args.constBegin(); it != args.constEnd(); ++it)
+ {
+ if (!it.value().canConvert(QVariant::String))
+ {
+ qWarning("Passed value cannot be converted to string!");
+ continue;
+ }
+
+ // The string version of bool is "true" or "false", but the API expects 1 or 0
+ QString value;
+ if (it.value().type() == QVariant::Bool)
+ {
+ value = it.value().toBool() ? "1" : "0";
+ }
+ else
+ {
+ value = it.value().toString();
+ }
+
+ if (it == args.constBegin())
+ result += QString(" %1=%2").arg(it.key(), value);
+ else
+ result += QString("&%1=%2").arg(it.key(), value);
+ }
+ return result.toUtf8();
+}
+
+} // namespace AniDBUdpClient
--- /dev/null
+#ifndef CLIENTINTERFACE_H
+#define CLIENTINTERFACE_H
+
+#include "anidbudpclient_global.h"
+#include <QObject>
+#include <QHostAddress>
+#include <QHostInfo>
+#include <QVariantMap>
+
+namespace AniDBUdpClient {
+
+class AbstractReply;
+
+class ANIDBUDPCLIENTSHARED_EXPORT ClientInterface : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString host READ host WRITE setHost)
+ Q_PROPERTY(quint16 hostPort READ hostPort WRITE setHostPort)
+ Q_PROPERTY(quint16 localPort READ localPort WRITE setLocalPort)
+
+ Q_PROPERTY(QString user READ user WRITE setUser)
+ Q_PROPERTY(QString pass READ pass WRITE setPass)
+
+ Q_PROPERTY(QString errorString READ errorString)
+
+public:
+ ClientInterface(QObject *parent = 0);
+ virtual ~ClientInterface() {}
+
+ QString host() const;
+ void setHost(const QString &host, quint16 port = 0);
+ quint16 hostPort() const;
+ void setHostPort(quint16 port);
+ quint16 localPort() const;
+ void setLocalPort(quint16 port);
+
+ virtual QString user() const = 0;
+ virtual void setUser(const QString &user) = 0;
+ virtual QString pass() const = 0;
+ virtual void setPass(const QString &user) = 0;
+
+ Error error() const;
+ QString errorString() const;
+
+ template<typename T> typename T::ReplyType *send(const T &command, QObject *parent = 0)
+ {
+ typename T::ReplyType *reply = createReply(command, parent);
+ send(reply);
+ return reply;
+ }
+
+protected:
+ template<typename T> typename T::ReplyType *createReply(const T &command, QObject *parent = 0)
+ {
+ return new typename T::ReplyType(command, nextCommandId(), parent);
+ }
+
+public slots:
+ virtual void connect() = 0;
+ virtual void disconnect(bool graceful = false) = 0;
+
+ virtual void send(AbstractReply *reply) = 0;
+
+// virtual void sendRaw(QByteArray command) = 0;
+ virtual void cancel(AbstractReply *command) = 0;
+
+signals:
+ void connectionError();
+
+protected:
+ QByteArray nextCommandId(int len = 5);
+ QByteArray buildCmd(const QString &cmd, const QVariantMap &args);
+
+ // Connection params
+ QString m_host;
+ QHostAddress m_hostAddress;
+ quint16 m_hostPort;
+ quint16 m_localPort;
+
+ Error m_error;
+ QString m_errorString;
+};
+
+} // namespace AniDBUdpClient
+
+#endif // CLIENTINTERFACE_H
fileCommand.setFmask(m_renameDelegate->requiredFMask());
}
- fileReply = Client::instance()->send(fileCommand);
+ fileReply = clientInstance()->send(fileCommand);
connect(fileReply, SIGNAL(replyReady(bool)), this, SLOT(finishRenaming(bool)));
updateStatus(Renaming, InProgress);
MyListAddCommand addCommand(m_ed2k, size(), false);
addCommand.setState(StateOnHdd);
- addReply = Client::instance()->send(addCommand);
+ addReply = clientInstance()->send(addCommand);
connect(addReply, SIGNAL(replyReady(bool)), this, SLOT(finishAdding(bool)));
markCommand.setViewed(true);
if (markReply) markReply->deleteLater();
- markReply = Client::instance()->send(markCommand);
+ markReply = clientInstance()->send(markCommand);
connect(markReply, SIGNAL(replyReady(bool)), this, SLOT(finishMarking(bool)));
updateStatus(MarkingWatched, InProgress);
emit statusUpdate(action, actionState);
}
+
+ClientInterface *File::clientInstance() const
+{
+ return m_clientInterface ? m_clientInterface : Client::instance();
+}
+
+ClientInterface *File::m_clientInterface = 0;
+
+ClientInterface *File::clientInterface()
+{
+ return m_clientInterface;
+}
+
+void File::setClientInterface(ClientInterface *clientInterface)
+{
+ m_clientInterface = clientInterface;
+}
+
} // namespace AniDBUdpClient
FileRenameDelegate *m_renameDelegate;
+ ClientInterface *clientInstance() const;
+
+ static ClientInterface *m_clientInterface;
+public:
+ static ClientInterface *clientInterface();
+ static void setClientInterface(ClientInterface *clientInterface);
+
};
} // namespace AniDBUdpClient
--- /dev/null
+#include "proxyclient.h"
+
+#include <QxtRPCPeer>
+
+#include "abstractcommand.h"
+
+#include <QDebug>
+
+namespace AniDBUdpClient {
+
+ProxyClient::ProxyClient(QObject *parent) :
+ ClientInterface(parent), peer(new QxtRPCPeer)
+{
+ m_hostPort = 9001;
+ peer->attachSlot("replyRecieved", this, SLOT(replyRecieved(QByteArray,int,QString)));
+ peer->attachSlot("errorRecieved", this, SLOT(errorRecieved(int)));
+}
+
+ProxyClient::~ProxyClient()
+{
+ disconnect();
+ delete peer;
+}
+
+QString ProxyClient::user() const
+{
+ return m_user;
+}
+
+void ProxyClient::setUser(const QString &user)
+{
+ m_user = user;
+}
+
+QString ProxyClient::pass() const
+{
+ return m_pass;
+}
+
+void ProxyClient::setPass(const QString &pass)
+{
+ m_pass = pass;
+}
+
+void ProxyClient::connect()
+{
+ peer->connect(m_host, m_hostPort);
+ peer->call("auth", m_user, m_pass);
+qDebug() << "[CLIENT] CALL auth" << m_user << m_pass;
+}
+
+void ProxyClient::disconnect(bool graceful)
+{
+ Q_UNUSED(graceful);
+ peer->disconnectServer();
+
+ for (QMap<QByteArray, AbstractReply *>::const_iterator i = commands.constBegin(); i != commands.constEnd(); ++i)
+ {
+ i.value()->setRawReply(CLIENT_DESTROYED, "");
+ }
+ commands.clear();
+}
+
+void ProxyClient::send(AbstractReply *reply)
+{
+ if (reply->command().waitForResult())
+ commands[reply->id()] = reply;
+
+ Command cmd = reply->command().rawCommand();
+ peer->call("sendCommand", reply->id(), buildCmd(cmd.first, cmd.second));
+qDebug() << "[CLIENT] CALL sendCommand" << reply->id() << buildCmd(cmd.first, cmd.second);
+ if (!reply->command().waitForResult())
+ delete reply;
+}
+
+void ProxyClient::cancel(AbstractReply *command)
+{
+ peer->call("cancel", command->id());
+qDebug() << "[CLIENT] CALL cancel";
+}
+
+void ProxyClient::replyRecieved(const QByteArray &id, int replyCodeAsInt, const QString &reply)
+{
+ ReplyCode replyCode = (ReplyCode) replyCodeAsInt;
+qDebug() << "[CLIENT] RECV replyRecieved" << id << replyCode << reply;
+ AbstractReply *command = commands.value(id, 0);
+
+ if (!command)
+ {
+ // Not interested in this reply
+ return;
+ }
+
+ command->setRawReply(replyCode, reply);
+}
+
+void ProxyClient::errorRecieved(int errorAsInt)
+{
+ Error error = (Error) errorAsInt;
+qDebug() << "[CLIENT] RECV errorRecieved" << error;
+ m_error = error;
+ emit connectionError();
+}
+
+} // namespace AniDBUdpClient
--- /dev/null
+#ifndef PROXYCLIENT_H
+#define PROXYCLIENT_H
+
+#include "anidbudpclient_global.h"
+#include "clientinterface.h"
+
+class QxtRPCPeer;
+
+namespace AniDBUdpClient {
+
+class ANIDBUDPCLIENTSHARED_EXPORT ProxyClient : public ClientInterface
+{
+ Q_OBJECT
+public:
+ explicit ProxyClient(QObject *parent = 0);
+ ~ProxyClient();
+
+ QString user() const;
+ void setUser(const QString &user);
+ QString pass() const;
+ void setPass(const QString &pass);
+
+ template<typename T> typename T::ReplyType *send(const T &command, QObject *parent = 0)
+ {
+ typename T::ReplyType *reply = createReply(command, parent);
+ send(reply);
+ return reply;
+ }
+
+protected:
+ template<typename T> typename T::ReplyType *createReply(const T &command, QObject *parent = 0)
+ {
+ return new typename T::ReplyType(command, nextCommandId(), parent);
+ }
+
+public slots:
+ void connect();
+ void disconnect(bool graceful = false);
+
+ void send(AbstractReply *reply);
+
+ void cancel(AbstractReply *command);
+
+private slots:
+ void replyRecieved(const QByteArray &id, int replyCodeAsInt, const QString &reply);
+ void errorRecieved(int errorAsInt);
+
+private:
+ QString m_user;
+ QString m_pass;
+
+ QxtRPCPeer *peer;
+
+ QMap<QByteArray, AbstractReply *> commands;
+};
+
+} // namespace AniDBUdpClient
+
+#endif // PROXYCLIENT_H
--- /dev/null
+#include "proxyserver.h"
+#include <QxtRPCPeer>
+
+#include "client.h"
+#include "rawcommand.h"
+
+#include <QDebug>
+
+namespace AniDBUdpClient {
+
+ProxyServer::ProxyServer(QObject *parent) :
+ QObject(parent), peer(new QxtRPCPeer)
+{
+ connect(peer, SIGNAL(clientConnected(quint64)), this, SLOT(clientConnected(quint64)));
+ connect(peer, SIGNAL(clientDisconnected(quint64)), this, SLOT(clientDisconnected(quint64)));
+ peer->attachSlot("auth", this, SLOT(auth(quint64,QString,QString)));
+ peer->attachSlot("sendCommand", this, SLOT(sendCommand(quint64,QByteArray,QByteArray)));
+ peer->attachSlot("cancel", this, SLOT(cancel(quint64,QByteArray)));
+}
+
+ProxyServer::~ProxyServer()
+{
+ peer->disconnectAll();
+
+ clientInfo.clear();
+ clientCommands.clear();
+ qDeleteAll(idMapping);
+ idMapping.clear();
+/* for (QMap<RawReply *, QByteArray>::const_iterator i = replyMapping.constBegin(); i != replyMapping.constEnd(); ++i)
+ {
+ i.key()->deleteLater();
+ }
+*/
+ replyMapping.clear();
+
+ delete peer;
+}
+
+QString ProxyServer::user() const
+{
+ return m_user;
+}
+
+void ProxyServer::setUser(const QString &user)
+{
+ m_user = user;
+}
+
+QString ProxyServer::pass() const
+{
+ return m_pass;
+}
+
+void ProxyServer::setPass(const QString &pass)
+{
+ m_pass = pass;
+}
+
+bool ProxyServer::listen(QHostAddress iface, int port)
+{
+ return peer->listen(iface, port);
+}
+
+void ProxyServer::diconnect()
+{
+ peer->disconnectAll();
+}
+
+void ProxyServer::auth(quint64 client, const QString &user, const QString &pass)
+{
+qDebug() << "[SERVER] RECV auth" << client << user << pass;
+ if (isAuthed(client))
+ return;
+
+ if (m_user != user || m_pass != pass)
+ {
+ peer->call(client, "errorRecieved", (int) AuthenticationError);
+qDebug() << "[SERVER] CALL errorRecieved" << AuthenticationError;
+ peer->disconnectClient(client);
+ return;
+ }
+ clientInfo[client].authed = true;
+ qDebug() << "[SERVER] Auth successful" << client;
+
+}
+
+void ProxyServer::sendCommand(quint64 client, const QByteArray &id, const QByteArray &rawCommand)
+{
+qDebug() << "[SERVER] RECV sendCommand" << client << id << rawCommand;
+ if (!isAuthed(client))
+ return;
+
+ RawReply *reply = Client::instance()->send(RawCommand(rawCommand));
+ connect(reply, SIGNAL(replyReady(bool)), this, SLOT(replyReady(bool)));
+
+ clientCommands[id] = client;
+ replyMapping[reply] = id;
+ idMapping[id] = reply;
+}
+
+void ProxyServer::cancel(quint64 client, const QByteArray &id)
+{
+ if (!isAuthed(client))
+ return;
+
+ if (!idMapping.contains(id))
+ return;
+
+ RawReply *reply = idMapping.take(id);
+ replyMapping.remove(reply);
+ clientCommands.remove(id);
+
+ Client::instance()->cancel(reply);
+ reply->deleteLater();
+}
+
+void ProxyServer::clientConnected(quint64 client)
+{
+qDebug() << "client connected" << client;
+ clientInfo.insert(client, ClientInfo());
+}
+
+void ProxyServer::clientDisconnected(quint64 client)
+{
+qDebug() << "[SERVER] RECV client disconnected" << client;
+ for (QMap<QByteArray, quint64>::iterator i = clientCommands.begin(); i != clientCommands.end(); )
+ {
+ if (i.value() != client)
+ {
+ ++i;
+ continue;
+ }
+
+ RawReply *reply = idMapping.take(i.key());
+ Client::instance()->cancel(reply);
+ replyMapping.remove(reply);
+ reply->deleteLater();
+ clientCommands.erase(i);
+ }
+
+ clientInfo.remove(client);
+}
+
+void ProxyServer::replyReady(bool success)
+{
+ Q_UNUSED(success);
+
+ RawReply *reply = (RawReply *) sender();
+
+ QByteArray id = replyMapping.take(reply);
+ quint64 client = clientCommands.take(id);
+ idMapping.remove(id);
+
+ peer->call(client, "replyRecieved", id, (int) reply->replyCode(), reply->rawReply());
+qDebug() << "[SERVER] CALL replyRecieved" << id << reply->replyCode() << reply->rawReply();
+ reply->deleteLater();
+}
+
+bool ProxyServer::isAuthed(quint64 client) const
+{
+ return clientInfo[client].authed;
+}
+
+} // namespace AniDBUdpClient
--- /dev/null
+#ifndef PROXYSERVER_H
+#define PROXYSERVER_H
+
+#include "anidbudpclient_global.h"
+#include <QObject>
+#include <QHostAddress>
+
+class QxtRPCPeer;
+
+namespace AniDBUdpClient {
+
+class RawReply;
+
+class ANIDBUDPCLIENTSHARED_EXPORT ProxyServer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString user READ user WRITE setUser)
+ Q_PROPERTY(QString pass READ pass WRITE setPass)
+
+ struct ClientInfo {
+ bool authed;
+
+ explicit ClientInfo() : authed(false) {}
+ };
+
+public:
+ explicit ProxyServer(QObject *parent = 0);
+ ~ProxyServer();
+
+ QString user() const;
+ void setUser(const QString &user);
+ QString pass() const;
+ void setPass(const QString &pass);
+
+signals:
+
+public slots:
+ bool listen(QHostAddress iface = QHostAddress::Any, int port = 9001);
+ void diconnect();
+
+private slots:
+ void auth(quint64 client, const QString &user, const QString &pass);
+ void sendCommand(quint64 client, const QByteArray &id, const QByteArray &rawCommand);
+ void cancel(quint64 client, const QByteArray &id);
+
+ void clientConnected(quint64 client);
+ void clientDisconnected(quint64 client);
+
+ void replyReady(bool success);
+
+private:
+ bool isAuthed(quint64 client) const;
+
+ QString m_user;
+ QString m_pass;
+
+ QxtRPCPeer *peer;
+
+ QMap<quint64, ClientInfo> clientInfo;
+ QMap<QByteArray, quint64> clientCommands;
+ QMap<QByteArray, RawReply *> idMapping;
+ QMap<RawReply *, QByteArray> replyMapping;
+};
+
+} // namespace AniDBUdpClient
+
+#endif // PROXYSERVER_H