diff --git a/src/eventmanager.cpp b/src/eventmanager.cpp new file mode 100644 index 000000000..a319687e3 --- /dev/null +++ b/src/eventmanager.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2007 by Ishan Arora + * ishanarora@gmail.com + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "eventmanager.h" +#include "json.h" +#include + +EventManager::EventManager(QObject *parent) + : QObject(parent) +{ + revision = 0; +} + +void EventManager::update(QVariantMap event) +{ + revision++; + events << QPair(revision, event); + emit updated(); + qDebug("Added the following event"); + qDebug() << event; +/* QLinkedList >::iterator i; + for (i = events.begin(); i != events.end(); i++) + qDebug() << *i;*/ +} + +QVariant EventManager::querySince(ulong r) const +{ + QVariantList list; + QLinkedListIterator > i(events); + i.toBack(); + while (i.hasPrevious()) + { + QPair pair = i.previous(); + if (pair.first <= r) + break; + list.prepend(QVariant(pair.second)); + } + QVariantMap map; + map["events"] = QVariant(list); + map["revision"] = QVariant((qulonglong) revision); + return QVariant(map); +} + +bool EventManager::isUpdated(ulong r) const +{ + return (r < revision); +} + +void EventManager::addedTorrent(QString, QTorrentHandle& h) +{ + QVariantMap event; + event["type"] = QVariant("add"); + event["hash"] = QVariant(h.hash()); + event["name"] = QVariant(h.name()); + update(event); +} + +void EventManager::deletedTorrent(QString hash) +{ + QVariantMap event; + event["type"] = QVariant("delete"); + event["hash"] = QVariant(hash); + QLinkedList >::iterator i = events.end(); + bool loop = true; + while (loop && i != events.begin()) { + --i; + QVariantMap oldevent = i->second; + if(oldevent["hash"] == QVariant(hash)) + { + if(oldevent["type"] == QVariant("add")) + loop = false; + i = events.erase(i); + } + } + update(event); +} + +void EventManager::modifiedTorrent(QTorrentHandle h) +{ + QString hash = h.hash(); + QVariantMap event; + QVariant v; + + if(h.is_paused()) + v = QVariant("paused"); + else + { + switch(h.state()) + { + case torrent_status::finished: + case torrent_status::seeding: + v = QVariant("seeding"); + break; + case torrent_status::checking_files: + case torrent_status::queued_for_checking: + v = QVariant("checking"); + break; + case torrent_status::connecting_to_tracker: + if(h.download_payload_rate() > 0) + v = QVariant("downloading"); + else + v = QVariant("connecting"); + break; + case torrent_status::downloading: + case torrent_status::downloading_metadata: + if(h.download_payload_rate() > 0) + v = QVariant("downloading"); + else + v = QVariant("stalled"); + break; + default: + v = QVariant(); + } + } + if(modify(hash, "state", v)) + event["state"] = v; + + v = QVariant(h.actual_size()); + if(modify(hash, "size", v)) + event["size"] = v; + + v = QVariant(h.progress()); + if(modify(hash, "progress", v)) + event["progress"] = v; + + v = QVariant(h.download_payload_rate()); + if(modify(hash, "dlspeed", v)) + event["dlspeed"] = v; + + v = QVariant(h.upload_payload_rate()); + if(modify(hash, "upspeed", v)) + event["upspeed"] = v; + + if(event.size() > 0) + { + event["type"] = QVariant("modify"); + event["hash"] = QVariant(hash); + update(event); + } +} + +bool EventManager::modify(QString hash, QString key, QVariant value) +{ + QLinkedList >::iterator i = events.end(); + while (i != events.begin()) { + --i; + QVariantMap event = i->second; + if(event["hash"] == QVariant(hash)) + { + if(event["type"] == QVariant("add")) + return true; + if(event.contains(key)) + { + if(event[key] == value) + return false; + else + { + if(event.size() <= 3) + i = events.erase(i); + else + i->second.remove(key); + return true; + } + } + } + } + return true; +} diff --git a/src/httpserver.cpp b/src/httpserver.cpp new file mode 100644 index 000000000..2478bff82 --- /dev/null +++ b/src/httpserver.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007 by Ishan Arora + * ishanarora@gmail.com + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "httpserver.h" +#include "httpconnection.h" +#include "eventmanager.h" +#include "bittorrent.h" +#include + +HttpServer::HttpServer(bittorrent *BTSession, int msec, QObject* parent) : QTcpServer(parent) +{ + base64 = QByteArray(":").toBase64(); + connect(this, SIGNAL(newConnection()), this, SLOT(newHttpConnection())); + HttpServer::BTSession = BTSession; + manager = new EventManager(this); + //add torrents + QStringList list = BTSession->getUnfinishedTorrents() + BTSession->getFinishedTorrents(); + QString hash; + foreach(hash, list) + { + QTorrentHandle h = BTSession->getTorrentHandle(hash); + if(h.is_valid()) + manager->addedTorrent(QString(), h); + } + //connect BTSession to manager + connect(BTSession, SIGNAL(addedTorrent(QString, QTorrentHandle&, bool)), manager, SLOT(addedTorrent(QString, QTorrentHandle&))); + connect(BTSession, SIGNAL(deletedTorrent(QString)), manager, SLOT(deletedTorrent(QString))); + //set timer + QTimer *timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(onTimer())); + timer->start(msec); +} + +HttpServer::~HttpServer() +{ + delete manager; +} + +void HttpServer::newHttpConnection() +{ + QTcpSocket *socket; + while((socket = nextPendingConnection())) + { + HttpConnection *connection = new HttpConnection(socket, this); + //connect connection to BTSession + connect(connection, SIGNAL(urlsReadyToBeDownloaded(const QStringList&)), BTSession, SLOT(downloadFromURLList(const QStringList&))); + connect(connection, SIGNAL(deleteTorrent(QString)), BTSession, SLOT(deleteTorrent(QString))); + connect(connection, SIGNAL(pauseTorrent(QString)), BTSession, SLOT(pauseTorrent(QString))); + connect(connection, SIGNAL(resumeTorrent(QString)), BTSession, SLOT(resumeTorrent(QString))); + connect(connection, SIGNAL(pauseAllTorrents()), BTSession, SLOT(pauseAllTorrents())); + connect(connection, SIGNAL(resumeAllTorrents()), BTSession, SLOT(resumeAllTorrents())); + } +} + +void HttpServer::onTimer() +{ + QStringList list = BTSession->getUnfinishedTorrents() + BTSession->getFinishedTorrents(); + foreach(QString hash, list) + { + QTorrentHandle h = BTSession->getTorrentHandle(hash); + if(h.is_valid()) + manager->modifiedTorrent(h); + } +} + +void HttpServer::setAuthorization(QString username, QString password) +{ + QString cat = username + ":" + password; + base64 = QByteArray(cat.toUtf8()).toBase64(); +} + +bool HttpServer::isAuthorized(QByteArray auth) const +{ + return (auth == base64); +} + +EventManager *HttpServer::eventManager() const +{ + return manager; +} diff --git a/src/json.cpp b/src/json.cpp new file mode 100644 index 000000000..1aad2fd18 --- /dev/null +++ b/src/json.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2007 by Ishan Arora + * ishanarora@gmail.com + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 "json.h" + +QString toJson(QVariant v) +{ + if (v.isNull()) + return "null"; + QString result; + switch(v.type()) + { + case QVariant::Bool: + case QVariant::Double: + case QVariant::Int: + case QVariant::LongLong: + case QVariant::UInt: + case QVariant::ULongLong: + return v.value(); + case QVariant::String: + { + QString s = v.value(); + result = "\""; + for(int i=0; i it(v.value()); + while (it.hasNext()) + result += toJson(it.next()) + ","; + if(result.size() > 1) + result.chop(1); + result += "]"; + return result; + } + case QVariant::Map: + { + result = "{"; + QMapIterator it(v.value()); + while (it.hasNext()) { + it.next(); + if(it.value().isValid()) + result += toJson(QVariant(it.key())) + ":" + toJson(it.value()) + ","; + } + if(result.size() > 1) + result.chop(1); + result += "}"; + return result; + } + default: + return "undefined"; + } +}