Added build script of Debian
[qtrapids] / src / server / TorrentSession.cpp
index 6158452..d9d2b95 100644 (file)
+/***************************************************************************
+ *   Copyright (C) 2010 by Ixonos Plc   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; version 2 of the License.               *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
 #include "TorrentSession.hpp"
 #include "TorrentHandle.hpp"
 #include "AlertWaiterThread.hpp"
-
+#include "ServerDb.hpp"
+#include <qtrapids/error.hpp>
 
 namespace qtrapids
 {
 
 
 
-    TorrentSession::TorrentSession(QObject *parent, QSettings *settings)
-        : QObject(parent)
-        , btSession_()
+TorrentSession::TorrentSession(QObject *parent, QSettings *settings)
+               : QObject(parent)
+               , btSession_()
                , alertWaiter_(new AlertWaiterThread(&btSession_, this))
-    {
-        qDBusRegisterMetaType<qtrapids::TorrentState>();
-        qDBusRegisterMetaType<qtrapids::ParamsMap_t>();
-        new QtRapidsServer(this);
-
-        QDBusConnection dbus = QDBusConnection::sessionBus();
-        dbus.registerObject("/qtrapids", this);
-        dbus.registerService("com.ixonos.qtrapids");
-
-        alertWaiter_->allAlerts();
-        connect(alertWaiter_, SIGNAL(alert()), this, SLOT(on_alert()));
-        alertWaiter_->start();
-
-
-    }
-
-    void TorrentSession::on_alert()
-    //NOTE: al parameter not necessarily needed here, as we pop_alert() now!
-    {
-
-        //qDebug() << "QBittorrentSession:on_alert(" << al << ")";
-        //     if (al)
-        //             qDebug() << "on_alert():" << QString::fromStdString(al->message());
-
-        std::auto_ptr<alert_t> alertPtr = btSession_.pop_alert();
-
-        if (alertPtr.get() != NULL) {
-
-            torrent_alert_t *ta = dynamic_cast<torrent_alert_t*> (alertPtr.get());
-
-            qDebug()
-                               << "QBittorrentSession::on_alert(): "
-                               << QString::fromStdString(alertPtr->message());
-
-
-            if (ta) {
-
-                if (!ta->handle.is_valid()) {
-                    qDebug() << "handle is invalid";
-                    return;
-                }
-
-                TorrentHandle handle(ta->handle);
-                TorrentState state;
-
-                state.hash = Hash2QStr(handle.hash());
-                state.is_new = false;
-                state.state = handle.state();
-                state.progress = handle.progress() * torrent_progress_max;
-                state.down_rate = handle.downloadRate();
-                state.up_rate = handle.uploadRate();
-                state.seeds = handle.numSeeds();
-                state.leeches = handle.numLeeches();
-            
-                ParamsMap_t params;
-                emit alert(state, params);
-            }
-
-        }
-    }
-
-    void TorrentSession::getState()
-    {
-        torrents_t::const_iterator p;
-        for (p = torrents_.constBegin(); p != torrents_.constEnd(); ++p) {
-            TorrentHandlePtr handle = *p;
-            TorrentState state;
-            QString hash = Hash2QStr(handle->hash());
-            
-            state.hash = hash;
-            state.name = handle->name();
-            state.is_new = true;
-            state.state = handle->state();
-            state.progress = handle->progress() * torrent_progress_max;
-            state.down_rate = handle->downloadRate();
-            state.up_rate = handle->uploadRate();
-            state.seeds = handle->numSeeds();
-            state.leeches = handle->numLeeches();
-            state.total_size = handle->getTotalSize();
-
-            emit alert(state, ParamsMap_t());
-        }
-    }
-
-    void TorrentSession::addTorrent(const QString &path, const QString &save_path
-                                    , qtrapids::ParamsMap_t other_params)
-    {
-        add_torrent_params_t addParams;
-        QFile torrent_file(path);
-        if (!torrent_file.exists()) {
-            qWarning() << "Torrent file " << path << "doesn't exist";
-            return;
-        }
-
-        qDebug() << "addTorrent: " << path << " save to " << save_path;
-        boost::intrusive_ptr<libtorrent::torrent_info> tiTmp
-            = new libtorrent::torrent_info
-            (boost::filesystem::path(path.toStdString()));
-        addParams.ti = tiTmp;
-
-        // save_path is the only mandatory parameter, rest are optional.
-        addParams.save_path = boost::filesystem::path(save_path.toStdString());
-        //addParams.storage_mode = libtorrent::storage_mode_allocate;
-
-        TorrentHandlePtr handle(new TorrentHandle(btSession_.add_torrent(addParams)));
-        QString hash = Hash2QStr(handle->hash());
-
-        TorrentState state;
-
-        state.hash = hash;
-        state.name = handle->name();
-        state.is_new = true;
-        state.state = handle->state();
-        state.progress = handle->progress() * torrent_progress_max;
-        state.down_rate = handle->downloadRate();
-        state.up_rate = handle->uploadRate();
-        state.seeds = handle->numSeeds();
-        state.leeches = handle->numLeeches();
-        state.total_size = handle->getTotalSize();
-
-        torrents_[hash] = handle;
-
-        emit alert(state, ParamsMap_t());
-    }
-
-    void TorrentSession::removeTorrent(const QString &hash)
-    {
-        torrents_t::iterator p = torrents_.find(hash);
-        if (p == torrents_.end()) {
-            qDebug() << "Invalid request to remove torrent with hash " << hash;
-            return;
-        }
-        try {
-            btSession_.remove_torrent(p.value()->getHandle());
-        } catch (torrent_exception_t e) {
-            qDebug() << // e.what()
-                "exception catched"
-                ;
-        }
-    }
+               , settings_(new ServerSettings(*settings))
+               , db_(new ServerDb(settings_.get()))
+{
+       qDBusRegisterMetaType<qtrapids::TorrentState>();
+       qDBusRegisterMetaType<qtrapids::ParamsMap_t>();
+       new QtRapidsServer(this);
+
+       QDBusConnection dbus = QDBusConnection::sessionBus();
+       dbus.registerObject("/qtrapids", this);
+       dbus.registerService("com.ixonos.qtrapids");
+       
+       alertWaiter_->allAlerts();
+       connect(alertWaiter_, SIGNAL(alert()), this, SLOT(on_alert()));
+       alertWaiter_->start();
+
+       loadState();
+       
+       // Lets force applying rate limits to local network also, at least for testing.
+       // Also, on the N900 device, rate limiting is necessary due to limited processign power
+       session_settings_t sessionSettings;
+       sessionSettings.ignore_limits_on_local_network = false;
+       btSession_.set_settings(sessionSettings);
+       
+}
+
+
+TorrentSession::~TorrentSession()
+{
+       alertWaiter_->stop();
+       alertWaiter_->wait();
+       emit sessionTerminated();
+}
+
+
+void TorrentSession::loadState()
+{
+       TorrentDownloadInfo info;
+       TorrentsStorage storage(*db_);
+       while (storage.nextTorrent(info)) {
+#ifdef QTRAPIDS_DEBUG
+               qDebug() << "adding " << info.path;
+#endif
+               addTorrent_(info.path, info.download_path, ParamsMap_t(), true);
+       }
+       btSession_.listen_on(settings_->getListenPorts());
+}
+
+void TorrentSession::on_alert()
+{
+       std::auto_ptr<alert_t> alertPtr = btSession_.pop_alert();
+
+       if (alertPtr.get() != NULL) {
+
+               torrent_alert_t *ta = dynamic_cast<torrent_alert_t*> (alertPtr.get());
+
+#ifdef QTRAPIDS_DEBUG
+               qDebug()
+               << "TorrentSession::on_alert(): "
+               << QString::fromStdString(alertPtr->message());
+#endif
+
+               if (ta) {
+                       if (!ta->handle.is_valid()) {
+#ifdef QTRAPIDS_DEBUG
+                               qDebug() << "handle is invalid";
+#endif
+                               return;
+                       }
+
+                       TorrentHandle handle(ta->handle);
+                       TorrentState state;
+
+                       state.hash = Hash2QStr(handle.hash());
+                       state.action = TorrentState::action_update;
+                       state.state = handle.state();
+                       state.progress = handle.progress() * torrent_progress_max;
+                       state.down_rate = handle.downloadRate();
+                       state.up_rate = handle.uploadRate();
+                       state.seeds = handle.numSeeds();
+                       state.leeches = handle.numLeeches();
+                       state.total_size = handle.getTotalSize();
+                       state.total_done = handle.getTotalDone();
+                       
+                       ParamsMap_t params;
+                       emit alert(state, params);
+               }
+
+       }
+}
+
+void TorrentSession::getState()
+{
+       torrents_t::const_iterator p;
+       for (p = torrents_.constBegin(); p != torrents_.constEnd(); ++p) {
+               TorrentHandlePtr handle = *p;
+               TorrentState state;
+               QString hash = Hash2QStr(handle->hash());
+
+               state.hash = hash;
+               state.name = handle->name();
+               state.action = TorrentState::action_add;
+               state.state = handle->state();
+               state.progress = handle->progress() * torrent_progress_max;
+               state.down_rate = handle->downloadRate();
+               state.up_rate = handle->uploadRate();
+               state.seeds = handle->numSeeds();
+               state.leeches = handle->numLeeches();
+               state.total_size = handle->getTotalSize();
+
+               emit alert(state, ParamsMap_t());
+       }
+}
+
+void TorrentSession::addTorrent(const QString &path, const QString &save_path
+                                , qtrapids::ParamsMap_t other_params)
+{
+       return addTorrent_(path, save_path, other_params, false);
+}
+
+void TorrentSession::addTorrent_(const QString &path, const QString &save_path
+                                 , const qtrapids::ParamsMap_t &other_params
+                                 , bool is_restore_session)
+{
+       add_torrent_params_t addParams;
+       QFile torrent_file(path);
+       QDir::home().mkdir(settings_->getTorrentsSubDir());
+
+       if (!torrent_file.exists()) {
+               qWarning() << "Torrent file " << path << "doesn't exist";
+               return;
+       }
+
+       QString new_torrent_fname(QDir(settings_->getTorrentsDir())
+                                 .filePath(QFileInfo(path).fileName()));
+#ifdef QTRAPIDS_DEBUG
+       qDebug() << "copy to " << new_torrent_fname;
+#endif
+
+       torrent_file.copy(new_torrent_fname);
+       
+#ifdef QTRAPIDS_DEBUG
+       qDebug() << "addTorrent: " << path << " save to " << save_path;
+#endif
+
+       boost::intrusive_ptr<libtorrent::torrent_info> tiTmp
+       = new libtorrent::torrent_info
+       (boost::filesystem::path(new_torrent_fname.toStdString()));
+       addParams.ti = tiTmp;
+
+       QString download_dir;
+       if (!save_path.isEmpty()) {
+               download_dir = save_path;
+       } else {
+               download_dir = settings_->getDownloadDir();
+       }
+       // save_path is the only mandatory parameter, rest are optional.
+       addParams.save_path = boost::filesystem::path(download_dir.toStdString());
+       //addParams.storage_mode = libtorrent::storage_mode_allocate;
+
+       TorrentHandlePtr handle(new TorrentHandle(btSession_.add_torrent(addParams)));
+       QString hash = Hash2QStr(handle->hash());
+
+       if (!is_restore_session) {
+               db_->addTorrent(hash, path, save_path);
+       }
+
+       TorrentState state;
+
+       state.hash = hash;
+       state.name = handle->name();
+       state.action = TorrentState::action_add;
+       state.state = handle->state();
+       state.progress = handle->progress() * torrent_progress_max;
+       state.down_rate = handle->downloadRate();
+       state.up_rate = handle->uploadRate();
+       state.seeds = handle->numSeeds();
+       state.leeches = handle->numLeeches();
+       state.total_size = handle->getTotalSize();
+
+       torrents_[hash] = handle;
+
+       emit alert(state, ParamsMap_t());
+}
+
+void TorrentSession::removeTorrent(const QString &hash)
+{
+       torrents_t::iterator p = torrents_.find(hash);
+
+       if (p == torrents_.end()) {
+#ifdef QTRAPIDS_DEBUG
+               qDebug() << "Invalid request to remove torrent with hash " << hash;
+#endif
+               return;
+       }
+       try {
+               btSession_.remove_torrent(p.value()->getHandle());
+       } catch (torrent_exception_t e) {
+               qDebug() << // e.what()
+               "exception catched"
+               ;
+       }
+
+       TorrentState state;
+       state.hash = hash;
+       state.action = TorrentState::action_remove;
+       emit alert(state, ParamsMap_t());
+       torrents_.erase(p);
+       db_->removeTorrent(hash);
+}
+
+
+void TorrentSession::setOptions(qtrapids::ParamsMap_t options)
+{
+       qtrapids::ParamsMapConstIterator_t end = options.end();
+       qtrapids::ParamsMapConstIterator_t tmpIter = options.find("net/downloadRate");
+       int rate = -1;
+
+       // Apply settings immediately to Bittorrent session:
+       // NOTE: QHash interface is not quite STL-like
+       
+       if (tmpIter != end) {
+               rate = tmpIter.value().toInt();
+               btSession_.set_download_rate_limit(rate);
+       }
+       
+       tmpIter = options.find("net/uploadRate");
+       if (tmpIter != end) {
+               rate = tmpIter.value().toInt();
+               btSession_.set_upload_rate_limit(rate);
+       }
+       
+       /// @todo Add more immediately applicable settings here, if needed.
+       
+       // Finally, save settings to persistent storage:
+       settings_->setOptions(options);
+}
+
+
+qtrapids::ParamsMap_t TorrentSession::getOptions()
+{
+       return settings_->getOptions();
+}
 
 
+void TorrentSession::terminateSession()
+{
+       qDebug() << "Terminate called";
+       // Emiting terminate() here causes the server application to quit in main()
+       emit terminate();
+}
+
 } // namespace qtrapids