Commit 4f7f45a2 authored by rakshasa's avatar rakshasa

Merge branch 'master' into ipv6

parents b80b5580 44b000ea
language: cpp
compiler:
- gcc
- clang
before_install:
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
- sudo apt-get update -qq
- sudo apt-get build-dep libtorrent-dev
- if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.7; fi
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.7" CC="gcc-4.7"; fi
# prevent `macro `AM_PATH_CPPUNIT' not found in library` in `autogen.sh`
- sudo apt-get install libcppunit-dev
# Figure out how to fix the issue running 'make check'.
script: ./autogen.sh && ./configure && make -j12 check && sudo make install
AC_INIT(libtorrent, 0.13.4, sundell.software@gmail.com)
AC_INIT(libtorrent, 0.13.6, sundell.software@gmail.com)
LT_INIT([disable-static])
dnl Find a better way to do this
AC_DEFINE(PEER_NAME, "-lt0D40-", Identifier that is part of the default peer id)
AC_DEFINE(PEER_VERSION, "lt\x0D\x40", 4 byte client and version identifier for DHT)
AC_DEFINE(PEER_NAME, "-lt0D60-", Identifier that is part of the default peer id)
AC_DEFINE(PEER_VERSION, "lt\x0D\x60", 4 byte client and version identifier for DHT)
LIBTORRENT_CURRENT=18
LIBTORRENT_CURRENT=19
LIBTORRENT_REVISION=0
LIBTORRENT_AGE=0
......
......@@ -39,13 +39,23 @@
#include <cstring>
#include <algorithm>
#include <functional>
#include <cstring>
#include <csignal>
#include <csetjmp>
#include "torrent/exceptions.h"
#include "chunk.h"
#include "chunk_iterator.h"
jmp_buf jmp_disk_full;
void
bus_handler(int sig, siginfo_t *si, void *vuctx)
{
if (si->si_code == BUS_ADRERR)
longjmp(jmp_disk_full, 1);
}
namespace torrent {
bool
......@@ -226,6 +236,13 @@ Chunk::to_buffer(void* buffer, uint32_t position, uint32_t length) {
// matching.
bool
Chunk::from_buffer(const void* buffer, uint32_t position, uint32_t length) {
struct sigaction sa, oldact;
std::memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = bus_handler;
sa.sa_flags = SA_SIGINFO;
sigfillset(&sa.sa_mask);
sigaction(SIGBUS, &sa, &oldact);
if (position + length > m_chunkSize)
throw internal_error("Chunk::from_buffer(...) position + length > m_chunkSize.");
......@@ -235,12 +252,18 @@ Chunk::from_buffer(const void* buffer, uint32_t position, uint32_t length) {
Chunk::data_type data;
ChunkIterator itr(this, position, position + length);
do {
data = itr.data();
std::memcpy(data.first, buffer, data.second);
if (setjmp(jmp_disk_full) == 0) {
do {
data = itr.data();
std::memcpy(data.first, buffer, data.second);
buffer = static_cast<const char*>(buffer) + data.second;
} while (itr.next());
buffer = static_cast<const char*>(buffer) + data.second;
} while (itr.next());
} else {
throw storage_error("no space left on disk");
}
sigaction(SIGBUS, &oldact, NULL);
return true;
}
......
......@@ -804,6 +804,9 @@ DhtServer::process_queue(packet_queue& queue, uint32_t* quota) {
while (!queue.empty()) {
DhtTransactionPacket* packet = queue.front();
DhtTransaction::key_type transactionKey = 0;
if(packet->has_transaction())
transactionKey = packet->transaction()->key(packet->id());
// Make sure its transaction hasn't timed out yet, if it has/had one
// and don't bother sending non-transaction packets (replies) after
......@@ -836,7 +839,7 @@ DhtServer::process_queue(packet_queue& queue, uint32_t* quota) {
} catch (network_error& e) {
// Couldn't write packet, maybe something wrong with node address or routing, so mark node as bad.
if (packet->has_transaction()) {
transaction_itr itr = m_transactions.find(packet->transaction()->key(packet->id()));
transaction_itr itr = m_transactions.find(transactionKey);
if (itr == m_transactions.end())
throw internal_error("DhtServer::process_queue could not find transaction.");
......@@ -844,8 +847,12 @@ DhtServer::process_queue(packet_queue& queue, uint32_t* quota) {
}
}
if (packet->has_transaction())
packet->transaction()->set_packet(NULL);
if (packet->has_transaction()) {
// here transaction can be already deleted by failed_transaction.
transaction_itr itr = m_transactions.find(transactionKey);
if (itr != m_transactions.end())
packet->transaction()->set_packet(NULL);
}
delete packet;
}
......
......@@ -46,14 +46,15 @@
namespace torrent {
DhtSearch::DhtSearch(const HashString& target, const DhtBucket& contacts)
: base_type(dht_compare_closer(m_target = target)),
: base_type(dht_compare_closer(target)),
m_pending(0),
m_contacted(0),
m_replied(0),
m_concurrency(3),
m_restart(false),
m_started(false),
m_next(end()) {
m_next(end()),
m_target(target) {
add_contacts(contacts);
}
......
......@@ -241,6 +241,7 @@ DownloadWrapper::receive_hash_done(ChunkHandle handle, const char* hash) {
}
}
data()->call_chunk_done(handle.object());
m_main->chunk_list()->release(&handle);
}
......
......@@ -394,7 +394,7 @@ ProtocolExtension::send_metadata_piece(size_t piece) {
if (m_download->info()->is_meta_download() || piece >= pieceEnd) {
// reject: { "msg_type" => 2, "piece" => ... }
m_pendingType = UT_METADATA;
m_pending = build_bencode(40, "d8:msg_typei2e5:piecei%zuee", piece);
m_pending = build_bencode(sizeof(size_t) + 36, "d8:msg_typei2e5:piecei%zuee", piece);
return;
}
......@@ -407,7 +407,7 @@ ProtocolExtension::send_metadata_piece(size_t piece) {
// data: { "msg_type" => 1, "piece" => ..., "total_size" => ... } followed by piece data (outside of dictionary)
size_t length = piece == pieceEnd - 1 ? m_download->info()->metadata_size() % metadata_piece_size : metadata_piece_size;
m_pendingType = UT_METADATA;
m_pending = build_bencode(length + 128, "d8:msg_typei1e5:piecei%zue10:total_sizei%zuee", piece, metadataSize);
m_pending = build_bencode((2 * sizeof(size_t)) + length + 120, "d8:msg_typei1e5:piecei%zue10:total_sizei%zuee", piece, metadataSize);
memcpy(m_pending.end(), buffer + (piece << metadata_piece_shift), length);
m_pending.set(m_pending.data(), m_pending.end() + length, m_pending.owned());
......
......@@ -289,7 +289,8 @@ Handshake::read_encryption_key() {
if (m_incoming)
prepare_key_plus_pad();
m_encryption.key()->compute_secret(m_readBuffer.position(), 96);
if(!m_encryption.key()->compute_secret(m_readBuffer.position(), 96))
throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_encryption);
m_readBuffer.consume(96);
// Determine the synchronisation string.
......@@ -737,7 +738,7 @@ restart:
break;
if (m_readBuffer.remaining() > m_encryption.length_ia())
throw internal_error("Read past initial payload after incoming encrypted handshake.");
throw handshake_error(ConnectionManager::handshake_failed, e_handshake_invalid_value);
if (m_encryption.crypto() != HandshakeEncryption::crypto_rc4)
m_encryption.info()->set_obfuscated();
......
......@@ -45,7 +45,7 @@
#include <torrent/utils/ranges.h>
namespace torrent {
class ChunkListNode;
class ChunkSelector;
class Download;
class DownloadWrapper;
......@@ -59,6 +59,8 @@ public:
typedef std::function<function_void> slot_void;
typedef void (function_chunk_list_node_p)(ChunkListNode *);
typedef std::function<function_chunk_list_node_p> slot_chunk_list_node_p;
download_data() : m_wanted_chunks(0) {}
const HashString& hash() const { return m_hash; }
......@@ -81,6 +83,7 @@ public:
slot_void& slot_download_done() const { return m_slot_download_done; }
slot_void& slot_partially_done() const { return m_slot_partially_done; }
slot_void& slot_partially_restarted() const { return m_slot_partially_restarted; }
slot_chunk_list_node_p& slot_chunk_done() const {return m_slot_chunk_done;}
protected:
friend class ChunkList;
......@@ -103,7 +106,7 @@ protected:
void call_download_done() { if (m_slot_download_done) m_slot_download_done(); }
void call_partially_done() { if (m_slot_partially_done) m_slot_partially_done(); }
void call_partially_restarted() { if (m_slot_partially_restarted) m_slot_partially_restarted(); }
void call_chunk_done(ChunkListNode* chunk_ptr) {if(m_slot_chunk_done) m_slot_chunk_done(chunk_ptr);}
private:
HashString m_hash;
......@@ -119,6 +122,7 @@ private:
mutable slot_void m_slot_download_done;
mutable slot_void m_slot_partially_done;
mutable slot_void m_slot_partially_restarted;
mutable slot_chunk_list_node_p m_slot_chunk_done;
};
}
......
......@@ -177,13 +177,14 @@ File::resize_file() {
if (m_size == SocketFile(m_fd).size())
return true;
// For now make it so that the fallocate flag indicates if we want
// to do potentially blocking allocation, while FS supported
// non-blocking allocation is done always.
int flags = SocketFile::flag_fallocate;
int flags = 0;
if (m_flags & flag_fallocate)
// Set FS supported non-blocking allocation flag and potentially
// blocking allocation flag if fallocate flag is set.
if (m_flags & flag_fallocate) {
flags |= SocketFile::flag_fallocate;
flags |= SocketFile::flag_fallocate_blocking;
}
return SocketFile(m_fd).set_size(m_size, flags);
}
......
......@@ -71,15 +71,15 @@ namespace torrent {
void
verify_file_list(const FileList* fl) {
if (fl->empty())
throw internal_error("verify_file_list() 1.");
throw internal_error("verify_file_list() 1.", fl->data()->hash());
if ((*fl->begin())->match_depth_prev() != 0 || (*fl->rbegin())->match_depth_next() != 0)
throw internal_error("verify_file_list() 2.");
throw internal_error("verify_file_list() 2.", fl->data()->hash());
for (FileList::const_iterator itr = fl->begin(), last = fl->end() - 1; itr != last; itr++)
if ((*itr)->match_depth_next() != (*(itr + 1))->match_depth_prev() ||
(*itr)->match_depth_next() >= (*itr)->path()->size())
throw internal_error("verify_file_list() 3.");
throw internal_error("verify_file_list() 3.", fl->data()->hash());
}
FileList::FileList() :
......@@ -145,7 +145,7 @@ FileList::completed_bytes() const {
} else {
if (completed_chunks() == 0)
throw internal_error("FileList::bytes_completed() completed_chunks() == 0.");
throw internal_error("FileList::bytes_completed() completed_chunks() == 0.", data()->hash());
return (completed_chunks() - 1) * cs + size_bytes() % cs;
}
......@@ -156,10 +156,10 @@ FileList::left_bytes() const {
uint64_t left = size_bytes() - completed_bytes();
if (left > ((uint64_t)1 << 60))
throw internal_error("FileList::bytes_left() is too large.");
throw internal_error("FileList::bytes_left() is too large.", data()->hash());
if (completed_chunks() == size_chunks() && left != 0)
throw internal_error("FileList::bytes_left() has an invalid size.");
throw internal_error("FileList::bytes_left() has an invalid size.", data()->hash());
return left;
}
......@@ -214,10 +214,10 @@ FileList::free_diskspace() const {
FileList::iterator_range
FileList::split(iterator position, split_type* first, split_type* last) {
if (is_open())
throw internal_error("FileList::split(...) is_open().");
throw internal_error("FileList::split(...) is_open().", data()->hash());
if (first == last || position == end())
throw internal_error("FileList::split(...) invalid arguments.");
throw internal_error("FileList::split(...) invalid arguments.", data()->hash());
if (position != begin())
(*(position - 1))->set_match_depth_next(0);
......@@ -252,7 +252,7 @@ FileList::split(iterator position, split_type* first, split_type* last) {
}
if (offset != oldFile->offset() + oldFile->size_bytes())
throw internal_error("FileList::split(...) split size does not match the old size.");
throw internal_error("FileList::split(...) split size does not match the old size.", data()->hash());
delete oldFile;
return iterator_range(position, itr);
......@@ -369,10 +369,10 @@ FileList::make_all_paths() {
void
FileList::initialize(uint64_t torrentSize, uint32_t chunkSize) {
if (sizeof(off_t) != 8)
throw internal_error("Last minute panic; sizeof(off_t) != 8.");
throw internal_error("Last minute panic; sizeof(off_t) != 8.", data()->hash());
if (chunkSize == 0)
throw internal_error("FileList::initialize() chunk_size() == 0.");
throw internal_error("FileList::initialize() chunk_size() == 0.", data()->hash());
m_chunkSize = chunkSize;
m_torrentSize = torrentSize;
......@@ -405,7 +405,7 @@ FileList::open(int flags) {
LT_LOG_FL(INFO, "Opening.", 0);
if (m_rootDir.empty())
throw internal_error("FileList::open() m_rootDir.empty().");
throw internal_error("FileList::open() m_rootDir.empty().", data()->hash());
m_indirectLinks.push_back(m_rootDir);
......@@ -589,7 +589,7 @@ FileList::create_chunk_part(FileList::iterator itr, uint64_t offset, uint32_t le
length = std::min<uint64_t>(length, (*itr)->size_bytes() - offset);
if ((int64_t)offset < 0)
throw internal_error("FileList::chunk_part(...) caught a negative offset");
throw internal_error("FileList::chunk_part(...) caught a negative offset", data()->hash());
// Check that offset != length of file.
......@@ -602,14 +602,14 @@ FileList::create_chunk_part(FileList::iterator itr, uint64_t offset, uint32_t le
Chunk*
FileList::create_chunk(uint64_t offset, uint32_t length, int prot) {
if (offset + length > m_torrentSize)
throw internal_error("Tried to access chunk out of range in FileList");
throw internal_error("Tried to access chunk out of range in FileList", data()->hash());
std::auto_ptr<Chunk> chunk(new Chunk);
for (iterator itr = std::find_if(begin(), end(), std::bind2nd(std::mem_fun(&File::is_valid_position), offset)); length != 0; ++itr) {
if (itr == end())
throw internal_error("FileList could not find a valid file for chunk");
throw internal_error("FileList could not find a valid file for chunk", data()->hash());
if ((*itr)->size_bytes() == 0)
continue;
......@@ -620,10 +620,10 @@ FileList::create_chunk(uint64_t offset, uint32_t length, int prot) {
return NULL;
if (mc.size() == 0)
throw internal_error("FileList::create_chunk(...) mc.size() == 0.");
throw internal_error("FileList::create_chunk(...) mc.size() == 0.", data()->hash());
if (mc.size() > length)
throw internal_error("FileList::create_chunk(...) mc.size() > length.");
throw internal_error("FileList::create_chunk(...) mc.size() > length.", data()->hash());
chunk->push_back(ChunkPart::MAPPED_MMAP, mc);
chunk->back().set_file(*itr, offset - (*itr)->offset());
......@@ -646,19 +646,19 @@ FileList::create_chunk_index(uint32_t index, int prot) {
void
FileList::mark_completed(uint32_t index) {
if (index >= size_chunks() || completed_chunks() >= size_chunks())
throw internal_error("FileList::mark_completed(...) received an invalid index.");
throw internal_error("FileList::mark_completed(...) received an invalid index.", data()->hash());
if (bitfield()->empty())
throw internal_error("FileList::mark_completed(...) bitfield is empty.");
throw internal_error("FileList::mark_completed(...) bitfield is empty.", data()->hash());
if (bitfield()->size_bits() != size_chunks())
throw internal_error("FileList::mark_completed(...) bitfield is not the right size.");
throw internal_error("FileList::mark_completed(...) bitfield is not the right size.", data()->hash());
if (bitfield()->get(index))
throw internal_error("FileList::mark_completed(...) received a chunk that has already been finished.");
throw internal_error("FileList::mark_completed(...) received a chunk that has already been finished.", data()->hash());
if (bitfield()->size_set() >= bitfield()->size_bits())
throw internal_error("FileList::mark_completed(...) bitfield()->size_set() >= bitfield()->size_bits().");
throw internal_error("FileList::mark_completed(...) bitfield()->size_set() >= bitfield()->size_bits().", data()->hash());
LT_LOG_FL(DEBUG, "Done chunk: index:%" PRIu32 ".", index);
......@@ -668,7 +668,7 @@ FileList::mark_completed(uint32_t index) {
// TODO: Remember to validate 'wanted_chunks'.
if (m_data.normal_priority()->has(index) || m_data.high_priority()->has(index)) {
if (m_data.wanted_chunks() == 0)
throw internal_error("FileList::mark_completed(...) m_data.wanted_chunks() == 0.");
throw internal_error("FileList::mark_completed(...) m_data.wanted_chunks() == 0.", data()->hash());
m_data.set_wanted_chunks(m_data.wanted_chunks() - 1);
}
......@@ -680,7 +680,7 @@ FileList::inc_completed(iterator firstItr, uint32_t index) {
iterator lastItr = std::find_if(firstItr, end(), rak::less(index + 1, std::mem_fun(&File::range_second)));
if (firstItr == end())
throw internal_error("FileList::inc_completed() first == m_entryList->end().");
throw internal_error("FileList::inc_completed() first == m_entryList->end().", data()->hash());
// TODO: Check if this works right for zero-length files.
std::for_each(firstItr,
......@@ -693,7 +693,7 @@ FileList::inc_completed(iterator firstItr, uint32_t index) {
void
FileList::update_completed() {
if (!bitfield()->is_tail_cleared())
throw internal_error("Content::update_done() called but m_bitfield's tail isn't cleared.");
throw internal_error("Content::update_done() called but m_bitfield's tail isn't cleared.", data()->hash());
m_data.update_wanted_chunks();
......
......@@ -46,6 +46,7 @@
#include <exception>
#include <string>
#include <torrent/common.h>
#include <torrent/hash_string.h>
namespace torrent {
......@@ -61,6 +62,10 @@ public:
class LIBTORRENT_EXPORT internal_error : public base_error {
public:
internal_error(const char* msg) { initialize(msg); }
internal_error(const char* msg, const std::string& context) {
initialize(std::string(msg) + " [" + context + "]"); }
internal_error(const char* msg, const HashString& hash) {
initialize(std::string(msg) + " [#" + hash_string_to_hex_str(hash) + "]"); }
internal_error(const std::string& msg) { initialize(msg); }
virtual ~internal_error() throw() {}
......
......@@ -104,7 +104,8 @@ object_read_bencode_c_string(const char* first, const char* last) {
while (first != last && *first >= '0' && *first <= '9')
length = length * 10 + (*first++ - '0');
if (length + 1 > (unsigned int)std::distance(first, last) || *first++ != ':')
if (length + 1 > (unsigned int)std::distance(first, last) || *first++ != ':'
|| length + 1 == 0)
throw torrent::bencode_error("Invalid bencode data.");
return raw_string(first, length);
......
......@@ -61,6 +61,7 @@ ClientList::ClientList() {
insert_helper(ClientInfo::TYPE_AZUREUS, "KT", NULL, NULL, "KTorrent");
insert_helper(ClientInfo::TYPE_AZUREUS, "LT", NULL, NULL, "libtorrent");
insert_helper(ClientInfo::TYPE_AZUREUS, "lt", NULL, NULL, "libTorrent");
insert_helper(ClientInfo::TYPE_AZUREUS, "UM", NULL, NULL, "uTorrent Mac");
insert_helper(ClientInfo::TYPE_AZUREUS, "UT", NULL, NULL, "uTorrent");
insert_helper(ClientInfo::TYPE_MAINLINE, "M", NULL, NULL, "Mainline");
......@@ -72,6 +73,7 @@ ClientList::ClientList() {
insert_helper(ClientInfo::TYPE_AZUREUS, "BB", NULL, NULL, "BitBuddy");
insert_helper(ClientInfo::TYPE_AZUREUS, "BX", NULL, NULL, "Bittorrent X");
insert_helper(ClientInfo::TYPE_AZUREUS, "BS", NULL, NULL, "BTSlave");
insert_helper(ClientInfo::TYPE_AZUREUS, "BT", NULL, NULL, "BBTor");
insert_helper(ClientInfo::TYPE_AZUREUS, "CT", NULL, NULL, "CTorrent");
insert_helper(ClientInfo::TYPE_AZUREUS, "DE", NULL, NULL, "DelugeTorrent");
insert_helper(ClientInfo::TYPE_AZUREUS, "ES", NULL, NULL, "Electric Sheep");
......
......@@ -213,8 +213,13 @@ PollEPoll::do_poll(int64_t timeout_usec, int flags) {
thread_base::acquire_global_lock();
}
if (status == -1 && rak::error_number::current().value() != rak::error_number::e_intr)
throw std::runtime_error("Poll::work(): " + std::string(rak::error_number::current().c_str()));
if (status == -1) {
if (rak::error_number::current().value() != rak::error_number::e_intr) {
throw std::runtime_error("PollEPoll::work(): " + std::string(rak::error_number::current().c_str()));
}
return 0;
}
return perform();
}
......
......@@ -272,8 +272,13 @@ PollKQueue::do_poll(int64_t timeout_usec, int flags) {
thread_base::acquire_global_lock();
}
if (status == -1 && rak::error_number::current().value() != rak::error_number::e_intr)
throw std::runtime_error("Poll::work(): " + std::string(rak::error_number::current().c_str()));
if (status == -1) {
if (rak::error_number::current().value() != rak::error_number::e_intr) {
throw std::runtime_error("PollKQueue::work(): " + std::string(rak::error_number::current().c_str()));
}
return 0;
}
return perform();
}
......
......@@ -254,8 +254,13 @@ PollSelect::do_poll(int64_t timeout_usec, int flags) {
thread_base::acquire_global_lock();
}
if (status == -1 && rak::error_number::current().value() != rak::error_number::e_intr)
throw std::runtime_error("Poll::work(): " + std::string(rak::error_number::current().c_str()));
if (status == -1) {
if (rak::error_number::current().value() != rak::error_number::e_intr) {
throw std::runtime_error("PollSelect::work(): " + std::string(rak::error_number::current().c_str()));
}
return 0;
}
return perform(read_set, write_set, error_set);
}
......
......@@ -80,7 +80,7 @@ DiffieHellman::is_valid() const {
#endif
}
void
bool
DiffieHellman::compute_secret(const unsigned char *pubkey, unsigned int length) {
#ifdef USE_OPENSSL
BIGNUM* k = BN_bin2bn(pubkey, length, NULL);
......@@ -91,6 +91,10 @@ DiffieHellman::compute_secret(const unsigned char *pubkey, unsigned int length)
m_size = DH_compute_key((unsigned char*)m_secret, k, m_dh);
BN_free(k);
return m_size != -1;
#else
return false;
#endif
};
......
......@@ -53,7 +53,7 @@ public:
const unsigned char generator[], int generatorLength);
~DiffieHellman();
void compute_secret(const unsigned char pubkey[], unsigned int length);
bool compute_secret(const unsigned char pubkey[], unsigned int length);
void store_pub_key(unsigned char* dest, unsigned int length);
bool is_valid() const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment