revert lt sync for later testing

This commit is contained in:
Marcos Pinto 2007-09-21 00:22:38 +00:00
commit 0b746d2ab1
123 changed files with 2461 additions and 5456 deletions

View file

@ -25,8 +25,6 @@ extern char const* peer_error_alert_doc;
extern char const* invalid_request_alert_doc; extern char const* invalid_request_alert_doc;
extern char const* peer_request_doc; extern char const* peer_request_doc;
extern char const* torrent_finished_alert_doc; extern char const* torrent_finished_alert_doc;
extern char const* torrent_paused_alert_doc;
extern char const* storage_moved_alert_doc;
extern char const* metadata_failed_alert_doc; extern char const* metadata_failed_alert_doc;
extern char const* metadata_received_alert_doc; extern char const* metadata_received_alert_doc;
extern char const* fastresume_rejected_alert_doc; extern char const* fastresume_rejected_alert_doc;
@ -142,18 +140,7 @@ void bind_alert()
) )
.def_readonly("handle", &torrent_finished_alert::handle) .def_readonly("handle", &torrent_finished_alert::handle)
; ;
class_<torrent_paused_alert, bases<alert>, noncopyable>(
"torrent_paused_alert", torrent_paused_alert_doc, no_init
)
.def_readonly("handle", &torrent_paused_alert::handle)
;
class_<storage_moved_alert, bases<alert>, noncopyable>(
"storage_moved_alert", storage_moved_alert_doc, no_init
)
.def_readonly("handle", &storage_moved_alert::handle)
;
class_<metadata_failed_alert, bases<alert>, noncopyable>( class_<metadata_failed_alert, bases<alert>, noncopyable>(
"metadata_failed_alert", metadata_failed_alert_doc, no_init "metadata_failed_alert", metadata_failed_alert_doc, no_init
) )

View file

@ -164,14 +164,14 @@ char const* session_set_severity_level_doc =
""; "";
char const* session_pop_alert_doc = char const* session_pop_alert_doc =
""; "";
char const* session_start_upnp_doc = char const* session_start_upnp_doc =
""; "";
char const* session_stop_upnp_doc = char const* session_stop_upnp_doc =
""; "";
char const* session_start_natpmp_doc = char const* session_start_natpmp_doc =
"";
char const* session_stop_natpmp_doc =
""; "";
char const* session_stop_natpmp_doc =
"";
// -- alert ----------------------------------------------------------------- // -- alert -----------------------------------------------------------------
char const* alert_doc = char const* alert_doc =
@ -257,17 +257,6 @@ char const* torrent_finished_alert_doc =
"It contains a `torrent_handle` to the torrent in question. This alert\n" "It contains a `torrent_handle` to the torrent in question. This alert\n"
"is generated as severity level `alert.severity_levels.info`."; "is generated as severity level `alert.severity_levels.info`.";
char const* torrent_paused_alert_doc =
"This alert is generated when a torrent switches from being a\n"
"active to paused.\n"
"It contains a `torrent_handle` to the torrent in question. This alert\n"
"is generated as severity level `alert.severity_levels.warning`.";
char const* storage_moved_alert_doc =
"This alert is generated when a torrent moves storage.\n"
"It contains a `torrent_handle` to the torrent in question. This alert\n"
"is generated as severity level `alert.severity_levels.warning`.";
char const* metadata_failed_alert_doc = char const* metadata_failed_alert_doc =
"This alert is generated when the metadata has been completely\n" "This alert is generated when the metadata has been completely\n"
"received and the info-hash failed to match it. i.e. the\n" "received and the info-hash failed to match it. i.e. the\n"

View file

@ -142,6 +142,7 @@ void bind_extensions()
// TODO move to it's own file // TODO move to it's own file
class_<peer_connection, boost::noncopyable>("peer_connection", no_init); class_<peer_connection, boost::noncopyable>("peer_connection", no_init);
class_<torrent_plugin, boost::shared_ptr<torrent_plugin> >("torrent_plugin", no_init);
def("create_ut_pex_plugin", create_ut_pex_plugin); def("create_ut_pex_plugin", create_ut_pex_plugin);
def("create_metadata_plugin", create_metadata_plugin); def("create_metadata_plugin", create_metadata_plugin);
} }

View file

@ -46,7 +46,7 @@ extern char const* session_set_max_connections_doc;
extern char const* session_set_max_half_open_connections_doc; extern char const* session_set_max_half_open_connections_doc;
extern char const* session_set_settings_doc; extern char const* session_set_settings_doc;
extern char const* session_set_pe_settings_doc; extern char const* session_set_pe_settings_doc;
extern char const* session_get_pe_settings_doc; extern char const* session_get_pe_settings_doc;
extern char const* session_set_severity_level_doc; extern char const* session_set_severity_level_doc;
extern char const* session_pop_alert_doc; extern char const* session_pop_alert_doc;
extern char const* session_start_upnp_doc; extern char const* session_start_upnp_doc;
@ -86,10 +86,11 @@ namespace
torrent_handle add_torrent(session& s, torrent_info const& ti torrent_handle add_torrent(session& s, torrent_info const& ti
, boost::filesystem::path const& save, entry const& resume , boost::filesystem::path const& save, entry const& resume
, bool compact, bool paused) , bool compact, int block_size)
{ {
allow_threading_guard guard; allow_threading_guard guard;
return s.add_torrent(ti, save, resume, compact, paused, default_storage_constructor); return s.add_torrent(ti, save, resume, compact, block_size
, default_storage_constructor);
} }
} // namespace unnamed } // namespace unnamed
@ -174,7 +175,7 @@ void bind_session()
"add_torrent", &add_torrent "add_torrent", &add_torrent
, ( , (
arg("torrent_info"), "save_path", arg("resume_data") = entry() arg("torrent_info"), "save_path", arg("resume_data") = entry()
, arg("compact_mode") = true, arg("paused") = false , arg("compact_mode") = true, arg("block_size") = 16 * 1024
) )
, session_add_torrent_doc , session_add_torrent_doc
) )

View file

@ -47,7 +47,7 @@ void bind_session_settings()
.value("http", proxy_settings::http) .value("http", proxy_settings::http)
.value("http_pw", proxy_settings::http_pw) .value("http_pw", proxy_settings::http_pw)
; ;
class_<proxy_settings>("proxy_settings") class_<proxy_settings>("proxy_settings")
.def_readwrite("hostname", &proxy_settings::hostname) .def_readwrite("hostname", &proxy_settings::hostname)
.def_readwrite("port", &proxy_settings::port) .def_readwrite("port", &proxy_settings::port)
.def_readwrite("password", &proxy_settings::password) .def_readwrite("password", &proxy_settings::password)
@ -64,7 +64,7 @@ void bind_session_settings()
enum_<pe_settings::enc_level>("enc_level") enum_<pe_settings::enc_level>("enc_level")
.value("rc4", pe_settings::rc4) .value("rc4", pe_settings::rc4)
.value("plaintext", pe_settings::plaintext) .value("plaintext", pe_settings::plaintext)
.value("both", pe_settings::both) .value("both", pe_settings::both)
; ;
class_<pe_settings>("pe_settings") class_<pe_settings>("pe_settings")

View file

@ -16,6 +16,7 @@ namespace
return i.trackers().begin(); return i.trackers().begin();
} }
std::vector<announce_entry>::const_iterator end_trackers(torrent_info& i) std::vector<announce_entry>::const_iterator end_trackers(torrent_info& i)
{ {
return i.trackers().end(); return i.trackers().end();
@ -40,29 +41,6 @@ namespace
return result; return result;
} }
std::vector<file_entry>::const_iterator begin_files(torrent_info& i, bool storage)
{
return i.begin_files(storage);
}
std::vector<file_entry>::const_iterator end_files(torrent_info& i, bool storage)
{
return i.end_files(storage);
}
//list files(torrent_info const& ti, bool storage) {
list files(torrent_info const& ti, bool storage) {
list result;
typedef std::vector<file_entry> list_type;
for (list_type::const_iterator i = ti.begin_files(storage); i != ti.end_files(storage); ++i)
result.append(*i);
return result;
}
} // namespace unnamed } // namespace unnamed
void bind_torrent_info() void bind_torrent_info()
@ -93,9 +71,9 @@ void bind_torrent_info()
.def("hash_for_piece", &torrent_info::hash_for_piece, copy) .def("hash_for_piece", &torrent_info::hash_for_piece, copy)
.def("piece_size", &torrent_info::piece_size) .def("piece_size", &torrent_info::piece_size)
.def("num_files", &torrent_info::num_files, (arg("storage")=false)) .def("num_files", &torrent_info::num_files)
.def("file_at", &torrent_info::file_at, return_internal_reference<>()) .def("file_at", &torrent_info::file_at, return_internal_reference<>())
.def("files", &files, (arg("storage")=false)) .def("files", range(&torrent_info::begin_files, &torrent_info::end_files))
.def("priv", &torrent_info::priv) .def("priv", &torrent_info::priv)
.def("set_priv", &torrent_info::set_priv) .def("set_priv", &torrent_info::set_priv)
@ -106,8 +84,9 @@ void bind_torrent_info()
.def("add_node", &add_node) .def("add_node", &add_node)
.def("nodes", &nodes) .def("nodes", &nodes)
; ;
class_<file_entry>("file_entry") class_<file_entry>("file_entry")
.add_property( .add_property(
"path" "path"
, make_getter( , make_getter(
&file_entry::path, return_value_policy<copy_non_const_reference>() &file_entry::path, return_value_policy<copy_non_const_reference>()

View file

@ -238,9 +238,6 @@ public:
* with the asio::error::operation_aborted error. * with the asio::error::operation_aborted error.
* *
* @throws asio::system_error Thrown on failure. * @throws asio::system_error Thrown on failure.
*
* @note For portable behaviour with respect to graceful closure of a
* connected socket, call shutdown() before closing the socket.
*/ */
void close() void close()
{ {
@ -268,9 +265,6 @@ public:
* // An error occurred. * // An error occurred.
* } * }
* @endcode * @endcode
*
* @note For portable behaviour with respect to graceful closure of a
* connected socket, call shutdown() before closing the socket.
*/ */
asio::error_code close(asio::error_code& ec) asio::error_code close(asio::error_code& ec)
{ {

View file

@ -542,10 +542,9 @@ inline const_buffers_1 buffer(const PodType (&data)[N],
? N * sizeof(PodType) : max_size_in_bytes)); ? N * sizeof(PodType) : max_size_in_bytes));
} }
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \ #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
|| BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
// Borland C++ and Sun Studio think the overloads: // Borland C++ thinks the overloads:
// //
// unspecified buffer(boost::array<PodType, N>& array ...); // unspecified buffer(boost::array<PodType, N>& array ...);
// //
@ -611,7 +610,6 @@ buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
} }
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
// || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
/// Create a new modifiable buffer that represents the given POD array. /// Create a new modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N> template <typename PodType, std::size_t N>
@ -652,7 +650,6 @@ inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
} }
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
// || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
/// Create a new non-modifiable buffer that represents the given POD array. /// Create a new non-modifiable buffer that represents the given POD array.
template <typename PodType, std::size_t N> template <typename PodType, std::size_t N>

View file

@ -71,28 +71,6 @@ private:
/// Return a completion condition function object that indicates that a read or /// Return a completion condition function object that indicates that a read or
/// write operation should continue until all of the data has been transferred, /// write operation should continue until all of the data has been transferred,
/// or until an error occurs. /// or until an error occurs.
/**
* This function is used to create an object, of unspecified type, that meets
* CompletionCondition requirements.
*
* @par Example
* Reading until a buffer is full:
* @code
* boost::array<char, 128> buf;
* asio::error_code ec;
* std::size_t n = asio::read(
* sock, asio::buffer(buf),
* asio::transfer_all(), ec);
* if (ec)
* {
* // An error occurred.
* }
* else
* {
* // n == 128
* }
* @endcode
*/
#if defined(GENERATING_DOCUMENTATION) #if defined(GENERATING_DOCUMENTATION)
unspecified transfer_all(); unspecified transfer_all();
#else #else
@ -105,28 +83,6 @@ inline detail::transfer_all_t transfer_all()
/// Return a completion condition function object that indicates that a read or /// Return a completion condition function object that indicates that a read or
/// write operation should continue until a minimum number of bytes has been /// write operation should continue until a minimum number of bytes has been
/// transferred, or until an error occurs. /// transferred, or until an error occurs.
/**
* This function is used to create an object, of unspecified type, that meets
* CompletionCondition requirements.
*
* @par Example
* Reading until a buffer is full or contains at least 64 bytes:
* @code
* boost::array<char, 128> buf;
* asio::error_code ec;
* std::size_t n = asio::read(
* sock, asio::buffer(buf),
* asio::transfer_at_least(64), ec);
* if (ec)
* {
* // An error occurred.
* }
* else
* {
* // n >= 64 && n <= 128
* }
* @endcode
*/
#if defined(GENERATING_DOCUMENTATION) #if defined(GENERATING_DOCUMENTATION)
unspecified transfer_at_least(std::size_t minimum); unspecified transfer_at_least(std::size_t minimum);
#else #else

View file

@ -157,8 +157,7 @@ public:
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0) if (result != 0)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
read_op_queue_.dispatch_all_operations(descriptor, ec); read_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -191,8 +190,7 @@ public:
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0) if (result != 0)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -221,8 +219,7 @@ public:
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0) if (result != 0)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -253,8 +250,7 @@ public:
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0) if (result != 0)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
} }
@ -335,10 +331,7 @@ public:
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token) std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
{ {
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
std::size_t n = timer_queue.cancel_timer(token); return timer_queue.cancel_timer(token);
if (n > 0)
interrupter_.interrupt();
return n;
} }
private: private:
@ -354,13 +347,16 @@ private:
read_op_queue_.dispatch_cancellations(); read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations(); write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations(); except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->dispatch_cancellations();
// Check if the thread is supposed to stop. // Check if the thread is supposed to stop.
if (stop_thread_) if (stop_thread_)
{ {
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
return; return;
} }
@ -369,7 +365,12 @@ private:
if (!block && read_op_queue_.empty() && write_op_queue_.empty() if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty()) && except_op_queue_.empty() && all_timer_queues_are_empty())
{ {
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
return; return;
} }
@ -397,45 +398,59 @@ private:
} }
else else
{ {
bool more_reads = false; if (events[i].events & (EPOLLERR | EPOLLHUP))
bool more_writes = false;
bool more_except = false;
asio::error_code ec;
// Exception operations must be processed first to ensure that any
// out-of-band data is read before normal data.
if (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP))
more_except = except_op_queue_.dispatch_operation(descriptor, ec);
else
more_except = except_op_queue_.has_operation(descriptor);
if (events[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP))
more_reads = read_op_queue_.dispatch_operation(descriptor, ec);
else
more_reads = read_op_queue_.has_operation(descriptor);
if (events[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
more_writes = write_op_queue_.dispatch_operation(descriptor, ec);
else
more_writes = write_op_queue_.has_operation(descriptor);
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLERR | EPOLLHUP;
if (more_reads)
ev.events |= EPOLLIN;
if (more_writes)
ev.events |= EPOLLOUT;
if (more_except)
ev.events |= EPOLLPRI;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{ {
ec = asio::error_code(errno, asio::error_code ec;
asio::error::system_category); except_op_queue_.dispatch_all_operations(descriptor, ec);
read_op_queue_.dispatch_all_operations(descriptor, ec); read_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec);
epoll_event ev = { 0, { 0 } };
ev.events = 0;
ev.data.fd = descriptor;
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
}
else
{
bool more_reads = false;
bool more_writes = false;
bool more_except = false;
asio::error_code ec;
// Exception operations must be processed first to ensure that any
// out-of-band data is read before normal data.
if (events[i].events & EPOLLPRI)
more_except = except_op_queue_.dispatch_operation(descriptor, ec);
else
more_except = except_op_queue_.has_operation(descriptor);
if (events[i].events & EPOLLIN)
more_reads = read_op_queue_.dispatch_operation(descriptor, ec);
else
more_reads = read_op_queue_.has_operation(descriptor);
if (events[i].events & EPOLLOUT)
more_writes = write_op_queue_.dispatch_operation(descriptor, ec);
else
more_writes = write_op_queue_.has_operation(descriptor);
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLERR | EPOLLHUP;
if (more_reads)
ev.events |= EPOLLIN;
if (more_writes)
ev.events |= EPOLLOUT;
if (more_except)
ev.events |= EPOLLPRI;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
ec = asio::error_code(errno, asio::native_ecat);
read_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
} }
} }
} }
@ -443,17 +458,19 @@ private:
write_op_queue_.dispatch_cancellations(); write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations(); except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i) for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
timer_queues_[i]->dispatch_timers(); timer_queues_[i]->dispatch_timers();
timer_queues_[i]->dispatch_cancellations();
}
// Issue any pending cancellations. // Issue any pending cancellations.
for (size_t i = 0; i < pending_cancellations_.size(); ++i) for (size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]); cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear(); pending_cancellations_.clear();
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
} }
// Run the select loop in the thread. // Run the select loop in the thread.
@ -490,10 +507,8 @@ private:
int fd = epoll_create(epoll_size); int fd = epoll_create(epoll_size);
if (fd == -1) if (fd == -1)
{ {
boost::throw_exception( boost::throw_exception(asio::system_error(
asio::system_error( asio::error_code(errno, asio::native_ecat),
asio::error_code(errno,
asio::error::system_category),
"epoll")); "epoll"));
} }
return fd; return fd;
@ -551,22 +566,6 @@ private:
interrupter_.interrupt(); interrupter_.interrupt();
} }
// Clean up operations and timers. We must not hold the lock since the
// destructors may make calls back into this reactor. We make a copy of the
// vector of timer queues since the original may be modified while the lock
// is not held.
void cleanup_operations_and_timers(
asio::detail::mutex::scoped_lock& lock)
{
timer_queues_for_cleanup_ = timer_queues_;
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
timer_queues_for_cleanup_[i]->cleanup_timers();
}
// Mutex to protect access to internal data. // Mutex to protect access to internal data.
asio::detail::mutex mutex_; asio::detail::mutex mutex_;
@ -591,10 +590,6 @@ private:
// The timer queues. // The timer queues.
std::vector<timer_queue_base*> timer_queues_; std::vector<timer_queue_base*> timer_queues_;
// A copy of the timer queues, used when cleaning up timers. The copy is
// stored as a class data member to avoid unnecessary memory allocation.
std::vector<timer_queue_base*> timer_queues_for_cleanup_;
// The descriptors that are pending cancellation. // The descriptors that are pending cancellation.
std::vector<socket_type> pending_cancellations_; std::vector<socket_type> pending_cancellations_;

View file

@ -150,8 +150,7 @@ public:
EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
read_op_queue_.dispatch_all_operations(descriptor, ec); read_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -177,8 +176,7 @@ public:
EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -203,8 +201,7 @@ public:
EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -227,8 +224,7 @@ public:
EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
} }
} }
@ -242,8 +238,7 @@ public:
EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code ec(errno, asio::error_code ec(errno, asio::native_ecat);
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, ec); except_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec); write_op_queue_.dispatch_all_operations(descriptor, ec);
} }
@ -326,10 +321,7 @@ public:
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token) std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
{ {
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
std::size_t n = timer_queue.cancel_timer(token); return timer_queue.cancel_timer(token);
if (n > 0)
interrupter_.interrupt();
return n;
} }
private: private:
@ -345,13 +337,16 @@ private:
read_op_queue_.dispatch_cancellations(); read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations(); write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations(); except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->dispatch_cancellations();
// Check if the thread is supposed to stop. // Check if the thread is supposed to stop.
if (stop_thread_) if (stop_thread_)
{ {
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
return; return;
} }
@ -360,7 +355,12 @@ private:
if (!block && read_op_queue_.empty() && write_op_queue_.empty() if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty()) && except_op_queue_.empty() && all_timer_queues_are_empty())
{ {
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
return; return;
} }
@ -397,7 +397,7 @@ private:
if (events[i].flags & EV_ERROR) if (events[i].flags & EV_ERROR)
{ {
asio::error_code error( asio::error_code error(
events[i].data, asio::error::system_category); events[i].data, asio::native_ecat);
except_op_queue_.dispatch_all_operations(descriptor, error); except_op_queue_.dispatch_all_operations(descriptor, error);
read_op_queue_.dispatch_all_operations(descriptor, error); read_op_queue_.dispatch_all_operations(descriptor, error);
} }
@ -427,8 +427,7 @@ private:
EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code error(errno, asio::error_code error(errno, asio::native_ecat);
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, error); except_op_queue_.dispatch_all_operations(descriptor, error);
read_op_queue_.dispatch_all_operations(descriptor, error); read_op_queue_.dispatch_all_operations(descriptor, error);
} }
@ -440,7 +439,7 @@ private:
if (events[i].flags & EV_ERROR) if (events[i].flags & EV_ERROR)
{ {
asio::error_code error( asio::error_code error(
events[i].data, asio::error::system_category); events[i].data, asio::native_ecat);
write_op_queue_.dispatch_all_operations(descriptor, error); write_op_queue_.dispatch_all_operations(descriptor, error);
} }
else else
@ -457,8 +456,7 @@ private:
EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{ {
asio::error_code error(errno, asio::error_code error(errno, asio::native_ecat);
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, error); write_op_queue_.dispatch_all_operations(descriptor, error);
} }
} }
@ -468,17 +466,19 @@ private:
write_op_queue_.dispatch_cancellations(); write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations(); except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i) for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
timer_queues_[i]->dispatch_timers(); timer_queues_[i]->dispatch_timers();
timer_queues_[i]->dispatch_cancellations();
}
// Issue any pending cancellations. // Issue any pending cancellations.
for (std::size_t i = 0; i < pending_cancellations_.size(); ++i) for (std::size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]); cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear(); pending_cancellations_.clear();
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
} }
// Run the select loop in the thread. // Run the select loop in the thread.
@ -512,10 +512,8 @@ private:
int fd = kqueue(); int fd = kqueue();
if (fd == -1) if (fd == -1)
{ {
boost::throw_exception( boost::throw_exception(asio::system_error(
asio::system_error( asio::error_code(errno, asio::native_ecat),
asio::error_code(errno,
asio::error::system_category),
"kqueue")); "kqueue"));
} }
return fd; return fd;
@ -575,22 +573,6 @@ private:
interrupter_.interrupt(); interrupter_.interrupt();
} }
// Clean up operations and timers. We must not hold the lock since the
// destructors may make calls back into this reactor. We make a copy of the
// vector of timer queues since the original may be modified while the lock
// is not held.
void cleanup_operations_and_timers(
asio::detail::mutex::scoped_lock& lock)
{
timer_queues_for_cleanup_ = timer_queues_;
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
timer_queues_for_cleanup_[i]->cleanup_timers();
}
// Mutex to protect access to internal data. // Mutex to protect access to internal data.
asio::detail::mutex mutex_; asio::detail::mutex mutex_;
@ -615,10 +597,6 @@ private:
// The timer queues. // The timer queues.
std::vector<timer_queue_base*> timer_queues_; std::vector<timer_queue_base*> timer_queues_;
// A copy of the timer queues, used when cleaning up timers. The copy is
// stored as a class data member to avoid unnecessary memory allocation.
std::vector<timer_queue_base*> timer_queues_for_cleanup_;
// The descriptors that are pending cancellation. // The descriptors that are pending cancellation.
std::vector<socket_type> pending_cancellations_; std::vector<socket_type> pending_cancellations_;

View file

@ -43,20 +43,17 @@ public:
} }
// Signal the event. // Signal the event.
template <typename Lock> void signal()
void signal(Lock&)
{ {
} }
// Reset the event. // Reset the event.
template <typename Lock> void clear()
void clear(Lock&)
{ {
} }
// Wait for the event to become signalled. // Wait for the event to become signalled.
template <typename Lock> void wait()
void wait(Lock&)
{ {
} }
}; };

View file

@ -24,12 +24,10 @@
#if defined(BOOST_HAS_PTHREADS) #if defined(BOOST_HAS_PTHREADS)
#include "asio/detail/push_options.hpp" #include "asio/detail/push_options.hpp"
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <pthread.h> #include <pthread.h>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp" #include "asio/detail/noncopyable.hpp"
@ -44,11 +42,21 @@ public:
posix_event() posix_event()
: signalled_(false) : signalled_(false)
{ {
int error = ::pthread_cond_init(&cond_, 0); int error = ::pthread_mutex_init(&mutex_, 0);
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error, asio::native_ecat),
"event");
boost::throw_exception(e);
}
error = ::pthread_cond_init(&cond_, 0);
if (error != 0)
{
::pthread_mutex_destroy(&mutex_);
asio::system_error e(
asio::error_code(error, asio::native_ecat),
"event"); "event");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -58,37 +66,37 @@ public:
~posix_event() ~posix_event()
{ {
::pthread_cond_destroy(&cond_); ::pthread_cond_destroy(&cond_);
::pthread_mutex_destroy(&mutex_);
} }
// Signal the event. // Signal the event.
template <typename Lock> void signal()
void signal(Lock& lock)
{ {
BOOST_ASSERT(lock.locked()); ::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK.
(void)lock;
signalled_ = true; signalled_ = true;
::pthread_cond_signal(&cond_); // Ignore EINVAL. ::pthread_cond_signal(&cond_); // Ignore EINVAL.
::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM.
} }
// Reset the event. // Reset the event.
template <typename Lock> void clear()
void clear(Lock& lock)
{ {
BOOST_ASSERT(lock.locked()); ::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK.
(void)lock;
signalled_ = false; signalled_ = false;
::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM.
} }
// Wait for the event to become signalled. // Wait for the event to become signalled.
template <typename Lock> void wait()
void wait(Lock& lock)
{ {
BOOST_ASSERT(lock.locked()); ::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK.
while (!signalled_) while (!signalled_)
::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL. ::pthread_cond_wait(&cond_, &mutex_); // Ignore EINVAL.
::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM.
} }
private: private:
::pthread_mutex_t mutex_;
::pthread_cond_t cond_; ::pthread_cond_t cond_;
bool signalled_; bool signalled_;
}; };

View file

@ -28,7 +28,6 @@
#include <pthread.h> #include <pthread.h>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp" #include "asio/detail/noncopyable.hpp"
#include "asio/detail/scoped_lock.hpp" #include "asio/detail/scoped_lock.hpp"
@ -36,8 +35,6 @@
namespace asio { namespace asio {
namespace detail { namespace detail {
class posix_event;
class posix_mutex class posix_mutex
: private noncopyable : private noncopyable
{ {
@ -51,7 +48,7 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error, asio::native_ecat),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -70,7 +67,7 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error, asio::native_ecat),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -83,14 +80,13 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error, asio::native_ecat),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }
} }
private: private:
friend class posix_event;
::pthread_mutex_t mutex_; ::pthread_mutex_t mutex_;
}; };

View file

@ -29,7 +29,6 @@
#include <pthread.h> #include <pthread.h>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp" #include "asio/detail/noncopyable.hpp"
@ -53,7 +52,7 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error, asio::native_ecat),
"thread"); "thread");
boost::throw_exception(e); boost::throw_exception(e);
} }

View file

@ -28,7 +28,6 @@
#include <pthread.h> #include <pthread.h>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp" #include "asio/detail/noncopyable.hpp"
@ -47,7 +46,7 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error, asio::native_ecat),
"tss"); "tss");
boost::throw_exception(e); boost::throw_exception(e);
} }

View file

