diff --git a/0001-Backport-to-1.3-Add-workaround-for-broken-handling-o.patch b/0001-Backport-to-1.3-Add-workaround-for-broken-handling-o.patch new file mode 100644 index 0000000..58c2d0e --- /dev/null +++ b/0001-Backport-to-1.3-Add-workaround-for-broken-handling-o.patch @@ -0,0 +1,138 @@ +From f76e1b0b637e53af64ecd813e8541019e50bb8bb Mon Sep 17 00:00:00 2001 +From: Joris Guisson +Date: Mon, 24 Sep 2012 11:07:44 +0200 +Subject: [PATCH 1/9] Backport to 1.3: Add workaround for broken handling of + btrfs subvolumes by solid + +CCBUG: 306825 +--- + ChangeLog | 3 +++ + src/util/fileops.cpp | 65 ++++++++++++++++++++++++++++++++++------------------ + 2 files changed, 46 insertions(+), 22 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index fe2cc21..c037d28 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,6 @@ ++Changes in 1.3.1: ++- Add workaround for broken handling of btrfs subvolumes by solid (306825) ++ + Changes in 1.3: + - Do not pass link local IPv6 addresses to ip parameter of tracker (305187) + +diff --git a/src/util/fileops.cpp b/src/util/fileops.cpp +index 637074d..1e5d7d5 100644 +--- a/src/util/fileops.cpp ++++ b/src/util/fileops.cpp +@@ -30,12 +30,15 @@ + #include + #include + #include ++#include ++#include + #include + #include + #include +-#include +-#include +-#include ++#include ++#include ++#include ++#include + #include "error.h" + #include "log.h" + #include "file.h" +@@ -73,12 +76,14 @@ typedef int64_t __s64; + #endif + + #ifndef Q_WS_WIN ++#include + #include + #endif + #ifdef CopyFile + #undef CopyFile + #endif + ++ + namespace bt + { + void MakeDir(const QString & dir,bool nothrow) +@@ -619,38 +624,54 @@ namespace bt + return ret; + } + +- QString MountPoint(const QString& path) ++ QSet AccessibleMountPoints() + { +- QList devs = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess); +- QString mountpoint; ++ QSet result; ++#ifndef Q_WS_WIN ++ FILE* fptr = setmntent("/proc/mounts", "r"); ++ if(!fptr) ++ return result; ++ ++ struct mntent mnt; ++ char buf[PATH_MAX]; ++ while(getmntent_r(fptr, &mnt, buf, PATH_MAX)) ++ { ++ result.insert(QString(mnt.mnt_dir)); ++ } + ++ endmntent(fptr); ++ ++#else ++ QList devs = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess); + foreach (Solid::Device dev,devs) + { + Solid::StorageAccess* sa = dev.as(); +- if (path.startsWith(sa->filePath())) ++ if(!sa->filePath().isEmpty() && sa->isAccessible()) ++ result.insert(sa->filePa()); ++ } ++#endif ++ return result; ++ } ++ ++ QString MountPoint(const QString& path) ++ { ++ QSet mount_points = AccessibleMountPoints(); ++ QString mount_point; ++ foreach (const QString & mp, mount_points) ++ { ++ if (path.startsWith(mp) && (mount_point.isEmpty() || mp.startsWith(mount_point))) + { +- if (mountpoint.isEmpty() || sa->filePath().startsWith(mountpoint)) +- mountpoint = sa->filePath(); ++ mount_point = mp; + } + } + +- return mountpoint; ++ return mount_point; + } + ++ + bool IsMounted(const QString& mount_point) + { +- QList devs = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess); +- +- foreach (Solid::Device dev,devs) +- { +- Solid::StorageAccess* sa = dev.as(); +- if (sa->filePath() == mount_point) +- { +- return sa->isAccessible(); +- } +- } +- +- return false; ++ return AccessibleMountPoints().contains(mount_point); + } + + } +-- +1.8.0.2 + diff --git a/0002-Backport-to-1.3-Fix-crash-when-preallocating-diskspa.patch b/0002-Backport-to-1.3-Fix-crash-when-preallocating-diskspa.patch new file mode 100644 index 0000000..4696182 --- /dev/null +++ b/0002-Backport-to-1.3-Fix-crash-when-preallocating-diskspa.patch @@ -0,0 +1,55 @@ +From 30c07792eda0ac656f5173852a059705d8b85163 Mon Sep 17 00:00:00 2001 +From: Joris Guisson +Date: Mon, 24 Sep 2012 13:23:41 +0200 +Subject: [PATCH 2/9] Backport to 1.3: Fix crash when preallocating diskspace + when a file is enabled during the download of a torrent + +CCBUG: 307178 +--- + ChangeLog | 1 + + src/diskio/multifilecache.cpp | 3 ++- + src/diskio/preallocationthread.cpp | 3 ++- + 3 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index c037d28..7ce9c53 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,5 +1,6 @@ + Changes in 1.3.1: + - Add workaround for broken handling of btrfs subvolumes by solid (306825) ++- Fix crash when preallocating diskspace when a file is enabled during the download of a torrent (307178) + + Changes in 1.3: + - Do not pass link local IPv6 addresses to ip parameter of tracker (305187) +diff --git a/src/diskio/multifilecache.cpp b/src/diskio/multifilecache.cpp +index ce19ffd..8e3d90f 100644 +--- a/src/diskio/multifilecache.cpp ++++ b/src/diskio/multifilecache.cpp +@@ -783,7 +783,8 @@ namespace bt + while(i != files.end()) + { + CacheFile::Ptr cf = i.value(); +- prealloc->add(cf); ++ if(cf) ++ prealloc->add(cf); + i++; + } + } +diff --git a/src/diskio/preallocationthread.cpp b/src/diskio/preallocationthread.cpp +index 1a8856c..914d859 100644 +--- a/src/diskio/preallocationthread.cpp ++++ b/src/diskio/preallocationthread.cpp +@@ -51,7 +51,8 @@ namespace bt + + void PreallocationThread::add(CacheFile::Ptr cache_file) + { +- todo.append(cache_file); ++ if(cache_file) ++ todo.append(cache_file); + } + + +-- +1.8.0.2 + diff --git a/0003-Backport-to-1.3-Unbreak-the-non-Linux-case-after-4ff.patch b/0003-Backport-to-1.3-Unbreak-the-non-Linux-case-after-4ff.patch new file mode 100644 index 0000000..7a4b9a3 --- /dev/null +++ b/0003-Backport-to-1.3-Unbreak-the-non-Linux-case-after-4ff.patch @@ -0,0 +1,29 @@ +From 5e4226614361095fc6e83f4abc1dca268de8005b Mon Sep 17 00:00:00 2001 +From: Raphael Kubo da Costa +Date: Wed, 10 Oct 2012 20:59:36 +0300 +Subject: [PATCH 3/9] Backport to 1.3: Unbreak the non-Linux case after + 4ffaa9e. + +Use the right method name, filePa() does not exist. + +(cherry picked from commit 258ae24d6c6be31362b8877c704ddf3f8b253f62) +--- + src/util/fileops.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/util/fileops.cpp b/src/util/fileops.cpp +index 1e5d7d5..329462e 100644 +--- a/src/util/fileops.cpp ++++ b/src/util/fileops.cpp +@@ -647,7 +647,7 @@ namespace bt + { + Solid::StorageAccess* sa = dev.as(); + if(!sa->filePath().isEmpty() && sa->isAccessible()) +- result.insert(sa->filePa()); ++ result.insert(sa->filePath()); + } + #endif + return result; +-- +1.8.0.2 + diff --git a/0006-Backport-to-1.3-Make-sure-stats-get-updated-properly.patch b/0006-Backport-to-1.3-Make-sure-stats-get-updated-properly.patch new file mode 100644 index 0000000..fb77549 --- /dev/null +++ b/0006-Backport-to-1.3-Make-sure-stats-get-updated-properly.patch @@ -0,0 +1,44 @@ +From 92e8fc65cf0bc35be5fa5cd1bb5e76061745a0cd Mon Sep 17 00:00:00 2001 +From: Joris Guisson +Date: Fri, 2 Nov 2012 13:29:06 +0100 +Subject: [PATCH 6/9] Backport to 1.3: Make sure stats get updated properly + during data check + +CCBUG: 308707 + +Conflicts: + + src/torrent/torrentcontrol.cpp +--- + ChangeLog | 1 + + src/torrent/torrentcontrol.cpp | 2 -- + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index 7ce9c53..b66d050 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,6 +1,7 @@ + Changes in 1.3.1: + - Add workaround for broken handling of btrfs subvolumes by solid (306825) + - Fix crash when preallocating diskspace when a file is enabled during the download of a torrent (307178) ++- Make sure stats get updated properly during data check (308707) + + Changes in 1.3: + - Do not pass link local IPv6 addresses to ip parameter of tracker (305187) +diff --git a/src/torrent/torrentcontrol.cpp b/src/torrent/torrentcontrol.cpp +index 7cb4eeb..1a01bf2 100644 +--- a/src/torrent/torrentcontrol.cpp ++++ b/src/torrent/torrentcontrol.cpp +@@ -134,8 +134,6 @@ namespace bt + void TorrentControl::update() + { + UpdateCurrentTime(); +- if (job_queue->runningJobs()) +- return; + + if (istats.io_error) + { +-- +1.8.0.2 + diff --git a/0007-Bind-peer-sockets-to-preferred-interface-for-outboun.patch b/0007-Bind-peer-sockets-to-preferred-interface-for-outboun.patch new file mode 100644 index 0000000..2e52172 --- /dev/null +++ b/0007-Bind-peer-sockets-to-preferred-interface-for-outboun.patch @@ -0,0 +1,646 @@ +From 495ce3f3cec2337b31bdd4015ed80849affca0fd Mon Sep 17 00:00:00 2001 +From: Joris Guisson +Date: Mon, 17 Dec 2012 12:23:01 +0100 +Subject: [PATCH 7/9] Bind peer sockets to preferred interface for outbound + connections + +--- + ChangeLog | 1 + + src/diskio/cache.cpp | 3 + + src/net/trafficshapedsocket.cpp | 260 ++++++++++++++++++++------------------ + src/tracker/httpannouncejob.cpp | 272 ++++++++++++++++++++-------------------- + src/tracker/httptracker.cpp | 8 +- + 5 files changed, 279 insertions(+), 265 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index b66d050..bfa8fbe 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -2,6 +2,7 @@ Changes in 1.3.1: + - Add workaround for broken handling of btrfs subvolumes by solid (306825) + - Fix crash when preallocating diskspace when a file is enabled during the download of a torrent (307178) + - Make sure stats get updated properly during data check (308707) ++- Bind peer sockets to preferred interface for outbound connections + + Changes in 1.3: + - Do not pass link local IPv6 addresses to ip parameter of tracker (305187) +diff --git a/src/diskio/cache.cpp b/src/diskio/cache.cpp +index 703a846..ed43c85 100644 +--- a/src/diskio/cache.cpp ++++ b/src/diskio/cache.cpp +@@ -203,6 +203,9 @@ namespace bt + + bool Cache::isStorageMounted(QStringList& missing) + { ++ if(mount_points.isEmpty()) ++ return true; ++ + missing.clear(); + foreach(const QString & mount_point, mount_points) + { +diff --git a/src/net/trafficshapedsocket.cpp b/src/net/trafficshapedsocket.cpp +index d3e6c90..336acac 100644 +--- a/src/net/trafficshapedsocket.cpp ++++ b/src/net/trafficshapedsocket.cpp +@@ -20,137 +20,147 @@ + + + #include "trafficshapedsocket.h" ++ ++#include ++#include + #include "speed.h" + #include "socket.h" + +-#define OUTPUT_BUFFER_SIZE 16393 ++const bt::Uint32 OUTPUT_BUFFER_SIZE = 16393; + + using namespace bt; + + namespace net + { + +- TrafficShapedSocket::TrafficShapedSocket(SocketDevice* sock) : +- rdr(0), +- up_gid(0), +- down_gid(0), +- sock(sock), +- mutex(QMutex::Recursive) +- { +- down_speed = new Speed(); +- up_speed = new Speed(); +- } +- +- TrafficShapedSocket::TrafficShapedSocket(int fd, int ip_version) : +- rdr(0), +- up_gid(0), +- down_gid(0), +- mutex(QMutex::Recursive) +- { +- sock = new Socket(fd, ip_version); +- down_speed = new Speed(); +- up_speed = new Speed(); +- } +- +- TrafficShapedSocket::TrafficShapedSocket(bool tcp, int ip_version) : +- rdr(0), +- up_gid(0), +- down_gid(0), +- mutex(QMutex::Recursive) +- { +- sock = new Socket(tcp, ip_version); +- down_speed = new Speed(); +- up_speed = new Speed(); +- } +- +- TrafficShapedSocket::~TrafficShapedSocket() +- { +- delete up_speed; +- delete down_speed; +- delete sock; +- } +- +- void TrafficShapedSocket::setGroupID(Uint32 gid,bool upload) +- { +- if (upload) +- up_gid = gid; +- else +- down_gid = gid; +- } +- +- int TrafficShapedSocket::getDownloadRate() const +- { +- // getRate is atomic +- return down_speed->getRate(); +- } +- +- int TrafficShapedSocket::getUploadRate() const +- { +- // getRate is atomic +- return up_speed->getRate(); +- } +- +- void TrafficShapedSocket::updateSpeeds(bt::TimeStamp now) +- { +- mutex.lock(); +- up_speed->update(now); +- down_speed->update(now); +- mutex.unlock(); +- } +- +- static bt::Uint8 input_buffer[OUTPUT_BUFFER_SIZE]; +- +- Uint32 TrafficShapedSocket::read(bt::Uint32 max_bytes_to_read, bt::TimeStamp now) +- { +- Uint32 br = 0; +- bool no_limit = (max_bytes_to_read == 0); +- Uint32 ba = sock->bytesAvailable(); +- if (ba == 0) +- { +- // For some strange reason, sometimes bytesAvailable returns 0, while there are +- // bytes to read, so give ba the maximum value it can be +- ba = max_bytes_to_read > 0 ? max_bytes_to_read : OUTPUT_BUFFER_SIZE; +- } +- +- while ((br < max_bytes_to_read || no_limit) && ba > 0) +- { +- Uint32 tr = ba; +- if (tr > OUTPUT_BUFFER_SIZE) +- tr = OUTPUT_BUFFER_SIZE; +- if (!no_limit && tr + br > max_bytes_to_read) +- tr = max_bytes_to_read - br; +- +- int ret = sock->recv(input_buffer,tr); +- if (ret > 0) +- { +- mutex.lock(); +- down_speed->onData(ret,now); +- mutex.unlock(); +- if (rdr) +- { +- postProcess(input_buffer, ret); +- rdr->onDataReady(input_buffer,ret); +- } +- br += ret; +- ba -= ret; +- } +- else if (ret < 0) +- { +- return br; +- } +- else +- { +- sock->close(); +- return br; +- } +- } +- return br; +- } +- +- +- void TrafficShapedSocket::postProcess(Uint8* data, Uint32 size) +- { +- Q_UNUSED(data); +- Q_UNUSED(size); +- } +-} +\ No newline at end of file ++ TrafficShapedSocket::TrafficShapedSocket(SocketDevice* sock) : ++ rdr(0), ++ up_gid(0), ++ down_gid(0), ++ sock(sock), ++ mutex(QMutex::Recursive) ++ { ++ down_speed = new Speed(); ++ up_speed = new Speed(); ++ } ++ ++ TrafficShapedSocket::TrafficShapedSocket(int fd, int ip_version) : ++ rdr(0), ++ up_gid(0), ++ down_gid(0), ++ mutex(QMutex::Recursive) ++ { ++ sock = new Socket(fd, ip_version); ++ down_speed = new Speed(); ++ up_speed = new Speed(); ++ } ++ ++ TrafficShapedSocket::TrafficShapedSocket(bool tcp, int ip_version) : ++ rdr(0), ++ up_gid(0), ++ down_gid(0), ++ mutex(QMutex::Recursive) ++ { ++ Socket* socket = new Socket(tcp, ip_version); ++ ++ QString iface = NetworkInterface(); ++ QStringList ips = NetworkInterfaceIPAddresses(iface); ++ if (ips.size() > 0) ++ socket->bind(ips.front(), 0, false); ++ ++ sock = socket; ++ down_speed = new Speed(); ++ up_speed = new Speed(); ++ } ++ ++ TrafficShapedSocket::~TrafficShapedSocket() ++ { ++ delete up_speed; ++ delete down_speed; ++ delete sock; ++ } ++ ++ void TrafficShapedSocket::setGroupID(Uint32 gid, bool upload) ++ { ++ if (upload) ++ up_gid = gid; ++ else ++ down_gid = gid; ++ } ++ ++ int TrafficShapedSocket::getDownloadRate() const ++ { ++ // getRate is atomic ++ return down_speed->getRate(); ++ } ++ ++ int TrafficShapedSocket::getUploadRate() const ++ { ++ // getRate is atomic ++ return up_speed->getRate(); ++ } ++ ++ void TrafficShapedSocket::updateSpeeds(bt::TimeStamp now) ++ { ++ mutex.lock(); ++ up_speed->update(now); ++ down_speed->update(now); ++ mutex.unlock(); ++ } ++ ++ static bt::Uint8 input_buffer[OUTPUT_BUFFER_SIZE]; ++ ++ Uint32 TrafficShapedSocket::read(bt::Uint32 max_bytes_to_read, bt::TimeStamp now) ++ { ++ Uint32 br = 0; ++ bool no_limit = (max_bytes_to_read == 0); ++ Uint32 ba = sock->bytesAvailable(); ++ if (ba == 0) ++ { ++ // For some strange reason, sometimes bytesAvailable returns 0, while there are ++ // bytes to read, so give ba the maximum value it can be ++ ba = max_bytes_to_read > 0 ? max_bytes_to_read : OUTPUT_BUFFER_SIZE; ++ } ++ ++ while ((br < max_bytes_to_read || no_limit) && ba > 0) ++ { ++ Uint32 tr = ba; ++ if (tr > OUTPUT_BUFFER_SIZE) ++ tr = OUTPUT_BUFFER_SIZE; ++ if (!no_limit && tr + br > max_bytes_to_read) ++ tr = max_bytes_to_read - br; ++ ++ int ret = sock->recv(input_buffer, tr); ++ if (ret > 0) ++ { ++ mutex.lock(); ++ down_speed->onData(ret, now); ++ mutex.unlock(); ++ if (rdr) ++ { ++ postProcess(input_buffer, ret); ++ rdr->onDataReady(input_buffer, ret); ++ } ++ br += ret; ++ ba -= ret; ++ } ++ else if (ret < 0) ++ { ++ return br; ++ } ++ else ++ { ++ sock->close(); ++ return br; ++ } ++ } ++ return br; ++ } ++ ++ ++ void TrafficShapedSocket::postProcess(Uint8* data, Uint32 size) ++ { ++ Q_UNUSED(data); ++ Q_UNUSED(size); ++ } ++} +diff --git a/src/tracker/httpannouncejob.cpp b/src/tracker/httpannouncejob.cpp +index 0e5d29f..11f760f 100644 +--- a/src/tracker/httpannouncejob.cpp ++++ b/src/tracker/httpannouncejob.cpp +@@ -20,147 +20,149 @@ + #include + #include + #include ++#include + #include + #include ++#include + + namespace bt + { + +- HTTPAnnounceJob::HTTPAnnounceJob(const KUrl& url) : url(url),get_id(0),proxy_port(-1) +- { +- http = new QHttp(this); +- connect(http,SIGNAL(requestFinished(int,bool)),this,SLOT(requestFinished(int,bool))); +- connect(http,SIGNAL(readyRead(QHttpResponseHeader)),this,SLOT(readData(QHttpResponseHeader))); +- connect(http,SIGNAL(sslErrors(QList)),this,SLOT(sslErrors(QList))); +- } +- +- HTTPAnnounceJob::~HTTPAnnounceJob() +- { +- } +- +- void HTTPAnnounceJob::start() +- { +- sendRequest(); +- } +- +- void HTTPAnnounceJob::sendRequest() +- { +- QHttp::ConnectionMode mode = url.protocol() == "https" ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp; +- quint16 port = url.port() < 0 ? 0 : url.port(); +- quint16 default_port = mode == QHttp::ConnectionModeHttps ? 443 : 80; +- http->setHost(url.host(),mode,port); +- if (!proxy_host.isEmpty() && proxy_port > 0) +- http->setProxy(proxy_host,proxy_port); +- +- QHttpRequestHeader hdr("GET",url.encodedPathAndQuery(),1,1); +- hdr.setValue("User-Agent",bt::GetVersionString()); +- hdr.setValue("Connection","close"); +- hdr.setValue("Host",QString("%1:%2").arg(url.host()).arg(url.port(default_port))); +- get_id = http->request(hdr); +- Out(SYS_TRK|LOG_DEBUG) << "Request sent" << endl; +- } +- +- void HTTPAnnounceJob::kill(bool quietly) +- { +- http->abort(); +- if (!quietly) +- emitResult(); +- } +- +- void HTTPAnnounceJob::requestFinished(int id, bool err) +- { +- if (get_id != id) +- return; +- +- if (err) +- { +- setErrorText(http->errorString()); +- emitResult(); +- } +- else +- { +- switch (http->lastResponse().statusCode()) +- { +- case 300: +- case 301: +- case 302: +- case 303: +- case 307: +- handleRedirect(http->lastResponse()); +- break; +- case 403: +- setError(KIO::ERR_ACCESS_DENIED); +- emitResult(); +- break; +- case 404: +- setError(KIO::ERR_DOES_NOT_EXIST); +- emitResult(); +- break; +- case 500: +- setError(KIO::ERR_INTERNAL_SERVER); +- emitResult(); +- break; +- default: +- emitResult(); +- break; +- } +- } +- } +- +- void HTTPAnnounceJob::readData(const QHttpResponseHeader& hdr) +- { +- const int MAX_REPLY_SIZE = 1024 * 1024; +- +- int ba = http->bytesAvailable(); +- int current_size = reply_data.size(); +- if (current_size + ba > MAX_REPLY_SIZE) +- { +- // If the reply is larger then a mega byte, the server +- // has probably gone bonkers +- http->abort(); +- Out(SYS_TRK|LOG_DEBUG) << "Tracker sending back to much data in announce reply, aborting ..." << endl; +- } +- else +- { +- // enlarge reply data and read data to it +- reply_data.resize(current_size + ba); +- http->read(reply_data.data() + current_size,ba); +- } +- } +- +- void HTTPAnnounceJob::setProxy(const QString& host, int port) +- { +- proxy_host = host; +- proxy_port = port; +- } +- +- +- void HTTPAnnounceJob::handleRedirect(const QHttpResponseHeader& hdr) +- { +- if (!hdr.hasKey("Location")) +- { +- setErrorText(i18n("Redirect without a redirect location")); +- emitResult(); +- } +- else +- { +- reply_data.clear(); +- url = hdr.value("Location"); +- Out(SYS_TRK|LOG_DEBUG) << "Redirected to " << hdr.value("Location") << endl; +- sendRequest(); +- } +- } +- +- void HTTPAnnounceJob::sslErrors(const QList& errors) +- { +- KUrl u = url; +- u.setQuery(QString()); +- Out(SYS_TRK|LOG_NOTICE) << "SSL errors detected when announcing to " << u.prettyUrl() << ":" << endl; +- foreach (const QSslError & err,errors) +- Out(SYS_TRK|LOG_NOTICE) << err.errorString() << endl; +- Out(SYS_TRK|LOG_NOTICE) << "Errors will be ignored " << endl; +- http->ignoreSslErrors(); +- } ++ HTTPAnnounceJob::HTTPAnnounceJob(const KUrl& url) : url(url), get_id(0), proxy_port(-1) ++ { ++ http = new QHttp(this); ++ connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(requestFinished(int, bool))); ++ connect(http, SIGNAL(readyRead(QHttpResponseHeader)), this, SLOT(readData(QHttpResponseHeader))); ++ connect(http, SIGNAL(sslErrors(QList)), this, SLOT(sslErrors(QList))); ++ } ++ ++ HTTPAnnounceJob::~HTTPAnnounceJob() ++ { ++ } ++ ++ void HTTPAnnounceJob::start() ++ { ++ sendRequest(); ++ } ++ ++ void HTTPAnnounceJob::sendRequest() ++ { ++ QHttp::ConnectionMode mode = url.protocol() == "https" ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp; ++ quint16 port = url.port() < 0 ? 0 : url.port(); ++ quint16 default_port = mode == QHttp::ConnectionModeHttps ? 443 : 80; ++ http->setHost(url.host(), mode, port); ++ if (!proxy_host.isEmpty() && proxy_port > 0) ++ http->setProxy(proxy_host, proxy_port); ++ ++ QHttpRequestHeader hdr("GET", url.encodedPathAndQuery(), 1, 1); ++ hdr.setValue("User-Agent", bt::GetVersionString()); ++ hdr.setValue("Connection", "close"); ++ hdr.setValue("Host", QString("%1:%2").arg(url.host()).arg(url.port(default_port))); ++ get_id = http->request(hdr); ++ Out(SYS_TRK | LOG_DEBUG) << "Request sent" << endl; ++ } ++ ++ void HTTPAnnounceJob::kill(bool quietly) ++ { ++ http->abort(); ++ if (!quietly) ++ emitResult(); ++ } ++ ++ void HTTPAnnounceJob::requestFinished(int id, bool err) ++ { ++ if (get_id != id) ++ return; ++ ++ if (err) ++ { ++ setErrorText(http->errorString()); ++ emitResult(); ++ } ++ else ++ { ++ switch (http->lastResponse().statusCode()) ++ { ++ case 300: ++ case 301: ++ case 302: ++ case 303: ++ case 307: ++ handleRedirect(http->lastResponse()); ++ break; ++ case 403: ++ setError(KIO::ERR_ACCESS_DENIED); ++ emitResult(); ++ break; ++ case 404: ++ setError(KIO::ERR_DOES_NOT_EXIST); ++ emitResult(); ++ break; ++ case 500: ++ setError(KIO::ERR_INTERNAL_SERVER); ++ emitResult(); ++ break; ++ default: ++ emitResult(); ++ break; ++ } ++ } ++ } ++ ++ void HTTPAnnounceJob::readData(const QHttpResponseHeader& hdr) ++ { ++ const int MAX_REPLY_SIZE = 1024 * 1024; ++ ++ int ba = http->bytesAvailable(); ++ int current_size = reply_data.size(); ++ if (current_size + ba > MAX_REPLY_SIZE) ++ { ++ // If the reply is larger then a mega byte, the server ++ // has probably gone bonkers ++ http->abort(); ++ Out(SYS_TRK | LOG_DEBUG) << "Tracker sending back to much data in announce reply, aborting ..." << endl; ++ } ++ else ++ { ++ // enlarge reply data and read data to it ++ reply_data.resize(current_size + ba); ++ http->read(reply_data.data() + current_size, ba); ++ } ++ } ++ ++ void HTTPAnnounceJob::setProxy(const QString& host, int port) ++ { ++ proxy_host = host; ++ proxy_port = port; ++ } ++ ++ ++ void HTTPAnnounceJob::handleRedirect(const QHttpResponseHeader& hdr) ++ { ++ if (!hdr.hasKey("Location")) ++ { ++ setErrorText(i18n("Redirect without a redirect location")); ++ emitResult(); ++ } ++ else ++ { ++ reply_data.clear(); ++ url = hdr.value("Location"); ++ Out(SYS_TRK | LOG_DEBUG) << "Redirected to " << hdr.value("Location") << endl; ++ sendRequest(); ++ } ++ } ++ ++ void HTTPAnnounceJob::sslErrors(const QList& errors) ++ { ++ KUrl u = url; ++ u.setQuery(QString()); ++ Out(SYS_TRK | LOG_NOTICE) << "SSL errors detected when announcing to " << u.prettyUrl() << ":" << endl; ++ foreach (const QSslError& err, errors) ++ Out(SYS_TRK | LOG_NOTICE) << err.errorString() << endl; ++ Out(SYS_TRK | LOG_NOTICE) << "Errors will be ignored " << endl; ++ http->ignoreSslErrors(); ++ } + + } + +diff --git a/src/tracker/httptracker.cpp b/src/tracker/httptracker.cpp +index cef3179..a20f9b5 100644 +--- a/src/tracker/httptracker.cpp ++++ b/src/tracker/httptracker.cpp +@@ -157,11 +157,11 @@ namespace bt + + KIO::StoredTransferJob* st = (KIO::StoredTransferJob*)j; + BDecoder dec(st->data(), false, 0); +- BNode* n = 0; ++ QScopedPointer n; + + try + { +- n = dec.decode(); ++ n.reset(dec.decode()); + } + catch (bt::Error & err) + { +@@ -171,7 +171,7 @@ namespace bt + + if (n && n->getType() == BNode::DICT) + { +- BDictNode* d = (BDictNode*)n; ++ BDictNode* d = (BDictNode*)n.data(); + d = d->getDict(QString("files")); + if (d) + { +@@ -198,8 +198,6 @@ namespace bt + } + } + } +- +- delete n; + } + + void HTTPTracker::doRequest(WaitJob* wjob) +-- +1.8.0.2 + diff --git a/libktorrent.spec b/libktorrent.spec index 1945d06..d124dbf 100644 --- a/libktorrent.spec +++ b/libktorrent.spec @@ -2,15 +2,19 @@ Name: libktorrent Version: 1.3.0 -Release: 1%{?pre}%{?dist} +Release: 2%{?pre}%{?dist} Summary: Library providing torrent downloading code -Group: System Environment/Libraries License: GPLv2+ URL: http://ktorrent.org/ Source0: http://ktorrent.org/downloads/4.3.0%{?pre}/libktorrent-%{version}%{?pre}.tar.bz2 ## upstream patches +Patch101: 0001-Backport-to-1.3-Add-workaround-for-broken-handling-o.patch +Patch102: 0002-Backport-to-1.3-Fix-crash-when-preallocating-diskspa.patch +Patch103: 0003-Backport-to-1.3-Unbreak-the-non-Linux-case-after-4ff.patch +Patch106: 0006-Backport-to-1.3-Make-sure-stats-get-updated-properly.patch +Patch107: 0007-Bind-peer-sockets-to-preferred-interface-for-outboun.patch BuildRequires: boost-devel BuildRequires: gettext @@ -26,7 +30,6 @@ BuildRequires: pkgconfig(qca2) %package devel Summary: Developer files for %{name} -Group: Development/Libraries Obsoletes: ktorrent-devel <= 4.0 Requires: %{name}%{?_isa} = %{version}-%{release} Requires: kdelibs4-devel%{?_isa} @@ -36,10 +39,15 @@ Requires: gmp-devel%{?_isa} %{summary}. - %prep %setup -q -n %{name}-%{version}%{?pre} +%patch101 -p1 -b .0001 +%patch102 -p1 -b .0002 +%patch103 -p1 -b .0003 +%patch106 -p1 -b .0006 +%patch107 -p1 -b .0007 + %build mkdir -p %{_target_platform} @@ -51,33 +59,28 @@ make %{?_smp_mflags} -C %{_target_platform} %install -rm -rf %{buildroot} - make install/fast DESTDIR=%{buildroot} -C %{_target_platform} %find_lang %{name} --with-kde -%clean -rm -rf %{buildroot} - - %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files -f %{name}.lang -%defattr(-,root,root,-) %doc ChangeLog COPYING %{_kde4_libdir}/libktorrent.so.5* %files devel -%defattr(-,root,root,-) %{_kde4_appsdir}/cmake/modules/FindKTorrent.cmake %{_kde4_includedir}/libktorrent/ %{_kde4_libdir}/libktorrent.so %changelog +* Mon Dec 24 2012 Rex Dieter 1.3.0-2 +- backport some upstream fixes, and some .spec cleanup + * Sat Sep 1 2012 Alexey Kurov - 1.3.0-1 - libktorrent-1.3.0