#ifndef AGENT_H #define AGENT_H #include #include #include #include "compressor.h" class Agent : public QObject { Q_OBJECT Q_FLAGS(SyncFlag SyncFlags) public: enum SyncFlag { SYNC_NORMAL = 0, SYNC_PULL = 0x1, SYNC_READ_ONLY = 0x2, SYNC_COMPRESS = 0x8 }; Q_DECLARE_FLAGS(SyncFlags, SyncFlag) public: explicit Agent(QSslSocket *socket, const QDir& dir, SyncFlags flags, QObject *parent = 0); static const uint servicePort = 17451; signals: void finished(); protected: #pragma pack(push) #pragma pack(1) enum MessageType { MSG_HELLO = 0, MSG_HELLO_REPLY, MSG_SET_SUBROOT, //args: string MSG_FILE_LIST, //args: FileListItem[] MSG_FILE_ACTIONS_REPLY, //args: ActionItem[] MSG_PULL_FILE, //args: string MSG_PULL_FILE_REPLY, //args: data MSG_PUSH_FILE, //args: FileNameItem + data MSG_PUSH_FILE_METADATA, //args: FileListItem[] MSG_DELETE_FILE, //args: string MSG_BYE }; struct MessageHeader { quint32 msg; quint32 len; }; enum FileType { FILE_TYPE_NONE = 0, FILE_TYPE_FILE, FILE_TYPE_DIR }; struct FileListItem { quint64 size; quint32 mtime; quint16 name_len; quint8 type; char name[]; }; enum FileAction { ACTION_NONE = 0, ACTION_PULL_METADATA, ACTION_PUSH_METADATA, ACTION_PULL, ACTION_PUSH, ACTION_PULL_DELETE, ACTION_PUSH_DELETE }; struct ActionItem { quint64 size; quint32 mtime; quint16 name_len; quint8 type; quint8 action; char name[]; }; struct FileNameItem { quint16 name_len; char name[]; }; #pragma pack(pop) protected: class RemoteFileInfo { public: RemoteFileInfo(); RemoteFileInfo(const QString &name, FileType type, const QDateTime &mtime, qint64 size); inline qint64 size() const { return _size; } inline QDateTime lastModified() const { return _mtime; } inline QString name() const { return _name; } inline bool isDir() const { return _type == FILE_TYPE_DIR; } private: QString _name; FileType _type; QDateTime _mtime; qint64 _size; }; typedef QList RemoteFileInfoList; class ActionInfo { public: ActionInfo(FileAction action, const QFileInfo& fileInfo); inline FileAction action() const { return _action; } inline QFileInfo fileInfo() const { return _info; } private: FileAction _action; QFileInfo _info; }; typedef QList ActionInfoList; class RemoteActionInfo { public: RemoteActionInfo(FileAction action, const QString& name, FileType type, const QDateTime& mtime, qint64 size); inline FileAction action() const { return _action; } inline RemoteFileInfo fileInfo() const { return _info; } private: FileAction _action; RemoteFileInfo _info; }; typedef QList RemoteActionInfoList; protected: void sendMessage(MessageType msg, const QByteArray& data = QByteArray()); virtual void handleMessage(MessageType msg, const QByteArray& data) = 0; int inBufRequiredData() const; bool equalDateTime(const QDateTime& dt1, const QDateTime& dt2); void setLocalFileDateTime(const QString &path, const QDateTime& dt); QString wireToLocalPath(const QString& path); QString localToWirePath(const QString& path); QString wireParentPath(const QString& path); QString findExistingCommonAncestor(const QString& path, const QHash& local_files, const QHash& remote_files); static bool lessPathDepthThan(const QString& s1, const QString& s2); static bool morePathDepthThan(const QString& s1, const QString& s2); static QFileInfoList scanFiles(const QDir& dir); QByteArray encodeFileInfoList(const QFileInfoList& list); RemoteFileInfoList decodeFileInfoList(const QByteArray& ba); QByteArray encodeActionInfoList(const ActionInfoList& list); RemoteActionInfoList decodeActionInfoList(const QByteArray& ba); static bool lessPathDepthThan(const ActionInfo& a1, const ActionInfo& a2); static bool morePathDepthThan(const ActionInfo& a1, const ActionInfo& a2); QByteArray encodeFileName(const QString& wire_path); QString decodeFileName(const QByteArray& ba); QByteArray encodeFileNameItem(const QString& wire_path); QString decodeFileNameItem(const QByteArray& ba, int* length); protected: QDir _dir; QString _subPath; SyncFlags _flags; QSslSocket *_socket; QByteArray _inBuf; private slots: void handleDataAvailable(); void handleSslErrors(const QList& errors); void handleDisconnected(); }; Q_DECLARE_OPERATORS_FOR_FLAGS(Agent::SyncFlags) #endif // AGENT_H