@ -86,7 +86,7 @@ public:
}; };
// The maximum number of buffers to support in a single operation. // The maximum number of buffers to support in a single operation.
enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; enum { max_buffers = 16 };
// Constructor. // Constructor.
reactive_socket_service(asio::io_service& io_service) reactive_socket_service(asio::io_service& io_service)
@ -157,7 +157,7 @@ public:
if (int err = reactor_.register_descriptor(sock.get())) if (int err = reactor_.register_descriptor(sock.get()))
{ {
ec = asio::error_code(err, asio::error::system_category); ec = asio::error_code(err, asio::native_ecat);
return ec; return ec;
} }
@ -181,7 +181,7 @@ public:
if (int err = reactor_.register_descriptor(native_socket)) if (int err = reactor_.register_descriptor(native_socket))
{ {
ec = asio::error_code(err, asio::error::system_category); ec = asio::error_code(err, asio::native_ecat);
return ec; return ec;
} }
@ -1124,7 +1124,7 @@ public:
bool operator()(const asio::error_code& result) bool operator()(const asio::error_code& result)
{ {
// Check whether the operation was successful. // Check whether the operation was successful.
if (result) if (result != 0)
{ {
io_service_.post(bind_handler(handler_, result, 0)); io_service_.post(bind_handler(handler_, result, 0));
return true; return true;
@ -1489,7 +1489,7 @@ public:
if (connect_error) if (connect_error)
{ {
ec = asio::error_code(connect_error, ec = asio::error_code(connect_error,
asio::error::system_category); asio::native_ecat);
io_service_.post(bind_handler(handler_, ec)); io_service_.post(bind_handler(handler_, ec));
return true; return true;
} }

View file

@ -63,18 +63,6 @@ public:
} }
} }
// Test whether the lock is held.
bool locked() const
{
return locked_;
}
// Get the underlying mutex.
Mutex& mutex()
{
return mutex_;
}
private: private:
// The underlying mutex. // The underlying mutex.
Mutex& mutex_; Mutex& mutex_;

View file

@ -229,10 +229,7 @@ public:
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token) std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
{ {
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
std::size_t n = timer_queue.cancel_timer(token); return timer_queue.cancel_timer(token);
if (n > 0)
interrupter_.interrupt();
return n;
} }
private: private:
@ -248,13 +245,16 @@ private:
read_op_queue_.dispatch_cancellations(); read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations(); write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations(); except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->dispatch_cancellations();
// Check if the thread is supposed to stop. // Check if the thread is supposed to stop.
if (stop_thread_) if (stop_thread_)
{ {
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
return; return;
} }
@ -263,7 +263,12 @@ private:
if (!block && read_op_queue_.empty() && write_op_queue_.empty() if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty()) && except_op_queue_.empty() && all_timer_queues_are_empty())
{ {
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
return; return;
} }
@ -316,17 +321,19 @@ private:
write_op_queue_.dispatch_cancellations(); write_op_queue_.dispatch_cancellations();
} }
for (std::size_t i = 0; i < timer_queues_.size(); ++i) for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
timer_queues_[i]->dispatch_timers(); timer_queues_[i]->dispatch_timers();
timer_queues_[i]->dispatch_cancellations();
}
// Issue any pending cancellations. // Issue any pending cancellations.
for (size_t i = 0; i < pending_cancellations_.size(); ++i) for (size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]); cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear(); pending_cancellations_.clear();
cleanup_operations_and_timers(lock); // Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
} }
// Run the select loop in the thread. // Run the select loop in the thread.
@ -407,22 +414,6 @@ private:
interrupter_.interrupt(); interrupter_.interrupt();
} }
// Clean up operations and timers. We must not hold the lock since the
// destructors may make calls back into this reactor. We make a copy of the
// vector of timer queues since the original may be modified while the lock
// is not held.
void cleanup_operations_and_timers(
asio::detail::mutex::scoped_lock& lock)
{
timer_queues_for_cleanup_ = timer_queues_;
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
timer_queues_for_cleanup_[i]->cleanup_timers();
}
// Mutex to protect access to internal data. // Mutex to protect access to internal data.
asio::detail::mutex mutex_; asio::detail::mutex mutex_;
@ -444,10 +435,6 @@ private:
// The timer queues. // The timer queues.
std::vector<timer_queue_base*> timer_queues_; std::vector<timer_queue_base*> timer_queues_;
// A copy of the timer queues, used when cleaning up timers. The copy is
// stored as a class data member to avoid unnecessary memory allocation.
std::vector<timer_queue_base*> timer_queues_for_cleanup_;
// The descriptors that are pending cancellation. // The descriptors that are pending cancellation.
std::vector<socket_type> pending_cancellations_; std::vector<socket_type> pending_cancellations_;

View file

@ -166,8 +166,7 @@ private:
} }
// Check if a service matches the given id. // Check if a service matches the given id.
static bool service_id_matches( bool service_id_matches(const asio::io_service::service& service,
const asio::io_service::service& service,
const asio::io_service::id& id) const asio::io_service::id& id)
{ {
return service.id_ == &id; return service.id_ == &id;
@ -175,8 +174,7 @@ private:
// Check if a service matches the given id. // Check if a service matches the given id.
template <typename Service> template <typename Service>
static bool service_id_matches( bool service_id_matches(const asio::io_service::service& service,
const asio::io_service::service& service,
const asio::detail::service_id<Service>& /*id*/) const asio::detail::service_id<Service>& /*id*/)
{ {
return service.type_info_ != 0 && *service.type_info_ == typeid(Service); return service.type_info_ != 0 && *service.type_info_ == typeid(Service);

View file

@ -52,10 +52,9 @@ inline ReturnType error_wrapper(ReturnType return_value,
asio::error_code& ec) asio::error_code& ec)
{ {
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
ec = asio::error_code(WSAGetLastError(), ec = asio::error_code(WSAGetLastError(), asio::native_ecat);
asio::error::system_category);
#else #else
ec = asio::error_code(errno, asio::error::system_category); ec = asio::error_code(errno, asio::native_ecat);
#endif #endif
return return_value; return return_value;
} }
@ -924,13 +923,6 @@ inline void gai_free(void* p)
::operator delete(p); ::operator delete(p);
} }
inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
{
using namespace std;
*target = 0;
strncat(target, source, max_size);
}
enum { gai_clone_flag = 1 << 30 }; enum { gai_clone_flag = 1 << 30 };
inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints, inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
@ -1300,15 +1292,14 @@ inline int getaddrinfo_emulation(const char* host, const char* service,
if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0] if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]
&& (hints.ai_flags & AI_CANONNAME) && canon == 0) && (hints.ai_flags & AI_CANONNAME) && canon == 0)
{ {
std::size_t canon_len = strlen(hptr->h_name) + 1; canon = gai_alloc<char>(strlen(hptr->h_name) + 1);
canon = gai_alloc<char>(canon_len);
if (canon == 0) if (canon == 0)
{ {
freeaddrinfo_emulation(aihead); freeaddrinfo_emulation(aihead);
socket_ops::freehostent(hptr); socket_ops::freehostent(hptr);
return EAI_MEMORY; return EAI_MEMORY;
} }
gai_strcpy(canon, hptr->h_name, canon_len); strcpy(canon, hptr->h_name);
} }
// Create an addrinfo structure for each returned address. // Create an addrinfo structure for each returned address.
@ -1344,14 +1335,13 @@ inline int getaddrinfo_emulation(const char* host, const char* service,
} }
else else
{ {
std::size_t canonname_len = strlen(search[0].host) + 1; aihead->ai_canonname = gai_alloc<char>(strlen(search[0].host) + 1);
aihead->ai_canonname = gai_alloc<char>(canonname_len);
if (aihead->ai_canonname == 0) if (aihead->ai_canonname == 0)
{ {
freeaddrinfo_emulation(aihead); freeaddrinfo_emulation(aihead);
return EAI_MEMORY; return EAI_MEMORY;
} }
gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len); strcpy(aihead->ai_canonname, search[0].host);
} }
} }
gai_free(canon); gai_free(canon);
@ -1434,7 +1424,8 @@ inline asio::error_code getnameinfo_emulation(
*dot = 0; *dot = 0;
} }
} }
gai_strcpy(host, hptr->h_name, hostlen); *host = '\0';
strncat(host, hptr->h_name, hostlen);
socket_ops::freehostent(hptr); socket_ops::freehostent(hptr);
} }
else else
@ -1472,7 +1463,8 @@ inline asio::error_code getnameinfo_emulation(
servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0); servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
if (sptr && sptr->s_name && sptr->s_name[0] != '\0') if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
{ {
gai_strcpy(serv, sptr->s_name, servlen); *serv = '\0';
strncat(serv, sptr->s_name, servlen);
} }
else else
{ {
@ -1512,12 +1504,6 @@ inline asio::error_code translate_addrinfo_error(int error)
case EAI_MEMORY: case EAI_MEMORY:
return asio::error::no_memory; return asio::error::no_memory;
case EAI_NONAME: case EAI_NONAME:
#if defined(EAI_ADDRFAMILY)
case EAI_ADDRFAMILY:
#endif
#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
case EAI_NODATA:
#endif
return asio::error::host_not_found; return asio::error::host_not_found;
case EAI_SERVICE: case EAI_SERVICE:
return asio::error::service_not_found; return asio::error::service_not_found;
@ -1526,10 +1512,10 @@ inline asio::error_code translate_addrinfo_error(int error)
default: // Possibly the non-portable EAI_SYSTEM. default: // Possibly the non-portable EAI_SYSTEM.
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
return asio::error_code( return asio::error_code(
WSAGetLastError(), asio::error::system_category); WSAGetLastError(), asio::native_ecat);
#else #else
return asio::error_code( return asio::error_code(
errno, asio::error::system_category); errno, asio::native_ecat);
#endif #endif
} }
} }

View file

@ -110,19 +110,8 @@ public:
template <typename Protocol> template <typename Protocol>
void resize(const Protocol&, std::size_t s) void resize(const Protocol&, std::size_t s)
{ {
// On some platforms (e.g. Windows Vista), the getsockopt function will if (s != sizeof(value_))
// return the size of a boolean socket option as one byte, even though a
// four byte integer was passed in.
switch (s)
{
case sizeof(char):
value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0;
break;
case sizeof(value_):
break;
default:
throw std::length_error("boolean socket option resize"); throw std::length_error("boolean socket option resize");
}
} }
private: private:

View file

@ -98,7 +98,6 @@
# include <arpa/inet.h> # include <arpa/inet.h>
# include <netdb.h> # include <netdb.h>
# include <net/if.h> # include <net/if.h>
# include <limits.h>
# if defined(__sun) # if defined(__sun)
# include <sys/filio.h> # include <sys/filio.h>
# include <sys/sockio.h> # include <sys/sockio.h>
@ -142,11 +141,6 @@ const int shutdown_both = SD_BOTH;
const int message_peek = MSG_PEEK; const int message_peek = MSG_PEEK;
const int message_out_of_band = MSG_OOB; const int message_out_of_band = MSG_OOB;
const int message_do_not_route = MSG_DONTROUTE; const int message_do_not_route = MSG_DONTROUTE;
# if defined (_WIN32_WINNT)
const int max_iov_len = 64;
# else
const int max_iov_len = 16;
# endif
#else #else
typedef int socket_type; typedef int socket_type;
const int invalid_socket = -1; const int invalid_socket = -1;
@ -172,7 +166,6 @@ const int shutdown_both = SHUT_RDWR;
const int message_peek = MSG_PEEK; const int message_peek = MSG_PEEK;
const int message_out_of_band = MSG_OOB; const int message_out_of_band = MSG_OOB;
const int message_do_not_route = MSG_DONTROUTE; const int message_do_not_route = MSG_DONTROUTE;
const int max_iov_len = IOV_MAX;
#endif #endif
const int custom_socket_option_level = 0xA5100000; const int custom_socket_option_level = 0xA5100000;
const int enable_connection_aborted_option = 1; const int enable_connection_aborted_option = 1;

View file

@ -239,7 +239,6 @@ public:
#else #else
BOOST_ASSERT(size <= strand_impl::handler_storage_type::size); BOOST_ASSERT(size <= strand_impl::handler_storage_type::size);
#endif #endif
(void)size;
return impl_->handler_storage_.address(); return impl_->handler_storage_.address();
} }
@ -416,14 +415,14 @@ public:
} }
else else
{ {
asio::detail::mutex::scoped_lock lock(impl->mutex_);
// Allocate and construct an object to wrap the handler. // Allocate and construct an object to wrap the handler.
typedef handler_wrapper<Handler> value_type; typedef handler_wrapper<Handler> value_type;
typedef handler_alloc_traits<Handler, value_type> alloc_traits; typedef handler_alloc_traits<Handler, value_type> alloc_traits;
raw_handler_ptr<alloc_traits> raw_ptr(handler); raw_handler_ptr<alloc_traits> raw_ptr(handler);
handler_ptr<alloc_traits> ptr(raw_ptr, handler); handler_ptr<alloc_traits> ptr(raw_ptr, handler);
asio::detail::mutex::scoped_lock lock(impl->mutex_);
if (impl->current_handler_ == 0) if (impl->current_handler_ == 0)
{ {
// This handler now has the lock, so can be dispatched immediately. // This handler now has the lock, so can be dispatched immediately.
@ -456,14 +455,14 @@ public:
template <typename Handler> template <typename Handler>
void post(implementation_type& impl, Handler handler) void post(implementation_type& impl, Handler handler)
{ {
asio::detail::mutex::scoped_lock lock(impl->mutex_);
// Allocate and construct an object to wrap the handler. // Allocate and construct an object to wrap the handler.
typedef handler_wrapper<Handler> value_type; typedef handler_wrapper<Handler> value_type;
typedef handler_alloc_traits<Handler, value_type> alloc_traits; typedef handler_alloc_traits<Handler, value_type> alloc_traits;
raw_handler_ptr<alloc_traits> raw_ptr(handler); raw_handler_ptr<alloc_traits> raw_ptr(handler);
handler_ptr<alloc_traits> ptr(raw_ptr, handler); handler_ptr<alloc_traits> ptr(raw_ptr, handler);
asio::detail::mutex::scoped_lock lock(impl->mutex_);
if (impl->current_handler_ == 0) if (impl->current_handler_ == 0)
{ {
// This handler now has the lock, so can be dispatched immediately. // This handler now has the lock, so can be dispatched immediately.

View file

@ -40,7 +40,6 @@ public:
: asio::detail::service_base<task_io_service<Task> >(io_service), : asio::detail::service_base<task_io_service<Task> >(io_service),
mutex_(), mutex_(),
task_(use_service<Task>(io_service)), task_(use_service<Task>(io_service)),
task_interrupted_(true),
outstanding_work_(0), outstanding_work_(0),
handler_queue_(&task_handler_), handler_queue_(&task_handler_),
handler_queue_end_(&task_handler_), handler_queue_end_(&task_handler_),
@ -81,7 +80,8 @@ public:
typename call_stack<task_io_service>::context ctx(this); typename call_stack<task_io_service>::context ctx(this);
idle_thread_info this_idle_thread; idle_thread_info this_idle_thread;
this_idle_thread.next = 0; this_idle_thread.prev = &this_idle_thread;
this_idle_thread.next = &this_idle_thread;
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
@ -98,7 +98,8 @@ public:
typename call_stack<task_io_service>::context ctx(this); typename call_stack<task_io_service>::context ctx(this);
idle_thread_info this_idle_thread; idle_thread_info this_idle_thread;
this_idle_thread.next = 0; this_idle_thread.prev = &this_idle_thread;
this_idle_thread.next = &this_idle_thread;
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
@ -133,7 +134,7 @@ public:
void stop() void stop()
{ {
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
stop_all_threads(lock); stop_all_threads();
} }
// Reset in preparation for a subsequent run invocation. // Reset in preparation for a subsequent run invocation.
@ -155,7 +156,7 @@ public:
{ {
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
if (--outstanding_work_ == 0) if (--outstanding_work_ == 0)
stop_all_threads(lock); stop_all_threads();
} }
// Request invocation of the given handler. // Request invocation of the given handler.
@ -200,14 +201,9 @@ public:
++outstanding_work_; ++outstanding_work_;
// Wake up a thread to execute the handler. // Wake up a thread to execute the handler.
if (!interrupt_one_idle_thread(lock)) if (!interrupt_one_idle_thread())
{ if (task_handler_.next_ == 0 && handler_queue_end_ != &task_handler_)
if (!task_interrupted_)
{
task_interrupted_ = true;
task_.interrupt(); task_.interrupt();
}
}
} }
private: private:
@ -218,7 +214,7 @@ private:
{ {
if (outstanding_work_ == 0 && !stopped_) if (outstanding_work_ == 0 && !stopped_)
{ {
stop_all_threads(lock); stop_all_threads();
ec = asio::error_code(); ec = asio::error_code();
return 0; return 0;
} }
@ -234,14 +230,11 @@ private:
handler_queue_ = h->next_; handler_queue_ = h->next_;
if (handler_queue_ == 0) if (handler_queue_ == 0)
handler_queue_end_ = 0; handler_queue_end_ = 0;
h->next_ = 0; bool more_handlers = (handler_queue_ != 0);
lock.unlock();
if (h == &task_handler_) if (h == &task_handler_)
{ {
bool more_handlers = (handler_queue_ != 0);
task_interrupted_ = more_handlers || polling;
lock.unlock();
// If the task has already run and we're polling then we're done. // If the task has already run and we're polling then we're done.
if (task_has_run && polling) if (task_has_run && polling)
{ {
@ -259,7 +252,6 @@ private:
} }
else else
{ {
lock.unlock();
handler_cleanup c(lock, *this); handler_cleanup c(lock, *this);
// Invoke the handler. May throw an exception. // Invoke the handler. May throw an exception.
@ -272,10 +264,31 @@ private:
else if (this_idle_thread) else if (this_idle_thread)
{ {
// Nothing to run right now, so just wait for work to do. // Nothing to run right now, so just wait for work to do.
this_idle_thread->next = first_idle_thread_; if (first_idle_thread_)
{
this_idle_thread->next = first_idle_thread_;
this_idle_thread->prev = first_idle_thread_->prev;
first_idle_thread_->prev->next = this_idle_thread;
first_idle_thread_->prev = this_idle_thread;
}
first_idle_thread_ = this_idle_thread; first_idle_thread_ = this_idle_thread;
this_idle_thread->wakeup_event.clear(lock); this_idle_thread->wakeup_event.clear();
this_idle_thread->wakeup_event.wait(lock); lock.unlock();
this_idle_thread->wakeup_event.wait();
lock.lock();
if (this_idle_thread->next == this_idle_thread)
{
first_idle_thread_ = 0;
}
else
{
if (first_idle_thread_ == this_idle_thread)
first_idle_thread_ = this_idle_thread->next;
this_idle_thread->next->prev = this_idle_thread->prev;
this_idle_thread->prev->next = this_idle_thread->next;
this_idle_thread->next = this_idle_thread;
this_idle_thread->prev = this_idle_thread;
}
} }
else else
{ {
@ -289,44 +302,39 @@ private:
} }
// Stop the task and all idle threads. // Stop the task and all idle threads.
void stop_all_threads( void stop_all_threads()
asio::detail::mutex::scoped_lock& lock)
{ {
stopped_ = true; stopped_ = true;
interrupt_all_idle_threads(lock); interrupt_all_idle_threads();
if (!task_interrupted_) if (task_handler_.next_ == 0 && handler_queue_end_ != &task_handler_)
{
task_interrupted_ = true;
task_.interrupt(); task_.interrupt();
}
} }
// Interrupt a single idle thread. Returns true if a thread was interrupted, // Interrupt a single idle thread. Returns true if a thread was interrupted,
// false if no running thread could be found to interrupt. // false if no running thread could be found to interrupt.
bool interrupt_one_idle_thread( bool interrupt_one_idle_thread()
asio::detail::mutex::scoped_lock& lock)
{ {
if (first_idle_thread_) if (first_idle_thread_)
{ {
idle_thread_info* idle_thread = first_idle_thread_; first_idle_thread_->wakeup_event.signal();
first_idle_thread_ = idle_thread->next; first_idle_thread_ = first_idle_thread_->next;
idle_thread->next = 0;
idle_thread->wakeup_event.signal(lock);
return true; return true;
} }
return false; return false;
} }
// Interrupt all idle threads. // Interrupt all idle threads.
void interrupt_all_idle_threads( void interrupt_all_idle_threads()
asio::detail::mutex::scoped_lock& lock)
{ {
while (first_idle_thread_) if (first_idle_thread_)
{ {
idle_thread_info* idle_thread = first_idle_thread_; first_idle_thread_->wakeup_event.signal();
first_idle_thread_ = idle_thread->next; idle_thread_info* current_idle_thread = first_idle_thread_->next;
idle_thread->next = 0; while (current_idle_thread != first_idle_thread_)
idle_thread->wakeup_event.signal(lock); {
current_idle_thread->wakeup_event.signal();
current_idle_thread = current_idle_thread->next;
}
} }
} }
@ -432,7 +440,6 @@ private:
{ {
// Reinsert the task at the end of the handler queue. // Reinsert the task at the end of the handler queue.
lock_.lock(); lock_.lock();
task_io_service_.task_interrupted_ = true;
task_io_service_.task_handler_.next_ = 0; task_io_service_.task_handler_.next_ = 0;
if (task_io_service_.handler_queue_end_) if (task_io_service_.handler_queue_end_)
{ {
@ -471,7 +478,7 @@ private:
{ {
lock_.lock(); lock_.lock();
if (--task_io_service_.outstanding_work_ == 0) if (--task_io_service_.outstanding_work_ == 0)
task_io_service_.stop_all_threads(lock_); task_io_service_.stop_all_threads();
} }
private: private:
@ -496,9 +503,6 @@ private:
} }
} task_handler_; } task_handler_;
// Whether the task has been interrupted.
bool task_interrupted_;
// The count of unfinished work. // The count of unfinished work.
int outstanding_work_; int outstanding_work_;
@ -518,6 +522,7 @@ private:
struct idle_thread_info struct idle_thread_info
{ {
event wakeup_event; event wakeup_event;
idle_thread_info* prev;
idle_thread_info* next; idle_thread_info* next;
}; };

View file

@ -48,9 +48,7 @@ public:
// Constructor. // Constructor.
timer_queue() timer_queue()
: timers_(), : timers_(),
heap_(), heap_()
cancelled_timers_(0),
cleanup_timers_(0)
{ {
} }
@ -113,17 +111,12 @@ public:
{ {
timer_base* t = heap_[0]; timer_base* t = heap_[0];
remove_timer(t); remove_timer(t);
t->prev_ = 0;
t->next_ = cleanup_timers_;
cleanup_timers_ = t;
t->invoke(asio::error_code()); t->invoke(asio::error_code());
} }
} }
// Cancel the timers with the given token. Any timers pending for the token // Cancel the timer with the given token. The handler will be invoked
// will be notified that they have been cancelled next time // immediately with the result operation_aborted.
// dispatch_cancellations is called. Returns the number of timers that were
// cancelled.
std::size_t cancel_timer(void* timer_token) std::size_t cancel_timer(void* timer_token)
{ {
std::size_t num_cancelled = 0; std::size_t num_cancelled = 0;
@ -136,9 +129,7 @@ public:
{ {
timer_base* next = t->next_; timer_base* next = t->next_;
remove_timer(t); remove_timer(t);
t->prev_ = 0; t->invoke(asio::error::operation_aborted);
t->next_ = cancelled_timers_;
cancelled_timers_ = t;
t = next; t = next;
++num_cancelled; ++num_cancelled;
} }
@ -146,31 +137,6 @@ public:
return num_cancelled; return num_cancelled;
} }
// Dispatch any pending cancels for timers.
virtual void dispatch_cancellations()
{
while (cancelled_timers_)
{
timer_base* this_timer = cancelled_timers_;
cancelled_timers_ = this_timer->next_;
this_timer->next_ = cleanup_timers_;
cleanup_timers_ = this_timer;
this_timer->invoke(asio::error::operation_aborted);
}
}
// Destroy timers that are waiting to be cleaned up.
virtual void cleanup_timers()
{
while (cleanup_timers_)
{
timer_base* next_timer = cleanup_timers_->next_;
cleanup_timers_->next_ = 0;
cleanup_timers_->destroy();
cleanup_timers_ = next_timer;
}
}
// Destroy all timers. // Destroy all timers.
virtual void destroy_timers() virtual void destroy_timers()
{ {
@ -185,7 +151,6 @@ public:
} }
heap_.clear(); heap_.clear();
timers_.clear(); timers_.clear();
cleanup_timers();
} }
private: private:
@ -273,7 +238,8 @@ private:
static void invoke_handler(timer_base* base, static void invoke_handler(timer_base* base,
const asio::error_code& result) const asio::error_code& result)
{ {
static_cast<timer<Handler>*>(base)->handler_(result); std::auto_ptr<timer<Handler> > t(static_cast<timer<Handler>*>(base));
t->handler_(result);
} }
// Destroy the handler. // Destroy the handler.
@ -372,12 +338,6 @@ private:
// The heap of timers, with the earliest timer at the front. // The heap of timers, with the earliest timer at the front.
std::vector<timer_base*> heap_; std::vector<timer_base*> heap_;
// The list of timers to be cancelled.
timer_base* cancelled_timers_;
// The list of timers to be destroyed.
timer_base* cleanup_timers_;
}; };
} // namespace detail } // namespace detail

View file

@ -44,12 +44,6 @@ public:
// Dispatch all ready timers. // Dispatch all ready timers.
virtual void dispatch_timers() = 0; virtual void dispatch_timers() = 0;
// Dispatch any pending cancels for timers.
virtual void dispatch_cancellations() = 0;
// Destroy timers that are waiting to be cleaned up.
virtual void cleanup_timers() = 0;
// Destroy all timers. // Destroy all timers.
virtual void destroy_timers() = 0; virtual void destroy_timers() = 0;
}; };

View file

@ -23,13 +23,11 @@
#if defined(BOOST_WINDOWS) #if defined(BOOST_WINDOWS)
#include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp" #include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp" #include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp" #include "asio/detail/push_options.hpp"
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
@ -48,8 +46,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error, asio::native_ecat),
asio::error::system_category),
"event"); "event");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -62,31 +59,21 @@ public:
} }
// Signal the event. // Signal the event.
template <typename Lock> void signal()
void signal(Lock& lock)
{ {
BOOST_ASSERT(lock.locked());
(void)lock;
::SetEvent(event_); ::SetEvent(event_);
} }
// Reset the event. // Reset the event.
template <typename Lock> void clear()
void clear(Lock& lock)
{ {
BOOST_ASSERT(lock.locked());
(void)lock;
::ResetEvent(event_); ::ResetEvent(event_);
} }
// Wait for the event to become signalled. // Wait for the event to become signalled.
template <typename Lock> void wait()
void wait(Lock& lock)
{ {
BOOST_ASSERT(lock.locked());
lock.unlock();
::WaitForSingleObject(event_, INFINITE); ::WaitForSingleObject(event_, INFINITE);
lock.lock();
} }
private: private:

View file

@ -63,8 +63,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error, asio::native_ecat),
asio::error::system_category),
"iocp"); "iocp");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -174,8 +173,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error, asio::native_ecat),
asio::error::system_category),
"pqcs"); "pqcs");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -230,8 +228,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error, asio::native_ecat),
asio::error::system_category),
"pqcs"); "pqcs");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -250,8 +247,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error, asio::native_ecat),
asio::error::system_category),
"pqcs"); "pqcs");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -316,7 +312,7 @@ private:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error, ec = asio::error_code(last_error,
asio::error::system_category); asio::native_ecat);
return 0; return 0;
} }

