aheinecke@10: #ifndef DOWNLOADER_H aheinecke@10: #define DOWNLOADER_H aheinecke@10: /** aheinecke@10: * @file downloader.h aheinecke@10: * @brief High level API to download necessary data. aheinecke@10: * aheinecke@10: */ aheinecke@10: aheinecke@10: #include aheinecke@10: #include aheinecke@10: #include aheinecke@15: #include andre@27: #include aheinecke@15: andre@27: #include andre@27: #include andre@27: #include andre@27: #include aheinecke@10: aheinecke@10: class Downloader: public QThread aheinecke@10: { aheinecke@10: Q_OBJECT aheinecke@10: aheinecke@10: public: aheinecke@10: /** aheinecke@15: * @brief Construct a downloader with a specific certificate aheinecke@10: * aheinecke@15: * The downloader will check the last-modified date of the aheinecke@15: * certificate list / sw on the server at the specified url aheinecke@15: * and download those accordingly. If newestSW or newestList is aheinecke@15: * are valid datetimes only files modified after the respective date aheinecke@15: * are downloaded. aheinecke@15: * aheinecke@15: * Downloaded files are placed in QStandardPaths::DataLocation aheinecke@10: * aheinecke@10: * @param[in] parent the parent object. aheinecke@10: * @param[in] url the Url to download data from aheinecke@15: * @param[in] certificate optional certificate to validate https connection aheinecke@15: * @param[in] newestSW datetime after which software should be downloaded aheinecke@15: * @param[in] newestList datetime after which the list should be downloaded aheinecke@10: */ aheinecke@10: Downloader(QObject* parent, const QString& url, aheinecke@15: const QByteArray& certificate = QByteArray(), aheinecke@15: const QDateTime& newestSW = QDateTime(), aheinecke@15: const QDateTime& newestList = QDateTime()); aheinecke@10: andre@27: ~Downloader(); aheinecke@10: aheinecke@10: enum ErrorCode { andre@27: NoError, aheinecke@10: NoConnection, andre@32: SSLHandshakeFailed, aheinecke@10: InvalidCertificate, andre@27: InvalidPinnedCertificate, andre@32: InvalidResponse, aheinecke@10: ConnectionLost, aheinecke@10: Timeout, aheinecke@15: ErrUnknown aheinecke@10: }; aheinecke@10: aheinecke@10: /** aheinecke@15: * @brief get the directory where the downloader saves data aheinecke@10: * aheinecke@15: * If the directory does not exist this function ensures that it aheinecke@15: * is created. aheinecke@15: * aheinecke@15: * @returns The directory in which downloaded files are placed. aheinecke@15: **/ aheinecke@15: QString getDataDirectory(); aheinecke@15: andre@27: /** andre@27: * @brief get the current error state andre@27: * andre@27: * @returns The current error state. andre@27: **/ andre@27: ErrorCode getErrorState(); aheinecke@10: aheinecke@10: protected: aheinecke@10: void run(); aheinecke@10: aheinecke@10: private: andre@27: QUrl mUrl; andre@27: QByteArray mPinnedCert; andre@27: x509_crt mX509PinnedCert; andre@27: entropy_context mEntropy; andre@27: ctr_drbg_context mCtr_drbg; andre@27: ssl_context mSSL; aheinecke@10: aheinecke@15: QDateTime mLastModSW; aheinecke@15: QDateTime mLastModList; aheinecke@15: andre@27: /* Convienience to avoid having to parse all andre@27: * PolarSSL errors */ andre@27: ErrorCode mErrorState; aheinecke@15: andre@27: bool mInitialized; andre@32: bool mConnectionEstablished; andre@27: andre@27: int mServerFD; andre@27: andre@27: andre@27: /* @brief: Initialize polarssl structures aheinecke@15: * andre@27: * This wraps polarssl initialization functions andre@27: * that can return an error. andre@27: * Sets the error state accordingly. aheinecke@15: * andre@27: * @returns: 0 on success a polarssl error otherwise. aheinecke@15: */ andre@27: int init(); aheinecke@15: andre@32: /** @brief: Establish the ssl connection andre@32: * andre@32: * Modifies the error state. Before calling this the mServerFD should andre@32: * be set to a valid socket. aheinecke@15: * andre@27: * @returns 0 on success otherwise a polarssl error or -1 is returned aheinecke@15: */ andre@27: int establishSSLConnection(); andre@32: andre@32: /** @brief get the last modified header of a resource. andre@32: * andre@32: * Connection should be established beforehand. andre@32: * Modifies the error state. andre@32: * andre@32: * @param[in] resource The resource to check andre@32: * andre@32: * @returns the last modified date or a null datetime in case of errors andre@32: */ andre@32: QDateTime getLastModifiedHeader(const QString &resource); andre@32: andre@32: /** @brief Download resource andre@32: * andre@32: * Download a resource with the established connection. andre@32: * Modifies the error state. andre@32: * andre@32: * @param[in] resource the resource to download andre@32: * @param[in] filename where the file should be saved. andre@32: * @param[in] maxSize maximum amount of bytes to download andre@32: * andre@32: * @returns True if the download was successful. andre@32: */ andre@32: bool downloadFile(const QString &resource, const QString &filename, andre@32: size_t maxSize); aheinecke@15: aheinecke@10: Q_SIGNALS: aheinecke@10: /** aheinecke@15: * @brief software update is available aheinecke@15: */ aheinecke@15: void newSoftwareAvailable(const QString &fileName, aheinecke@15: const QDateTime &lastMod); aheinecke@15: aheinecke@15: /** aheinecke@15: * @brief new certificate list available aheinecke@15: */ aheinecke@15: void newListAvailable(const QString &fileName, const QDateTime &lastMod); aheinecke@15: aheinecke@15: /** aheinecke@10: * @brief Some progress has been made. aheinecke@10: * aheinecke@10: * @param[out] message: A message to show. Can be empty. aheinecke@10: * @param[out] current: Value of current progress. aheinecke@10: * @param[out] total: Total value of possible progress aheinecke@10: */ aheinecke@10: void progress(const QString &message, int current, int total); aheinecke@10: aheinecke@10: /** aheinecke@10: * @brief An error happened aheinecke@10: * aheinecke@10: * @param[out] message: A message to show. Can be empty. aheinecke@10: * @param[out] errorCode: ErrorCode of this error. aheinecke@10: */ andre@27: void error(const QString &message, Downloader::ErrorCode error); aheinecke@10: }; aheinecke@10: #endif