mirror of https://github.com/aria2/aria2
Merge branch 'master' into dynamic-select-file
commit
9727b5b256
6
AUTHORS
6
AUTHORS
|
@ -16,13 +16,17 @@ ITriskTI
|
||||||
Igor Khomyakov
|
Igor Khomyakov
|
||||||
Jarda Snajdr
|
Jarda Snajdr
|
||||||
Kcchouette
|
Kcchouette
|
||||||
|
Kurt Kartaltepe
|
||||||
|
Mingye Wang
|
||||||
Nils Maier
|
Nils Maier
|
||||||
ORiON-
|
ORiON-
|
||||||
|
ReadmeCritic
|
||||||
Ross Smith II
|
Ross Smith II
|
||||||
Ryan Steinmetz
|
Ryan Steinmetz
|
||||||
Ryo ONODERA
|
Ryo ONODERA
|
||||||
Sarim Khan
|
Sarim Khan
|
||||||
Sergey Zolotarev
|
Sergey Zolotarev
|
||||||
|
Sonny Piers
|
||||||
Tatsuhiro Tsujikawa
|
Tatsuhiro Tsujikawa
|
||||||
Vasilij Schneidermann
|
Vasilij Schneidermann
|
||||||
Zoltan Toth-Czifra
|
Zoltan Toth-Czifra
|
||||||
|
@ -36,6 +40,6 @@ luokar
|
||||||
mozillazg
|
mozillazg
|
||||||
multisnow
|
multisnow
|
||||||
oliviercommelarbre
|
oliviercommelarbre
|
||||||
Sonny Piers
|
rotor
|
||||||
|
|
||||||
[1] https://gist.github.com/tatsuhiro-t/deaffeb064652104ad11
|
[1] https://gist.github.com/tatsuhiro-t/deaffeb064652104ad11
|
||||||
|
|
84
NEWS
84
NEWS
|
@ -1,37 +1,79 @@
|
||||||
aria2 1.22.0
|
aria2 1.23.0
|
||||||
============
|
============
|
||||||
|
|
||||||
Release Note
|
Release Note
|
||||||
------------
|
------------
|
||||||
|
|
||||||
This release adds new feature that manages the number of concurrent
|
This release fixes several bugs reported by users, and adds several
|
||||||
downloads dynamically. --stream-piece-selector option gets new value
|
new features. Read the following section for details.
|
||||||
"random" which randomizes the piece selection for HTTP/FTP downloads.
|
|
||||||
This effectively randomizes the order of files on multi-file Web
|
|
||||||
Seeding. Now all contributor's names are in AUTHORS file.
|
|
||||||
Previously, aria2 shows error when it sees floating point number in a
|
|
||||||
torrent file because torrent file specification does not allow
|
|
||||||
floating point number. In this release, they are just ignored, and
|
|
||||||
aria2 continues to parse the rest of the torrent file as if there is
|
|
||||||
nothing wrong.
|
|
||||||
|
|
||||||
Changes
|
Changes
|
||||||
-------
|
-------
|
||||||
|
|
||||||
* Add description about possible fragmentation with
|
* Simplify cache write
|
||||||
--file-allocation=trunc
|
|
||||||
|
|
||||||
* Make single-entry metalink download with multi-file torrent work
|
The previous cache write routine was too complex. I'm sure I can
|
||||||
|
rewrite it to more elegantly. But the primary motivation of this
|
||||||
|
complex logic is for disk activity reduction on Windows 7, and I
|
||||||
|
observed it on my old IDE disk. I checked it again recently, and
|
||||||
|
there is no difference between with and without this complex logic.
|
||||||
|
For this reason, it was removed. Will revert this change if many of
|
||||||
|
users are not happy with this.
|
||||||
|
|
||||||
* Add all contributor's names in AUTHORS
|
* Allow subsecond value in ns cookie.txt file's expiry time field
|
||||||
|
|
||||||
* Ignore floating number in torrent file
|
Fixes GH-655
|
||||||
|
|
||||||
* Added support for a dynamic management of the number of concurrent
|
* Adjust chromium cookie time
|
||||||
downloads as a function of the overall bandwidth observed
|
|
||||||
|
|
||||||
This change adds --optimize-concurrent-downloads option.
|
* import-po: iterate on glob, not ls output
|
||||||
|
|
||||||
Patch from oliviercommelarbre
|
Patch from Mingye Wang
|
||||||
|
|
||||||
* Add --stream-piece-selector=random
|
* Add --stderr option to redirect all stdout log output to stderr
|
||||||
|
|
||||||
|
Fixes GH-638
|
||||||
|
|
||||||
|
* Add "hide" to --download-result option
|
||||||
|
|
||||||
|
Fixes GH-639
|
||||||
|
|
||||||
|
* Fix downloaded metaurl torrent filename
|
||||||
|
|
||||||
|
* Add a little bit of color to have a better visual of important
|
||||||
|
informations
|
||||||
|
|
||||||
|
Patch from rotor
|
||||||
|
|
||||||
|
* Update README URLs based on HTTP redirects
|
||||||
|
|
||||||
|
Patch from ReadmeCritic
|
||||||
|
|
||||||
|
* Relocate from github.com/tatsuhiro-t/aria2 to github.com/aria2/aria2
|
||||||
|
|
||||||
|
Fixes GH-602
|
||||||
|
|
||||||
|
* mingw: Defer the falloc warning until falloc is specified by option
|
||||||
|
|
||||||
|
Fixes GH-594
|
||||||
|
|
||||||
|
* Add bittorrent key to aria2.tellStopped status
|
||||||
|
|
||||||
|
Fixes GH-612
|
||||||
|
|
||||||
|
* Addsystem.listNotifications RPC method
|
||||||
|
|
||||||
|
Merges GH-620
|
||||||
|
|
||||||
|
Patch from Sonny Piers
|
||||||
|
|
||||||
|
* Report CheckIntegrity info in tellStatus
|
||||||
|
|
||||||
|
- Adds verifiedLength to tellStatus. Reports the length of data that
|
||||||
|
has been verified of the current RequestGroup being verified.
|
||||||
|
- Adds verifyPending to tellStatus. Reports if the RequestGroup has
|
||||||
|
a verification of integrity pending.
|
||||||
|
|
||||||
|
Closes GH-561
|
||||||
|
|
||||||
|
Patch from Kurt Kartaltepe
|
||||||
|
|
|
@ -42,7 +42,7 @@ aria2c executable was generated using android-ndk-r10d.
|
||||||
|
|
||||||
The following libraries were statically linked.
|
The following libraries were statically linked.
|
||||||
|
|
||||||
* openssl 1.0.2g
|
* openssl 1.0.2h
|
||||||
* expat 2.1.0
|
* expat 2.1.0
|
||||||
* c-ares 1.11.0
|
* c-ares 1.11.0
|
||||||
* libssh2 1.7.0
|
* libssh2 1.7.0
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
#
|
#
|
||||||
AC_PREREQ([2.67])
|
AC_PREREQ([2.67])
|
||||||
AC_INIT([aria2],[1.22.0],[https://github.com/aria2/aria2/issues],[aria2],[https://aria2.github.io/])
|
AC_INIT([aria2],[1.23.0],[https://github.com/aria2/aria2/issues],[aria2],[https://aria2.github.io/])
|
||||||
|
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
AC_CANONICAL_TARGET
|
AC_CANONICAL_TARGET
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -30,7 +30,7 @@ echo "Renaming po files..."
|
||||||
mv "$WORK_DIR"/aria2/*.po "$WORK_DIR"
|
mv "$WORK_DIR"/aria2/*.po "$WORK_DIR"
|
||||||
|
|
||||||
echo -n "en@quot en@boldquot" > "$PO_DIR"/LINGUAS
|
echo -n "en@quot en@boldquot" > "$PO_DIR"/LINGUAS
|
||||||
for file in `ls "$WORK_DIR"/*.po`; do
|
for file in "$WORK_DIR"/*.po; do
|
||||||
# First remove useless '\r' in messages
|
# First remove useless '\r' in messages
|
||||||
sed -i -e 's/\\r//' "$file"
|
sed -i -e 's/\\r//' "$file"
|
||||||
bn=`basename "$file"`
|
bn=`basename "$file"`
|
||||||
|
|
|
@ -21,5 +21,5 @@ Importing PO files from launchpad-export.tar.gz
|
||||||
The downloaded file is named as launchpad-export.tar.gz at the time of
|
The downloaded file is named as launchpad-export.tar.gz at the time of
|
||||||
this writing. It includes all PO files translated at launchpad. To
|
this writing. It includes all PO files translated at launchpad. To
|
||||||
import those files, use ``import-po`` script in the top directory. It
|
import those files, use ``import-po`` script in the top directory. It
|
||||||
will deflate the tar.gz file and rename PO files and move them to po
|
will inflate the tar.gz file and rename PO files and move them to po
|
||||||
directory and run ``make update-po``.
|
directory and run ``make update-po``.
|
||||||
|
|
|
@ -96,49 +96,10 @@ ssize_t AbstractSingleDiskAdaptor::readDataDropCache(unsigned char* data,
|
||||||
|
|
||||||
void AbstractSingleDiskAdaptor::writeCache(const WrDiskCacheEntry* entry)
|
void AbstractSingleDiskAdaptor::writeCache(const WrDiskCacheEntry* entry)
|
||||||
{
|
{
|
||||||
// Write cached data in 4KiB aligned offset. This reduces disk
|
for (auto& d : entry->getDataSet()) {
|
||||||
// activity especially on Windows 7 NTFS. In this code, we assume
|
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", d->goff, d->len));
|
||||||
// that maximum length of DataCell data is 16KiB to simplify the
|
writeData(d->data + d->offset, d->len, d->goff);
|
||||||
// code.
|
|
||||||
unsigned char buf[16_k];
|
|
||||||
int64_t start = 0;
|
|
||||||
size_t buflen = 0;
|
|
||||||
size_t buffoffset = 0;
|
|
||||||
const WrDiskCacheEntry::DataCellSet& dataSet = entry->getDataSet();
|
|
||||||
for (auto& d : dataSet) {
|
|
||||||
if (start + static_cast<ssize_t>(buflen) < d->goff) {
|
|
||||||
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", start,
|
|
||||||
static_cast<unsigned long>(buflen)));
|
|
||||||
writeData(buf + buffoffset, buflen - buffoffset, start);
|
|
||||||
start = d->goff;
|
|
||||||
buflen = buffoffset = 0;
|
|
||||||
}
|
}
|
||||||
if (buflen == 0 && (d->goff & 0xfff) == 0 && (d->len & 0xfff) == 0) {
|
|
||||||
// Already aligned. Write it without copy.
|
|
||||||
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", start,
|
|
||||||
static_cast<unsigned long>(d->len)));
|
|
||||||
writeData(d->data + d->offset, d->len, start);
|
|
||||||
start += d->len;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (buflen == 0) {
|
|
||||||
buflen = buffoffset = d->goff & 0xfff;
|
|
||||||
}
|
|
||||||
size_t wlen = std::min(sizeof(buf) - buflen, d->len);
|
|
||||||
memcpy(buf + buflen, d->data + d->offset, wlen);
|
|
||||||
buflen += wlen;
|
|
||||||
if (buflen == sizeof(buf)) {
|
|
||||||
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", start,
|
|
||||||
static_cast<unsigned long>(buflen)));
|
|
||||||
writeData(buf + buffoffset, buflen - buffoffset, start);
|
|
||||||
memcpy(buf, d->data + d->offset + wlen, d->len - wlen);
|
|
||||||
start += sizeof(buf) - buffoffset;
|
|
||||||
buflen = d->len - wlen;
|
|
||||||
buffoffset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writeData(buf + buffoffset, buflen - buffoffset, start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractSingleDiskAdaptor::fileExists()
|
bool AbstractSingleDiskAdaptor::fileExists()
|
||||||
|
|
|
@ -37,16 +37,13 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "BtConstants.h"
|
|
||||||
#include "a2functional.h"
|
#include "a2functional.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
|
const unsigned char BtHandshakeMessage::BT_PSTR[] = "BitTorrent protocol";
|
||||||
const char BtHandshakeMessage::NAME[] = "handshake";
|
const char BtHandshakeMessage::NAME[] = "handshake";
|
||||||
|
|
||||||
const unsigned char* BtHandshakeMessage::BT_PSTR =
|
|
||||||
reinterpret_cast<const unsigned char*>("BitTorrent protocol");
|
|
||||||
|
|
||||||
BtHandshakeMessage::BtHandshakeMessage() : SimpleBtMessage(ID, NAME) { init(); }
|
BtHandshakeMessage::BtHandshakeMessage() : SimpleBtMessage(ID, NAME) { init(); }
|
||||||
|
|
||||||
BtHandshakeMessage::BtHandshakeMessage(const unsigned char* infoHash,
|
BtHandshakeMessage::BtHandshakeMessage(const unsigned char* infoHash,
|
||||||
|
@ -54,19 +51,17 @@ BtHandshakeMessage::BtHandshakeMessage(const unsigned char* infoHash,
|
||||||
: SimpleBtMessage(ID, NAME)
|
: SimpleBtMessage(ID, NAME)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
memcpy(infoHash_, infoHash, INFO_HASH_LENGTH);
|
std::copy_n(infoHash, infoHash_.size(), std::begin(infoHash_));
|
||||||
memcpy(peerId_, peerId, PEER_ID_LENGTH);
|
std::copy_n(peerId, peerId_.size(), std::begin(peerId_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BtHandshakeMessage::~BtHandshakeMessage() {}
|
||||||
|
|
||||||
void BtHandshakeMessage::init()
|
void BtHandshakeMessage::init()
|
||||||
{
|
{
|
||||||
pstrlen_ = 19;
|
pstrlen_ = 19;
|
||||||
pstr_ = new unsigned char[PSTR_LENGTH];
|
std::copy_n(BT_PSTR, pstr_.size(), std::begin(pstr_));
|
||||||
reserved_ = new unsigned char[RESERVED_LENGTH];
|
std::fill(std::begin(reserved_), std::end(reserved_), 0);
|
||||||
infoHash_ = new unsigned char[INFO_HASH_LENGTH];
|
|
||||||
peerId_ = new unsigned char[PEER_ID_LENGTH];
|
|
||||||
memcpy(pstr_, BT_PSTR, PSTR_LENGTH);
|
|
||||||
memset(reserved_, 0, RESERVED_LENGTH);
|
|
||||||
// fast extension
|
// fast extension
|
||||||
reserved_[7] |= 0x04u;
|
reserved_[7] |= 0x04u;
|
||||||
// extended messaging
|
// extended messaging
|
||||||
|
@ -76,23 +71,25 @@ void BtHandshakeMessage::init()
|
||||||
std::unique_ptr<BtHandshakeMessage>
|
std::unique_ptr<BtHandshakeMessage>
|
||||||
BtHandshakeMessage::create(const unsigned char* data, size_t dataLength)
|
BtHandshakeMessage::create(const unsigned char* data, size_t dataLength)
|
||||||
{
|
{
|
||||||
auto message = make_unique<BtHandshakeMessage>();
|
auto msg = make_unique<BtHandshakeMessage>();
|
||||||
message->pstrlen_ = data[0];
|
msg->pstrlen_ = data[0];
|
||||||
memcpy(message->pstr_, &data[1], PSTR_LENGTH);
|
std::copy_n(&data[1], msg->pstr_.size(), std::begin(msg->pstr_));
|
||||||
memcpy(message->reserved_, &data[20], RESERVED_LENGTH);
|
std::copy_n(&data[20], msg->reserved_.size(), std::begin(msg->reserved_));
|
||||||
memcpy(message->infoHash_, &data[28], INFO_HASH_LENGTH);
|
std::copy_n(&data[28], msg->infoHash_.size(), std::begin(msg->infoHash_));
|
||||||
memcpy(message->peerId_, &data[48], PEER_ID_LENGTH);
|
std::copy_n(&data[48], msg->peerId_.size(), std::begin(msg->peerId_));
|
||||||
return message;
|
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* BtHandshakeMessage::createMessage()
|
unsigned char* BtHandshakeMessage::createMessage()
|
||||||
{
|
{
|
||||||
auto msg = new unsigned char[MESSAGE_LENGTH];
|
auto msg = new unsigned char[MESSAGE_LENGTH];
|
||||||
msg[0] = pstrlen_;
|
auto dst = msg;
|
||||||
memcpy(msg + 1, pstr_, PSTR_LENGTH);
|
*dst++ = pstrlen_;
|
||||||
memcpy(msg + 20, reserved_, RESERVED_LENGTH);
|
dst = std::copy(std::begin(pstr_), std::end(pstr_), dst);
|
||||||
memcpy(msg + 28, infoHash_, INFO_HASH_LENGTH);
|
dst = std::copy(std::begin(reserved_), std::end(reserved_), dst);
|
||||||
memcpy(msg + 48, peerId_, PEER_ID_LENGTH);
|
dst = std::copy(std::begin(infoHash_), std::end(infoHash_), dst);
|
||||||
|
std::copy(std::begin(peerId_), std::end(peerId_), dst);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,8 +98,8 @@ size_t BtHandshakeMessage::getMessageLength() { return MESSAGE_LENGTH; }
|
||||||
std::string BtHandshakeMessage::toString() const
|
std::string BtHandshakeMessage::toString() const
|
||||||
{
|
{
|
||||||
return fmt("%s peerId=%s, reserved=%s", NAME,
|
return fmt("%s peerId=%s, reserved=%s", NAME,
|
||||||
util::percentEncode(peerId_, PEER_ID_LENGTH).c_str(),
|
util::percentEncode(peerId_.data(), peerId_.size()).c_str(),
|
||||||
util::toHex(reserved_, RESERVED_LENGTH).c_str());
|
util::toHex(reserved_.data(), reserved_.size()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BtHandshakeMessage::isFastExtensionSupported() const
|
bool BtHandshakeMessage::isFastExtensionSupported() const
|
||||||
|
@ -119,12 +116,12 @@ bool BtHandshakeMessage::isDHTEnabled() const { return reserved_[7] & 0x01u; }
|
||||||
|
|
||||||
void BtHandshakeMessage::setInfoHash(const unsigned char* infoHash)
|
void BtHandshakeMessage::setInfoHash(const unsigned char* infoHash)
|
||||||
{
|
{
|
||||||
memcpy(infoHash_, infoHash, INFO_HASH_LENGTH);
|
std::copy_n(infoHash, infoHash_.size(), std::begin(infoHash_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BtHandshakeMessage::setPeerId(const unsigned char* peerId)
|
void BtHandshakeMessage::setPeerId(const unsigned char* peerId)
|
||||||
{
|
{
|
||||||
memcpy(peerId_, peerId, PEER_ID_LENGTH);
|
std::copy_n(peerId, peerId_.size(), std::begin(peerId_));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -37,21 +37,26 @@
|
||||||
|
|
||||||
#include "SimpleBtMessage.h"
|
#include "SimpleBtMessage.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "BtConstants.h"
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
class BtHandshakeMessage : public SimpleBtMessage {
|
class BtHandshakeMessage : public SimpleBtMessage {
|
||||||
public:
|
public:
|
||||||
static const size_t PSTR_LENGTH = 19;
|
constexpr static size_t PSTR_LENGTH = 19;
|
||||||
static const unsigned char* BT_PSTR;
|
constexpr static size_t RESERVED_LENGTH = 8;
|
||||||
static const size_t RESERVED_LENGTH = 8;
|
constexpr static size_t MESSAGE_LENGTH = 68;
|
||||||
static const size_t MESSAGE_LENGTH = 68;
|
const static unsigned char BT_PSTR[];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t pstrlen_;
|
uint8_t pstrlen_;
|
||||||
unsigned char* pstr_;
|
std::array<unsigned char, PSTR_LENGTH> pstr_;
|
||||||
unsigned char* reserved_;
|
std::array<unsigned char, RESERVED_LENGTH> reserved_;
|
||||||
unsigned char* infoHash_;
|
std::array<unsigned char, INFO_HASH_LENGTH> infoHash_;
|
||||||
unsigned char* peerId_;
|
std::array<unsigned char, PEER_ID_LENGTH> peerId_;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -66,17 +71,11 @@ public:
|
||||||
static std::unique_ptr<BtHandshakeMessage> create(const unsigned char* data,
|
static std::unique_ptr<BtHandshakeMessage> create(const unsigned char* data,
|
||||||
size_t dataLength);
|
size_t dataLength);
|
||||||
|
|
||||||
virtual ~BtHandshakeMessage()
|
virtual ~BtHandshakeMessage();
|
||||||
{
|
|
||||||
delete[] pstr_;
|
|
||||||
delete[] reserved_;
|
|
||||||
delete[] infoHash_;
|
|
||||||
delete[] peerId_;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8_t ID = INT8_MAX;
|
static const uint8_t ID = INT8_MAX;
|
||||||
|
|
||||||
static const char NAME[];
|
const static char NAME[];
|
||||||
|
|
||||||
virtual void doReceivedAction() CXX11_OVERRIDE{};
|
virtual void doReceivedAction() CXX11_OVERRIDE{};
|
||||||
|
|
||||||
|
@ -104,15 +103,15 @@ public:
|
||||||
|
|
||||||
uint8_t getPstrlen() const { return pstrlen_; }
|
uint8_t getPstrlen() const { return pstrlen_; }
|
||||||
|
|
||||||
const unsigned char* getPstr() const { return pstr_; }
|
const unsigned char* getPstr() const { return pstr_.data(); }
|
||||||
|
|
||||||
const unsigned char* getReserved() const { return reserved_; }
|
const unsigned char* getReserved() const { return reserved_.data(); }
|
||||||
|
|
||||||
const unsigned char* getInfoHash() const { return infoHash_; }
|
const unsigned char* getInfoHash() const { return infoHash_.data(); }
|
||||||
|
|
||||||
void setInfoHash(const unsigned char* infoHash);
|
void setInfoHash(const unsigned char* infoHash);
|
||||||
|
|
||||||
const unsigned char* getPeerId() const { return peerId_; }
|
const unsigned char* getPeerId() const { return peerId_.data(); }
|
||||||
|
|
||||||
void setPeerId(const unsigned char* peerId);
|
void setPeerId(const unsigned char* peerId);
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "DHTGetPeersReplyMessage.h"
|
#include "DHTGetPeersReplyMessage.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
#include "DHTNode.h"
|
#include "DHTNode.h"
|
||||||
#include "DHTBucket.h"
|
#include "DHTBucket.h"
|
||||||
|
@ -81,24 +82,24 @@ std::unique_ptr<Dict> DHTGetPeersReplyMessage::getResponse()
|
||||||
rDict->put(TOKEN, token_);
|
rDict->put(TOKEN, token_);
|
||||||
// TODO want parameter
|
// TODO want parameter
|
||||||
if (!closestKNodes_.empty()) {
|
if (!closestKNodes_.empty()) {
|
||||||
unsigned char buffer[DHTBucket::K * 38];
|
std::array<unsigned char, DHTBucket::K * 38> buffer;
|
||||||
const int clen = bittorrent::getCompactLength(family_);
|
const auto clen = bittorrent::getCompactLength(family_);
|
||||||
const int unit = clen + 20;
|
const auto unit = clen + DHT_ID_LENGTH;
|
||||||
size_t offset = 0;
|
auto last = std::begin(buffer);
|
||||||
size_t k = 0;
|
size_t k = 0;
|
||||||
for (auto i = std::begin(closestKNodes_), eoi = std::end(closestKNodes_);
|
for (auto i = std::begin(closestKNodes_);
|
||||||
i != eoi && k < DHTBucket::K; ++i) {
|
i != std::end(closestKNodes_) && k < DHTBucket::K; ++i) {
|
||||||
memcpy(buffer + offset, (*i)->getID(), DHT_ID_LENGTH);
|
std::array<unsigned char, COMPACT_LEN_IPV6> compact;
|
||||||
unsigned char compact[COMPACT_LEN_IPV6];
|
auto compactlen = bittorrent::packcompact(
|
||||||
int compactlen = bittorrent::packcompact(compact, (*i)->getIPAddress(),
|
compact.data(), (*i)->getIPAddress(), (*i)->getPort());
|
||||||
(*i)->getPort());
|
|
||||||
if (compactlen == clen) {
|
if (compactlen == clen) {
|
||||||
memcpy(buffer + 20 + offset, compact, compactlen);
|
last = std::copy_n((*i)->getID(), DHT_ID_LENGTH, last);
|
||||||
offset += unit;
|
last = std::copy_n(std::begin(compact), compactlen, last);
|
||||||
++k;
|
++k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rDict->put(family_ == AF_INET ? NODES : NODES6, String::g(buffer, offset));
|
rDict->put(family_ == AF_INET ? NODES : NODES6,
|
||||||
|
String::g(std::begin(buffer), last));
|
||||||
}
|
}
|
||||||
if (!values_.empty()) {
|
if (!values_.empty()) {
|
||||||
// Limit the size of values list. The maximum size of UDP datagram
|
// Limit the size of values list. The maximum size of UDP datagram
|
||||||
|
@ -123,16 +124,16 @@ std::unique_ptr<Dict> DHTGetPeersReplyMessage::getResponse()
|
||||||
// doesn't specify the maximum size of token, reply message
|
// doesn't specify the maximum size of token, reply message
|
||||||
// template may get bigger than 395 bytes. So we use 25 as maximum
|
// template may get bigger than 395 bytes. So we use 25 as maximum
|
||||||
// number of peer info that a message can carry.
|
// number of peer info that a message can carry.
|
||||||
static const size_t MAX_VALUES_SIZE = 25;
|
constexpr size_t MAX_VALUES_SIZE = 25;
|
||||||
auto valuesList = List::g();
|
auto valuesList = List::g();
|
||||||
for (auto i = std::begin(values_), eoi = std::end(values_);
|
for (auto i = std::begin(values_);
|
||||||
i != eoi && valuesList->size() < MAX_VALUES_SIZE; ++i) {
|
i != std::end(values_) && valuesList->size() < MAX_VALUES_SIZE; ++i) {
|
||||||
unsigned char compact[COMPACT_LEN_IPV6];
|
std::array<unsigned char, COMPACT_LEN_IPV6> compact;
|
||||||
const int clen = bittorrent::getCompactLength(family_);
|
const auto clen = bittorrent::getCompactLength(family_);
|
||||||
int compactlen = bittorrent::packcompact(compact, (*i)->getIPAddress(),
|
auto compactlen = bittorrent::packcompact(
|
||||||
(*i)->getPort());
|
compact.data(), (*i)->getIPAddress(), (*i)->getPort());
|
||||||
if (compactlen == clen) {
|
if (compactlen == clen) {
|
||||||
valuesList->append(String::g(compact, compactlen));
|
valuesList->append(String::g(compact.data(), compactlen));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rDict->put(VALUES, std::move(valuesList));
|
rDict->put(VALUES, std::move(valuesList));
|
||||||
|
|
|
@ -412,98 +412,10 @@ ssize_t MultiDiskAdaptor::readData(unsigned char* data, size_t len,
|
||||||
|
|
||||||
void MultiDiskAdaptor::writeCache(const WrDiskCacheEntry* entry)
|
void MultiDiskAdaptor::writeCache(const WrDiskCacheEntry* entry)
|
||||||
{
|
{
|
||||||
// Write cached data in 4KiB aligned offset. This reduces disk
|
for (auto& d : entry->getDataSet()) {
|
||||||
// activity especially on Windows 7 NTFS.
|
A2_LOG_DEBUG(fmt("Cache flush goff=%" PRId64 ", len=%lu", d->goff, d->len));
|
||||||
unsigned char buf[16_k];
|
writeData(d->data + d->offset, d->len, d->goff);
|
||||||
size_t buflen = 0;
|
|
||||||
size_t buffoffset = 0;
|
|
||||||
auto& dataSet = entry->getDataSet();
|
|
||||||
if (dataSet.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
auto dent =
|
|
||||||
findFirstDiskWriterEntry(diskWriterEntries_, (*dataSet.begin())->goff),
|
|
||||||
eod = diskWriterEntries_.cend();
|
|
||||||
auto i = std::begin(dataSet), eoi = std::end(dataSet);
|
|
||||||
size_t celloff = 0;
|
|
||||||
for (; dent != eod; ++dent) {
|
|
||||||
int64_t lstart = 0, lp = 0;
|
|
||||||
auto& fent = (*dent)->getFileEntry();
|
|
||||||
if (fent->getLength() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (; i != eoi;) {
|
|
||||||
if (std::max(fent->getOffset(),
|
|
||||||
static_cast<int64_t>((*i)->goff + celloff)) <
|
|
||||||
std::min(fent->getLastOffset(),
|
|
||||||
static_cast<int64_t>((*i)->goff + (*i)->len))) {
|
|
||||||
openIfNot((*dent).get(), &DiskWriterEntry::openFile);
|
|
||||||
if (!(*dent)->isOpen()) {
|
|
||||||
throwOnDiskWriterNotOpened((*dent).get(), (*i)->goff + celloff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
A2_LOG_DEBUG(fmt("%s Cache flush loff=%" PRId64 ", len=%lu",
|
|
||||||
fent->getPath().c_str(), lstart,
|
|
||||||
static_cast<unsigned long>(buflen - buffoffset)));
|
|
||||||
(*dent)->getDiskWriter()->writeData(buf + buffoffset,
|
|
||||||
buflen - buffoffset, lstart);
|
|
||||||
buflen = buffoffset = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int64_t loff = fent->gtoloff((*i)->goff + celloff);
|
|
||||||
if (static_cast<int64_t>(lstart + buflen) < loff) {
|
|
||||||
A2_LOG_DEBUG(fmt("%s Cache flush loff=%" PRId64 ", len=%lu",
|
|
||||||
fent->getPath().c_str(), lstart,
|
|
||||||
static_cast<unsigned long>(buflen - buffoffset)));
|
|
||||||
(*dent)->getDiskWriter()->writeData(buf + buffoffset,
|
|
||||||
buflen - buffoffset, lstart);
|
|
||||||
lstart = lp = loff;
|
|
||||||
buflen = buffoffset = 0;
|
|
||||||
}
|
|
||||||
// If the position of the cache data is not aligned, offset
|
|
||||||
// buffer so that next write can be aligned.
|
|
||||||
if (buflen == 0) {
|
|
||||||
buflen = buffoffset = loff & 0xfff;
|
|
||||||
}
|
|
||||||
assert((*i)->len > celloff);
|
|
||||||
for (;;) {
|
|
||||||
size_t wlen = std::min(static_cast<int64_t>((*i)->len - celloff),
|
|
||||||
fent->getLength() - lp);
|
|
||||||
wlen = std::min(wlen, sizeof(buf) - buflen);
|
|
||||||
memcpy(buf + buflen, (*i)->data + (*i)->offset + celloff, wlen);
|
|
||||||
buflen += wlen;
|
|
||||||
celloff += wlen;
|
|
||||||
lp += wlen;
|
|
||||||
if (lp == fent->getLength() || buflen == sizeof(buf)) {
|
|
||||||
A2_LOG_DEBUG(fmt("%s Cache flush loff=%" PRId64 ", len=%lu",
|
|
||||||
fent->getPath().c_str(), lstart,
|
|
||||||
static_cast<unsigned long>(buflen - buffoffset)));
|
|
||||||
(*dent)->getDiskWriter()->writeData(buf + buffoffset,
|
|
||||||
buflen - buffoffset, lstart);
|
|
||||||
lstart += buflen - buffoffset;
|
|
||||||
lp = lstart;
|
|
||||||
buflen = buffoffset = 0;
|
|
||||||
}
|
|
||||||
if (lp == fent->getLength() || celloff == (*i)->len) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (celloff == (*i)->len) {
|
|
||||||
++i;
|
|
||||||
celloff = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i == eoi) {
|
|
||||||
A2_LOG_DEBUG(fmt("%s Cache flush loff=%" PRId64 ", len=%lu",
|
|
||||||
fent->getPath().c_str(), lstart,
|
|
||||||
static_cast<unsigned long>(buflen - buffoffset)));
|
|
||||||
(*dent)->getDiskWriter()->writeData(buf + buffoffset, buflen - buffoffset,
|
|
||||||
lstart);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(i == eoi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MultiDiskAdaptor::fileExists()
|
bool MultiDiskAdaptor::fileExists()
|
||||||
|
|
|
@ -69,10 +69,15 @@ std::unique_ptr<Cookie> parseNsCookie(const std::string& cookieStr,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
int64_t expiryTime;
|
int64_t expiryTime;
|
||||||
if (!util::parseLLIntNoThrow(expiryTime,
|
{
|
||||||
|
// chrome extension uses subsecond resolution for expiry time.
|
||||||
|
double expiryTimeDouble;
|
||||||
|
if (!util::parseDoubleNoThrow(expiryTimeDouble,
|
||||||
std::string(vs[4].first, vs[4].second))) {
|
std::string(vs[4].first, vs[4].second))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
expiryTime = static_cast<int64_t>(expiryTimeDouble);
|
||||||
|
}
|
||||||
if (std::numeric_limits<time_t>::max() < expiryTime) {
|
if (std::numeric_limits<time_t>::max() < expiryTime) {
|
||||||
expiryTime = std::numeric_limits<time_t>::max();
|
expiryTime = std::numeric_limits<time_t>::max();
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,8 +59,13 @@ Sqlite3ChromiumCookieParser::~Sqlite3ChromiumCookieParser() {}
|
||||||
|
|
||||||
const char* Sqlite3ChromiumCookieParser::getQuery() const
|
const char* Sqlite3ChromiumCookieParser::getQuery() const
|
||||||
{
|
{
|
||||||
return "SELECT host_key, path, secure, expires_utc, name, value, "
|
// chrome's time is microsecond resolution, and its epoc is Jan 1
|
||||||
"last_access_utc"
|
// 00:00:00 +0000 1601, so we have to convert it to second from UNIX
|
||||||
|
// epoc. 11644473600 is the second between chrome's epoc and UNIX
|
||||||
|
// epoc. e.g., date +%s -d 'Jan 1 00:00:00 +0000 1601'
|
||||||
|
return "SELECT host_key, path, secure, expires_utc / 1000000 - 11644473600 "
|
||||||
|
"as expires_utc, name, value, "
|
||||||
|
"last_access_utc / 1000000 - 11644473600 as last_access_utc"
|
||||||
" FROM cookies";
|
" FROM cookies";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
src/util.cc
27
src/util.cc
|
@ -596,6 +596,33 @@ bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool parseDoubleNoThrow(double& res, const std::string& s)
|
||||||
|
{
|
||||||
|
if (s.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
char* endptr;
|
||||||
|
auto d = strtod(s.c_str(), &endptr);
|
||||||
|
|
||||||
|
if (errno == ERANGE) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endptr != s.c_str() + s.size()) {
|
||||||
|
for (auto i = std::begin(s) + (endptr - s.c_str()); i != std::end(s); ++i) {
|
||||||
|
if (!isspace(*i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = d;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
SegList<int> parseIntSegments(const std::string& src)
|
SegList<int> parseIntSegments(const std::string& src)
|
||||||
{
|
{
|
||||||
SegList<int> sgl;
|
SegList<int> sgl;
|
||||||
|
|
|
@ -280,6 +280,10 @@ bool parseUIntNoThrow(uint32_t& res, const std::string& s, int base = 10);
|
||||||
|
|
||||||
bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base = 10);
|
bool parseLLIntNoThrow(int64_t& res, const std::string& s, int base = 10);
|
||||||
|
|
||||||
|
// Parses |s| as floating point number, and stores the result into
|
||||||
|
// |res|. This function returns true if it succeeds.
|
||||||
|
bool parseDoubleNoThrow(double& res, const std::string& s);
|
||||||
|
|
||||||
SegList<int> parseIntSegments(const std::string& src);
|
SegList<int> parseIntSegments(const std::string& src);
|
||||||
|
|
||||||
// Parses string which specifies the range of piece index for higher
|
// Parses string which specifies the range of piece index for higher
|
||||||
|
|
|
@ -328,10 +328,10 @@ void CookieStorageTest::testLoad()
|
||||||
c = cookies[3];
|
c = cookies[3];
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("TAX"), c->getName());
|
CPPUNIT_ASSERT_EQUAL(std::string("TAX"), c->getName());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("1000"), c->getValue());
|
CPPUNIT_ASSERT_EQUAL(std::string("1000"), c->getValue());
|
||||||
CPPUNIT_ASSERT((time_t)INT32_MAX <= c->getExpiryTime());
|
CPPUNIT_ASSERT_EQUAL((time_t)1463304912, c->getExpiryTime());
|
||||||
CPPUNIT_ASSERT(c->getPersistent());
|
CPPUNIT_ASSERT(c->getPersistent());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("/"), c->getPath());
|
CPPUNIT_ASSERT_EQUAL(std::string("/"), c->getPath());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("overflow"), c->getDomain());
|
CPPUNIT_ASSERT_EQUAL(std::string("something"), c->getDomain());
|
||||||
CPPUNIT_ASSERT(!c->getSecure());
|
CPPUNIT_ASSERT(!c->getSecure());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,9 +69,9 @@ void NsCookieParserTest::testParse()
|
||||||
c = cookies[3].get();
|
c = cookies[3].get();
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("TAX"), c->getName());
|
CPPUNIT_ASSERT_EQUAL(std::string("TAX"), c->getName());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("1000"), c->getValue());
|
CPPUNIT_ASSERT_EQUAL(std::string("1000"), c->getValue());
|
||||||
CPPUNIT_ASSERT((time_t)INT32_MAX <= c->getExpiryTime());
|
CPPUNIT_ASSERT_EQUAL((time_t)1463304912, c->getExpiryTime());
|
||||||
CPPUNIT_ASSERT(c->getPersistent());
|
CPPUNIT_ASSERT(c->getPersistent());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("overflow"), c->getDomain());
|
CPPUNIT_ASSERT_EQUAL(std::string("something"), c->getDomain());
|
||||||
CPPUNIT_ASSERT(c->getHostOnly());
|
CPPUNIT_ASSERT(c->getHostOnly());
|
||||||
CPPUNIT_ASSERT_EQUAL(std::string("/"), c->getPath());
|
CPPUNIT_ASSERT_EQUAL(std::string("/"), c->getPath());
|
||||||
CPPUNIT_ASSERT(!c->getSecure());
|
CPPUNIT_ASSERT(!c->getSecure());
|
||||||
|
|
|
@ -66,6 +66,7 @@ class UtilTest2 : public CppUnit::TestFixture {
|
||||||
CPPUNIT_TEST(testInPrivateAddress);
|
CPPUNIT_TEST(testInPrivateAddress);
|
||||||
CPPUNIT_TEST(testSecfmt);
|
CPPUNIT_TEST(testSecfmt);
|
||||||
CPPUNIT_TEST(testTlsHostnameMatch);
|
CPPUNIT_TEST(testTlsHostnameMatch);
|
||||||
|
CPPUNIT_TEST(testParseDoubleNoThrow);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -115,6 +116,7 @@ public:
|
||||||
void testInPrivateAddress();
|
void testInPrivateAddress();
|
||||||
void testSecfmt();
|
void testSecfmt();
|
||||||
void testTlsHostnameMatch();
|
void testTlsHostnameMatch();
|
||||||
|
void testParseDoubleNoThrow();
|
||||||
};
|
};
|
||||||
|
|
||||||
CPPUNIT_TEST_SUITE_REGISTRATION(UtilTest2);
|
CPPUNIT_TEST_SUITE_REGISTRATION(UtilTest2);
|
||||||
|
@ -978,4 +980,21 @@ void UtilTest2::testTlsHostnameMatch()
|
||||||
CPPUNIT_ASSERT(!util::tlsHostnameMatch("xn--*.a.b", "xn--c.a.b"));
|
CPPUNIT_ASSERT(!util::tlsHostnameMatch("xn--*.a.b", "xn--c.a.b"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UtilTest2::testParseDoubleNoThrow()
|
||||||
|
{
|
||||||
|
double n;
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, " 123 "));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(123., n);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, "3.14"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(3.14, n);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(util::parseDoubleNoThrow(n, "-3.14"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(-3.14, n);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(!util::parseDoubleNoThrow(n, ""));
|
||||||
|
CPPUNIT_ASSERT(!util::parseDoubleNoThrow(n, "123x"));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
Binary file not shown.
|
@ -5,5 +5,5 @@ expired FALSE / FALSE 1000 user me
|
||||||
|
|
||||||
192.168.0.1 TRUE /cgi-bin FALSE 0 passwd secret
|
192.168.0.1 TRUE /cgi-bin FALSE 0 passwd secret
|
||||||
badformat
|
badformat
|
||||||
overflow FALSE / FALSE 9223372036854775807 TAX 1000
|
something FALSE / FALSE 1463304912.5 TAX 1000
|
||||||
.example.org TRUE / FALSE 2147483647 novalue
|
.example.org TRUE / FALSE 2147483647.123 novalue
|
||||||
|
|
Loading…
Reference in New Issue