View file

@ -21,8 +21,6 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#include "asio/detail/socket_types.hpp"
// This service is only supported on Win32 (NT4 and later). // This service is only supported on Win32 (NT4 and later).
#if !defined(ASIO_DISABLE_IOCP) #if !defined(ASIO_DISABLE_IOCP)
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)

View file

@ -137,7 +137,7 @@ public:
enum enum
{ {
enable_connection_aborted = 1, // User wants connection_aborted errors. enable_connection_aborted = 1, // User wants connection_aborted errors.
close_might_block = 2, // User set linger option for blocking close. user_set_linger = 2, // The user set the linger option.
user_set_non_blocking = 4 // The user wants a non-blocking socket. user_set_non_blocking = 4 // The user wants a non-blocking socket.
}; };
@ -170,7 +170,7 @@ public:
typedef detail::select_reactor<true> reactor_type; typedef detail::select_reactor<true> reactor_type;
// The maximum number of buffers to support in a single operation. // The maximum number of buffers to support in a single operation.
enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len }; enum { max_buffers = 16 };
// Constructor. // Constructor.
win_iocp_socket_service(asio::io_service& io_service) win_iocp_socket_service(asio::io_service& io_service)
@ -192,7 +192,7 @@ public:
while (impl) while (impl)
{ {
asio::error_code ignored_ec; asio::error_code ignored_ec;
close_for_destruction(*impl); close(*impl, ignored_ec);
impl = impl->next_; impl = impl->next_;
} }
} }
@ -217,7 +217,34 @@ public:
// Destroy a socket implementation. // Destroy a socket implementation.
void destroy(implementation_type& impl) void destroy(implementation_type& impl)
{ {
close_for_destruction(impl); if (impl.socket_ != invalid_socket)
{
// Check if the reactor was created, in which case we need to close the
// socket on the reactor as well to cancel any operations that might be
// running there.
reactor_type* reactor = static_cast<reactor_type*>(
interlocked_compare_exchange_pointer(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (reactor)
reactor->close_descriptor(impl.socket_);
if (impl.flags_ & implementation_type::user_set_linger)
{
::linger opt;
opt.l_onoff = 0;
opt.l_linger = 0;
asio::error_code ignored_ec;
socket_ops::setsockopt(impl.socket_,
SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
}
asio::error_code ignored_ec;
socket_ops::close(impl.socket_, ignored_ec);
impl.socket_ = invalid_socket;
impl.flags_ = 0;
impl.cancel_token_.reset();
impl.safe_cancellation_thread_id_ = 0;
}
// Remove implementation from linked list of all implementations. // Remove implementation from linked list of all implementations.
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
@ -326,25 +353,6 @@ public:
{ {
ec = asio::error::bad_descriptor; ec = asio::error::bad_descriptor;
} }
else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
::GetModuleHandle("KERNEL32"), "CancelIoEx"))
{
// The version of Windows supports cancellation from any thread.
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
socket_type sock = impl.socket_;
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
if (!cancel_io_ex(sock_as_handle, 0))
{
DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error,
asio::error::system_category);
}
else
{
ec = asio::error_code();
}
}
else if (impl.safe_cancellation_thread_id_ == 0) else if (impl.safe_cancellation_thread_id_ == 0)
{ {
// No operations have been started, so there's nothing to cancel. // No operations have been started, so there's nothing to cancel.
@ -359,8 +367,7 @@ public:
if (!::CancelIo(sock_as_handle)) if (!::CancelIo(sock_as_handle))
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error, ec = asio::error_code(last_error, asio::native_ecat);
asio::error::system_category);
} }
else else
{ {
@ -468,12 +475,7 @@ public:
if (option.level(impl.protocol_) == SOL_SOCKET if (option.level(impl.protocol_) == SOL_SOCKET
&& option.name(impl.protocol_) == SO_LINGER) && option.name(impl.protocol_) == SO_LINGER)
{ {
const ::linger* linger_option = impl.flags_ |= implementation_type::user_set_linger;
reinterpret_cast<const ::linger*>(option.data(impl.protocol_));
if (linger_option->l_onoff != 0 && linger_option->l_linger != 0)
impl.flags_ |= implementation_type::close_might_block;
else
impl.flags_ &= ~implementation_type::close_might_block;
} }
socket_ops::setsockopt(impl.socket_, socket_ops::setsockopt(impl.socket_,
@ -666,8 +668,7 @@ public:
last_error = WSAECONNRESET; last_error = WSAECONNRESET;
else if (last_error == ERROR_PORT_UNREACHABLE) else if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED; last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, ec = asio::error_code(last_error, asio::native_ecat);
asio::error::system_category);
return 0; return 0;
} }
@ -718,8 +719,7 @@ public:
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Map non-portable errors to their portable counterparts. // Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
if (ec.value() == ERROR_NETNAME_DELETED) if (ec.value() == ERROR_NETNAME_DELETED)
{ {
if (handler_op->cancel_token_.expired()) if (handler_op->cancel_token_.expired())
@ -821,8 +821,7 @@ public:
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
} }
else else
@ -866,8 +865,7 @@ public:
DWORD last_error = ::WSAGetLastError(); DWORD last_error = ::WSAGetLastError();
if (last_error == ERROR_PORT_UNREACHABLE) if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED; last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, ec = asio::error_code(last_error, asio::native_ecat);
asio::error::system_category);
return 0; return 0;
} }
@ -916,8 +914,7 @@ public:
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Map non-portable errors to their portable counterparts. // Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
if (ec.value() == ERROR_PORT_UNREACHABLE) if (ec.value() == ERROR_PORT_UNREACHABLE)
{ {
ec = asio::error::connection_refused; ec = asio::error::connection_refused;
@ -1000,8 +997,7 @@ public:
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
} }
else else
@ -1055,8 +1051,7 @@ public:
last_error = WSAECONNRESET; last_error = WSAECONNRESET;
else if (last_error == ERROR_PORT_UNREACHABLE) else if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED; last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, ec = asio::error_code(last_error, asio::native_ecat);
asio::error::system_category);
return 0; return 0;
} }
if (bytes_transferred == 0) if (bytes_transferred == 0)
@ -1114,8 +1109,7 @@ public:
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Map non-portable errors to their portable counterparts. // Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
if (ec.value() == ERROR_NETNAME_DELETED) if (ec.value() == ERROR_NETNAME_DELETED)
{ {
if (handler_op->cancel_token_.expired()) if (handler_op->cancel_token_.expired())
@ -1222,8 +1216,7 @@ public:
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
} }
else else
@ -1269,8 +1262,7 @@ public:
DWORD last_error = ::WSAGetLastError(); DWORD last_error = ::WSAGetLastError();
if (last_error == ERROR_PORT_UNREACHABLE) if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED; last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, ec = asio::error_code(last_error, asio::native_ecat);
asio::error::system_category);
return 0; return 0;
} }
if (bytes_transferred == 0) if (bytes_transferred == 0)
@ -1336,8 +1328,7 @@ public:
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Map non-portable errors to their portable counterparts. // Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
if (ec.value() == ERROR_PORT_UNREACHABLE) if (ec.value() == ERROR_PORT_UNREACHABLE)
{ {
ec = asio::error::connection_refused; ec = asio::error::connection_refused;
@ -1431,8 +1422,7 @@ public:
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
} }
else else
@ -1669,8 +1659,7 @@ public:
ptr.reset(); ptr.reset();
// Call the handler. // Call the handler.
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
asio_handler_invoke_helpers::invoke( asio_handler_invoke_helpers::invoke(
detail::bind_handler(handler, ec), &handler); detail::bind_handler(handler, ec), &handler);
} }
@ -1770,8 +1759,7 @@ public:
{ {
asio::io_service::work work(this->io_service()); asio::io_service::work work(this->io_service());
ptr.reset(); ptr.reset();
asio::error_code ec(last_error, asio::error_code ec(last_error, asio::native_ecat);
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec)); iocp_service_.post(bind_handler(handler, ec));
} }
} }
@ -1847,8 +1835,8 @@ public:
// If connection failed then post the handler with the error code. // If connection failed then post the handler with the error code.
if (connect_error) if (connect_error)
{ {
ec = asio::error_code(connect_error, ec = asio::error_code(
asio::error::system_category); connect_error, asio::native_ecat);
io_service_.post(bind_handler(handler_, ec)); io_service_.post(bind_handler(handler_, ec));
return true; return true;
} }
@ -1962,66 +1950,26 @@ public:
} }
private: private:
// Helper function to close a socket when the associated object is being // Helper function to provide InterlockedCompareExchangePointer functionality
// destroyed. // on very old Platform SDKs.
void close_for_destruction(implementation_type& impl)
{
if (is_open(impl))
{
// Check if the reactor was created, in which case we need to close the
// socket on the reactor as well to cancel any operations that might be
// running there.
reactor_type* reactor = static_cast<reactor_type*>(
interlocked_compare_exchange_pointer(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (reactor)
reactor->close_descriptor(impl.socket_);
// The socket destructor must not block. If the user has changed the
// linger option to block in the foreground, we will change it back to the
// default so that the closure is performed in the background.
if (impl.flags_ & implementation_type::close_might_block)
{
::linger opt;
opt.l_onoff = 0;
opt.l_linger = 0;
asio::error_code ignored_ec;
socket_ops::setsockopt(impl.socket_,
SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
}
asio::error_code ignored_ec;
socket_ops::close(impl.socket_, ignored_ec);
impl.socket_ = invalid_socket;
impl.flags_ = 0;
impl.cancel_token_.reset();
impl.safe_cancellation_thread_id_ = 0;
}
}
// Helper function to emulate InterlockedCompareExchangePointer functionality
// for:
// - very old Platform SDKs; and
// - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp) void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp)
{ {
#if defined(_M_IX86) #if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x400) && (_M_IX86)
return reinterpret_cast<void*>(InterlockedCompareExchange( return reinterpret_cast<void*>(InterlockedCompareExchange(
reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch), reinterpret_cast<LONG*>(dest), reinterpret_cast<LONG>(exch),
reinterpret_cast<LONG>(cmp))); reinterpret_cast<LONG>(cmp)));
#else #else
return InterlockedCompareExchangePointer(dest, exch, cmp); return InterlockedCompareExchangePointer(dest, exch, cmp);
#endif #endif
} }
// Helper function to emulate InterlockedExchangePointer functionality for: // Helper function to provide InterlockedExchangePointer functionality on very
// - very old Platform SDKs; and // old Platform SDKs.
// - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
void* interlocked_exchange_pointer(void** dest, void* val) void* interlocked_exchange_pointer(void** dest, void* val)
{ {
#if defined(_M_IX86) #if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x400) && (_M_IX86)
return reinterpret_cast<void*>(InterlockedExchange( return reinterpret_cast<void*>(InterlockedExchange(
reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val))); reinterpret_cast<LONG*>(dest), reinterpret_cast<LONG>(val)));
#else #else
return InterlockedExchangePointer(dest, val); return InterlockedExchangePointer(dest, val);
#endif #endif

View file

@ -23,7 +23,6 @@
#if defined(BOOST_WINDOWS) #if defined(BOOST_WINDOWS)
#include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp" #include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp" #include "asio/detail/socket_types.hpp"
@ -49,7 +48,7 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error, asio::native_ecat),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }
@ -68,7 +67,7 @@ public:
if (error != 0) if (error != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(error, asio::error::system_category), asio::error_code(error, asio::native_ecat),
"mutex"); "mutex");
boost::throw_exception(e); boost::throw_exception(e);
} }

View file

@ -23,7 +23,6 @@
#if defined(BOOST_WINDOWS) #if defined(BOOST_WINDOWS)
#include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp" #include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp" #include "asio/detail/socket_types.hpp"
@ -55,8 +54,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error, asio::native_ecat),
asio::error::system_category),
"thread"); "thread");
boost::throw_exception(e); boost::throw_exception(e);
} }

View file

@ -23,7 +23,6 @@
#if defined(BOOST_WINDOWS) #if defined(BOOST_WINDOWS)
#include "asio/error.hpp"
#include "asio/system_error.hpp" #include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp" #include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp" #include "asio/detail/socket_types.hpp"
@ -48,8 +47,7 @@ public:
{ {
DWORD last_error = ::GetLastError(); DWORD last_error = ::GetLastError();
asio::system_error e( asio::system_error e(
asio::error_code(last_error, asio::error_code(last_error, asio::native_ecat),
asio::error::system_category),
"tss"); "tss");
boost::throw_exception(e); boost::throw_exception(e);
} }

View file

@ -85,8 +85,7 @@ public:
if (this != &instance_ && ref_->result() != 0) if (this != &instance_ && ref_->result() != 0)
{ {
asio::system_error e( asio::system_error e(
asio::error_code(ref_->result(), asio::error_code(ref_->result(), asio::native_ecat),
asio::error::system_category),
"winsock"); "winsock");
boost::throw_exception(e); boost::throw_exception(e);
} }

View file

@ -17,10 +17,6 @@
#include "asio/detail/push_options.hpp" #include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/type_traits.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/bind_handler.hpp" #include "asio/detail/bind_handler.hpp"
#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"
@ -34,9 +30,7 @@ class wrapped_handler
public: public:
typedef void result_type; typedef void result_type;
wrapped_handler( wrapped_handler(Dispatcher& dispatcher, Handler handler)
typename boost::add_reference<Dispatcher>::type dispatcher,
Handler handler)
: dispatcher_(dispatcher), : dispatcher_(dispatcher),
handler_(handler) handler_(handler)
{ {
@ -123,7 +117,7 @@ public:
} }
//private: //private:
Dispatcher dispatcher_; Dispatcher& dispatcher_;
Handler handler_; Handler handler_;
}; };
@ -177,9 +171,9 @@ inline void asio_handler_invoke(const Function& function,
function, this_handler->handler_)); function, this_handler->handler_));
} }
template <typename Function, typename Handler, typename Context> template <typename Function, typename Dispatcher, typename Handler>
inline void asio_handler_invoke(const Function& function, inline void asio_handler_invoke(const Function& function,
rewrapped_handler<Handler, Context>* this_handler) rewrapped_handler<Dispatcher, Handler>* this_handler)
{ {
asio_handler_invoke_helpers::invoke( asio_handler_invoke_helpers::invoke(
function, &this_handler->context_); function, &this_handler->context_);

View file

@ -37,195 +37,327 @@
/// INTERNAL ONLY. /// INTERNAL ONLY.
# define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined # define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# define ASIO_NATIVE_ERROR(e) e # define ASIO_NATIVE_ERROR(e) \
# define ASIO_SOCKET_ERROR(e) WSA ## e asio::error_code(e, \
# define ASIO_NETDB_ERROR(e) WSA ## e asio::native_ecat)
# define ASIO_GETADDRINFO_ERROR(e) WSA ## e # define ASIO_SOCKET_ERROR(e) \
asio::error_code(WSA ## e, \
asio::native_ecat)
# define ASIO_NETDB_ERROR(e) \
asio::error_code(WSA ## e, \
asio::native_ecat)
# define ASIO_GETADDRINFO_ERROR(e) \
asio::error_code(WSA ## e, \
asio::native_ecat)
# define ASIO_MISC_ERROR(e) \
asio::error_code(e, \
asio::misc_ecat)
# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_win # define ASIO_WIN_OR_POSIX(e_win, e_posix) e_win
#else #else
# define ASIO_NATIVE_ERROR(e) e # define ASIO_NATIVE_ERROR(e) \
# define ASIO_SOCKET_ERROR(e) e asio::error_code(e, \
# define ASIO_NETDB_ERROR(e) e asio::native_ecat)
# define ASIO_GETADDRINFO_ERROR(e) e # define ASIO_SOCKET_ERROR(e) \
asio::error_code(e, \
asio::native_ecat)
# define ASIO_NETDB_ERROR(e) \
asio::error_code(e, \
asio::netdb_ecat)
# define ASIO_GETADDRINFO_ERROR(e) \
asio::error_code(e, \
asio::addrinfo_ecat)
# define ASIO_MISC_ERROR(e) \
asio::error_code(e, \
asio::misc_ecat)
# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix # define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix
#endif #endif
namespace asio { namespace asio {
namespace error {
enum basic_errors namespace detail {
/// Hack to keep asio library header-file-only.
template <typename T>
class error_base
{ {
public:
// boostify: error category declarations go here.
/// Permission denied. /// Permission denied.
access_denied = ASIO_SOCKET_ERROR(EACCES), static const asio::error_code access_denied;
/// Address family not supported by protocol. /// Address family not supported by protocol.
address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT), static const asio::error_code address_family_not_supported;
/// Address already in use. /// Address already in use.
address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE), static const asio::error_code address_in_use;
/// Transport endpoint is already connected. /// Transport endpoint is already connected.
already_connected = ASIO_SOCKET_ERROR(EISCONN), static const asio::error_code already_connected;
/// Already open.
static const asio::error_code already_open;
/// Operation already in progress. /// Operation already in progress.
already_started = ASIO_SOCKET_ERROR(EALREADY), static const asio::error_code already_started;
/// A connection has been aborted. /// A connection has been aborted.
connection_aborted = ASIO_SOCKET_ERROR(ECONNABORTED), static const asio::error_code connection_aborted;
/// Connection refused. /// Connection refused.
connection_refused = ASIO_SOCKET_ERROR(ECONNREFUSED), static const asio::error_code connection_refused;
/// Connection reset by peer. /// Connection reset by peer.
connection_reset = ASIO_SOCKET_ERROR(ECONNRESET), static const asio::error_code connection_reset;
/// Bad file descriptor. /// Bad file descriptor.
bad_descriptor = ASIO_SOCKET_ERROR(EBADF), static const asio::error_code bad_descriptor;
/// Bad address.
fault = ASIO_SOCKET_ERROR(EFAULT),
/// No route to host.
host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH),
/// Operation now in progress.
in_progress = ASIO_SOCKET_ERROR(EINPROGRESS),
/// Interrupted system call.
interrupted = ASIO_SOCKET_ERROR(EINTR),
/// Invalid argument.
invalid_argument = ASIO_SOCKET_ERROR(EINVAL),
/// Message too long.
message_size = ASIO_SOCKET_ERROR(EMSGSIZE),
/// Network is down.
network_down = ASIO_SOCKET_ERROR(ENETDOWN),
/// Network dropped connection on reset.
network_reset = ASIO_SOCKET_ERROR(ENETRESET),
/// Network is unreachable.
network_unreachable = ASIO_SOCKET_ERROR(ENETUNREACH),
/// Too many open files.
no_descriptors = ASIO_SOCKET_ERROR(EMFILE),
/// No buffer space available.
no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS),
/// Cannot allocate memory.
no_memory = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(ERROR_OUTOFMEMORY),
ASIO_NATIVE_ERROR(ENOMEM)),
/// Operation not permitted.
no_permission = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(ERROR_ACCESS_DENIED),
ASIO_NATIVE_ERROR(EPERM)),
/// Protocol not available.
no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT),
/// Transport endpoint is not connected.
not_connected = ASIO_SOCKET_ERROR(ENOTCONN),
/// Socket operation on non-socket.
not_socket = ASIO_SOCKET_ERROR(ENOTSOCK),
/// Operation cancelled.
operation_aborted = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(ERROR_OPERATION_ABORTED),
ASIO_NATIVE_ERROR(ECANCELED)),
/// Operation not supported.
operation_not_supported = ASIO_SOCKET_ERROR(EOPNOTSUPP),
/// Cannot send after transport endpoint shutdown.
shut_down = ASIO_SOCKET_ERROR(ESHUTDOWN),
/// Connection timed out.
timed_out = ASIO_SOCKET_ERROR(ETIMEDOUT),
/// Resource temporarily unavailable.
try_again = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(ERROR_RETRY),
ASIO_NATIVE_ERROR(EAGAIN)),
/// The socket is marked non-blocking and the requested operation would block.
would_block = ASIO_SOCKET_ERROR(EWOULDBLOCK)
};
enum netdb_errors
{
/// Host not found (authoritative).
host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND),
/// Host not found (non-authoritative).
host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN),
/// The query is valid but does not have associated address data.
no_data = ASIO_NETDB_ERROR(NO_DATA),
/// A non-recoverable error occurred.
no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY)
};
enum addrinfo_errors
{
/// The service is not supported for the given socket type.
service_not_found = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(WSATYPE_NOT_FOUND),
ASIO_GETADDRINFO_ERROR(EAI_SERVICE)),
/// The socket type is not supported.
socket_type_not_supported = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(WSAESOCKTNOSUPPORT),
ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE))
};
enum misc_errors
{
/// Already open.
already_open = 1,
/// End of file or stream. /// End of file or stream.
eof, static const asio::error_code eof;
/// Bad address.
static const asio::error_code fault;
/// Host not found (authoritative).
static const asio::error_code host_not_found;
/// Host not found (non-authoritative).
static const asio::error_code host_not_found_try_again;
/// No route to host.
static const asio::error_code host_unreachable;
/// Operation now in progress.
static const asio::error_code in_progress;
/// Interrupted system call.
static const asio::error_code interrupted;
/// Invalid argument.
static const asio::error_code invalid_argument;
/// Message too long.
static const asio::error_code message_size;
/// Network is down.
static const asio::error_code network_down;
/// Network dropped connection on reset.
static const asio::error_code network_reset;
/// Network is unreachable.
static const asio::error_code network_unreachable;
/// Too many open files.
static const asio::error_code no_descriptors;
/// No buffer space available.
static const asio::error_code no_buffer_space;
/// The query is valid but does not have associated address data.
static const asio::error_code no_data;
/// Cannot allocate memory.
static const asio::error_code no_memory;
/// Operation not permitted.
static const asio::error_code no_permission;
/// Protocol not available.
static const asio::error_code no_protocol_option;
/// A non-recoverable error occurred.
static const asio::error_code no_recovery;
/// Transport endpoint is not connected.
static const asio::error_code not_connected;
/// Element not found. /// Element not found.
not_found static const asio::error_code not_found;
/// Socket operation on non-socket.
static const asio::error_code not_socket;
/// Operation cancelled.
static const asio::error_code operation_aborted;
/// Operation not supported.
static const asio::error_code operation_not_supported;
/// The service is not supported for the given socket type.
static const asio::error_code service_not_found;
/// The socket type is not supported.
static const asio::error_code socket_type_not_supported;
/// Cannot send after transport endpoint shutdown.
static const asio::error_code shut_down;
/// Connection timed out.
static const asio::error_code timed_out;
/// Resource temporarily unavailable.
static const asio::error_code try_again;
/// The socket is marked non-blocking and the requested operation would block.
static const asio::error_code would_block;
private:
error_base();
}; };
// boostify: error category definitions go here. // boostify: error category definitions go here.
inline asio::error_code make_error_code(basic_errors e) template <typename T> const asio::error_code
{ error_base<T>::access_denied = ASIO_SOCKET_ERROR(EACCES);
return asio::error_code(static_cast<int>(e), system_category);
}
inline asio::error_code make_error_code(netdb_errors e) template <typename T> const asio::error_code
{ error_base<T>::address_family_not_supported = ASIO_SOCKET_ERROR(
return asio::error_code(static_cast<int>(e), netdb_category); EAFNOSUPPORT);
}
inline asio::error_code make_error_code(addrinfo_errors e) template <typename T> const asio::error_code
{ error_base<T>::address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE);
return asio::error_code(static_cast<int>(e), addrinfo_category);
}
inline asio::error_code make_error_code(misc_errors e) template <typename T> const asio::error_code
{ error_base<T>::already_connected = ASIO_SOCKET_ERROR(EISCONN);
return asio::error_code(static_cast<int>(e), misc_category);
} template <typename T> const asio::error_code
error_base<T>::already_open = ASIO_MISC_ERROR(1);
template <typename T> const asio::error_code
error_base<T>::already_started = ASIO_SOCKET_ERROR(EALREADY);
template <typename T> const asio::error_code
error_base<T>::connection_aborted = ASIO_SOCKET_ERROR(ECONNABORTED);
template <typename T> const asio::error_code
error_base<T>::connection_refused = ASIO_SOCKET_ERROR(ECONNREFUSED);
template <typename T> const asio::error_code
error_base<T>::connection_reset = ASIO_SOCKET_ERROR(ECONNRESET);
template <typename T> const asio::error_code
error_base<T>::bad_descriptor = ASIO_SOCKET_ERROR(EBADF);
template <typename T> const asio::error_code
error_base<T>::eof = ASIO_MISC_ERROR(2);
template <typename T> const asio::error_code
error_base<T>::fault = ASIO_SOCKET_ERROR(EFAULT);
template <typename T> const asio::error_code
error_base<T>::host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND);
template <typename T> const asio::error_code
error_base<T>::host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN);
template <typename T> const asio::error_code
error_base<T>::host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH);
template <typename T> const asio::error_code
error_base<T>::in_progress = ASIO_SOCKET_ERROR(EINPROGRESS);
template <typename T> const asio::error_code
error_base<T>::interrupted = ASIO_SOCKET_ERROR(EINTR);
template <typename T> const asio::error_code
error_base<T>::invalid_argument = ASIO_SOCKET_ERROR(EINVAL);
template <typename T> const asio::error_code
error_base<T>::message_size = ASIO_SOCKET_ERROR(EMSGSIZE);
template <typename T> const asio::error_code
error_base<T>::network_down = ASIO_SOCKET_ERROR(ENETDOWN);
template <typename T> const asio::error_code
error_base<T>::network_reset = ASIO_SOCKET_ERROR(ENETRESET);
template <typename T> const asio::error_code
error_base<T>::network_unreachable = ASIO_SOCKET_ERROR(ENETUNREACH);
template <typename T> const asio::error_code
error_base<T>::no_descriptors = ASIO_SOCKET_ERROR(EMFILE);
template <typename T> const asio::error_code
error_base<T>::no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS);
template <typename T> const asio::error_code
error_base<T>::no_data = ASIO_NETDB_ERROR(NO_DATA);
template <typename T> const asio::error_code
error_base<T>::no_memory = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(ERROR_OUTOFMEMORY),
ASIO_NATIVE_ERROR(ENOMEM));
template <typename T> const asio::error_code
error_base<T>::no_permission = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(ERROR_ACCESS_DENIED),
ASIO_NATIVE_ERROR(EPERM));
template <typename T> const asio::error_code
error_base<T>::no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT);
template <typename T> const asio::error_code
error_base<T>::no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY);
template <typename T> const asio::error_code
error_base<T>::not_connected = ASIO_SOCKET_ERROR(ENOTCONN);
template <typename T> const asio::error_code
error_base<T>::not_found = ASIO_MISC_ERROR(3);
template <typename T> const asio::error_code
error_base<T>::not_socket = ASIO_SOCKET_ERROR(ENOTSOCK);
template <typename T> const asio::error_code
error_base<T>::operation_aborted = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(ERROR_OPERATION_ABORTED),
ASIO_NATIVE_ERROR(ECANCELED));
template <typename T> const asio::error_code
error_base<T>::operation_not_supported = ASIO_SOCKET_ERROR(EOPNOTSUPP);
template <typename T> const asio::error_code
error_base<T>::service_not_found = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(WSATYPE_NOT_FOUND),
ASIO_GETADDRINFO_ERROR(EAI_SERVICE));
template <typename T> const asio::error_code
error_base<T>::socket_type_not_supported = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(WSAESOCKTNOSUPPORT),
ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE));
template <typename T> const asio::error_code
error_base<T>::shut_down = ASIO_SOCKET_ERROR(ESHUTDOWN);
template <typename T> const asio::error_code
error_base<T>::timed_out = ASIO_SOCKET_ERROR(ETIMEDOUT);
template <typename T> const asio::error_code
error_base<T>::try_again = ASIO_WIN_OR_POSIX(
ASIO_NATIVE_ERROR(ERROR_RETRY),
ASIO_NATIVE_ERROR(EAGAIN));
template <typename T> const asio::error_code
error_base<T>::would_block = ASIO_SOCKET_ERROR(EWOULDBLOCK);
} // namespace detail
/// Contains error constants.
class error : public asio::detail::error_base<error>
{
private:
error();
};
} // namespace error
} // namespace asio } // namespace asio
#undef ASIO_NATIVE_ERROR #undef ASIO_NATIVE_ERROR
#undef ASIO_SOCKET_ERROR #undef ASIO_SOCKET_ERROR
#undef ASIO_NETDB_ERROR #undef ASIO_NETDB_ERROR
#undef ASIO_GETADDRINFO_ERROR #undef ASIO_GETADDRINFO_ERROR
#undef ASIO_MISC_ERROR
#undef ASIO_WIN_OR_POSIX #undef ASIO_WIN_OR_POSIX
#include "asio/impl/error_code.ipp" #include "asio/impl/error_code.ipp"

View file

@ -32,27 +32,24 @@
namespace asio { namespace asio {
namespace error /// Available error code categories.
enum error_category
{ {
/// Available error code categories. /// Native error codes.
enum error_category native_ecat = ASIO_WIN_OR_POSIX(0, 0),
{
/// System error codes.
system_category = ASIO_WIN_OR_POSIX(0, 0),
/// Error codes from NetDB functions. /// Error codes from NetDB functions.
netdb_category = ASIO_WIN_OR_POSIX(system_category, 1), netdb_ecat = ASIO_WIN_OR_POSIX(native_ecat, 1),
/// Error codes from getaddrinfo. /// Error codes from getaddrinfo.
addrinfo_category = ASIO_WIN_OR_POSIX(system_category, 2), addrinfo_ecat = ASIO_WIN_OR_POSIX(native_ecat, 2),
/// Miscellaneous error codes. /// Miscellaneous error codes.
misc_category = ASIO_WIN_OR_POSIX(3, 3), misc_ecat = ASIO_WIN_OR_POSIX(3, 3),
/// SSL error codes. /// SSL error codes.
ssl_category = ASIO_WIN_OR_POSIX(4, 4) ssl_ecat = ASIO_WIN_OR_POSIX(4, 4)
}; };
} // namespace error
/// Class to represent an error code value. /// Class to represent an error code value.
class error_code class error_code
@ -64,24 +61,17 @@ public:
/// Default constructor. /// Default constructor.
error_code() error_code()
: value_(0), : value_(0),
category_(error::system_category) category_(native_ecat)
{ {
} }
/// Construct with specific error code and category. /// Construct with specific error code and category.
error_code(value_type v, error::error_category c) error_code(value_type v, error_category c)
: value_(v), : value_(v),
category_(c) category_(c)
{ {
} }
/// Construct from an error code enum.
template <typename ErrorEnum>
error_code(ErrorEnum e)
{
*this = make_error_code(e);
}
/// Get the error value. /// Get the error value.
value_type value() const value_type value() const
{ {
@ -89,7 +79,7 @@ public:
} }
/// Get the error category. /// Get the error category.
error::error_category category() const error_category category() const
{ {
return category_; return category_;
} }
@ -135,7 +125,7 @@ private:
value_type value_; value_type value_;
// The category associated with the error code. // The category associated with the error code.
error::error_category category_; error_category category_;
}; };
} // namespace asio } // namespace asio

View file

@ -35,12 +35,10 @@ inline std::string error_code::message() const
return "Already open."; return "Already open.";
if (*this == error::not_found) if (*this == error::not_found)
return "Not found."; return "Not found.";
if (category_ == error::ssl_category) if (category_ == ssl_ecat)
return "SSL error."; return "SSL error.";
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
value_type value = value_; value_type value = value_;
if (category() != error::system_category && *this != error::eof)
return "asio error";
if (*this == error::eof) if (*this == error::eof)
value = ERROR_HANDLE_EOF; value = ERROR_HANDLE_EOF;
char* msg = 0; char* msg = 0;
@ -78,8 +76,6 @@ inline std::string error_code::message() const
return "Service not found."; return "Service not found.";
if (*this == error::socket_type_not_supported) if (*this == error::socket_type_not_supported)
return "Socket type not supported."; return "Socket type not supported.";
if (category() != error::system_category)
return "asio error";
#if defined(__sun) || defined(__QNX__) #if defined(__sun) || defined(__QNX__)
return strerror(value_); return strerror(value_);
#elif defined(__MACH__) && defined(__APPLE__) \ #elif defined(__MACH__) && defined(__APPLE__) \

View file

@ -128,11 +128,11 @@ template <typename Handler>
#if defined(GENERATING_DOCUMENTATION) #if defined(GENERATING_DOCUMENTATION)
unspecified unspecified
#else #else
inline detail::wrapped_handler<io_service&, Handler> inline detail::wrapped_handler<io_service, Handler>
#endif #endif
io_service::wrap(Handler handler) io_service::wrap(Handler handler)
{ {
return detail::wrapped_handler<io_service&, Handler>(*this, handler); return detail::wrapped_handler<io_service, Handler>(*this, handler);
} }
inline io_service::work::work(asio::io_service& io_service) inline io_service::work::work(asio::io_service& io_service)

View file

@ -311,8 +311,7 @@ namespace detail
if (streambuf_.size() == streambuf_.max_size()) if (streambuf_.size() == streambuf_.max_size())
{ {
std::size_t bytes = 0; std::size_t bytes = 0;
asio::error_code ec(error::not_found); handler_(error::not_found, bytes);
handler_(ec, bytes);
return; return;
} }
@ -389,8 +388,7 @@ void async_read_until(AsyncReadStream& s,
// No match. Check if buffer is full. // No match. Check if buffer is full.
if (b.size() == b.max_size()) if (b.size() == b.max_size())
{ {
asio::error_code ec(error::not_found); s.io_service().post(detail::bind_handler(handler, error::not_found, 0));
s.io_service().post(detail::bind_handler(handler, ec, 0));
return; return;
} }
@ -471,8 +469,7 @@ namespace detail
if (streambuf_.size() == streambuf_.max_size()) if (streambuf_.size() == streambuf_.max_size())
{ {
std::size_t bytes = 0; std::size_t bytes = 0;
asio::error_code ec(error::not_found); handler_(error::not_found, bytes);
handler_(ec, bytes);
return; return;
} }
@ -562,8 +559,7 @@ void async_read_until(AsyncReadStream& s,
// Check if buffer is full. // Check if buffer is full.
if (b.size() == b.max_size()) if (b.size() == b.max_size())
{ {
asio::error_code ec(error::not_found); s.io_service().post(detail::bind_handler(handler, error::not_found, 0));
s.io_service().post(detail::bind_handler(handler, ec, 0));
return; return;
} }
@ -645,8 +641,7 @@ namespace detail
if (streambuf_.size() == streambuf_.max_size()) if (streambuf_.size() == streambuf_.max_size())
{ {
std::size_t bytes = 0; std::size_t bytes = 0;
asio::error_code ec(error::not_found); handler_(error::not_found, bytes);
handler_(ec, bytes);
return; return;
} }
@ -736,8 +731,7 @@ void async_read_until(AsyncReadStream& s,
// Check if buffer is full. // Check if buffer is full.
if (b.size() == b.max_size()) if (b.size() == b.max_size())
{ {
asio::error_code ec(error::not_found); s.io_service().post(detail::bind_handler(handler, error::not_found, 0));
s.io_service().post(detail::bind_handler(handler, ec, 0));
return; return;
} }

View file

@ -320,7 +320,7 @@ public:
#if defined(GENERATING_DOCUMENTATION) #if defined(GENERATING_DOCUMENTATION)
unspecified unspecified
#else #else
detail::wrapped_handler<io_service&, Handler> detail::wrapped_handler<io_service, Handler>
#endif #endif
wrap(Handler handler); wrap(Handler handler);

View file

@ -172,7 +172,7 @@ public:
/// The protocol associated with the endpoint. /// The protocol associated with the endpoint.
protocol_type protocol() const protocol_type protocol() const
{ {
if (is_v4(data_)) if (is_v4())
return InternetProtocol::v4(); return InternetProtocol::v4();
return InternetProtocol::v6(); return InternetProtocol::v6();
} }
@ -192,7 +192,7 @@ public:
/// Get the underlying size of the endpoint in the native type. /// Get the underlying size of the endpoint in the native type.
size_type size() const size_type size() const
{ {
if (is_v4(data_)) if (is_v4())
return sizeof(asio::detail::sockaddr_in4_type); return sizeof(asio::detail::sockaddr_in4_type);
else else
return sizeof(asio::detail::sockaddr_in6_type); return sizeof(asio::detail::sockaddr_in6_type);
@ -218,7 +218,7 @@ public:
/// the host's byte order. /// the host's byte order.
unsigned short port() const unsigned short port() const
{ {
if (is_v4(data_)) if (is_v4())
{ {
return asio::detail::socket_ops::network_to_host_short( return asio::detail::socket_ops::network_to_host_short(
reinterpret_cast<const asio::detail::sockaddr_in4_type&>( reinterpret_cast<const asio::detail::sockaddr_in4_type&>(
@ -236,7 +236,7 @@ public:
/// the host's byte order. /// the host's byte order.
void port(unsigned short port_num) void port(unsigned short port_num)
{ {
if (is_v4(data_)) if (is_v4())
{ {
reinterpret_cast<asio::detail::sockaddr_in4_type&>(data_).sin_port reinterpret_cast<asio::detail::sockaddr_in4_type&>(data_).sin_port
= asio::detail::socket_ops::host_to_network_short(port_num); = asio::detail::socket_ops::host_to_network_short(port_num);
@ -252,7 +252,7 @@ public:
asio::ip::address address() const asio::ip::address address() const
{ {
using namespace std; // For memcpy. using namespace std; // For memcpy.
if (is_v4(data_)) if (is_v4())
{ {
const asio::detail::sockaddr_in4_type& data const asio::detail::sockaddr_in4_type& data
= reinterpret_cast<const asio::detail::sockaddr_in4_type&>( = reinterpret_cast<const asio::detail::sockaddr_in4_type&>(
@ -306,26 +306,14 @@ public:
private: private:
// Helper function to determine whether the endpoint is IPv4. // Helper function to determine whether the endpoint is IPv4.
bool is_v4() const
{
#if defined(_AIX) #if defined(_AIX)
template <typename T, unsigned char (T::*)> struct is_v4_helper {}; return data_.__ss_family == AF_INET;
template <typename T>
static bool is_v4(const T& ss, is_v4_helper<T, &T::ss_family>* = 0)
{
return ss.ss_family == AF_INET;
}
template <typename T>
static bool is_v4(const T& ss, is_v4_helper<T, &T::__ss_family>* = 0)
{
return ss.__ss_family == AF_INET;
}
#else #else
static bool is_v4(const asio::detail::sockaddr_storage_type& ss) return data_.ss_family == AF_INET;
{
return ss.ss_family == AF_INET;
}
#endif #endif
}
// The underlying IP socket address. // The underlying IP socket address.
asio::detail::sockaddr_storage_type data_; asio::detail::sockaddr_storage_type data_;

View file

@ -174,12 +174,12 @@ public:
if (error_code == SSL_ERROR_SYSCALL) if (error_code == SSL_ERROR_SYSCALL)
{ {
return handler_(asio::error_code( return handler_(asio::error_code(
sys_error_code, asio::error::system_category), rc); sys_error_code, asio::native_ecat), rc);
} }
else else
{ {
return handler_(asio::error_code( return handler_(asio::error_code(
error_code, asio::error::ssl_category), rc); error_code, asio::ssl_ecat), rc);
} }
} }

View file

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
#include <queue> #include <queue>
#include <string> #include <string>
#include <cassert>
#include <typeinfo> #include <typeinfo>
#ifdef _MSC_VER #ifdef _MSC_VER
@ -55,7 +56,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#ifndef TORRENT_MAX_ALERT_TYPES #ifndef TORRENT_MAX_ALERT_TYPES
#define TORRENT_MAX_ALERT_TYPES 15 #define TORRENT_MAX_ALERT_TYPES 15

View file

@ -38,7 +38,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/peer_connection.hpp" #include "libtorrent/peer_connection.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -224,7 +223,7 @@ namespace libtorrent
{ {
block_downloading_alert( block_downloading_alert(
const torrent_handle& h const torrent_handle& h
, char const* speedmsg , std::string& speedmsg
, int block_num , int block_num
, int piece_num , int piece_num
, const std::string& msg) , const std::string& msg)
@ -262,17 +261,6 @@ namespace libtorrent
{ return std::auto_ptr<alert>(new torrent_paused_alert(*this)); } { return std::auto_ptr<alert>(new torrent_paused_alert(*this)); }
}; };
struct TORRENT_EXPORT torrent_checked_alert: torrent_alert
{
torrent_checked_alert(torrent_handle const& h, std::string const& msg)
: torrent_alert(h, alert::info, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_checked_alert(*this)); }
};
struct TORRENT_EXPORT url_seed_alert: torrent_alert struct TORRENT_EXPORT url_seed_alert: torrent_alert
{ {
url_seed_alert( url_seed_alert(

View file

@ -1,54 +0,0 @@
/*
Copyright (c) 2007, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <cassert>
#ifndef NDEBUG
#if (defined __linux__ || defined __MACH__) && defined __GNUC__
#ifdef assert
#undef assert
#endif
#include "libtorrent/config.hpp"
TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function);
#define assert(x) if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__)
#endif
#else
#ifndef assert
#define assert(x) (void)
#endif
#endif

View file

@ -83,7 +83,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket_type.hpp" #include "libtorrent/socket_type.hpp"
#include "libtorrent/connection_queue.hpp" #include "libtorrent/connection_queue.hpp"
#include "libtorrent/disk_io_thread.hpp" #include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -185,7 +184,7 @@ namespace libtorrent
~session_impl(); ~session_impl();
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext); void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
#endif #endif
void operator()(); void operator()();
@ -241,13 +240,12 @@ namespace libtorrent
bool is_listening() const; bool is_listening() const;
torrent_handle add_torrent( torrent_handle add_torrent(
boost::intrusive_ptr<torrent_info> ti torrent_info const& ti
, fs::path const& save_path , fs::path const& save_path
, entry const& resume_data , entry const& resume_data
, bool compact_mode , bool compact_mode
, storage_constructor_type sc , int block_size
, bool paused , storage_constructor_type sc);
, void* userdata);
torrent_handle add_torrent( torrent_handle add_torrent(
char const* tracker_url char const* tracker_url
@ -256,9 +254,8 @@ namespace libtorrent
, fs::path const& save_path , fs::path const& save_path
, entry const& resume_data , entry const& resume_data
, bool compact_mode , bool compact_mode
, storage_constructor_type sc , int block_size
, bool paused , storage_constructor_type sc);
, void* userdata);
void remove_torrent(torrent_handle const& h); void remove_torrent(torrent_handle const& h);
@ -276,21 +273,8 @@ namespace libtorrent
void set_max_connections(int limit); void set_max_connections(int limit);
void set_max_uploads(int limit); void set_max_uploads(int limit);
int max_connections() const { return m_max_connections; } int num_uploads() const;
int max_uploads() const { return m_max_uploads; } int num_connections() const;
int max_half_open_connections() const { return m_half_open.limit(); }
int num_uploads() const { return m_num_unchoked; }
int num_connections() const
{ return m_connections.size(); }
void unchoke_peer(peer_connection& c)
{
torrent* t = c.associated_torrent().lock().get();
assert(t);
if (t->unchoke_peer(c))
++m_num_unchoked;
}
session_status status() const; session_status status() const;
void set_peer_id(peer_id const& id); void set_peer_id(peer_id const& id);
@ -433,28 +417,6 @@ namespace libtorrent
int m_max_uploads; int m_max_uploads;
int m_max_connections; int m_max_connections;
// the number of unchoked peers
int m_num_unchoked;
// this is initialized to the unchoke_interval
// session_setting and decreased every second.
// when it reaches zero, it is reset to the
// unchoke_interval and the unchoke set is
// recomputed.
int m_unchoke_time_scaler;
// works like unchoke_time_scaler but it
// is only decresed when the unchoke set
// is recomputed, and when it reaches zero,
// the optimistic unchoke is moved to another peer.
int m_optimistic_unchoke_time_scaler;
// works like unchoke_time_scaler. Each time
// it reaches 0, and all the connections are
// used, the worst connection will be disconnected
// from the torrent with the most peers
int m_disconnect_time_scaler;
// statistics gathered from all torrents. // statistics gathered from all torrents.
stat m_stat; stat m_stat;
@ -497,7 +459,7 @@ namespace libtorrent
// This implements a round robin. // This implements a round robin.
int m_next_connect_torrent; int m_next_connect_torrent;
#ifndef NDEBUG #ifndef NDEBUG
void check_invariant() const; void check_invariant(const char *place = 0);
#endif #endif
#ifdef TORRENT_STATS #ifdef TORRENT_STATS
@ -521,7 +483,7 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::function<boost::shared_ptr< typedef std::list<boost::function<boost::shared_ptr<
torrent_plugin>(torrent*, void*)> > extension_list_t; torrent_plugin>(torrent*)> > extension_list_t;
extension_list_t m_extensions; extension_list_t m_extensions;
#endif #endif

View file

@ -33,6 +33,9 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED #ifndef TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED #define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#include "libtorrent/socket.hpp"
#include "libtorrent/invariant_check.hpp"
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
@ -41,17 +44,11 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <deque> #include <deque>
#include "libtorrent/socket.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp"
using boost::weak_ptr; using boost::weak_ptr;
using boost::shared_ptr; using boost::shared_ptr;
using boost::intrusive_ptr; using boost::intrusive_ptr;
using boost::bind; using boost::bind;
//#define TORRENT_VERBOSE_BANDWIDTH_LIMIT
namespace libtorrent { namespace libtorrent {
// the maximum block of bandwidth quota to // the maximum block of bandwidth quota to
@ -180,7 +177,6 @@ struct bandwidth_manager
, m_limit(bandwidth_limit::inf) , m_limit(bandwidth_limit::inf)
, m_current_quota(0) , m_current_quota(0)
, m_channel(channel) , m_channel(channel)
, m_in_hand_out_bandwidth(false)
{} {}
void throttle(int limit) throw() void throttle(int limit) throw()
@ -241,10 +237,8 @@ struct bandwidth_manager
i = j; i = j;
} }
} }
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
std::cerr << " req_bandwidht. m_queue.size() = " << m_queue.size() << std::endl; if (m_queue.size() == 1) hand_out_bandwidth();
#endif
if (!m_queue.empty()) hand_out_bandwidth();
} }
#ifndef NDEBUG #ifndef NDEBUG
@ -329,10 +323,6 @@ private:
void hand_out_bandwidth() throw() void hand_out_bandwidth() throw()
{ {
// if we're already handing out bandwidth, just return back
// to the loop further down on the callstack
if (m_in_hand_out_bandwidth) return;
m_in_hand_out_bandwidth = true;
#ifndef NDEBUG #ifndef NDEBUG
try { try {
#endif #endif
@ -347,18 +337,10 @@ private:
// available bandwidth to hand out // available bandwidth to hand out
int amount = limit - m_current_quota; int amount = limit - m_current_quota;
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
std::cerr << " hand_out_bandwidht. m_queue.size() = " << m_queue.size()
<< " amount = " << amount
<< " limit = " << limit
<< " m_current_quota = " << m_current_quota << std::endl;
#endif
while (!m_queue.empty() && amount > 0) while (!m_queue.empty() && amount > 0)
{ {
assert(amount == limit - m_current_quota); assert(amount == limit - m_current_quota);
bw_queue_entry<PeerConnection> qe = m_queue.front(); bw_queue_entry<PeerConnection> qe = m_queue.front();
assert(qe.max_block_size > 0);
m_queue.pop_front(); m_queue.pop_front();
shared_ptr<Torrent> t = qe.peer->associated_torrent().lock(); shared_ptr<Torrent> t = qe.peer->associated_torrent().lock();
@ -366,7 +348,6 @@ private:
if (qe.peer->is_disconnecting()) if (qe.peer->is_disconnecting())
{ {
t->expire_bandwidth(m_channel, qe.max_block_size); t->expire_bandwidth(m_channel, qe.max_block_size);
assert(amount == limit - m_current_quota);
continue; continue;
} }
@ -380,7 +361,6 @@ private:
if (max_assignable == 0) if (max_assignable == 0)
{ {
t->expire_bandwidth(m_channel, qe.max_block_size); t->expire_bandwidth(m_channel, qe.max_block_size);
assert(amount == limit - m_current_quota);
continue; continue;
} }
@ -394,16 +374,17 @@ private:
// block size must be smaller for lower rates. This is because // block size must be smaller for lower rates. This is because
// the history window is one second, and the block will be forgotten // the history window is one second, and the block will be forgotten
// after one second. // after one second.
int block_size = (std::min)(qe.peer->bandwidth_throttle(m_channel) int block_size = (std::min)(qe.max_block_size
, limit / 10); , (std::min)(qe.peer->bandwidth_throttle(m_channel)
, m_limit / 10));
if (block_size < min_bandwidth_block_size) if (block_size < min_bandwidth_block_size)
{ {
block_size = (std::min)(int(min_bandwidth_block_size), limit); block_size = min_bandwidth_block_size;
} }
else if (block_size > max_bandwidth_block_size) else if (block_size > max_bandwidth_block_size)
{ {
if (limit == bandwidth_limit::inf) if (m_limit == bandwidth_limit::inf)
{ {
block_size = max_bandwidth_block_size; block_size = max_bandwidth_block_size;
} }
@ -414,15 +395,11 @@ private:
// as possible // as possible
// TODO: move this calculcation to where the limit // TODO: move this calculcation to where the limit
// is changed // is changed
block_size = limit block_size = m_limit
/ (limit / max_bandwidth_block_size); / (m_limit / max_bandwidth_block_size);
} }
} }
if (block_size > qe.max_block_size) block_size = qe.max_block_size;
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
std::cerr << " block_size = " << block_size << " amount = " << amount << std::endl;
#endif
if (amount < block_size / 2) if (amount < block_size / 2)
{ {
m_queue.push_front(qe); m_queue.push_front(qe);
@ -435,21 +412,18 @@ private:
int hand_out_amount = (std::min)((std::min)(block_size, max_assignable) int hand_out_amount = (std::min)((std::min)(block_size, max_assignable)
, amount); , amount);
assert(hand_out_amount > 0); assert(hand_out_amount > 0);
assert(amount == limit - m_current_quota);
amount -= hand_out_amount; amount -= hand_out_amount;
assert(hand_out_amount <= qe.max_block_size); assert(hand_out_amount <= qe.max_block_size);
t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size); t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size);
qe.peer->assign_bandwidth(m_channel, hand_out_amount); qe.peer->assign_bandwidth(m_channel, hand_out_amount);
add_history_entry(history_entry<PeerConnection, Torrent>( add_history_entry(history_entry<PeerConnection, Torrent>(
qe.peer, t, hand_out_amount, now + bw_window_size)); qe.peer, t, hand_out_amount, now + bw_window_size));
assert(amount == limit - m_current_quota);
} }
#ifndef NDEBUG #ifndef NDEBUG
} }
catch (std::exception& e) catch (std::exception& e)
{ assert(false); }; { assert(false); };
#endif #endif
m_in_hand_out_bandwidth = false;
} }
@ -482,11 +456,6 @@ private:
// this is the channel within the consumers // this is the channel within the consumers
// that bandwidth is assigned to (upload or download) // that bandwidth is assigned to (upload or download)
int m_channel; int m_channel;
// this is true while we're in the hand_out_bandwidth loop
// to prevent recursive invocations to interfere
bool m_in_hand_out_bandwidth;
}; };
} }

View file

@ -79,8 +79,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#if defined(_MSC_VER) #if defined(_MSC_VER)
namespace std namespace std
{ {

View file

@ -1,84 +0,0 @@
/*
Copyright (c) 2007, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#include "libtorrent/socket.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <list>
namespace libtorrent
{
bool is_local(address const& a);
bool is_loopback(address const& addr);
bool is_multicast(address const& addr);
address_v4 guess_local_address(asio::io_service&);
typedef boost::function<void(udp::endpoint const& from
, char* buffer, int size)> receive_handler_t;
class broadcast_socket
{
public:
broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint
, receive_handler_t const& handler, bool loopback = true);
~broadcast_socket() { close(); }
void send(char const* buffer, int size, asio::error_code& ec);
void close();
private:
struct socket_entry
{
socket_entry(boost::shared_ptr<datagram_socket> const& s): socket(s) {}
boost::shared_ptr<datagram_socket> socket;
char buffer[1024];
udp::endpoint remote;
};
void on_receive(socket_entry* s, asio::error_code const& ec
, std::size_t bytes_transferred);
std::list<socket_entry> m_sockets;
udp::endpoint m_multicast_endpoint;
receive_handler_t m_on_receive;
};
}
#endif

View file

@ -65,6 +65,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp" #include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp" #include "libtorrent/torrent.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/peer_request.hpp" #include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp" #include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
@ -121,16 +122,8 @@ namespace libtorrent
msg_request, msg_request,
msg_piece, msg_piece,
msg_cancel, msg_cancel,
// DHT extension
msg_dht_port, msg_dht_port,
// FAST extension // extension protocol message
msg_suggest_piece = 0xd,
msg_have_all,
msg_have_none,
msg_reject_request,
msg_allowed_fast,
// extension protocol message
msg_extended = 20, msg_extended = 20,
num_supported_messages num_supported_messages
@ -181,17 +174,8 @@ namespace libtorrent
void on_request(int received); void on_request(int received);
void on_piece(int received); void on_piece(int received);
void on_cancel(int received); void on_cancel(int received);
// DHT extension
void on_dht_port(int received); void on_dht_port(int received);
// FAST extension
void on_suggest_piece(int received);
void on_have_all(int received);
void on_have_none(int received);
void on_reject_request(int received);
void on_allowed_fast(int received);
void on_extended(int received); void on_extended(int received);
void on_extended_handshake(); void on_extended_handshake();
@ -217,16 +201,7 @@ namespace libtorrent
void write_metadata(std::pair<int, int> req); void write_metadata(std::pair<int, int> req);
void write_metadata_request(std::pair<int, int> req); void write_metadata_request(std::pair<int, int> req);
void write_keepalive(); void write_keepalive();
// DHT extension
void write_dht_port(int listen_port); void write_dht_port(int listen_port);
// FAST extension
void write_have_all();
void write_have_none();
void write_reject_request(peer_request const&);
void write_allow_fast(int piece);
void on_connected(); void on_connected();
void on_metadata(); void on_metadata();
@ -350,7 +325,6 @@ namespace libtorrent
bool m_supports_extensions; bool m_supports_extensions;
#endif #endif
bool m_supports_dht_port; bool m_supports_dht_port;
bool m_supports_fast;
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
// this is set to true after the encryption method has been // this is set to true after the encryption method has been

View file

@ -34,9 +34,8 @@ POSSIBILITY OF SUCH DAMAGE.
//#define TORRENT_BUFFER_DEBUG //#define TORRENT_BUFFER_DEBUG
#include <memory>
#include "libtorrent/invariant_check.hpp" #include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp" #include <memory>
namespace libtorrent { namespace libtorrent {

View file

@ -36,7 +36,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <list> #include <list>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
@ -89,10 +88,6 @@ private:
int m_half_open_limit; int m_half_open_limit;
deadline_timer m_timer; deadline_timer m_timer;
typedef boost::recursive_mutex mutex_t;
mutable mutex_t m_mutex;
#ifndef NDEBUG #ifndef NDEBUG
bool m_in_timeout_function; bool m_in_timeout_function;
#endif #endif

View file

@ -80,4 +80,3 @@ namespace libtorrent
} }
#endif // TORRENT_DEBUG_HPP_INCLUDED #endif // TORRENT_DEBUG_HPP_INCLUDED

View file

@ -30,10 +30,6 @@ POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifdef TORRENT_DISK_STATS
#include <fstream>
#endif
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
@ -54,7 +50,6 @@ namespace libtorrent
, buffer_size(0) , buffer_size(0)
, piece(0) , piece(0)
, offset(0) , offset(0)
, priority(0)
{} {}
enum action_t enum action_t
@ -77,12 +72,6 @@ namespace libtorrent
// to the error message // to the error message
std::string str; std::string str;
// priority decides whether or not this
// job will skip entries in the queue or
// not. It always skips in front of entries
// with lower priority
int priority;
// this is called when operation completes // this is called when operation completes
boost::function<void(int, disk_io_job const&)> callback; boost::function<void(int, disk_io_job const&)> callback;
}; };
@ -126,10 +115,6 @@ namespace libtorrent
int m_block_size; int m_block_size;
#endif #endif
#ifdef TORRENT_DISK_STATS
std::ofstream m_log;
#endif
// thread for performing blocking disk io operations // thread for performing blocking disk io operations
boost::thread m_disk_io_thread; boost::thread m_disk_io_thread;
}; };

View file

@ -64,10 +64,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include <list> #include <list>
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include <cassert>
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {

View file

@ -1,44 +0,0 @@
/*
Copyright (c) 2007, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_ENUM_NET_HPP_INCLUDED
#define TORRENT_ENUM_NET_HPP_INCLUDED
#include "libtorrent/socket.hpp"
namespace libtorrent
{
std::vector<address> const& enum_net_interfaces(asio::io_service& ios, asio::error_code& ec);
}
#endif

View file

@ -131,15 +131,6 @@ namespace libtorrent
virtual bool on_bitfield(std::vector<bool> const& bitfield) virtual bool on_bitfield(std::vector<bool> const& bitfield)
{ return false; } { return false; }
virtual bool on_have_all()
{ return false; }
virtual bool on_have_none()
{ return false; }
virtual bool on_allowed_fast(int index)
{ return false; }
virtual bool on_request(peer_request const& req) virtual bool on_request(peer_request const& req)
{ return false; } { return false; }
@ -149,12 +140,6 @@ namespace libtorrent
virtual bool on_cancel(peer_request const& req) virtual bool on_cancel(peer_request const& req)
{ return false; } { return false; }
virtual bool on_reject(peer_request const& req)
{ return false; }
virtual bool on_suggest(int index)
{ return false; }
// called when an extended message is received. If returning true, // called when an extended message is received. If returning true,
// the message is not processed by any other plugin and if false // the message is not processed by any other plugin and if false
// is returned the next plugin in the chain will receive it to // is returned the next plugin in the chain will receive it to

View file

@ -48,7 +48,7 @@ namespace libtorrent
{ {
struct torrent_plugin; struct torrent_plugin;
class torrent; class torrent;
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent*, void*); TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent*);
} }
#endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED #endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED

View file

@ -48,7 +48,7 @@ namespace libtorrent
{ {
struct torrent_plugin; struct torrent_plugin;
class torrent; class torrent;
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent*, void*); TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent*);
} }
#endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED #endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED

View file

@ -37,7 +37,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sstream> #include <sstream>
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -92,4 +91,3 @@ namespace libtorrent
} }
#endif // TORRENT_FINGERPRINT_HPP_INCLUDED #endif // TORRENT_FINGERPRINT_HPP_INCLUDED

View file

@ -33,11 +33,11 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_HASHER_HPP_INCLUDED #ifndef TORRENT_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED #define TORRENT_HASHER_HPP_INCLUDED
#include <cassert>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include "zlib.h" #include "zlib.h"
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL

View file

@ -44,18 +44,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/http_tracker_connection.hpp" #include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
struct http_connection;
typedef boost::function<void(asio::error_code const& typedef boost::function<void(asio::error_code const&
, http_parser const&, char const* data, int size)> http_handler; , http_parser const&, char const* data, int size)> http_handler;
typedef boost::function<void(http_connection&)> http_connect_handler;
// TODO: add bind interface // TODO: add bind interface
// when bottled, the last two arguments to the handler // when bottled, the last two arguments to the handler
@ -63,13 +58,11 @@ typedef boost::function<void(http_connection&)> http_connect_handler;
struct http_connection : boost::enable_shared_from_this<http_connection>, boost::noncopyable struct http_connection : boost::enable_shared_from_this<http_connection>, boost::noncopyable
{ {
http_connection(asio::io_service& ios, connection_queue& cc http_connection(asio::io_service& ios, connection_queue& cc
, http_handler const& handler, bool bottled = true , http_handler handler, bool bottled = true)
, http_connect_handler const& ch = http_connect_handler())
: m_sock(ios) : m_sock(ios)
, m_read_pos(0) , m_read_pos(0)
, m_resolver(ios) , m_resolver(ios)
, m_handler(handler) , m_handler(handler)
, m_connect_handler(ch)
, m_timer(ios) , m_timer(ios)
, m_last_receive(time_now()) , m_last_receive(time_now())
, m_bottled(bottled) , m_bottled(bottled)
@ -99,8 +92,6 @@ struct http_connection : boost::enable_shared_from_this<http_connection>, boost:
, time_duration timeout, bool handle_redirect = true); , time_duration timeout, bool handle_redirect = true);
void close(); void close();
tcp::socket const& socket() const { return m_sock; }
private: private:
void on_resolve(asio::error_code const& e void on_resolve(asio::error_code const& e
@ -121,7 +112,6 @@ private:
tcp::resolver m_resolver; tcp::resolver m_resolver;
http_parser m_parser; http_parser m_parser;
http_handler m_handler; http_handler m_handler;
http_connect_handler m_connect_handler;
deadline_timer m_timer; deadline_timer m_timer;
time_duration m_timeout; time_duration m_timeout;
ptime m_last_receive; ptime m_last_receive;

View file

@ -73,8 +73,6 @@ namespace libtorrent
T header(char const* key) const; T header(char const* key) const;
std::string const& protocol() const { return m_protocol; } std::string const& protocol() const { return m_protocol; }
int status_code() const { return m_status_code; } int status_code() const { return m_status_code; }
std::string const& method() const { return m_method; }
std::string const& path() const { return m_path; }
std::string message() const { return m_server_message; } std::string message() const { return m_server_message; }
buffer::const_interval get_body() const; buffer::const_interval get_body() const;
bool header_finished() const { return m_state == read_body; } bool header_finished() const { return m_state == read_body; }
@ -87,8 +85,6 @@ namespace libtorrent
private: private:
int m_recv_pos; int m_recv_pos;
int m_status_code; int m_status_code;
std::string m_method;
std::string m_path;
std::string m_protocol; std::string m_protocol;
std::string m_server_message; std::string m_server_message;

View file

@ -34,17 +34,14 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_INTRUSIVE_PTR_BASE #define TORRENT_INTRUSIVE_PTR_BASE
#include <boost/detail/atomic_count.hpp> #include <boost/detail/atomic_count.hpp>
#include <cassert>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
template<class T> template<class T>
struct intrusive_ptr_base struct intrusive_ptr_base
{ {
intrusive_ptr_base(intrusive_ptr_base<T> const&)
: m_refs(0) {}
friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s) friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s)
{ {
assert(s->m_refs >= 0); assert(s->m_refs >= 0);

View file

@ -5,7 +5,7 @@
#ifndef TORRENT_INVARIANT_ACCESS_HPP_INCLUDED #ifndef TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
#define TORRENT_INVARIANT_ACCESS_HPP_INCLUDED #define TORRENT_INVARIANT_ACCESS_HPP_INCLUDED
#include "libtorrent/assert.hpp" #include <cassert>
namespace libtorrent namespace libtorrent
{ {

View file

@ -33,9 +33,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_IP_FILTER_HPP #ifndef TORRENT_IP_FILTER_HPP
#define TORRENT_IP_FILTER_HPP #define TORRENT_IP_FILTER_HPP
#include <set>
#include <iostream>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
@ -51,7 +48,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/assert.hpp" #include <set>
#include <iostream>
namespace libtorrent namespace libtorrent
{ {

View file

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define NODE_HPP #define NODE_HPP
#include <algorithm> #include <algorithm>
#include <cassert>
#include <map> #include <map>
#include <set> #include <set>
@ -44,7 +45,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/io.hpp> #include <libtorrent/io.hpp>
#include <libtorrent/session_settings.hpp> #include <libtorrent/session_settings.hpp>
#include <libtorrent/assert.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>

View file

@ -33,10 +33,10 @@ POSSIBILITY OF SUCH DAMAGE.
#define NODE_ID_HPP #define NODE_ID_HPP
#include <algorithm> #include <algorithm>
#include <cassert>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {

View file

@ -50,7 +50,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <libtorrent/kademlia/node_entry.hpp> #include <libtorrent/kademlia/node_entry.hpp>
#include <libtorrent/session_settings.hpp> #include <libtorrent/session_settings.hpp>
#include <libtorrent/size_type.hpp> #include <libtorrent/size_type.hpp>
#include <libtorrent/assert.hpp>
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {

View file

@ -35,7 +35,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
@ -59,26 +58,35 @@ public:
, peer_callback_t const& cb); , peer_callback_t const& cb);
~lsd(); ~lsd();
// void rebind(address const& listen_interface); void rebind(address const& listen_interface);
void announce(sha1_hash const& ih, int listen_port); void announce(sha1_hash const& ih, int listen_port);
void close(); void close();
private: private:
static address_v4 lsd_multicast_address;
static udp::endpoint lsd_multicast_endpoint;
void resend_announce(asio::error_code const& e, std::string msg); void resend_announce(asio::error_code const& e, std::string msg);
void on_announce(udp::endpoint const& from, char* buffer void on_announce(asio::error_code const& e
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
// void setup_receive(); void setup_receive();
peer_callback_t m_callback; peer_callback_t m_callback;
// current retry count // current retry count
int m_retry_count; int m_retry_count;
// used to receive responses in
char m_receive_buffer[1024];
// the endpoint we received the message from
udp::endpoint m_remote;
// the udp socket used to send and receive // the udp socket used to send and receive
// multicast messages on // multicast messages on
broadcast_socket m_socket; datagram_socket m_socket;
// used to resend udp packets in case // used to resend udp packets in case
// they time out // they time out

View file

@ -35,12 +35,13 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED #ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
#define TORRENT_PE_CRYPTO_HPP_INCLUDED #define TORRENT_PE_CRYPTO_HPP_INCLUDED
#include <cassert>
#include <openssl/dh.h> #include <openssl/dh.h>
#include <openssl/engine.h> #include <openssl/engine.h>
#include <openssl/rc4.h> #include <openssl/rc4.h>
#include "libtorrent/peer_id.hpp" // For sha1_hash #include "peer_id.hpp" // For sha1_hash
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {

View file

@ -64,6 +64,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp" #include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp" #include "libtorrent/torrent.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/peer_request.hpp" #include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp" #include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
@ -72,7 +73,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/policy.hpp" #include "libtorrent/policy.hpp"
#include "libtorrent/socket_type.hpp" #include "libtorrent/socket_type.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -131,8 +131,6 @@ namespace libtorrent
enum peer_speed_t { slow, medium, fast }; enum peer_speed_t { slow, medium, fast };
peer_speed_t peer_speed(); peer_speed_t peer_speed();
void send_allowed_set();
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::shared_ptr<peer_plugin>); void add_extension(boost::shared_ptr<peer_plugin>);
#endif #endif
@ -153,17 +151,11 @@ namespace libtorrent
int upload_limit() const { return m_upload_limit; } int upload_limit() const { return m_upload_limit; }
int download_limit() const { return m_download_limit; } int download_limit() const { return m_download_limit; }
int prefer_whole_pieces() const bool prefer_whole_pieces() const
{ { return m_prefer_whole_pieces; }
if (on_parole()) return 1;
return m_prefer_whole_pieces;
}
bool on_parole() const void prefer_whole_pieces(bool b)
{ return peer_info_struct() && peer_info_struct()->on_parole; } { m_prefer_whole_pieces = b; }
void prefer_whole_pieces(int num)
{ m_prefer_whole_pieces = num; }
bool request_large_blocks() const bool request_large_blocks() const
{ return m_request_large_blocks; } { return m_request_large_blocks; }
@ -194,9 +186,9 @@ namespace libtorrent
void set_pid(const peer_id& pid) { m_peer_id = pid; } void set_pid(const peer_id& pid) { m_peer_id = pid; }
bool has_piece(int i) const; bool has_piece(int i) const;
std::deque<piece_block> const& download_queue() const; const std::deque<piece_block>& download_queue() const;
std::deque<piece_block> const& request_queue() const; const std::deque<piece_block>& request_queue() const;
std::deque<peer_request> const& upload_queue() const; const std::deque<peer_request>& upload_queue() const;
bool is_interesting() const { return m_interesting; } bool is_interesting() const { return m_interesting; }
bool is_choked() const { return m_choked; } bool is_choked() const { return m_choked; }
@ -219,14 +211,12 @@ namespace libtorrent
void add_stat(size_type downloaded, size_type uploaded); void add_stat(size_type downloaded, size_type uploaded);
// is called once every second by the main loop // is called once every second by the main loop
void second_tick(float tick_interval) throw(); void second_tick(float tick_interval);
boost::shared_ptr<socket_type> get_socket() const { return m_socket; } boost::shared_ptr<socket_type> get_socket() const { return m_socket; }
tcp::endpoint const& remote() const { return m_remote; } tcp::endpoint const& remote() const { return m_remote; }
std::vector<bool> const& get_bitfield() const; std::vector<bool> const& get_bitfield() const;
std::vector<int> const& allowed_fast();
std::vector<int> const& suggested_pieces() const { return m_suggested_pieces; }
void timed_out(); void timed_out();
// this will cause this peer_connection to be disconnected. // this will cause this peer_connection to be disconnected.
@ -304,14 +294,7 @@ namespace libtorrent
void incoming_piece(peer_request const& p, char const* data); void incoming_piece(peer_request const& p, char const* data);
void incoming_piece_fragment(); void incoming_piece_fragment();
void incoming_cancel(peer_request const& r); void incoming_cancel(peer_request const& r);
void incoming_dht_port(int listen_port); void incoming_dht_port(int listen_port);
void incoming_reject_request(peer_request const& r);
void incoming_have_all();
void incoming_have_none();
void incoming_allowed_fast(int index);
void incoming_suggest(int index);
// the following functions appends messages // the following functions appends messages
// to the send buffer // to the send buffer
@ -390,9 +373,6 @@ namespace libtorrent
virtual void write_keepalive() = 0; virtual void write_keepalive() = 0;
virtual void write_piece(peer_request const& r, char const* buffer) = 0; virtual void write_piece(peer_request const& r, char const* buffer) = 0;
virtual void write_reject_request(peer_request const& r) = 0;
virtual void write_allow_fast(int piece) = 0;
virtual void on_connected() = 0; virtual void on_connected() = 0;
virtual void on_tick() {} virtual void on_tick() {}
@ -502,11 +482,6 @@ namespace libtorrent
// the time we sent a request to // the time we sent a request to
// this peer the last time // this peer the last time
ptime m_last_request; ptime m_last_request;
// the time we received the last
// piece request from the peer
ptime m_last_incoming_request;
// the time when we unchoked this peer
ptime m_last_unchoke;
int m_packet_size; int m_packet_size;
int m_recv_pos; int m_recv_pos;
@ -554,7 +529,7 @@ namespace libtorrent
// set to the torrent it belongs to. // set to the torrent it belongs to.
boost::weak_ptr<torrent> m_torrent; boost::weak_ptr<torrent> m_torrent;
// is true if it was we that connected to the peer // is true if it was we that connected to the peer
// and false if we got an incoming connection // and false if we got an incomming connection
// could be considered: true = local, false = remote // could be considered: true = local, false = remote
bool m_active; bool m_active;
@ -588,10 +563,6 @@ namespace libtorrent
// the pieces the other end have // the pieces the other end have
std::vector<bool> m_have_piece; std::vector<bool> m_have_piece;
// this is set to true when a have_all
// message is received. This information
// is used to fill the bitmask in init()
bool m_have_all;
// the number of pieces this peer // the number of pieces this peer
// has. Must be the same as // has. Must be the same as
@ -604,7 +575,7 @@ namespace libtorrent
std::deque<peer_request> m_requests; std::deque<peer_request> m_requests;
// the blocks we have reserved in the piece // the blocks we have reserved in the piece
// picker and will request from this peer. // picker and will send to this peer.
std::deque<piece_block> m_request_queue; std::deque<piece_block> m_request_queue;
// the queue of blocks we have requested // the queue of blocks we have requested
@ -672,13 +643,12 @@ namespace libtorrent
bool m_writing; bool m_writing;
bool m_reading; bool m_reading;
// if set to non-zero, this peer will always prefer // if set to true, this peer will always prefer
// to request entire n pieces, rather than blocks. // to request entire pieces, rather than blocks.
// where n is the value of this variable. // if it is false, the download rate limit setting
// if it is 0, the download rate limit setting
// will be used to determine if whole pieces // will be used to determine if whole pieces
// are preferred. // are preferred.
int m_prefer_whole_pieces; bool m_prefer_whole_pieces;
// if this is true, the blocks picked by the piece // if this is true, the blocks picked by the piece
// picker will be merged before passed to the // picker will be merged before passed to the
@ -725,18 +695,6 @@ namespace libtorrent
// was last updated // was last updated
ptime m_remote_dl_update; ptime m_remote_dl_update;
// the pieces we will send to the peer
// if requested (regardless of choke state)
std::set<int> m_accept_fast;
// the pieces the peer will send us if
// requested (regardless of choke state)
std::vector<int> m_allowed_fast;
// pieces that has been suggested to be
// downloaded from this peer
std::vector<int> m_suggested_pieces;
// the number of bytes send to the disk-io // the number of bytes send to the disk-io
// thread that hasn't yet been completely written. // thread that hasn't yet been completely written.
int m_outstanding_writing_bytes; int m_outstanding_writing_bytes;

View file

@ -35,12 +35,12 @@ POSSIBILITY OF SUCH DAMAGE.
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <cassert>
#include <cctype> #include <cctype>
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {

View file

@ -56,11 +56,10 @@ namespace libtorrent
connecting = 0x80, connecting = 0x80,
queued = 0x100, queued = 0x100,
on_parole = 0x200, on_parole = 0x200,
seed = 0x400, seed = 0x400
optimistic_unchoke = 0x800
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
, rc4_encrypted = 0x100000, , rc4_encrypted = 0x800,
plaintext_encrypted = 0x200000 plaintext_encrypted = 0x1000
#endif #endif
}; };
@ -72,8 +71,7 @@ namespace libtorrent
dht = 0x2, dht = 0x2,
pex = 0x4, pex = 0x4,
lsd = 0x8, lsd = 0x8,
resume_data = 0x10, resume_data = 0x10
incoming = 0x20
}; };
int source; int source;
@ -118,11 +116,6 @@ namespace libtorrent
// for yet // for yet
int download_queue_length; int download_queue_length;
// the number of requests that is
// tried to be maintained (this is
// typically a function of download speed)
int target_dl_queue_length;
// this is the number of requests // this is the number of requests
// the peer has sent to us // the peer has sent to us
// that we haven't sent yet // that we haven't sent yet

View file

@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <bitset> #include <bitset>
#include <cassert>
#include <utility> #include <utility>
#ifdef _MSC_VER #ifdef _MSC_VER
@ -51,7 +52,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/session_settings.hpp" #include "libtorrent/session_settings.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -191,33 +191,11 @@ namespace libtorrent
// THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION! // THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION!
// The last argument is the policy::peer pointer for the peer that // The last argument is the policy::peer pointer for the peer that
// we'll download from. // we'll download from.
void pick_pieces(std::vector<bool> const& pieces void pick_pieces(const std::vector<bool>& pieces
, std::vector<piece_block>& interesting_blocks , std::vector<piece_block>& interesting_blocks
, int num_pieces, int prefer_whole_pieces , int num_pieces, bool prefer_whole_pieces
, void* peer, piece_state_t speed , void* peer, piece_state_t speed
, bool rarest_first, bool on_parole , bool rarest_first) const;
, std::vector<int> const& suggested_pieces) const;
// picks blocks from each of the pieces in the piece_list
// vector that is also in the piece bitmask. The blocks
// are added to interesting_blocks, and busy blocks are
// added to backup_blocks. num blocks is the number of
// blocks to be picked. Blocks are not picked from pieces
// that are being downloaded
int add_blocks(std::vector<int> const& piece_list
, const std::vector<bool>& pieces
, std::vector<piece_block>& interesting_blocks
, int num_blocks, int prefer_whole_pieces
, void* peer, std::vector<int> const& ignore) const;
// picks blocks only from downloading pieces
int add_blocks_downloading(
std::vector<bool> const& pieces
, std::vector<piece_block>& interesting_blocks
, std::vector<piece_block>& backup_blocks
, int num_blocks, int prefer_whole_pieces
, void* peer, piece_state_t speed
, bool on_parole) const;
// clears the peer pointer in all downloading pieces with this // clears the peer pointer in all downloading pieces with this
// peer pointer // peer pointer
@ -233,7 +211,7 @@ namespace libtorrent
bool is_finished(piece_block block) const; bool is_finished(piece_block block) const;
// marks this piece-block as queued for downloading // marks this piece-block as queued for downloading
bool mark_as_downloading(piece_block block, void* peer void mark_as_downloading(piece_block block, void* peer
, piece_state_t s); , piece_state_t s);
void mark_as_writing(piece_block block, void* peer); void mark_as_writing(piece_block block, void* peer);
void mark_as_finished(piece_block block, void* peer); void mark_as_finished(piece_block block, void* peer);
@ -275,8 +253,6 @@ namespace libtorrent
#ifndef NDEBUG #ifndef NDEBUG
// used in debug mode // used in debug mode
void check_invariant(const torrent* t = 0) const; void check_invariant(const torrent* t = 0) const;
void verify_pick(std::vector<piece_block> const& picked
, std::vector<bool> const& bitfield) const;
#endif #endif
// functor that compares indices on downloading_pieces // functor that compares indices on downloading_pieces
@ -295,10 +271,6 @@ namespace libtorrent
private: private:
bool can_pick(int piece, std::vector<bool> const& bitmask) const;
std::pair<int, int> expand_piece(int piece, int whole_pieces
, std::vector<bool> const& have) const;
struct piece_pos struct piece_pos
{ {
piece_pos() {} piece_pos() {}
@ -348,9 +320,9 @@ namespace libtorrent
int priority(int limit) const int priority(int limit) const
{ {
if (downloading || filtered() || have()) return 0; if (filtered() || have()) return 0;
// pieces we are currently downloading have high priority // pieces we are currently downloading have high priority
int prio = peer_count * 2; int prio = downloading ? (std::min)(1, int(peer_count)) : peer_count * 2;
// if the peer_count is 0 or 1, the priority cannot be higher // if the peer_count is 0 or 1, the priority cannot be higher
if (prio <= 1) return prio; if (prio <= 1) return prio;
if (prio >= limit * 2) prio = limit * 2; if (prio >= limit * 2) prio = limit * 2;
@ -386,6 +358,14 @@ namespace libtorrent
void move(int vec_index, int elem_index); void move(int vec_index, int elem_index);
void sort_piece(std::vector<downloading_piece>::iterator dp); void sort_piece(std::vector<downloading_piece>::iterator dp);
int add_interesting_blocks(const std::vector<int>& piece_list
, const std::vector<bool>& pieces
, std::vector<piece_block>& interesting_blocks
, std::vector<piece_block>& backup_blocks
, int num_blocks, bool prefer_whole_pieces
, void* peer, piece_state_t speed
, bool ignore_downloading_pieces) const;
downloading_piece& add_download_piece(); downloading_piece& add_download_piece();
void erase_download_piece(std::vector<downloading_piece>::iterator i); void erase_download_piece(std::vector<downloading_piece>::iterator i);

View file

@ -89,7 +89,7 @@ namespace libtorrent
void new_connection(peer_connection& c); void new_connection(peer_connection& c);
// the given connection was just closed // the given connection was just closed
void connection_closed(const peer_connection& c) throw(); void connection_closed(const peer_connection& c);
// the peer has got at least one interesting piece // the peer has got at least one interesting piece
void peer_is_interesting(peer_connection& c); void peer_is_interesting(peer_connection& c);
@ -155,13 +155,6 @@ namespace libtorrent
// this is true if the peer is a seed // this is true if the peer is a seed
bool seed; bool seed;
// true if this peer currently is unchoked
// because of an optimistic unchoke.
// when the optimistic unchoke is moved to
// another peer, this peer will be choked
// if this is true
bool optimistically_unchoked;
// the time when this peer was optimistically unchoked // the time when this peer was optimistically unchoked
// the last time. // the last time.
libtorrent::ptime last_optimistically_unchoked; libtorrent::ptime last_optimistically_unchoked;
@ -210,18 +203,25 @@ namespace libtorrent
peer_connection* connection; peer_connection* connection;
}; };
int num_peers() const { return m_peers.size(); } int num_peers() const
{
return m_peers.size();
}
int num_uploads() const
{
return m_num_unchoked;
}
typedef std::list<peer>::iterator iterator; typedef std::list<peer>::iterator iterator;
typedef std::list<peer>::const_iterator const_iterator; typedef std::list<peer>::const_iterator const_iterator;
iterator begin_peer() { return m_peers.begin(); } iterator begin_peer() { return m_peers.begin(); }
iterator end_peer() { return m_peers.end(); } iterator end_peer() { return m_peers.end(); }
bool connect_one_peer(); bool connect_one_peer();
bool disconnect_one_peer();
private: private:
/*
bool unchoke_one_peer(); bool unchoke_one_peer();
void choke_one_peer(); void choke_one_peer();
iterator find_choke_candidate(); iterator find_choke_candidate();
@ -233,7 +233,8 @@ namespace libtorrent
void seed_choke_one_peer(); void seed_choke_one_peer();
iterator find_seed_choke_candidate(); iterator find_seed_choke_candidate();
iterator find_seed_unchoke_candidate(); iterator find_seed_unchoke_candidate();
*/
bool disconnect_one_peer();
iterator find_disconnect_candidate(); iterator find_disconnect_candidate();
iterator find_connect_candidate(); iterator find_connect_candidate();
@ -241,6 +242,10 @@ namespace libtorrent
torrent* m_torrent; torrent* m_torrent;
// the number of unchoked peers
// at any given time
int m_num_unchoked;
// free download we have got that hasn't // free download we have got that hasn't
// been distributed yet. // been distributed yet.
size_type m_available_free_upload; size_type m_available_free_upload;
@ -248,7 +253,7 @@ namespace libtorrent
// if there is a connection limit, // if there is a connection limit,
// we disconnect one peer every minute in hope of // we disconnect one peer every minute in hope of
// establishing a connection with a better peer // establishing a connection with a better peer
// ptime m_last_optimistic_disconnect; ptime m_last_optimistic_disconnect;
}; };
} }

View file

@ -53,7 +53,6 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp" #include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
@ -61,6 +60,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/version.hpp" #include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp" #include "libtorrent/fingerprint.hpp"
#include "libtorrent/resource_request.hpp"
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#ifdef _MSC_VER #ifdef _MSC_VER
@ -141,17 +141,22 @@ namespace libtorrent
, fs::path const& save_path , fs::path const& save_path
, entry const& resume_data = entry() , entry const& resume_data = entry()
, bool compact_mode = true , bool compact_mode = true
, bool paused = false , int block_size = 16 * 1024
, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED; , storage_constructor_type sc = default_storage_constructor);
// ==== deprecated, this is for backwards compatibility only
// instead, use one of the other add_torrent overloads
torrent_handle add_torrent( torrent_handle add_torrent(
boost::intrusive_ptr<torrent_info> ti entry const& e
, fs::path const& save_path , fs::path const& save_path
, entry const& resume_data = entry() , entry const& resume_data = entry()
, bool compact_mode = true , bool compact_mode = true
, bool paused = false , int block_size = 16 * 1024
, storage_constructor_type sc = default_storage_constructor , storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED
, void* userdata = 0); {
return add_torrent(torrent_info(e), save_path, resume_data
, compact_mode, block_size, sc);
}
torrent_handle add_torrent( torrent_handle add_torrent(
char const* tracker_url char const* tracker_url
@ -160,9 +165,8 @@ namespace libtorrent
, fs::path const& save_path , fs::path const& save_path
, entry const& resume_data = entry() , entry const& resume_data = entry()
, bool compact_mode = true , bool compact_mode = true
, bool paused = false , int block_size = 16 * 1024
, storage_constructor_type sc = default_storage_constructor , storage_constructor_type sc = default_storage_constructor);
, void* userdata = 0);
session_proxy abort() { return session_proxy(m_impl); } session_proxy abort() { return session_proxy(m_impl); }
@ -183,7 +187,7 @@ namespace libtorrent
#endif #endif
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext); void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
#endif #endif
void set_ip_filter(ip_filter const& f); void set_ip_filter(ip_filter const& f);
@ -239,7 +243,6 @@ namespace libtorrent
int upload_rate_limit() const; int upload_rate_limit() const;
int download_rate_limit() const; int download_rate_limit() const;
int max_half_open_connections() const;
void set_upload_rate_limit(int bytes_per_second); void set_upload_rate_limit(int bytes_per_second);
void set_download_rate_limit(int bytes_per_second); void set_download_rate_limit(int bytes_per_second);
@ -262,6 +265,12 @@ namespace libtorrent
void stop_natpmp(); void stop_natpmp();
void stop_upnp(); void stop_upnp();
// Resource management used for global limits.
resource_request m_ul_bandwidth_quota;
resource_request m_dl_bandwidth_quota;
resource_request m_uploads_quota;
resource_request m_connections_quota;
private: private:
// just a way to initialize boost.filesystem // just a way to initialize boost.filesystem

View file

@ -1,594 +0,0 @@
/*
Copyright (c) 2006, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_SESSION_IMPL_HPP_INCLUDED
#define TORRENT_SESSION_IMPL_HPP_INCLUDED
#include <ctime>
#include <algorithm>
#include <vector>
#include <set>
#include <list>
#include <deque>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/limits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/thread.hpp>
#include <boost/thread/recursive_mutex.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/torrent_info.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/policy.hpp"
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/peer_info.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/debug.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/ip_filter.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/kademlia/dht_tracker.hpp"
#include "libtorrent/session_status.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/bandwidth_manager.hpp"
#include "libtorrent/natpmp.hpp"
#include "libtorrent/upnp.hpp"
#include "libtorrent/lsd.hpp"
#include "libtorrent/socket_type.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/disk_io_thread.hpp"
namespace libtorrent
{
namespace fs = boost::filesystem;
namespace aux
{
struct session_impl;
// this data is shared between the main thread and the
// thread that initialize pieces
struct piece_checker_data
{
piece_checker_data()
: processing(false), progress(0.f), abort(false) {}
boost::shared_ptr<torrent> torrent_ptr;
fs::path save_path;
sha1_hash info_hash;
void parse_resume_data(
const entry& rd
, const torrent_info& info
, std::string& error);
std::vector<int> piece_map;
std::vector<piece_picker::downloading_piece> unfinished_pieces;
std::vector<piece_picker::block_info> block_info;
std::vector<tcp::endpoint> peers;
entry resume_data;
// this is true if this torrent is being processed (checked)
// if it is not being processed, then it can be removed from
// the queue without problems, otherwise the abort flag has
// to be set.
bool processing;
// is filled in by storage::initialize_pieces()
// and represents the progress. It should be a
// value in the range [0, 1]
float progress;
// abort defaults to false and is typically
// filled in by torrent_handle when the user
// aborts the torrent
bool abort;
};
struct checker_impl: boost::noncopyable
{
checker_impl(session_impl& s): m_ses(s), m_abort(false) {}
void operator()();
piece_checker_data* find_torrent(const sha1_hash& info_hash);
void remove_torrent(sha1_hash const& info_hash);
#ifndef NDEBUG
void check_invariant() const;
#endif
// when the files has been checked
// the torrent is added to the session
session_impl& m_ses;
mutable boost::mutex m_mutex;
boost::condition m_cond;
// a list of all torrents that are currently in queue
// or checking their files
std::deque<boost::shared_ptr<piece_checker_data> > m_torrents;
std::deque<boost::shared_ptr<piece_checker_data> > m_processing;
bool m_abort;
};
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
struct tracker_logger;
#endif
// this is the link between the main thread and the
// thread started to run the main downloader loop
struct session_impl: boost::noncopyable
{
#ifndef NDEBUG
friend class ::libtorrent::peer_connection;
#endif
friend struct checker_impl;
friend class invariant_access;
typedef std::map<boost::shared_ptr<socket_type>
, boost::intrusive_ptr<peer_connection> >
connection_map;
typedef std::map<sha1_hash, boost::shared_ptr<torrent> > torrent_map;
session_impl(
std::pair<int, int> listen_port_range
, fingerprint const& cl_fprint
, char const* listen_interface = "0.0.0.0");
~session_impl();
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
#endif
void operator()();
void open_listen_port();
void async_accept();
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
, boost::weak_ptr<socket_acceptor> const& as, asio::error_code const& e);
// must be locked to access the data
// in this struct
typedef boost::recursive_mutex mutex_t;
mutable mutex_t m_mutex;
boost::weak_ptr<torrent> find_torrent(const sha1_hash& info_hash);
peer_id const& get_peer_id() const { return m_peer_id; }
void close_connection(boost::intrusive_ptr<peer_connection> const& p);
void connection_failed(boost::shared_ptr<socket_type> const& s
, tcp::endpoint const& a, char const* message);
void set_settings(session_settings const& s);
session_settings const& settings() const { return m_settings; }
#ifndef TORRENT_DISABLE_DHT
void add_dht_node(std::pair<std::string, int> const& node);
void add_dht_node(udp::endpoint n);
void add_dht_router(std::pair<std::string, int> const& node);
void set_dht_settings(dht_settings const& s);
dht_settings const& get_dht_settings() const { return m_dht_settings; }
void start_dht(entry const& startup_state);
void stop_dht();
entry dht_state() const;
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
void set_pe_settings(pe_settings const& settings);
pe_settings const& get_pe_settings() const { return m_pe_settings; }
#endif
// called when a port mapping is successful, or a router returns
// a failure to map a port
void on_port_mapping(int tcp_port, int udp_port, std::string const& errmsg);
bool is_aborted() const { return m_abort; }
void set_ip_filter(ip_filter const& f);
void set_port_filter(port_filter const& f);
bool listen_on(
std::pair<int, int> const& port_range
, const char* net_interface = 0);
bool is_listening() const;
torrent_handle add_torrent(
torrent_info const& ti
, fs::path const& save_path
, entry const& resume_data
, bool compact_mode
, int block_size
, storage_constructor_type sc);
torrent_handle add_torrent(
char const* tracker_url
, sha1_hash const& info_hash
, char const* name
, fs::path const& save_path
, entry const& resume_data
, bool compact_mode
, int block_size
, storage_constructor_type sc);
void remove_torrent(torrent_handle const& h);
std::vector<torrent_handle> get_torrents();
void set_severity_level(alert::severity_t s);
std::auto_ptr<alert> pop_alert();
int upload_rate_limit() const;
int download_rate_limit() const;
void set_download_rate_limit(int bytes_per_second);
void set_upload_rate_limit(int bytes_per_second);
void set_max_half_open_connections(int limit);
void set_max_connections(int limit);
void set_max_uploads(int limit);
int max_connections() const { return m_max_connections; }
int max_uploads() const { return m_max_uploads; }
int num_uploads() const { return m_num_unchoked; }
int num_connections() const
{ return m_connections.size(); }
void unchoke_peer(peer_connection& c)
{
c.send_unchoke();
++m_num_unchoked;
}
session_status status() const;
void set_peer_id(peer_id const& id);
void set_key(int key);
unsigned short listen_port() const;
void abort();
torrent_handle find_torrent_handle(sha1_hash const& info_hash);
void announce_lsd(sha1_hash const& ih);
void set_peer_proxy(proxy_settings const& s)
{ m_peer_proxy = s; }
void set_web_seed_proxy(proxy_settings const& s)
{ m_web_seed_proxy = s; }
void set_tracker_proxy(proxy_settings const& s)
{ m_tracker_proxy = s; }
proxy_settings const& peer_proxy() const
{ return m_peer_proxy; }
proxy_settings const& web_seed_proxy() const
{ return m_web_seed_proxy; }
proxy_settings const& tracker_proxy() const
{ return m_tracker_proxy; }
#ifndef TORRENT_DISABLE_DHT
void set_dht_proxy(proxy_settings const& s)
{ m_dht_proxy = s; }
proxy_settings const& dht_proxy() const
{ return m_dht_proxy; }
#endif
void start_lsd();
void start_natpmp();
void start_upnp();
void stop_lsd();
void stop_natpmp();
void stop_upnp();
// handles delayed alerts
alert_manager m_alerts;
// private:
void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih);
// this is where all active sockets are stored.
// the selector can sleep while there's no activity on
// them
io_service m_io_service;
asio::strand m_strand;
// the file pool that all storages in this session's
// torrents uses. It sets a limit on the number of
// open files by this session.
// file pool must be destructed after the torrents
// since they will still have references to it
// when they are destructed.
file_pool m_files;
// handles disk io requests asynchronously
disk_io_thread m_disk_thread;
// this is a list of half-open tcp connections
// (only outgoing connections)
// this has to be one of the last
// members to be destructed
connection_queue m_half_open;
// the bandwidth manager is responsible for
// handing out bandwidth to connections that
// asks for it, it can also throttle the
// rate.
bandwidth_manager<peer_connection, torrent> m_download_channel;
bandwidth_manager<peer_connection, torrent> m_upload_channel;
bandwidth_manager<peer_connection, torrent>* m_bandwidth_manager[2];
tracker_manager m_tracker_manager;
torrent_map m_torrents;
// this maps sockets to their peer_connection
// object. It is the complete list of all connected
// peers.
connection_map m_connections;
// filters incoming connections
ip_filter m_ip_filter;
// filters outgoing connections
port_filter m_port_filter;
// the peer id that is generated at the start of the session
peer_id m_peer_id;
// the key is an id that is used to identify the
// client with the tracker only. It is randomized
// at startup
int m_key;
// the range of ports we try to listen on
std::pair<int, int> m_listen_port_range;
// the ip-address of the interface
// we are supposed to listen on.
// if the ip is set to zero, it means
// that we should let the os decide which
// interface to listen on
tcp::endpoint m_listen_interface;
// this is typically set to the same as the local
// listen port. In case a NAT port forward was
// successfully opened, this will be set to the
// port that is open on the external (NAT) interface
// on the NAT box itself. This is the port that has
// to be published to peers, since this is the port
// the client is reachable through.
int m_external_listen_port;
boost::shared_ptr<socket_acceptor> m_listen_socket;
// the settings for the client
session_settings m_settings;
// the proxy settings for different
// kinds of connections
proxy_settings m_peer_proxy;
proxy_settings m_web_seed_proxy;
proxy_settings m_tracker_proxy;
#ifndef TORRENT_DISABLE_DHT
proxy_settings m_dht_proxy;
#endif
// set to true when the session object
// is being destructed and the thread
// should exit
volatile bool m_abort;
int m_max_uploads;
int m_max_connections;
// the number of unchoked peers
int m_num_unchoked;
// this is initialized to the unchoke_interval
// session_setting and decreased every second.
// when it reaches zero, it is reset to the
// unchoke_interval and the unchoke set is
// recomputed.
int m_unchoke_time_scaler;
// works like unchoke_time_scaler but it
// is only decresed when the unchoke set
// is recomputed, and when it reaches zero,
// the optimistic unchoke is moved to another peer.
int m_optimistic_unchoke_time_scaler;
// works like unchoke_time_scaler. Each time
// it reaches 0, and all the connections are
// used, the worst connection will be disconnected
// from the torrent with the most peers
int m_disconnect_time_scaler;
// statistics gathered from all torrents.
stat m_stat;
// is false by default and set to true when
// the first incoming connection is established
// this is used to know if the client is behind
// NAT or not.
bool m_incoming_connection;
void second_tick(asio::error_code const& e);
ptime m_last_tick;
#ifndef TORRENT_DISABLE_DHT
boost::intrusive_ptr<dht::dht_tracker> m_dht;
dht_settings m_dht_settings;
// if this is set to true, the dht listen port
// will be set to the same as the tcp listen port
// and will be synchronlized with it as it changes
// it defaults to true
bool m_dht_same_port;
// see m_external_listen_port. This is the same
// but for the udp port used by the DHT.
int m_external_udp_port;
#endif
#ifndef TORRENT_DISABLE_ENCRYPTION
pe_settings m_pe_settings;
#endif
boost::shared_ptr<natpmp> m_natpmp;
boost::shared_ptr<upnp> m_upnp;
boost::shared_ptr<lsd> m_lsd;
// the timer used to fire the second_tick
deadline_timer m_timer;
// the index of the torrent that will be offered to
// connect to a peer next time second_tick is called.
// This implements a round robin.
int m_next_connect_torrent;
#ifndef NDEBUG
void check_invariant(const char *place = 0);
#endif
#ifdef TORRENT_STATS
// logger used to write bandwidth usage statistics
std::ofstream m_stats_logger;
int m_second_counter;
#endif
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
boost::shared_ptr<logger> create_log(std::string const& name
, int instance, bool append = true);
// this list of tracker loggers serves as tracker_callbacks when
// shutting down. This list is just here to keep them alive during
// whe shutting down process
std::list<boost::shared_ptr<tracker_logger> > m_tracker_loggers;
public:
boost::shared_ptr<logger> m_logger;
private:
#endif
#ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::function<boost::shared_ptr<
torrent_plugin>(torrent*)> > extension_list_t;
extension_list_t m_extensions;
#endif
// data shared between the main thread
// and the checker thread
checker_impl m_checker_impl;
// the main working thread
boost::scoped_ptr<boost::thread> m_thread;
// the thread that calls initialize_pieces()
// on all torrents before they start downloading
boost::scoped_ptr<boost::thread> m_checker_thread;
};
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
struct tracker_logger : request_callback
{
tracker_logger(session_impl& ses): m_ses(ses) {}
void tracker_warning(std::string const& str)
{
debug_log("*** tracker warning: " + str);
}
void tracker_response(tracker_request const&
, std::vector<peer_entry>& peers
, int interval
, int complete
, int incomplete)
{
std::stringstream s;
s << "TRACKER RESPONSE:\n"
"interval: " << interval << "\n"
"peers:\n";
for (std::vector<peer_entry>::const_iterator i = peers.begin();
i != peers.end(); ++i)
{
s << " " << std::setfill(' ') << std::setw(16) << i->ip
<< " " << std::setw(5) << std::dec << i->port << " ";
if (!i->pid.is_all_zeros()) s << " " << i->pid;
s << "\n";
}
debug_log(s.str());
}
void tracker_request_timed_out(
tracker_request const&)
{
debug_log("*** tracker timed out");
}
void tracker_request_error(
tracker_request const&
, int response_code
, const std::string& str)
{
debug_log(std::string("*** tracker error: ")
+ boost::lexical_cast<std::string>(response_code) + ": "
+ str);
}
void debug_log(const std::string& line)
{
(*m_ses.m_logger) << line << "\n";
}
session_impl& m_ses;
};
#endif
}
}
#endif

View file

@ -105,11 +105,9 @@ namespace libtorrent
, send_redundant_have(false) , send_redundant_have(false)
, lazy_bitfields(true) , lazy_bitfields(true)
, inactivity_timeout(600) , inactivity_timeout(600)
, unchoke_interval(15) , unchoke_interval(20)
, optimistic_unchoke_multiplier(4)
, num_want(200) , num_want(200)
, initial_picker_threshold(4) , initial_picker_threshold(4)
, allowed_fast_set_size(10)
, max_outstanding_disk_bytes_per_connection(64 * 1024) , max_outstanding_disk_bytes_per_connection(64 * 1024)
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
, use_dht_as_fallback(true) , use_dht_as_fallback(true)
@ -243,10 +241,6 @@ namespace libtorrent
// the number of seconds between chokes/unchokes // the number of seconds between chokes/unchokes
int unchoke_interval; int unchoke_interval;
// the number of unchoke intervals between
// optimistic unchokes
int optimistic_unchoke_multiplier;
// if this is set, this IP will be reported do the // if this is set, this IP will be reported do the
// tracker in the ip= parameter. // tracker in the ip= parameter.
address announce_ip; address announce_ip;
@ -258,10 +252,6 @@ namespace libtorrent
// random pieces instead of rarest first. // random pieces instead of rarest first.
int initial_picker_threshold; int initial_picker_threshold;
// the number of allowed pieces to send to peers
// that supports the fast extensions
int allowed_fast_set_size;
// the maximum number of bytes a connection may have // the maximum number of bytes a connection may have
// pending in the disk write queue before its download // pending in the disk write queue before its download
// rate is being throttled. This prevents fast downloads // rate is being throttled. This prevents fast downloads

View file

@ -40,7 +40,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/invariant_check.hpp" #include "libtorrent/invariant_check.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {

View file

@ -43,7 +43,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
@ -148,11 +147,10 @@ namespace libtorrent
}; };
typedef storage_interface* (&storage_constructor_type)( typedef storage_interface* (&storage_constructor_type)(
boost::intrusive_ptr<torrent_info const>, fs::path const& torrent_info const&, fs::path const&
, file_pool&); , file_pool&);
TORRENT_EXPORT storage_interface* default_storage_constructor( TORRENT_EXPORT storage_interface* default_storage_constructor(torrent_info const& ti
boost::intrusive_ptr<torrent_info const> ti
, fs::path const& path, file_pool& fp); , fs::path const& path, file_pool& fp);
// returns true if the filesystem the path relies on supports // returns true if the filesystem the path relies on supports
@ -171,7 +169,7 @@ namespace libtorrent
piece_manager( piece_manager(
boost::shared_ptr<void> const& torrent boost::shared_ptr<void> const& torrent
, boost::intrusive_ptr<torrent_info const> ti , torrent_info const& ti
, fs::path const& path , fs::path const& path
, file_pool& fp , file_pool& fp
, disk_io_thread& io , disk_io_thread& io
@ -201,9 +199,7 @@ namespace libtorrent
void async_read( void async_read(
peer_request const& r peer_request const& r
, boost::function<void(int, disk_io_job const&)> const& handler , boost::function<void(int, disk_io_job const&)> const& handler);
, char* buffer = 0
, int priority = 0);
void async_write( void async_write(
peer_request const& r peer_request const& r
@ -231,7 +227,7 @@ namespace libtorrent
{ return m_compact_mode; } { return m_compact_mode; }
#ifndef NDEBUG #ifndef NDEBUG
std::string name() const { return m_info->name(); } std::string name() const { return m_info.name(); }
#endif #endif
private: private:
@ -287,7 +283,7 @@ namespace libtorrent
// a bitmask representing the pieces we have // a bitmask representing the pieces we have
std::vector<bool> m_have_piece; std::vector<bool> m_have_piece;
boost::intrusive_ptr<torrent_info const> m_info; torrent_info const& m_info;
// slots that haven't had any file storage allocated // slots that haven't had any file storage allocated
std::vector<int> m_unallocated_slots; std::vector<int> m_unallocated_slots;
@ -317,6 +313,12 @@ namespace libtorrent
mutable boost::recursive_mutex m_mutex; mutable boost::recursive_mutex m_mutex;
bool m_allocating;
boost::mutex m_allocating_monitor;
boost::condition m_allocating_condition;
// these states are used while checking/allocating the torrent
enum { enum {
// the default initial state // the default initial state
state_none, state_none,
@ -331,11 +333,6 @@ namespace libtorrent
} m_state; } m_state;
int m_current_slot; int m_current_slot;
// this is saved in case we need to instantiate a new
// storage (osed when remapping files)
storage_constructor_type m_storage_constructor;
// temporary buffer used while checking
std::vector<char> m_piece_data; std::vector<char> m_piece_data;
// this maps a piece hash to piece index. It will be // this maps a piece hash to piece index. It will be
@ -343,9 +340,6 @@ namespace libtorrent
// isn't needed) // isn't needed)
std::multimap<sha1_hash, int> m_hash_to_piece; std::multimap<sha1_hash, int> m_hash_to_piece;
// this map contains partial hashes for downloading
// pieces. This is only accessed from within the
// disk-io thread.
std::map<int, partial_hash> m_piece_hasher; std::map<int, partial_hash> m_piece_hasher;
disk_io_thread& m_io_thread; disk_io_thread& m_io_thread;

View file

@ -55,7 +55,6 @@ namespace libtorrent
|| _POSIX_MONOTONIC_CLOCK < 0)) || defined (TORRENT_USE_BOOST_DATE_TIME) || _POSIX_MONOTONIC_CLOCK < 0)) || defined (TORRENT_USE_BOOST_DATE_TIME)
#include <boost/date_time/posix_time/posix_time_types.hpp> #include <boost/date_time/posix_time/posix_time_types.hpp>
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -86,7 +85,6 @@ namespace libtorrent
#include <asio/time_traits.hpp> #include <asio/time_traits.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -172,7 +170,6 @@ namespace asio
#include <mach/mach_time.h> #include <mach/mach_time.h>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"
// high precision timer for darwin intel and ppc // high precision timer for darwin intel and ppc
@ -252,7 +249,6 @@ namespace libtorrent
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <Windows.h> #include <Windows.h>
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -339,7 +335,6 @@ namespace libtorrent
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 #elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
#include <time.h> #include <time.h>
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -390,4 +385,4 @@ namespace libtorrent
#endif #endif
#endif #endif

View file

@ -62,13 +62,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/tracker_manager.hpp" #include "libtorrent/tracker_manager.hpp"
#include "libtorrent/stat.hpp" #include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
#include "libtorrent/resource_request.hpp"
#include "libtorrent/piece_picker.hpp" #include "libtorrent/piece_picker.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/escape_string.hpp" #include "libtorrent/escape_string.hpp"
#include "libtorrent/bandwidth_manager.hpp" #include "libtorrent/bandwidth_manager.hpp"
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp" #include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -98,13 +98,13 @@ namespace libtorrent
torrent( torrent(
aux::session_impl& ses aux::session_impl& ses
, aux::checker_impl& checker , aux::checker_impl& checker
, boost::intrusive_ptr<torrent_info> tf , torrent_info const& tf
, fs::path const& save_path , fs::path const& save_path
, tcp::endpoint const& net_interface , tcp::endpoint const& net_interface
, bool compact_mode , bool compact_mode
, int block_size , int block_size
, storage_constructor_type sc , session_settings const& s
, bool paused); , storage_constructor_type sc);
// used with metadata-less torrents // used with metadata-less torrents
// (the metadata is downloaded from the peers) // (the metadata is downloaded from the peers)
@ -118,8 +118,8 @@ namespace libtorrent
, tcp::endpoint const& net_interface , tcp::endpoint const& net_interface
, bool compact_mode , bool compact_mode
, int block_size , int block_size
, storage_constructor_type sc , session_settings const& s
, bool paused); , storage_constructor_type sc);
~torrent(); ~torrent();
@ -154,6 +154,10 @@ namespace libtorrent
bool verify_resume_data(entry& rd, std::string& error) bool verify_resume_data(entry& rd, std::string& error)
{ assert(m_storage); return m_storage->verify_resume_data(rd, error); } { assert(m_storage); return m_storage->verify_resume_data(rd, error); }
// is called every second by session. This will
// caclulate the upload/download and number
// of connections this torrent needs. And prepare
// it for being used by allocate_resources.
void second_tick(stat& accumulator, float tick_interval); void second_tick(stat& accumulator, float tick_interval);
// debug purpose only // debug purpose only
@ -250,15 +254,6 @@ namespace libtorrent
void remove_url_seed(std::string const& url) void remove_url_seed(std::string const& url)
{ m_web_seeds.erase(url); } { m_web_seeds.erase(url); }
std::set<std::string> url_seeds() const
{ return m_web_seeds; }
bool free_upload_slots() const
{ return m_num_uploads < m_max_uploads; }
void choke_peer(peer_connection& c);
bool unchoke_peer(peer_connection& c);
// used by peer_connection to attach itself to a torrent // used by peer_connection to attach itself to a torrent
// since incoming connections don't know what torrent // since incoming connections don't know what torrent
// they're a part of until they have received an info_hash. // they're a part of until they have received an info_hash.
@ -470,14 +465,14 @@ namespace libtorrent
bool is_seed() const bool is_seed() const
{ {
return valid_metadata() return valid_metadata()
&& m_num_pieces == m_torrent_file->num_pieces(); && m_num_pieces == m_torrent_file.num_pieces();
} }
// this is true if we have all the pieces that we want // this is true if we have all the pieces that we want
bool is_finished() const bool is_finished() const
{ {
if (is_seed()) return true; if (is_seed()) return true;
return valid_metadata() && m_torrent_file->num_pieces() return valid_metadata() && m_torrent_file.num_pieces()
- m_num_pieces - m_picker->num_filtered() == 0; - m_num_pieces - m_picker->num_filtered() == 0;
} }
@ -499,7 +494,7 @@ namespace libtorrent
} }
piece_manager& filesystem(); piece_manager& filesystem();
torrent_info const& torrent_file() const torrent_info const& torrent_file() const
{ return *m_torrent_file; } { return m_torrent_file; }
std::vector<announce_entry> const& trackers() const std::vector<announce_entry> const& trackers() const
{ return m_trackers; } { return m_trackers; }
@ -521,6 +516,11 @@ namespace libtorrent
// -------------------------------------------- // --------------------------------------------
// RESOURCE MANAGEMENT // RESOURCE MANAGEMENT
void distribute_resources(float tick_interval);
resource_request m_uploads_quota;
resource_request m_connections_quota;
void set_peer_upload_limit(tcp::endpoint ip, int limit); void set_peer_upload_limit(tcp::endpoint ip, int limit);
void set_peer_download_limit(tcp::endpoint ip, int limit); void set_peer_download_limit(tcp::endpoint ip, int limit);
@ -530,9 +530,7 @@ namespace libtorrent
int download_limit() const; int download_limit() const;
void set_max_uploads(int limit); void set_max_uploads(int limit);
int max_uploads() const { return m_max_uploads; }
void set_max_connections(int limit); void set_max_connections(int limit);
int max_connections() const { return m_max_connections; }
void move_storage(fs::path const& save_path); void move_storage(fs::path const& save_path);
// unless this returns true, new connections must wait // unless this returns true, new connections must wait
@ -540,7 +538,7 @@ namespace libtorrent
bool ready_for_connections() const bool ready_for_connections() const
{ return m_connections_initialized; } { return m_connections_initialized; }
bool valid_metadata() const bool valid_metadata() const
{ return m_torrent_file->is_valid(); } { return m_torrent_file.is_valid(); }
// parses the info section from the given // parses the info section from the given
// bencoded tree and moves the torrent // bencoded tree and moves the torrent
@ -564,7 +562,7 @@ namespace libtorrent
void update_peer_interest(); void update_peer_interest();
boost::intrusive_ptr<torrent_info> m_torrent_file; torrent_info m_torrent_file;
// is set to true when the torrent has // is set to true when the torrent has
// been aborted. // been aborted.
@ -707,9 +705,9 @@ namespace libtorrent
// determine the timeout until next try. // determine the timeout until next try.
int m_failed_trackers; int m_failed_trackers;
// this is a counter that is decreased every // this is a counter that is increased every
// second, and when it reaches 0, the policy::pulse() // second, and when it reaches 10, the policy::pulse()
// is called and the time scaler is reset to 10. // is called and the time scaler is reset to 0.
int m_time_scaler; int m_time_scaler;
// the bitmask that says which pieces we have // the bitmask that says which pieces we have
@ -776,15 +774,6 @@ namespace libtorrent
session_settings const& m_settings; session_settings const& m_settings;
storage_constructor_type m_storage_constructor; storage_constructor_type m_storage_constructor;
// the maximum number of uploads for this torrent
int m_max_uploads;
// the number of unchoked peers in this torrent
int m_num_uploads;
// the maximum number of connections for this torrent
int m_max_connections;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t; typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;

View file

@ -34,7 +34,6 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED #define TORRENT_TORRENT_HANDLE_HPP_INCLUDED
#include <vector> #include <vector>
#include <set>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
@ -274,9 +273,7 @@ namespace libtorrent
std::vector<announce_entry> const& trackers() const; std::vector<announce_entry> const& trackers() const;
void replace_trackers(std::vector<announce_entry> const&) const; void replace_trackers(std::vector<announce_entry> const&) const;
void add_url_seed(std::string const& url) const; void add_url_seed(std::string const& url);
void remove_url_seed(std::string const& url) const;
std::set<std::string> url_seeds() const;
bool has_metadata() const; bool has_metadata() const;
const torrent_info& get_torrent_info() const; const torrent_info& get_torrent_info() const;
@ -399,7 +396,6 @@ namespace libtorrent
, m_info_hash(h) , m_info_hash(h)
{ {
assert(m_ses != 0); assert(m_ses != 0);
assert(m_chk != 0);
} }
#ifndef NDEBUG #ifndef NDEBUG

View file

@ -57,8 +57,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/peer_request.hpp" #include "libtorrent/peer_request.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -73,7 +71,7 @@ namespace libtorrent
size_type offset; // the offset of this file inside the torrent size_type offset; // the offset of this file inside the torrent
size_type size; // the size of this file size_type size; // the size of this file
// if the path was incorrectly encoded, this is // if the path was incorrectly encoded, this is
// the original corrupt encoded string. It is // the origianal corrupt encoded string. It is
// preserved in order to be able to reproduce // preserved in order to be able to reproduce
// the correct info-hash // the correct info-hash
boost::shared_ptr<const fs::path> orig_path; boost::shared_ptr<const fs::path> orig_path;
@ -98,7 +96,7 @@ namespace libtorrent
virtual const char* what() const throw() { return "invalid torrent file"; } virtual const char* what() const throw() { return "invalid torrent file"; }
}; };
class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torrent_info> class TORRENT_EXPORT torrent_info
{ {
public: public:
@ -117,12 +115,8 @@ namespace libtorrent
void add_file(fs::path file, size_type size); void add_file(fs::path file, size_type size);
void add_url_seed(std::string const& url); void add_url_seed(std::string const& url);
bool remap_files(std::vector<std::pair<std::string, libtorrent::size_type> > const& map); std::vector<file_slice> map_block(int piece, size_type offset, int size) const;
peer_request map_file(int file, size_type offset, int size) const;
std::vector<file_slice> map_block(int piece, size_type offset
, int size, bool storage = false) const;
peer_request map_file(int file, size_type offset, int size
, bool storage = false) const;
std::vector<std::string> const& url_seeds() const std::vector<std::string> const& url_seeds() const
{ {
@ -134,60 +128,15 @@ namespace libtorrent
typedef std::vector<file_entry>::const_reverse_iterator reverse_file_iterator; typedef std::vector<file_entry>::const_reverse_iterator reverse_file_iterator;
// list the files in the torrent file // list the files in the torrent file
file_iterator begin_files(bool storage = false) const file_iterator begin_files() const { return m_files.begin(); }
{ file_iterator end_files() const { return m_files.end(); }
if (!storage || m_remapped_files.empty()) reverse_file_iterator rbegin_files() const { return m_files.rbegin(); }
return m_files.begin(); reverse_file_iterator rend_files() const { return m_files.rend(); }
else
return m_remapped_files.begin();
}
file_iterator end_files(bool storage = false) const int num_files() const
{ { assert(m_piece_length > 0); return (int)m_files.size(); }
if (!storage || m_remapped_files.empty()) const file_entry& file_at(int index) const
return m_files.end(); { assert(index >= 0 && index < (int)m_files.size()); return m_files[index]; }
else
return m_remapped_files.end();
}
reverse_file_iterator rbegin_files(bool storage = false) const
{
if (!storage || m_remapped_files.empty())
return m_files.rbegin();
else
return m_remapped_files.rbegin();
}
reverse_file_iterator rend_files(bool storage = false) const
{
if (!storage || m_remapped_files.empty())
return m_files.rend();
else
return m_remapped_files.rend();
}
int num_files(bool storage = false) const
{
assert(m_piece_length > 0);
if (!storage || m_remapped_files.empty())
return (int)m_files.size();
else
return (int)m_remapped_files.size();
}
const file_entry& file_at(int index, bool storage = false) const
{
if (!storage || m_remapped_files.empty())
{
assert(index >= 0 && index < (int)m_files.size());
return m_files[index];
}
else
{
assert(index >= 0 && index < (int)m_remapped_files.size());
return m_remapped_files[index];
}
}
const std::vector<announce_entry>& trackers() const { return m_urls; } const std::vector<announce_entry>& trackers() const { return m_urls; }
@ -269,13 +218,6 @@ namespace libtorrent
// the list of files that this torrent consists of // the list of files that this torrent consists of
std::vector<file_entry> m_files; std::vector<file_entry> m_files;
// this vector is typically empty. If it is not
// empty, it means the user has re-mapped the
// files in this torrent to diffefrent names
// on disk. This is only used when reading and
// writing the disk.
std::vector<file_entry> m_remapped_files;
nodes_t m_nodes; nodes_t m_nodes;
// the sum of all filesizes // the sum of all filesizes
@ -322,10 +264,8 @@ namespace libtorrent
entry m_extra_info; entry m_extra_info;
#ifndef NDEBUG #ifndef NDEBUG
public:
// this is set to true when seed_free() is called // this is set to true when seed_free() is called
bool m_half_metadata; bool m_half_metadata;
private:
#endif #endif
}; };

View file

@ -194,10 +194,11 @@ namespace libtorrent
, address bind_interface , address bind_interface
, boost::weak_ptr<request_callback> r); , boost::weak_ptr<request_callback> r);
boost::shared_ptr<request_callback> requester(); request_callback& requester();
virtual ~tracker_connection() {} virtual ~tracker_connection() {}
tracker_request const& tracker_req() const { return m_req; } tracker_request const& tracker_req() const { return m_req; }
bool has_requester() const { return !m_requester.expired(); }
void fail(int code, char const* msg); void fail(int code, char const* msg);
void fail_timeout(); void fail_timeout();

View file

@ -34,7 +34,6 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_UPNP_HPP #define TORRENT_UPNP_HPP
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/http_connection.hpp" #include "libtorrent/http_connection.hpp"
#include "libtorrent/connection_queue.hpp" #include "libtorrent/connection_queue.hpp"
@ -57,6 +56,9 @@ POSSIBILITY OF SUCH DAMAGE.
namespace libtorrent namespace libtorrent
{ {
bool is_local(address const& a);
address_v4 guess_local_address(asio::io_service&);
// int: external tcp port // int: external tcp port
// int: external udp port // int: external udp port
// std::string: error message // std::string: error message
@ -70,6 +72,8 @@ public:
, portmap_callback_t const& cb); , portmap_callback_t const& cb);
~upnp(); ~upnp();
void rebind(address const& listen_interface);
// maps the ports, if a port is set to 0 // maps the ports, if a port is set to 0
// it will not be mapped // it will not be mapped
void set_mappings(int tcp, int udp); void set_mappings(int tcp, int udp);
@ -86,7 +90,7 @@ private:
void update_mapping(int i, int port); void update_mapping(int i, int port);
void resend_request(asio::error_code const& e); void resend_request(asio::error_code const& e);
void on_reply(udp::endpoint const& from, char* buffer void on_reply(asio::error_code const& e
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
void discover_device(); void discover_device();
@ -102,15 +106,12 @@ private:
, int mapping); , int mapping);
void on_expire(asio::error_code const& e); void on_expire(asio::error_code const& e);
void post(rootdevice& d, std::stringstream const& s
, std::string const& soap_action);
void map_port(rootdevice& d, int i); void map_port(rootdevice& d, int i);
void unmap_port(rootdevice& d, int i); void unmap_port(rootdevice& d, int i);
void disable(); void disable();
void delete_port_mapping(rootdevice& d, int i);
void create_port_mapping(http_connection& c, rootdevice& d, int i);
void post(upnp::rootdevice const& d, std::string const& soap
, std::string const& soap_action);
struct mapping_t struct mapping_t
{ {
mapping_t() mapping_t()
@ -197,13 +198,18 @@ private:
// current retry count // current retry count
int m_retry_count; int m_retry_count;
asio::io_service& m_io_service; // used to receive responses in
char m_receive_buffer[1024];
asio::strand m_strand; // the endpoint we received the message from
udp::endpoint m_remote;
// the local address we're listening on
address_v4 m_local_ip;
// the udp socket used to send and receive // the udp socket used to send and receive
// multicast messages on the network // multicast messages on the network
broadcast_socket m_socket; datagram_socket m_socket;
// used to resend udp packets in case // used to resend udp packets in case
// they time out // they time out
@ -211,6 +217,8 @@ private:
// timer used to refresh mappings // timer used to refresh mappings
deadline_timer m_refresh_timer; deadline_timer m_refresh_timer;
asio::strand m_strand;
bool m_disabled; bool m_disabled;
bool m_closing; bool m_closing;

View file

@ -65,6 +65,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp" #include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp" #include "libtorrent/torrent.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/peer_request.hpp" #include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp" #include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
@ -125,8 +126,6 @@ namespace libtorrent
void write_piece(peer_request const& r, char const* buffer) { assert(false); } void write_piece(peer_request const& r, char const* buffer) { assert(false); }
void write_keepalive() {} void write_keepalive() {}
void on_connected(); void on_connected();
void write_reject_request(peer_request const&) {}
void write_allow_fast(int) {}
#ifndef NDEBUG #ifndef NDEBUG
void check_invariant() const; void check_invariant() const;

View file

@ -1,73 +0,0 @@
/*
Copyright (c) 2007, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef NDEBUG
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#if defined __linux__ && defined __GNUC__
#include <execinfo.h>
#endif
void assert_fail(char const* expr, int line, char const* file, char const* function)
{
fprintf(stderr, "assertion failed. Please file a bugreport at "
"http://code.rasterbar.com/libtorrent/newticket\n"
"Please include the following information:\n\n"
"file: '%s'\n"
"line: %d\n"
"function: %s\n"
"expression: %s\n"
"stack:\n", file, line, function, expr);
#if defined __linux__ && defined __GNUC__
void* stack[50];
int size = backtrace(stack, 50);
char** symbols = backtrace_symbols(stack, size);
for (int i = 0; i < size; ++i)
{
fprintf(stderr, "%d: %s\n", i, symbols[i]);
}
free(symbols);
#endif
// send SIGINT to the current process
// to break into the debugger
raise(SIGINT);
abort();
}
#endif

View file

@ -1,186 +0,0 @@
/*
Copyright (c) 2007, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include <asio/ip/host_name.hpp>
#include <asio/ip/multicast.hpp>
#include <boost/bind.hpp>
#include "libtorrent/socket.hpp"
#include "libtorrent/enum_net.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
bool is_local(address const& a)
{
if (a.is_v6()) return a.to_v6().is_link_local();
address_v4 a4 = a.to_v4();
unsigned long ip = a4.to_ulong();
return ((ip & 0xff000000) == 0x0a000000
|| (ip & 0xfff00000) == 0xac100000
|| (ip & 0xffff0000) == 0xc0a80000);
}
address_v4 guess_local_address(asio::io_service& ios)
{
// make a best guess of the interface we're using and its IP
udp::resolver r(ios);
udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(), "0"));
for (;i != udp::resolver_iterator(); ++i)
{
address const& a = i->endpoint().address();
// ignore non-IPv4 addresses
if (!a.is_v4()) break;
// ignore the loopback
if (a.to_v4() == address_v4::loopback()) continue;
}
if (i == udp::resolver_iterator()) return address_v4::any();
return i->endpoint().address().to_v4();
}
bool is_loopback(address const& addr)
{
if (addr.is_v4())
return addr.to_v4() == address_v4::loopback();
else
return addr.to_v6() == address_v6::loopback();
}
bool is_multicast(address const& addr)
{
if (addr.is_v4())
return addr.to_v4().is_multicast();
else
return addr.to_v6().is_multicast();
}
broadcast_socket::broadcast_socket(asio::io_service& ios
, udp::endpoint const& multicast_endpoint
, receive_handler_t const& handler
, bool loopback)
: m_multicast_endpoint(multicast_endpoint)
, m_on_receive(handler)
{
assert(is_multicast(m_multicast_endpoint.address()));
using namespace asio::ip::multicast;
asio::error_code ec;
std::vector<address> interfaces = enum_net_interfaces(ios, ec);
for (std::vector<address>::const_iterator i = interfaces.begin()
, end(interfaces.end()); i != end; ++i)
{
// only broadcast to IPv4 addresses that are not local
if (!is_local(*i)) continue;
// only multicast on compatible networks
if (i->is_v4() != multicast_endpoint.address().is_v4()) continue;
// ignore any loopback interface
if (is_loopback(*i)) continue;
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
if (i->is_v4())
{
s->open(udp::v4(), ec);
if (ec) continue;
s->set_option(datagram_socket::reuse_address(true), ec);
if (ec) continue;
s->bind(udp::endpoint(address_v4::any(), multicast_endpoint.port()), ec);
if (ec) continue;
s->set_option(join_group(multicast_endpoint.address()), ec);
if (ec) continue;
s->set_option(outbound_interface(i->to_v4()), ec);
if (ec) continue;
}
else
{
s->open(udp::v6(), ec);
if (ec) continue;
s->set_option(datagram_socket::reuse_address(true), ec);
if (ec) continue;
s->bind(udp::endpoint(address_v6::any(), multicast_endpoint.port()), ec);
if (ec) continue;
s->set_option(join_group(multicast_endpoint.address()), ec);
if (ec) continue;
// s->set_option(outbound_interface(i->to_v6()), ec);
// if (ec) continue;
}
s->set_option(hops(255), ec);
if (ec) continue;
s->set_option(enable_loopback(loopback), ec);
if (ec) continue;
m_sockets.push_back(socket_entry(s));
socket_entry& se = m_sockets.back();
s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
#ifndef NDEBUG
// std::cerr << "broadcast socket [ if: " << i->to_v4().to_string()
// << " group: " << multicast_endpoint.address() << " ]" << std::endl;
#endif
}
}
void broadcast_socket::send(char const* buffer, int size, asio::error_code& ec)
{
for (std::list<socket_entry>::iterator i = m_sockets.begin()
, end(m_sockets.end()); i != end; ++i)
{
asio::error_code e;
i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
#ifndef NDEBUG
// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << std::endl;
#endif
if (e) ec = e;
}
}
void broadcast_socket::on_receive(socket_entry* s, asio::error_code const& ec
, std::size_t bytes_transferred)
{
if (ec || bytes_transferred == 0) return;
m_on_receive(s->remote, s->buffer, bytes_transferred);
s->socket->async_receive_from(asio::buffer(s->buffer, sizeof(s->buffer))
, s->remote, bind(&broadcast_socket::on_receive, this, s, _1, _2));
}
void broadcast_socket::close()
{
for (std::list<socket_entry>::iterator i = m_sockets.begin()
, end(m_sockets.end()); i != end; ++i)
{
i->socket->close();
}
}
}

View file

@ -50,7 +50,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/version.hpp" #include "libtorrent/version.hpp"
#include "libtorrent/extensions.hpp" #include "libtorrent/extensions.hpp"
#include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/aux_/session_impl.hpp"
#include "libtorrent/enum_net.hpp"
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
#include "libtorrent/pe_crypto.hpp" #include "libtorrent/pe_crypto.hpp"
@ -76,14 +75,7 @@ namespace libtorrent
&bt_peer_connection::on_piece, &bt_peer_connection::on_piece,
&bt_peer_connection::on_cancel, &bt_peer_connection::on_cancel,
&bt_peer_connection::on_dht_port, &bt_peer_connection::on_dht_port,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// FAST extension messages
&bt_peer_connection::on_suggest_piece,
&bt_peer_connection::on_have_all,
&bt_peer_connection::on_have_none,
&bt_peer_connection::on_reject_request,
&bt_peer_connection::on_allowed_fast,
0, 0,
&bt_peer_connection::on_extended &bt_peer_connection::on_extended
}; };
@ -101,7 +93,6 @@ namespace libtorrent
, m_supports_extensions(false) , m_supports_extensions(false)
#endif #endif
, m_supports_dht_port(false) , m_supports_dht_port(false)
, m_supports_fast(false)
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
, m_encrypted(false) , m_encrypted(false)
, m_rc4_encrypted(false) , m_rc4_encrypted(false)
@ -133,7 +124,6 @@ namespace libtorrent
, m_supports_extensions(false) , m_supports_extensions(false)
#endif #endif
, m_supports_dht_port(false) , m_supports_dht_port(false)
, m_supports_fast(false)
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
, m_encrypted(false) , m_encrypted(false)
, m_rc4_encrypted(false) , m_rc4_encrypted(false)
@ -236,10 +226,6 @@ namespace libtorrent
boost::shared_ptr<torrent> t = associated_torrent().lock(); boost::shared_ptr<torrent> t = associated_torrent().lock();
assert(t); assert(t);
write_bitfield(t->pieces()); write_bitfield(t->pieces());
#ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port);
#endif
} }
void bt_peer_connection::write_dht_port(int listen_port) void bt_peer_connection::write_dht_port(int listen_port)
@ -260,75 +246,6 @@ namespace libtorrent
setup_send(); setup_send();
} }
void bt_peer_connection::write_have_all()
{
INVARIANT_CHECK;
assert(m_sent_handshake && !m_sent_bitfield);
#ifndef NDEBUG
m_sent_bitfield = true;
#endif
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string()
<< " ==> HAVE_ALL\n";
#endif
char buf[] = {0,0,0,1, msg_have_all};
send_buffer(buf, buf + sizeof(buf));
}
void bt_peer_connection::write_have_none()
{
INVARIANT_CHECK;
assert(m_sent_handshake && !m_sent_bitfield);
#ifndef NDEBUG
m_sent_bitfield = true;
#endif
#ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << time_now_string()
<< " ==> HAVE_NONE\n";
#endif
char buf[] = {0,0,0,1, msg_have_none};
send_buffer(buf, buf + sizeof(buf));
}
void bt_peer_connection::write_reject_request(peer_request const& r)
{
INVARIANT_CHECK;
assert(m_sent_handshake && m_sent_bitfield);
assert(associated_torrent().lock()->valid_metadata());
char buf[] = {0,0,0,13, msg_reject_request};
buffer::interval i = allocate_send_buffer(17);
std::copy(buf, buf + 5, i.begin);
i.begin += 5;
// index
detail::write_int32(r.piece, i.begin);
// begin
detail::write_int32(r.start, i.begin);
// length
detail::write_int32(r.length, i.begin);
assert(i.begin == i.end);
setup_send();
}
void bt_peer_connection::write_allow_fast(int piece)
{
INVARIANT_CHECK;
assert(m_sent_handshake && m_sent_bitfield);
assert(associated_torrent().lock()->valid_metadata());
char buf[] = {0,0,0,5, msg_allowed_fast, 0, 0, 0, 0};
char* ptr = buf + 5;
detail::write_int32(piece, ptr);
send_buffer(buf, buf + sizeof(buf));
}
void bt_peer_connection::get_specific_peer_info(peer_info& p) const void bt_peer_connection::get_specific_peer_info(peer_info& p) const
{ {
assert(!associated_torrent().expired()); assert(!associated_torrent().expired());
@ -711,17 +628,14 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
// indicate that we support the DHT messages // indicate that we support the DHT messages
*(i.begin + 7) |= 0x01; *(i.begin + 7) = 0x01;
#endif #endif
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
// we support extensions // we support extensions
*(i.begin + 5) |= 0x10; *(i.begin + 5) = 0x10;
#endif #endif
// we support FAST extension
*(i.begin + 7) |= 0x04;
i.begin += 8; i.begin += 8;
// info hash // info hash
@ -807,20 +721,6 @@ namespace libtorrent
if (!packet_finished()) return; if (!packet_finished()) return;
incoming_choke(); incoming_choke();
if (!m_supports_fast)
{
boost::shared_ptr<torrent> t = associated_torrent().lock();
assert(t);
while (!request_queue().empty())
{
piece_block const& b = request_queue().front();
peer_request r;
r.piece = b.piece_index;
r.start = b.block_index * t->block_size();
r.length = t->block_size();
incoming_reject_request(r);
}
}
} }
// ----------------------------- // -----------------------------
@ -1039,9 +939,6 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
if (!m_supports_dht_port)
throw protocol_error("got 'dht_port' message from peer that doesn't support it");
assert(received > 0); assert(received > 0);
if (packet_size() != 3) if (packet_size() != 3)
throw protocol_error("'dht_port' message size != 3"); throw protocol_error("'dht_port' message size != 3");
@ -1056,80 +953,6 @@ namespace libtorrent
incoming_dht_port(listen_port); incoming_dht_port(listen_port);
} }
void bt_peer_connection::on_suggest_piece(int received)
{
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'suggest_piece' without FAST extension support");
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
buffer::const_interval recv_buffer = receive_buffer();
const char* ptr = recv_buffer.begin + 1;
int piece = detail::read_uint32(ptr);
incoming_suggest(piece);
}
void bt_peer_connection::on_have_all(int received)
{
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'have_all' without FAST extension support");
m_statistics.received_bytes(0, received);
incoming_have_all();
}
void bt_peer_connection::on_have_none(int received)
{
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'have_none' without FAST extension support");
m_statistics.received_bytes(0, received);
incoming_have_none();
}
void bt_peer_connection::on_reject_request(int received)
{
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'reject_request' without FAST extension support");
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
buffer::const_interval recv_buffer = receive_buffer();
peer_request r;
const char* ptr = recv_buffer.begin + 1;
r.piece = detail::read_int32(ptr);
r.start = detail::read_int32(ptr);
r.length = detail::read_int32(ptr);
incoming_reject_request(r);
}
void bt_peer_connection::on_allowed_fast(int received)
{
INVARIANT_CHECK;
if (!m_supports_fast)
throw protocol_error("got 'allowed_fast' without FAST extension support");
m_statistics.received_bytes(0, received);
if (!packet_finished()) return;
buffer::const_interval recv_buffer = receive_buffer();
const char* ptr = recv_buffer.begin + 1;
int index = detail::read_int32(ptr);
incoming_allowed_fast(index);
}
// ----------------------------- // -----------------------------
// --------- EXTENDED ---------- // --------- EXTENDED ----------
// ----------------------------- // -----------------------------
@ -1222,7 +1045,7 @@ namespace libtorrent
{ {
tcp::endpoint adr(remote().address() tcp::endpoint adr(remote().address()
, (unsigned short)listen_port->integer()); , (unsigned short)listen_port->integer());
t->get_policy().peer_from_tracker(adr, pid(), peer_info::incoming, 0); t->get_policy().peer_from_tracker(adr, pid(), 0, 0);
} }
} }
// there should be a version too // there should be a version too
@ -1352,22 +1175,6 @@ namespace libtorrent
assert(m_sent_handshake && !m_sent_bitfield); assert(m_sent_handshake && !m_sent_bitfield);
assert(t->valid_metadata()); assert(t->valid_metadata());
// in this case, have_all or have_none should be sent instead
assert(!m_supports_fast || !t->is_seed() || t->num_pieces() != 0);
if (m_supports_fast && t->is_seed())
{
write_have_all();
send_allowed_set();
return;
}
else if (m_supports_fast && t->num_pieces() == 0)
{
write_have_none();
send_allowed_set();
return;
}
int num_pieces = bitfield.size(); int num_pieces = bitfield.size();
int lazy_pieces[50]; int lazy_pieces[50];
int num_lazy_pieces = 0; int num_lazy_pieces = 0;
@ -1376,7 +1183,7 @@ namespace libtorrent
assert(t->is_seed() == (std::count(bitfield.begin(), bitfield.end(), true) == num_pieces)); assert(t->is_seed() == (std::count(bitfield.begin(), bitfield.end(), true) == num_pieces));
if (t->is_seed() && m_ses.settings().lazy_bitfields) if (t->is_seed() && m_ses.settings().lazy_bitfields)
{ {
num_lazy_pieces = (std::min)(50, num_pieces / 10); num_lazy_pieces = std::min(50, num_pieces / 10);
if (num_lazy_pieces < 1) num_lazy_pieces = 1; if (num_lazy_pieces < 1) num_lazy_pieces = 1;
for (int i = 0; i < num_pieces; ++i) for (int i = 0; i < num_pieces; ++i)
{ {
@ -1444,9 +1251,6 @@ namespace libtorrent
#endif #endif
} }
} }
if (m_supports_fast)
send_allowed_set();
} }
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
@ -1475,19 +1279,6 @@ namespace libtorrent
detail::write_address(remote().address(), out); detail::write_address(remote().address(), out);
handshake["yourip"] = remote_address; handshake["yourip"] = remote_address;
handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue; handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue;
asio::error_code ec;
std::vector<address> const& interfaces = enum_net_interfaces(get_socket()->io_service(), ec);
for (std::vector<address>::const_iterator i = interfaces.begin()
, end(interfaces.end()); i != end; ++i)
{
// TODO: only use global IPv6 addresses
if (!i->is_v6() || i->to_v6().is_link_local()) continue;
std::string ipv6_address;
std::back_insert_iterator<std::string> out(ipv6_address);
detail::write_address(*i, out);
handshake["ipv6"] = ipv6_address;
break;
}
// loop backwards, to make the first extension be the last // loop backwards, to make the first extension be the last
// to fill in the handshake (i.e. give the first extensions priority) // to fill in the handshake (i.e. give the first extensions priority)
@ -1755,7 +1546,7 @@ namespace libtorrent
if (m_sync_bytes_read >= 512) if (m_sync_bytes_read >= 512)
throw protocol_error("sync hash not found within 532 bytes"); throw protocol_error("sync hash not found within 532 bytes");
cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+20) - m_sync_bytes_read)); cut_receive_buffer(bytes_processed, std::min(packet_size(), (512+20) - m_sync_bytes_read));
assert(!packet_finished()); assert(!packet_finished());
return; return;
@ -1893,7 +1684,7 @@ namespace libtorrent
if (m_sync_bytes_read >= 512) if (m_sync_bytes_read >= 512)
throw protocol_error("sync verification constant not found within 520 bytes"); throw protocol_error("sync verification constant not found within 520 bytes");
cut_receive_buffer(bytes_processed, (std::min)(packet_size(), (512+8) - m_sync_bytes_read)); cut_receive_buffer(bytes_processed, std::min(packet_size(), (512+8) - m_sync_bytes_read));
assert(!packet_finished()); assert(!packet_finished());
return; return;
@ -2225,9 +2016,6 @@ namespace libtorrent
if (recv_buffer[7] & 0x01) if (recv_buffer[7] & 0x01)
m_supports_dht_port = true; m_supports_dht_port = true;
if (recv_buffer[7] & 0x04)
m_supports_fast = true;
// ok, now we have got enough of the handshake. Is this connection // ok, now we have got enough of the handshake. Is this connection
// attached to a torrent? // attached to a torrent?
if (!t) if (!t)
@ -2261,10 +2049,10 @@ namespace libtorrent
assert(t); assert(t);
// if this is a local connection, we have already // if this is a local connection, we have already
// sent the handshake // send the handshake
if (!is_local()) write_handshake(); if (!is_local()) write_handshake();
// if (t->valid_metadata()) if (t->valid_metadata())
// write_bitfield(t->pieces()); write_bitfield(t->pieces());
assert(t->get_policy().has_connection(this)); assert(t->get_policy().has_connection(this));
@ -2337,6 +2125,11 @@ namespace libtorrent
throw protocol_error("closing connection to ourself"); throw protocol_error("closing connection to ourself");
} }
#ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port);
#endif
m_client_version = identify_client(pid); m_client_version = identify_client(pid);
boost::optional<fingerprint> f = client_fingerprint(pid); boost::optional<fingerprint> f = client_fingerprint(pid);
if (f && std::equal(f->name, f->name + 2, "BC")) if (f && std::equal(f->name, f->name + 2, "BC"))
@ -2388,14 +2181,6 @@ namespace libtorrent
m_state = read_packet_size; m_state = read_packet_size;
reset_recv_buffer(4); reset_recv_buffer(4);
if (t->valid_metadata())
{
write_bitfield(t->pieces());
#ifndef TORRENT_DISABLE_DHT
if (m_supports_dht_port && m_ses.m_dht)
write_dht_port(m_ses.get_dht_settings().service_port);
#endif
}
assert(!packet_finished()); assert(!packet_finished());
return; return;

View file

@ -54,8 +54,6 @@ namespace libtorrent
, boost::function<void()> const& on_timeout , boost::function<void()> const& on_timeout
, time_duration timeout) , time_duration timeout)
{ {
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK; INVARIANT_CHECK;
m_queue.push_back(entry()); m_queue.push_back(entry());
@ -70,8 +68,6 @@ namespace libtorrent
void connection_queue::done(int ticket) void connection_queue::done(int ticket)
{ {
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK; INVARIANT_CHECK;
std::list<entry>::iterator i = std::find_if(m_queue.begin() std::list<entry>::iterator i = std::find_if(m_queue.begin()
@ -152,8 +148,6 @@ namespace libtorrent
void connection_queue::on_timeout(asio::error_code const& e) void connection_queue::on_timeout(asio::error_code const& e)
{ {
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK; INVARIANT_CHECK;
#ifndef NDEBUG #ifndef NDEBUG
function_guard guard_(m_in_timeout_function); function_guard guard_(m_in_timeout_function);
@ -164,35 +158,21 @@ namespace libtorrent
ptime next_expire = max_time(); ptime next_expire = max_time();
ptime now = time_now(); ptime now = time_now();
std::list<entry> timed_out;
for (std::list<entry>::iterator i = m_queue.begin(); for (std::list<entry>::iterator i = m_queue.begin();
!m_queue.empty() && i != m_queue.end();) !m_queue.empty() && i != m_queue.end();)
{ {
if (i->connecting && i->expires < now) if (i->connecting && i->expires < now)
{ {
std::list<entry>::iterator j = i; boost::function<void()> on_timeout = i->on_timeout;
++i; m_queue.erase(i++);
timed_out.splice(timed_out.end(), m_queue, j, i);
--m_num_connecting; --m_num_connecting;
try { on_timeout(); } catch (std::exception&) {}
continue; continue;
} }
if (i->expires < next_expire) if (i->expires < next_expire)
next_expire = i->expires; next_expire = i->expires;
++i; ++i;
} }
// we don't want to call the timeout callback while we're locked
// since that is a recepie for dead-locks
l.unlock();
for (std::list<entry>::iterator i = timed_out.begin()
, end(timed_out.end()); i != end; ++i)
{
try { i->on_timeout(); } catch (std::exception&) {}
}
l.lock();
if (next_expire < max_time()) if (next_expire < max_time())
{ {
m_timer.expires_at(next_expire); m_timer.expires_at(next_expire);

View file

@ -34,24 +34,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <deque> #include <deque>
#include "libtorrent/disk_io_thread.hpp" #include "libtorrent/disk_io_thread.hpp"
#ifdef TORRENT_DISK_STATS
#include "libtorrent/time.hpp"
#include <boost/lexical_cast.hpp>
namespace
{
std::string log_time()
{
using namespace libtorrent;
static ptime start = time_now();
return boost::lexical_cast<std::string>(
total_milliseconds(time_now() - start));
}
}
#endif
namespace libtorrent namespace libtorrent
{ {
@ -63,12 +45,7 @@ namespace libtorrent
, m_block_size(block_size) , m_block_size(block_size)
#endif #endif
, m_disk_io_thread(boost::ref(*this)) , m_disk_io_thread(boost::ref(*this))
{ {}
#ifdef TORRENT_DISK_STATS
m_log.open("disk_io_thread.log", std::ios::trunc);
#endif
}
disk_io_thread::~disk_io_thread() disk_io_thread::~disk_io_thread()
{ {
@ -112,15 +89,8 @@ namespace libtorrent
namespace namespace
{ {
// The semantic of this operator is:
// shouls lhs come before rhs in the job queue
bool operator<(disk_io_job const& lhs, disk_io_job const& rhs) bool operator<(disk_io_job const& lhs, disk_io_job const& rhs)
{ {
// NOTE: comparison inverted to make higher priority
// skip _in_front_of_ lower priority
if (lhs.priority > rhs.priority) return true;
if (lhs.priority < rhs.priority) return false;
if (lhs.storage.get() < rhs.storage.get()) return true; if (lhs.storage.get() < rhs.storage.get()) return true;
if (lhs.storage.get() > rhs.storage.get()) return false; if (lhs.storage.get() > rhs.storage.get()) return false;
if (lhs.piece < rhs.piece) return true; if (lhs.piece < rhs.piece) return true;
@ -195,9 +165,6 @@ namespace libtorrent
{ {
for (;;) for (;;)
{ {
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " idle" << std::endl;
#endif
boost::mutex::scoped_lock l(m_mutex); boost::mutex::scoped_lock l(m_mutex);
while (m_jobs.empty() && !m_abort) while (m_jobs.empty() && !m_abort)
m_signal.wait(l); m_signal.wait(l);
@ -212,46 +179,31 @@ namespace libtorrent
int ret = 0; int ret = 0;
bool free_buffer = true;
try try
{ {
#ifdef TORRENT_DISK_STATS
ptime start = time_now();
#endif
// std::cerr << "DISK THREAD: executing job: " << j.action << std::endl; // std::cerr << "DISK THREAD: executing job: " << j.action << std::endl;
switch (j.action) switch (j.action)
{ {
case disk_io_job::read: case disk_io_job::read:
#ifdef TORRENT_DISK_STATS l.lock();
m_log << log_time() << " read " << j.buffer_size << std::endl; j.buffer = (char*)m_pool.ordered_malloc();
#endif l.unlock();
if (j.buffer == 0) if (j.buffer == 0)
{ {
l.lock(); ret = -1;
j.buffer = (char*)m_pool.ordered_malloc(); j.str = "out of memory";
l.unlock();
assert(j.buffer_size <= m_block_size);
if (j.buffer == 0)
{
ret = -1;
j.str = "out of memory";
break;
}
} }
else else
{ {
free_buffer = false; assert(j.buffer_size <= m_block_size);
} ret = j.storage->read_impl(j.buffer, j.piece, j.offset
ret = j.storage->read_impl(j.buffer, j.piece, j.offset , j.buffer_size);
, j.buffer_size);
// simulates slow drives // simulates slow drives
// usleep(300); // usleep(300);
}
break; break;
case disk_io_job::write: case disk_io_job::write:
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " write " << j.buffer_size << std::endl;
#endif
assert(j.buffer); assert(j.buffer);
assert(j.buffer_size <= m_block_size); assert(j.buffer_size <= m_block_size);
j.storage->write_impl(j.buffer, j.piece, j.offset j.storage->write_impl(j.buffer, j.piece, j.offset
@ -262,25 +214,16 @@ namespace libtorrent
break; break;
case disk_io_job::hash: case disk_io_job::hash:
{ {
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " hash" << std::endl;
#endif
sha1_hash h = j.storage->hash_for_piece_impl(j.piece); sha1_hash h = j.storage->hash_for_piece_impl(j.piece);
j.str.resize(20); j.str.resize(20);
std::memcpy(&j.str[0], &h[0], 20); std::memcpy(&j.str[0], &h[0], 20);
} }
break; break;
case disk_io_job::move_storage: case disk_io_job::move_storage:
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " move" << std::endl;
#endif
ret = j.storage->move_storage_impl(j.str) ? 1 : 0; ret = j.storage->move_storage_impl(j.str) ? 1 : 0;
j.str = j.storage->save_path().string(); j.str = j.storage->save_path().string();
break; break;
case disk_io_job::release_files: case disk_io_job::release_files:
#ifdef TORRENT_DISK_STATS
m_log << log_time() << " release" << std::endl;
#endif
j.storage->release_files_impl(); j.storage->release_files_impl();
break; break;
} }
@ -297,7 +240,7 @@ namespace libtorrent
try { if (handler) handler(ret, j); } try { if (handler) handler(ret, j); }
catch (std::exception&) {} catch (std::exception&) {}
if (j.buffer && free_buffer) if (j.buffer)
{ {
l.lock(); l.lock();
m_pool.ordered_free(j.buffer); m_pool.ordered_free(j.buffer);

View file

@ -1,142 +0,0 @@
/*
Copyright (c) 2007, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#if defined __linux__ || defined __MACH__
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#endif
#include "libtorrent/enum_net.hpp"
namespace libtorrent
{
std::vector<address> const& enum_net_interfaces(asio::io_service& ios, asio::error_code& ec)
{
static std::vector<address> ret;
if (!ret.empty()) return ret;
#if defined __linux__ || defined __MACH__ || defined(__FreeBSD__)
int s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0)
{
ec = asio::error::fault;
return ret;
}
ifconf ifc;
char buf[1024];
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
{
close(s);
ec = asio::error::fault;
return ret;
}
close(s);
char *ifr = (char*)ifc.ifc_req;
int remaining = ifc.ifc_len;
while (remaining)
{
ifreq const& item = *reinterpret_cast<ifreq*>(ifr);
if (item.ifr_addr.sa_family == AF_INET)
{
typedef asio::ip::address_v4::bytes_type bytes_t;
bytes_t b;
memcpy(&b[0], &((sockaddr_in const*)&item.ifr_addr)->sin_addr, b.size());
ret.push_back(address_v4(b));
}
else if (item.ifr_addr.sa_family == AF_INET6)
{
typedef asio::ip::address_v6::bytes_type bytes_t;
bytes_t b;
memcpy(&b[0], &((sockaddr_in6 const*)&item.ifr_addr)->sin6_addr, b.size());
ret.push_back(address_v6(b));
}
#if defined __MACH__ || defined(__FreeBSD__)
int current_size = item.ifr_addr.sa_len + IFNAMSIZ;
#elif defined __linux__
int current_size = sizeof(ifreq);
#endif
ifr += current_size;
remaining -= current_size;
}
#elif defined WIN32
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == SOCKET_ERROR)
{
ec = asio::error::fault;
return ret;
}
INTERFACE_INFO buffer[30];
DWORD size;
if (WSAIoctl(s, SIO_GET_INTERFACE_LIST, 0, 0, buffer,
sizeof(buffer), &size, 0, 0) != 0)
{
closesocket(s);
ec = asio::error::fault;
return ret;
}
closesocket(s);
int n = size / sizeof(INTERFACE_INFO);
for (int i = 0; i < n; ++i)
{
sockaddr_in *sockaddr = (sockaddr_in*)&buffer[i].iiAddress;
address a(address::from_string(inet_ntoa(sockaddr->sin_addr)));
if (a == address_v4::any()) continue;
ret.push_back(a);
}
#else
// make a best guess of the interface we're using and its IP
udp::resolver r(ios);
udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(), "0"));
for (;i != udp::resolver_iterator(); ++i)
{
ret.push_back(i->endpoint().address());
}
#endif
return ret;
}
}

View file

@ -33,14 +33,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/pch.hpp" #include "libtorrent/pch.hpp"
#include <string> #include <string>
#include <cassert>
#include <stdexcept> #include <stdexcept>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <cctype> #include <cctype>
#include <algorithm> #include <algorithm>
#include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
std::string unescape_string(std::string const& s) std::string unescape_string(std::string const& s)

View file

@ -247,16 +247,19 @@ namespace libtorrent
void set_size(size_type s) void set_size(size_type s)
{ {
#ifdef _WIN32 size_type pos = tell();
#error file.cpp is for posix systems only. use file_win.cpp on windows // Only set size if current file size not equals s.
#else // 2 as "m" argument is to be sure seek() sets SEEK_END on
if (ftruncate(m_fd, s) < 0) // all compilers.
if(s != seek(0, 2))
{ {
std::stringstream msg; seek(s - 1);
msg << "ftruncate failed: '" << strerror(errno); char dummy = 0;
throw file_error(msg.str()); read(&dummy, 1);
seek(s - 1);
write(&dummy, 1);
} }
#endif seek(pos);
} }
size_type seek(size_type offset, int m = 1) size_type seek(size_type offset, int m = 1)

View file

@ -42,8 +42,6 @@ using boost::bind;
namespace libtorrent namespace libtorrent
{ {
enum { max_bottled_buffer = 1024 * 1024 };
void http_connection::get(std::string const& url, time_duration timeout void http_connection::get(std::string const& url, time_duration timeout
, bool handle_redirect) , bool handle_redirect)
{ {
@ -167,7 +165,6 @@ void http_connection::on_connect(asio::error_code const& e
if (!e) if (!e)
{ {
m_last_receive = time_now(); m_last_receive = time_now();
if (m_connect_handler) m_connect_handler(*this);
asio::async_write(m_sock, asio::buffer(sendbuffer) asio::async_write(m_sock, asio::buffer(sendbuffer)
, bind(&http_connection::on_write, shared_from_this(), _1)); , bind(&http_connection::on_write, shared_from_this(), _1));
} }
@ -313,8 +310,8 @@ void http_connection::on_read(asio::error_code const& e
} }
if (int(m_recvbuffer.size()) == m_read_pos) if (int(m_recvbuffer.size()) == m_read_pos)
m_recvbuffer.resize((std::min)(m_read_pos + 2048, int(max_bottled_buffer))); m_recvbuffer.resize((std::min)(m_read_pos + 2048, 1024*500));
if (m_read_pos == max_bottled_buffer) if (m_read_pos == 1024 * 500)
{ {
close(); close();
if (m_bottled && m_called) return; if (m_bottled && m_called) return;

View file

@ -148,19 +148,13 @@ namespace libtorrent
pos = newline; pos = newline;
line >> m_protocol; line >> m_protocol;
if (m_protocol.substr(0, 5) == "HTTP/") if (m_protocol.substr(0, 5) != "HTTP/")
{ {
line >> m_status_code; throw std::runtime_error("unknown protocol in HTTP response: "
std::getline(line, m_server_message); + m_protocol + " line: " + std::string(pos, newline));
}
else
{
m_method = m_protocol;
std::transform(m_method.begin(), m_method.end(), m_method.begin(), &to_lower);
m_protocol.clear();
line >> m_path >> m_protocol;
m_status_code = 0;
} }
line >> m_status_code;
std::getline(line, m_server_message);
m_state = read_header; m_state = read_header;
} }
@ -256,7 +250,7 @@ namespace libtorrent
assert(m_state == read_body); assert(m_state == read_body);
if (m_content_length >= 0) if (m_content_length >= 0)
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
, m_recv_buffer.begin + (std::min)(m_recv_pos , m_recv_buffer.begin + std::min(m_recv_pos
, m_body_start_pos + m_content_length)); , m_body_start_pos + m_content_length));
else else
return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos
@ -414,7 +408,7 @@ namespace libtorrent
{ {
m_send_buffer += "numwant="; m_send_buffer += "numwant=";
m_send_buffer += boost::lexical_cast<std::string>( m_send_buffer += boost::lexical_cast<std::string>(
(std::min)(req.num_want, 999)); std::min(req.num_want, 999));
m_send_buffer += '&'; m_send_buffer += '&';
} }
if (m_settings.announce_ip != address() && !url_has_argument(request, "ip")) if (m_settings.announce_ip != address() && !url_has_argument(request, "ip"))
@ -465,16 +459,14 @@ namespace libtorrent
m_send_buffer += "\r\n\r\n"; m_send_buffer += "\r\n\r\n";
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (has_requester())
boost::shared_ptr<request_callback> cb = requester();
if (cb)
{ {
cb->debug_log("==> TRACKER_REQUEST [ str: " + m_send_buffer + " ]"); requester().debug_log("==> TRACKER_REQUEST [ str: " + m_send_buffer + " ]");
std::stringstream info_hash_str; std::stringstream info_hash_str;
info_hash_str << req.info_hash; info_hash_str << req.info_hash;
cb->debug_log("info_hash: " requester().debug_log("info_hash: "
+ boost::lexical_cast<std::string>(req.info_hash)); + boost::lexical_cast<std::string>(req.info_hash));
cb->debug_log("name lookup: " + hostname); requester().debug_log("name lookup: " + hostname);
} }
#endif #endif
@ -499,9 +491,8 @@ namespace libtorrent
void http_tracker_connection::name_lookup(asio::error_code const& error void http_tracker_connection::name_lookup(asio::error_code const& error
, tcp::resolver::iterator i) try , tcp::resolver::iterator i) try
{ {
boost::shared_ptr<request_callback> cb = requester();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (cb) cb->debug_log("tracker name lookup handler called"); if (has_requester()) requester().debug_log("tracker name lookup handler called");
#endif #endif
if (error == asio::error::operation_aborted) return; if (error == asio::error::operation_aborted) return;
if (m_timed_out) return; if (m_timed_out) return;
@ -513,7 +504,7 @@ namespace libtorrent
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (cb) cb->debug_log("tracker name lookup successful"); if (has_requester()) requester().debug_log("tracker name lookup successful");
#endif #endif
restart_read_timeout(); restart_read_timeout();
@ -528,11 +519,11 @@ namespace libtorrent
if (target == end) if (target == end)
{ {
assert(target_address.address().is_v4() != bind_interface().is_v4()); assert(target_address.address().is_v4() != bind_interface().is_v4());
if (cb) if (has_requester())
{ {
std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6"; std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6";
std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
cb->tracker_warning("the tracker only resolves to an " requester().tracker_warning("the tracker only resolves to an "
+ tracker_address_type + " address, and you're listening on an " + tracker_address_type + " address, and you're listening on an "
+ bind_address_type + " socket. This may prevent you from receiving incoming connections."); + bind_address_type + " socket. This may prevent you from receiving incoming connections.");
} }
@ -542,7 +533,7 @@ namespace libtorrent
target_address = *target; target_address = *target;
} }
if (cb) cb->m_tracker_address = target_address; if (has_requester()) requester().m_tracker_address = target_address;
m_socket = instantiate_connection(m_name_lookup.io_service(), m_proxy); m_socket = instantiate_connection(m_name_lookup.io_service(), m_proxy);
if (m_proxy.type == proxy_settings::http if (m_proxy.type == proxy_settings::http
@ -583,8 +574,7 @@ namespace libtorrent
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
boost::shared_ptr<request_callback> cb = requester(); if (has_requester()) requester().debug_log("tracker connection successful");
if (cb) cb->debug_log("tracker connection successful");
#endif #endif
restart_read_timeout(); restart_read_timeout();
@ -608,8 +598,7 @@ namespace libtorrent
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
boost::shared_ptr<request_callback> cb = requester(); if (has_requester()) requester().debug_log("tracker send data completed");
if (cb) cb->debug_log("tracker send data completed");
#endif #endif
restart_read_timeout(); restart_read_timeout();
assert(m_buffer.size() - m_recv_pos > 0); assert(m_buffer.size() - m_recv_pos > 0);
@ -645,8 +634,7 @@ namespace libtorrent
restart_read_timeout(); restart_read_timeout();
assert(bytes_transferred > 0); assert(bytes_transferred > 0);
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
boost::shared_ptr<request_callback> cb = requester(); if (has_requester()) requester().debug_log("tracker connection reading "
if (cb) cb->debug_log("tracker connection reading "
+ boost::lexical_cast<std::string>(bytes_transferred)); + boost::lexical_cast<std::string>(bytes_transferred));
#endif #endif
@ -712,8 +700,6 @@ namespace libtorrent
} }
std::string location = m_parser.header<std::string>("location"); std::string location = m_parser.header<std::string>("location");
boost::shared_ptr<request_callback> cb = requester();
if (m_parser.status_code() >= 300 && m_parser.status_code() < 400) if (m_parser.status_code() >= 300 && m_parser.status_code() < 400)
{ {
@ -734,9 +720,9 @@ namespace libtorrent
} }
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (cb) cb->debug_log("Redirecting to \"" + location + "\""); if (has_requester()) requester().debug_log("Redirecting to \"" + location + "\"");
#endif #endif
if (cb) cb->tracker_warning("Redirecting to \"" + location + "\""); if (has_requester()) requester().tracker_warning("Redirecting to \"" + location + "\"");
tracker_request req = tracker_req(); tracker_request req = tracker_req();
req.url = location; req.url = location;
@ -759,18 +745,20 @@ namespace libtorrent
std::string content_encoding = m_parser.header<std::string>("content-encoding"); std::string content_encoding = m_parser.header<std::string>("content-encoding");
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (cb) cb->debug_log("content-encoding: \"" + content_encoding + "\""); if (has_requester()) requester().debug_log("content-encoding: \"" + content_encoding + "\"");
#endif #endif
if (content_encoding == "gzip" || content_encoding == "x-gzip") if (content_encoding == "gzip" || content_encoding == "x-gzip")
{ {
if (!cb) boost::shared_ptr<request_callback> r = m_requester.lock();
if (!r)
{ {
close(); close();
return; return;
} }
m_buffer.erase(m_buffer.begin(), m_buffer.begin() + m_parser.body_start()); m_buffer.erase(m_buffer.begin(), m_buffer.begin() + m_parser.body_start());
if (inflate_gzip(m_buffer, tracker_request(), cb.get(), if (inflate_gzip(m_buffer, tracker_request(), r.get(),
m_settings.tracker_maximum_response_length)) m_settings.tracker_maximum_response_length))
{ {
close(); close();
@ -847,8 +835,7 @@ namespace libtorrent
void http_tracker_connection::parse(entry const& e) void http_tracker_connection::parse(entry const& e)
{ {
boost::shared_ptr<request_callback> cb = requester(); if (!has_requester()) return;
if (!cb) return;
try try
{ {
@ -865,7 +852,8 @@ namespace libtorrent
try try
{ {
entry const& warning = e["warning message"]; entry const& warning = e["warning message"];
cb->tracker_warning(warning.string()); if (has_requester())
requester().tracker_warning(warning.string());
} }
catch(type_error const&) {} catch(type_error const&) {}
@ -879,7 +867,7 @@ namespace libtorrent
entry scrape_data = e["files"][ih]; entry scrape_data = e["files"][ih];
int complete = scrape_data["complete"].integer(); int complete = scrape_data["complete"].integer();
int incomplete = scrape_data["incomplete"].integer(); int incomplete = scrape_data["incomplete"].integer();
cb->tracker_response(tracker_request(), peer_list, 0, complete requester().tracker_response(tracker_request(), peer_list, 0, complete
, incomplete); , incomplete);
return; return;
} }
@ -896,7 +884,12 @@ namespace libtorrent
peer_entry p; peer_entry p;
p.pid.clear(); p.pid.clear();
p.ip = detail::read_v4_address(i).to_string(); std::stringstream ip_str;
ip_str << (int)detail::read_uint8(i) << ".";
ip_str << (int)detail::read_uint8(i) << ".";
ip_str << (int)detail::read_uint8(i) << ".";
ip_str << (int)detail::read_uint8(i);
p.ip = ip_str.str();
p.port = detail::read_uint16(i); p.port = detail::read_uint16(i);
peer_list.push_back(p); peer_list.push_back(p);
} }
@ -911,22 +904,6 @@ namespace libtorrent
} }
} }
if (entry const* ipv6_peers = e.find_key("peers6"))
{
std::string const& peers = ipv6_peers->string();
for (std::string::const_iterator i = peers.begin();
i != peers.end();)
{
if (std::distance(i, peers.end()) < 18) break;
peer_entry p;
p.pid.clear();
p.ip = detail::read_v6_address(i).to_string();
p.port = detail::read_uint16(i);
peer_list.push_back(p);
}
}
// look for optional scrape info // look for optional scrape info
int complete = -1; int complete = -1;
int incomplete = -1; int incomplete = -1;
@ -937,16 +914,16 @@ namespace libtorrent
try { incomplete = e["incomplete"].integer(); } try { incomplete = e["incomplete"].integer(); }
catch(type_error&) {} catch(type_error&) {}
cb->tracker_response(tracker_request(), peer_list, interval, complete requester().tracker_response(tracker_request(), peer_list, interval, complete
, incomplete); , incomplete);
} }
catch(type_error& e) catch(type_error& e)
{ {
cb->tracker_request_error(tracker_request(), m_parser.status_code(), e.what()); requester().tracker_request_error(tracker_request(), m_parser.status_code(), e.what());
} }
catch(std::runtime_error& e) catch(std::runtime_error& e)
{ {
cb->tracker_request_error(tracker_request(), m_parser.status_code(), e.what()); requester().tracker_request_error(tracker_request(), m_parser.status_code(), e.what());
} }
} }

Some files were not shown because too many files have changed in this diff Show more