libtorrent sync 1592

This commit is contained in:
Marcos Pinto 2007-09-20 23:43:07 +00:00
parent d44632f0a9
commit b2fe562dd4
133 changed files with 4077 additions and 3744 deletions

View File

@ -25,6 +25,8 @@ extern char const* peer_error_alert_doc;
extern char const* invalid_request_alert_doc;
extern char const* peer_request_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_received_alert_doc;
extern char const* fastresume_rejected_alert_doc;
@ -140,7 +142,18 @@ void bind_alert()
)
.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>(
"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_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 -----------------------------------------------------------------
char const* alert_doc =
@ -257,6 +257,17 @@ char const* torrent_finished_alert_doc =
"It contains a `torrent_handle` to the torrent in question. This alert\n"
"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 =
"This alert is generated when the metadata has been completely\n"
"received and the info-hash failed to match it. i.e. the\n"

View File

@ -142,7 +142,6 @@ void bind_extensions()
// TODO move to it's own file
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_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_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_pop_alert_doc;
extern char const* session_start_upnp_doc;
@ -86,11 +86,10 @@ namespace
torrent_handle add_torrent(session& s, torrent_info const& ti
, boost::filesystem::path const& save, entry const& resume
, bool compact, int block_size)
, bool compact, bool paused)
{
allow_threading_guard guard;
return s.add_torrent(ti, save, resume, compact, block_size
, default_storage_constructor);
return s.add_torrent(ti, save, resume, compact, paused, default_storage_constructor);
}
} // namespace unnamed
@ -175,7 +174,7 @@ void bind_session()
"add_torrent", &add_torrent
, (
arg("torrent_info"), "save_path", arg("resume_data") = entry()
, arg("compact_mode") = true, arg("block_size") = 16 * 1024
, arg("compact_mode") = true, arg("paused") = false
)
, session_add_torrent_doc
)

View File

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

View File

@ -16,7 +16,6 @@ namespace
return i.trackers().begin();
}
std::vector<announce_entry>::const_iterator end_trackers(torrent_info& i)
{
return i.trackers().end();
@ -41,6 +40,29 @@ namespace
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
void bind_torrent_info()
@ -71,9 +93,9 @@ void bind_torrent_info()
.def("hash_for_piece", &torrent_info::hash_for_piece, copy)
.def("piece_size", &torrent_info::piece_size)
.def("num_files", &torrent_info::num_files)
.def("num_files", &torrent_info::num_files, (arg("storage")=false))
.def("file_at", &torrent_info::file_at, return_internal_reference<>())
.def("files", range(&torrent_info::begin_files, &torrent_info::end_files))
.def("files", &files, (arg("storage")=false))
.def("priv", &torrent_info::priv)
.def("set_priv", &torrent_info::set_priv)
@ -84,9 +106,8 @@ void bind_torrent_info()
.def("add_node", &add_node)
.def("nodes", &nodes)
;
class_<file_entry>("file_entry")
.add_property(
.add_property(
"path"
, make_getter(
&file_entry::path, return_value_policy<copy_non_const_reference>()

View File

@ -1,45 +0,0 @@
/basic_datagram_socket.hpp/1.40/Thu Jan 4 05:44:43 2007//
/basic_deadline_timer.hpp/1.23/Sun May 20 00:49:02 2007//
/basic_io_object.hpp/1.8/Thu Jan 4 05:44:43 2007//
/basic_socket.hpp/1.16/Mon Jan 8 22:12:45 2007//
/basic_socket_acceptor.hpp/1.58/Fri Feb 9 05:47:48 2007//
/basic_socket_iostream.hpp/1.8/Thu Jan 18 11:41:36 2007//
/basic_socket_streambuf.hpp/1.6/Thu Jan 18 11:41:36 2007//
/basic_stream_socket.hpp/1.69/Mon Jan 8 22:12:45 2007//
/basic_streambuf.hpp/1.12/Thu Jan 4 10:23:31 2007//
/buffer.hpp/1.23/Thu Jun 21 14:03:36 2007//
/buffered_read_stream.hpp/1.17/Thu Jan 4 05:44:43 2007//
/buffered_read_stream_fwd.hpp/1.5/Thu Jan 4 05:44:43 2007//
/buffered_stream.hpp/1.32/Thu Jan 4 05:44:43 2007//
/buffered_stream_fwd.hpp/1.9/Thu Jan 4 05:44:43 2007//
/buffered_write_stream.hpp/1.17/Thu Jan 4 05:44:43 2007//
/buffered_write_stream_fwd.hpp/1.5/Thu Jan 4 05:44:43 2007//
/completion_condition.hpp/1.5/Thu Jan 4 05:44:43 2007//
/datagram_socket_service.hpp/1.34/Mon Jan 8 22:12:45 2007//
/deadline_timer.hpp/1.6/Thu Jan 4 05:44:43 2007//
/deadline_timer_service.hpp/1.29/Mon Jan 8 02:47:13 2007//
/error.hpp/1.39/Mon Jan 8 22:12:45 2007//
/error_code.hpp/1.4/Mon Jan 8 22:12:45 2007//
/handler_alloc_hook.hpp/1.11/Thu Jan 4 05:44:43 2007//
/handler_invoke_hook.hpp/1.3/Thu Jan 4 05:44:43 2007//
/io_service.hpp/1.24/Sun May 20 00:49:02 2007//
/is_read_buffered.hpp/1.6/Thu Jan 4 05:44:43 2007//
/is_write_buffered.hpp/1.6/Thu Jan 4 05:44:43 2007//
/placeholders.hpp/1.10/Thu Jan 4 05:44:43 2007//
/read.hpp/1.22/Thu Jan 4 05:44:43 2007//
/read_until.hpp/1.8/Thu Jan 4 05:44:44 2007//
/socket_acceptor_service.hpp/1.34/Fri Feb 9 05:47:48 2007//
/socket_base.hpp/1.23/Mon Jan 8 23:45:36 2007//
/ssl.hpp/1.4/Thu Jan 4 05:44:44 2007//
/strand.hpp/1.6/Tue May 8 13:13:55 2007//
/stream_socket_service.hpp/1.35/Mon Jan 8 22:12:46 2007//
/streambuf.hpp/1.3/Thu Jan 4 05:44:44 2007//
/system_error.hpp/1.3/Thu Jan 4 05:44:44 2007//
/thread.hpp/1.15/Thu Jan 4 05:44:44 2007//
/time_traits.hpp/1.9/Thu Jan 4 05:44:44 2007//
/version.hpp/1.1/Tue May 8 12:17:36 2007//
/write.hpp/1.21/Thu Jan 4 05:44:44 2007//
D/detail////
D/impl////
D/ip////
D/ssl////

View File

@ -1 +0,0 @@
asio/include/asio

View File

@ -1 +0,0 @@
:pserver:anonymous@asio.cvs.sourceforge.net:/cvsroot/asio

View File

@ -238,6 +238,9 @@ public:
* with the asio::error::operation_aborted error.
*
* @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()
{
@ -265,6 +268,9 @@ public:
* // An error occurred.
* }
* @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)
{

View File

@ -542,9 +542,10 @@ inline const_buffers_1 buffer(const PodType (&data)[N],
? 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++ thinks the overloads:
// Borland C++ and Sun Studio think the overloads:
//
// unspecified buffer(boost::array<PodType, N>& array ...);
//
@ -610,6 +611,7 @@ buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
}
#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.
template <typename PodType, std::size_t N>
@ -650,6 +652,7 @@ inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
}
#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.
template <typename PodType, std::size_t N>

View File

@ -71,6 +71,28 @@ private:
/// Return a completion condition function object that indicates that a read or
/// write operation should continue until all of the data has been 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:
* @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)
unspecified transfer_all();
#else
@ -83,6 +105,28 @@ inline detail::transfer_all_t transfer_all()
/// Return a completion condition function object that indicates that a read or
/// write operation should continue until a minimum number of bytes has been
/// 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)
unspecified transfer_at_least(std::size_t minimum);
#else

View File

@ -1,74 +0,0 @@
/bind_handler.hpp/1.18/Thu Jan 4 05:44:44 2007//
/buffer_resize_guard.hpp/1.9/Thu Jan 4 05:44:44 2007//
/buffered_stream_storage.hpp/1.5/Thu Jan 4 05:44:44 2007//
/call_stack.hpp/1.3/Thu Jan 4 05:44:44 2007//
/const_buffers_iterator.hpp/1.3/Thu Jan 4 05:44:44 2007//
/consuming_buffers.hpp/1.7/Sat Jan 13 13:41:09 2007//
/deadline_timer_service.hpp/1.7/Mon Jan 8 02:47:13 2007//
/epoll_reactor.hpp/1.40/Thu Jan 4 05:44:44 2007//
/epoll_reactor_fwd.hpp/1.3/Thu Jan 4 05:44:44 2007//
/event.hpp/1.13/Thu Jan 4 05:44:44 2007//
/fd_set_adapter.hpp/1.5/Thu Jan 4 05:44:44 2007//
/handler_alloc_helpers.hpp/1.8/Thu Jan 4 05:44:44 2007//
/handler_invoke_helpers.hpp/1.2/Thu Jan 4 05:44:44 2007//
/hash_map.hpp/1.19/Thu Mar 22 21:13:13 2007//
/io_control.hpp/1.5/Thu Jan 4 05:44:44 2007//
/kqueue_reactor.hpp/1.30/Thu Mar 22 21:08:02 2007//
/kqueue_reactor_fwd.hpp/1.3/Thu Jan 4 05:44:44 2007//
/local_free_on_block_exit.hpp/1.2/Thu Jan 4 05:44:44 2007//
/mutex.hpp/1.13/Thu Jan 4 05:44:44 2007//
/noncopyable.hpp/1.3/Thu Jan 4 05:44:44 2007//
/null_event.hpp/1.3/Thu Jan 4 05:44:44 2007//
/null_mutex.hpp/1.3/Thu Jan 4 05:44:44 2007//
/null_signal_blocker.hpp/1.3/Thu Jan 4 05:44:44 2007//
/null_thread.hpp/1.5/Mon Jan 8 22:12:46 2007//
/null_tss_ptr.hpp/1.3/Thu Jan 4 05:44:44 2007//
/old_win_sdk_compat.hpp/1.5/Sat May 12 08:16:25 2007//
/pipe_select_interrupter.hpp/1.11/Thu Jan 4 05:44:44 2007//
/pop_options.hpp/1.10/Thu Jan 4 05:44:44 2007//
/posix_event.hpp/1.16/Thu Jan 4 05:44:44 2007//
/posix_fd_set_adapter.hpp/1.4/Tue Feb 13 07:13:29 2007//
/posix_mutex.hpp/1.15/Thu Jan 4 05:44:44 2007//
/posix_signal_blocker.hpp/1.10/Sat Feb 17 22:57:37 2007//
/posix_thread.hpp/1.17/Thu Jan 4 05:44:45 2007//
/posix_tss_ptr.hpp/1.10/Thu Jan 4 05:44:45 2007//
/push_options.hpp/1.16/Thu Jan 4 05:44:45 2007//
/reactive_socket_service.hpp/1.59/Sun May 13 23:00:01 2007//
/reactor_op_queue.hpp/1.24/Thu Jan 4 05:44:45 2007//
/resolver_service.hpp/1.11/Thu Jan 4 09:06:56 2007//
/scoped_lock.hpp/1.9/Thu Jan 4 05:44:45 2007//
/select_interrupter.hpp/1.10/Thu Jan 4 05:44:45 2007//
/select_reactor.hpp/1.49/Thu Jan 4 05:44:45 2007//
/select_reactor_fwd.hpp/1.2/Thu Jan 4 05:44:45 2007//
/service_base.hpp/1.2/Thu Jan 4 05:44:45 2007//
/service_id.hpp/1.2/Thu Jan 4 05:44:45 2007//
/service_registry.hpp/1.19/Tue Feb 13 12:06:43 2007//
/service_registry_fwd.hpp/1.2/Thu Jan 4 05:44:45 2007//
/signal_blocker.hpp/1.10/Thu Jan 4 05:44:45 2007//
/signal_init.hpp/1.11/Thu Jan 4 05:44:45 2007//
/socket_holder.hpp/1.10/Thu Jan 4 05:44:45 2007//
/socket_ops.hpp/1.74/Mon May 21 12:34:39 2007//
/socket_option.hpp/1.7/Sat Feb 17 22:57:37 2007//
/socket_select_interrupter.hpp/1.15/Thu May 10 23:48:52 2007//
/socket_types.hpp/1.41/Sun May 13 07:59:21 2007//
/strand_service.hpp/1.15/Thu Jan 4 05:44:45 2007//
/task_io_service.hpp/1.18/Wed Feb 14 13:26:21 2007//
/task_io_service_fwd.hpp/1.2/Thu Jan 4 05:44:45 2007//
/thread.hpp/1.13/Thu Jan 4 05:44:45 2007//
/throw_error.hpp/1.3/Thu Jan 4 05:44:45 2007//
/timer_queue.hpp/1.6/Sun Apr 22 07:07:15 2007//
/timer_queue_base.hpp/1.2/Thu Jan 4 05:44:45 2007//
/tss_ptr.hpp/1.8/Thu Jan 4 05:44:45 2007//
/win_event.hpp/1.14/Thu Jan 4 05:44:45 2007//
/win_fd_set_adapter.hpp/1.4/Thu Jan 4 05:44:45 2007//
/win_iocp_io_service.hpp/1.24/Mon Jan 8 01:09:14 2007//
/win_iocp_io_service_fwd.hpp/1.4/Thu Jan 4 05:44:45 2007//
/win_iocp_operation.hpp/1.16/Thu Jan 4 05:44:45 2007//
/win_iocp_socket_service.hpp/1.75/Sat May 12 09:07:32 2007//
/win_mutex.hpp/1.16/Thu Jan 4 05:44:45 2007//
/win_signal_blocker.hpp/1.9/Thu Jan 4 05:44:45 2007//
/win_thread.hpp/1.20/Thu Jan 4 05:44:45 2007//
/win_tss_ptr.hpp/1.10/Thu Jan 4 05:44:45 2007//
/winsock_init.hpp/1.16/Thu Jan 4 05:44:45 2007//
/wrapped_handler.hpp/1.11/Thu Jan 4 05:44:45 2007//
D

View File

@ -1 +0,0 @@
asio/include/asio/detail

View File

@ -1 +0,0 @@
:pserver:anonymous@asio.cvs.sourceforge.net:/cvsroot/asio

View File

@ -157,7 +157,8 @@ public:
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
read_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -190,7 +191,8 @@ public:
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -219,7 +221,8 @@ public:
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -250,7 +253,8 @@ public:
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
@ -331,7 +335,10 @@ public:
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
{
asio::detail::mutex::scoped_lock lock(mutex_);
return timer_queue.cancel_timer(token);
std::size_t n = timer_queue.cancel_timer(token);
if (n > 0)
interrupter_.interrupt();
return n;
}
private:
@ -347,16 +354,13 @@ private:
read_op_queue_.dispatch_cancellations();
write_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.
if (stop_thread_)
{
// 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();
cleanup_operations_and_timers(lock);
return;
}
@ -365,12 +369,7 @@ private:
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty())
{
// 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();
cleanup_operations_and_timers(lock);
return;
}
@ -398,59 +397,45 @@ private:
}
else
{
if (events[i].events & (EPOLLERR | EPOLLHUP))
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 | 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)
{
asio::error_code ec;
except_op_queue_.dispatch_all_operations(descriptor, ec);
ec = asio::error_code(errno,
asio::error::system_category);
read_op_queue_.dispatch_all_operations(descriptor, ec);
write_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);
}
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
}
@ -458,19 +443,17 @@ private:
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
timer_queues_[i]->dispatch_timers();
timer_queues_[i]->dispatch_cancellations();
}
// Issue any pending cancellations.
for (size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
// 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();
cleanup_operations_and_timers(lock);
}
// Run the select loop in the thread.
@ -507,8 +490,10 @@ private:
int fd = epoll_create(epoll_size);
if (fd == -1)
{
boost::throw_exception(asio::system_error(
asio::error_code(errno, asio::native_ecat),
boost::throw_exception(
asio::system_error(
asio::error_code(errno,
asio::error::system_category),
"epoll"));
}
return fd;
@ -566,6 +551,22 @@ private:
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.
asio::detail::mutex mutex_;
@ -590,6 +591,10 @@ private:
// The 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.
std::vector<socket_type> pending_cancellations_;

View File

@ -150,7 +150,8 @@ public:
EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
read_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -176,7 +177,8 @@ public:
EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -201,7 +203,8 @@ public:
EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -224,7 +227,8 @@ public:
EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, ec);
}
}
@ -238,7 +242,8 @@ public:
EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code ec(errno, asio::native_ecat);
asio::error_code ec(errno,
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, ec);
write_op_queue_.dispatch_all_operations(descriptor, ec);
}
@ -321,7 +326,10 @@ public:
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
{
asio::detail::mutex::scoped_lock lock(mutex_);
return timer_queue.cancel_timer(token);
std::size_t n = timer_queue.cancel_timer(token);
if (n > 0)
interrupter_.interrupt();
return n;
}
private:
@ -337,16 +345,13 @@ private:
read_op_queue_.dispatch_cancellations();
write_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.
if (stop_thread_)
{
// 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();
cleanup_operations_and_timers(lock);
return;
}
@ -355,12 +360,7 @@ private:
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty())
{
// 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();
cleanup_operations_and_timers(lock);
return;
}
@ -397,7 +397,7 @@ private:
if (events[i].flags & EV_ERROR)
{
asio::error_code error(
events[i].data, asio::native_ecat);
events[i].data, asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, error);
read_op_queue_.dispatch_all_operations(descriptor, error);
}
@ -427,7 +427,8 @@ private:
EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code error(errno, asio::native_ecat);
asio::error_code error(errno,
asio::error::system_category);
except_op_queue_.dispatch_all_operations(descriptor, error);
read_op_queue_.dispatch_all_operations(descriptor, error);
}
@ -439,7 +440,7 @@ private:
if (events[i].flags & EV_ERROR)
{
asio::error_code error(
events[i].data, asio::native_ecat);
events[i].data, asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, error);
}
else
@ -456,7 +457,8 @@ private:
EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
{
asio::error_code error(errno, asio::native_ecat);
asio::error_code error(errno,
asio::error::system_category);
write_op_queue_.dispatch_all_operations(descriptor, error);
}
}
@ -466,19 +468,17 @@ private:
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
timer_queues_[i]->dispatch_timers();
timer_queues_[i]->dispatch_cancellations();
}
// Issue any pending cancellations.
for (std::size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
// 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();
cleanup_operations_and_timers(lock);
}
// Run the select loop in the thread.
@ -512,8 +512,10 @@ private:
int fd = kqueue();
if (fd == -1)
{
boost::throw_exception(asio::system_error(
asio::error_code(errno, asio::native_ecat),
boost::throw_exception(
asio::system_error(
asio::error_code(errno,
asio::error::system_category),
"kqueue"));
}
return fd;
@ -573,6 +575,22 @@ private:
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.
asio::detail::mutex mutex_;
@ -597,6 +615,10 @@ private:
// The 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.
std::vector<socket_type> pending_cancellations_;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -229,7 +229,10 @@ public:
std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
{
asio::detail::mutex::scoped_lock lock(mutex_);
return timer_queue.cancel_timer(token);
std::size_t n = timer_queue.cancel_timer(token);
if (n > 0)
interrupter_.interrupt();
return n;
}
private:
@ -245,16 +248,13 @@ private:
read_op_queue_.dispatch_cancellations();
write_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.
if (stop_thread_)
{
// 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();
cleanup_operations_and_timers(lock);
return;
}
@ -263,12 +263,7 @@ private:
if (!block && read_op_queue_.empty() && write_op_queue_.empty()
&& except_op_queue_.empty() && all_timer_queues_are_empty())
{
// 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();
cleanup_operations_and_timers(lock);
return;
}
@ -321,19 +316,17 @@ private:
write_op_queue_.dispatch_cancellations();
}
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
{
timer_queues_[i]->dispatch_timers();
timer_queues_[i]->dispatch_cancellations();
}
// Issue any pending cancellations.
for (size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
// 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();
cleanup_operations_and_timers(lock);
}
// Run the select loop in the thread.
@ -414,6 +407,22 @@ private:
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.
asio::detail::mutex mutex_;
@ -435,6 +444,10 @@ private:
// The 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.
std::vector<socket_type> pending_cancellations_;

View File

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

View File

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

View File

@ -110,8 +110,19 @@ public:
template <typename Protocol>
void resize(const Protocol&, std::size_t s)
{
if (s != sizeof(value_))
// On some platforms (e.g. Windows Vista), the getsockopt function will
// 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");
}
}
private:

View File

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

View File

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

View File

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

View File

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

View File

@ -44,6 +44,12 @@ public:
// Dispatch all ready timers.
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.
virtual void destroy_timers() = 0;
};

View File

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

View File

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

View File

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

View File

@ -137,7 +137,7 @@ public:
enum
{
enable_connection_aborted = 1, // User wants connection_aborted errors.
user_set_linger = 2, // The user set the linger option.
close_might_block = 2, // User set linger option for blocking close.
user_set_non_blocking = 4 // The user wants a non-blocking socket.
};
@ -170,7 +170,7 @@ public:
typedef detail::select_reactor<true> reactor_type;
// The maximum number of buffers to support in a single operation.
enum { max_buffers = 16 };
enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
// Constructor.
win_iocp_socket_service(asio::io_service& io_service)
@ -192,7 +192,7 @@ public:
while (impl)
{
asio::error_code ignored_ec;
close(*impl, ignored_ec);
close_for_destruction(*impl);
impl = impl->next_;
}
}
@ -217,34 +217,7 @@ public:
// Destroy a socket implementation.
void destroy(implementation_type& 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;
}
close_for_destruction(impl);
// Remove implementation from linked list of all implementations.
asio::detail::mutex::scoped_lock lock(mutex_);
@ -353,6 +326,25 @@ public:
{
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)
{
// No operations have been started, so there's nothing to cancel.
@ -367,7 +359,8 @@ public:
if (!::CancelIo(sock_as_handle))
{
DWORD last_error = ::GetLastError();
ec = asio::error_code(last_error, asio::native_ecat);
ec = asio::error_code(last_error,
asio::error::system_category);
}
else
{
@ -475,7 +468,12 @@ public:
if (option.level(impl.protocol_) == SOL_SOCKET
&& option.name(impl.protocol_) == SO_LINGER)
{
impl.flags_ |= implementation_type::user_set_linger;
const ::linger* linger_option =
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_,
@ -668,7 +666,8 @@ public:
last_error = WSAECONNRESET;
else if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, asio::native_ecat);
ec = asio::error_code(last_error,
asio::error::system_category);
return 0;
}
@ -719,7 +718,8 @@ public:
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
if (ec.value() == ERROR_NETNAME_DELETED)
{
if (handler_op->cancel_token_.expired())
@ -821,7 +821,8 @@ public:
{
asio::io_service::work work(this->io_service());
ptr.reset();
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
}
else
@ -865,7 +866,8 @@ public:
DWORD last_error = ::WSAGetLastError();
if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, asio::native_ecat);
ec = asio::error_code(last_error,
asio::error::system_category);
return 0;
}
@ -914,7 +916,8 @@ public:
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
if (ec.value() == ERROR_PORT_UNREACHABLE)
{
ec = asio::error::connection_refused;
@ -997,7 +1000,8 @@ public:
{
asio::io_service::work work(this->io_service());
ptr.reset();
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
}
else
@ -1051,7 +1055,8 @@ public:
last_error = WSAECONNRESET;
else if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, asio::native_ecat);
ec = asio::error_code(last_error,
asio::error::system_category);
return 0;
}
if (bytes_transferred == 0)
@ -1109,7 +1114,8 @@ public:
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
if (ec.value() == ERROR_NETNAME_DELETED)
{
if (handler_op->cancel_token_.expired())
@ -1216,7 +1222,8 @@ public:
{
asio::io_service::work work(this->io_service());
ptr.reset();
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
}
else
@ -1262,7 +1269,8 @@ public:
DWORD last_error = ::WSAGetLastError();
if (last_error == ERROR_PORT_UNREACHABLE)
last_error = WSAECONNREFUSED;
ec = asio::error_code(last_error, asio::native_ecat);
ec = asio::error_code(last_error,
asio::error::system_category);
return 0;
}
if (bytes_transferred == 0)
@ -1328,7 +1336,8 @@ public:
#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
// Map non-portable errors to their portable counterparts.
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
if (ec.value() == ERROR_PORT_UNREACHABLE)
{
ec = asio::error::connection_refused;
@ -1422,7 +1431,8 @@ public:
{
asio::io_service::work work(this->io_service());
ptr.reset();
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
}
else
@ -1659,7 +1669,8 @@ public:
ptr.reset();
// Call the handler.
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
asio_handler_invoke_helpers::invoke(
detail::bind_handler(handler, ec), &handler);
}
@ -1759,7 +1770,8 @@ public:
{
asio::io_service::work work(this->io_service());
ptr.reset();
asio::error_code ec(last_error, asio::native_ecat);
asio::error_code ec(last_error,
asio::error::system_category);
iocp_service_.post(bind_handler(handler, ec));
}
}
@ -1835,8 +1847,8 @@ public:
// If connection failed then post the handler with the error code.
if (connect_error)
{
ec = asio::error_code(
connect_error, asio::native_ecat);
ec = asio::error_code(connect_error,
asio::error::system_category);
io_service_.post(bind_handler(handler_, ec));
return true;
}
@ -1950,26 +1962,66 @@ public:
}
private:
// Helper function to provide InterlockedCompareExchangePointer functionality
// on very old Platform SDKs.
// Helper function to close a socket when the associated object is being
// destroyed.
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)
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x400) && (_M_IX86)
#if defined(_M_IX86)
return reinterpret_cast<void*>(InterlockedCompareExchange(
reinterpret_cast<LONG*>(dest), reinterpret_cast<LONG>(exch),
reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),
reinterpret_cast<LONG>(cmp)));
#else
return InterlockedCompareExchangePointer(dest, exch, cmp);
#endif
}
// Helper function to provide InterlockedExchangePointer functionality on very
// old Platform SDKs.
// Helper function to emulate InterlockedExchangePointer functionality for:
// - very old Platform SDKs; and
// - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
void* interlocked_exchange_pointer(void** dest, void* val)
{
#if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x400) && (_M_IX86)
#if defined(_M_IX86)
return reinterpret_cast<void*>(InterlockedExchange(
reinterpret_cast<LONG*>(dest), reinterpret_cast<LONG>(val)));
reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));
#else
return InterlockedExchangePointer(dest, val);
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +0,0 @@
/error_code.ipp/1.6/Sun Mar 25 14:06:36 2007//
/io_service.ipp/1.12/Mon Jan 8 01:04:08 2007//
/read.ipp/1.16/Sat Jan 13 13:30:12 2007//
/read_until.ipp/1.10/Sun Jan 7 08:05:53 2007//
/write.ipp/1.14/Sat Jan 13 13:30:12 2007//
D

View File

@ -1 +0,0 @@
asio/include/asio/impl

View File

@ -1 +0,0 @@
:pserver:anonymous@asio.cvs.sourceforge.net:/cvsroot/asio

View File

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

View File

@ -128,11 +128,11 @@ template <typename Handler>
#if defined(GENERATING_DOCUMENTATION)
unspecified
#else
inline detail::wrapped_handler<io_service, Handler>
inline detail::wrapped_handler<io_service&, Handler>
#endif
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)

View File

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

View File

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

View File

@ -1,17 +0,0 @@
/address.hpp/1.9/Thu Jan 4 05:44:46 2007//
/address_v4.hpp/1.11/Thu Jan 4 05:44:46 2007//
/address_v6.hpp/1.11/Mon Feb 19 01:46:31 2007//
/basic_endpoint.hpp/1.16/Wed Feb 14 13:26:26 2007//
/basic_resolver.hpp/1.5/Thu Jan 4 05:44:46 2007//
/basic_resolver_entry.hpp/1.5/Thu Jan 4 05:44:46 2007//
/basic_resolver_iterator.hpp/1.10/Sun Apr 8 23:47:05 2007//
/basic_resolver_query.hpp/1.12/Thu Jan 4 05:44:46 2007//
/host_name.hpp/1.5/Thu Jan 4 05:44:46 2007//
/multicast.hpp/1.8/Sat Feb 17 22:57:39 2007//
/resolver_query_base.hpp/1.3/Thu Jan 4 05:44:46 2007//
/resolver_service.hpp/1.7/Thu Jan 4 05:44:46 2007//
/tcp.hpp/1.14/Sun May 20 00:49:02 2007//
/udp.hpp/1.12/Sun May 20 00:49:02 2007//
/unicast.hpp/1.2/Sat Feb 17 22:57:39 2007//
/v6_only.hpp/1.2/Sun May 13 07:59:22 2007//
D/detail////

View File

@ -1 +0,0 @@
asio/include/asio/ip

View File

@ -1 +0,0 @@
:pserver:anonymous@asio.cvs.sourceforge.net:/cvsroot/asio

View File

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

View File

@ -1,8 +0,0 @@
/basic_context.hpp/1.11/Thu Dec 21 12:29:03 2006//
/context.hpp/1.3/Mon Apr 10 12:17:44 2006//
/context_base.hpp/1.6/Sun Sep 24 07:46:22 2006//
/context_service.hpp/1.11/Fri Dec 29 02:01:24 2006//
/stream.hpp/1.13/Thu Dec 21 12:29:03 2006//
/stream_base.hpp/1.4/Wed Nov 30 01:57:07 2005//
/stream_service.hpp/1.10/Fri Dec 29 02:01:24 2006//
D/detail////

View File

@ -1 +0,0 @@
asio/include/asio/ssl

View File

@ -1 +0,0 @@
:pserver:anonymous@asio.cvs.sourceforge.net:/cvsroot/asio

View File

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

View File

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

View File

@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
@ -223,7 +224,7 @@ namespace libtorrent
{
block_downloading_alert(
const torrent_handle& h
, std::string& speedmsg
, char const* speedmsg
, int block_num
, int piece_num
, const std::string& msg)
@ -261,6 +262,17 @@ namespace libtorrent
{ 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
{
url_seed_alert(

View File

@ -0,0 +1,52 @@
/*
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 __GNUC__
#ifdef assert
#undef assert
#endif
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,6 +83,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket_type.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
@ -240,12 +241,12 @@ namespace libtorrent
bool is_listening() const;
torrent_handle add_torrent(
torrent_info const& ti
boost::intrusive_ptr<torrent_info> ti
, fs::path const& save_path
, entry const& resume_data
, bool compact_mode
, int block_size
, storage_constructor_type sc);
, storage_constructor_type sc
, bool paused);
torrent_handle add_torrent(
char const* tracker_url
@ -254,8 +255,8 @@ namespace libtorrent
, fs::path const& save_path
, entry const& resume_data
, bool compact_mode
, int block_size
, storage_constructor_type sc);
, storage_constructor_type sc
, bool paused);
void remove_torrent(torrent_handle const& h);
@ -273,8 +274,21 @@ namespace libtorrent
void set_max_connections(int limit);
void set_max_uploads(int limit);
int num_uploads() const;
int num_connections() const;
int max_connections() const { return m_max_connections; }
int max_uploads() const { return m_max_uploads; }
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;
void set_peer_id(peer_id const& id);
@ -417,6 +431,28 @@ namespace libtorrent
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;
@ -459,7 +495,7 @@ namespace libtorrent
// This implements a round robin.
int m_next_connect_torrent;
#ifndef NDEBUG
void check_invariant(const char *place = 0);
void check_invariant() const;
#endif
#ifdef TORRENT_STATS

View File

@ -33,9 +33,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef 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/intrusive_ptr.hpp>
#include <boost/function.hpp>
@ -44,11 +41,17 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/thread/mutex.hpp>
#include <deque>
#include "libtorrent/socket.hpp"
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp"
using boost::weak_ptr;
using boost::shared_ptr;
using boost::intrusive_ptr;
using boost::bind;
//#define TORRENT_VERBOSE_BANDWIDTH_LIMIT
namespace libtorrent {
// the maximum block of bandwidth quota to
@ -237,8 +240,10 @@ struct bandwidth_manager
i = j;
}
}
if (m_queue.size() == 1) hand_out_bandwidth();
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
std::cerr << " req_bandwidht. m_queue.size() = " << m_queue.size() << std::endl;
#endif
if (!m_queue.empty()) hand_out_bandwidth();
}
#ifndef NDEBUG
@ -337,10 +342,18 @@ private:
// available bandwidth to hand out
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)
{
assert(amount == limit - m_current_quota);
bw_queue_entry<PeerConnection> qe = m_queue.front();
assert(qe.max_block_size > 0);
m_queue.pop_front();
shared_ptr<Torrent> t = qe.peer->associated_torrent().lock();
@ -374,13 +387,12 @@ private:
// block size must be smaller for lower rates. This is because
// the history window is one second, and the block will be forgotten
// after one second.
int block_size = (std::min)(qe.max_block_size
, (std::min)(qe.peer->bandwidth_throttle(m_channel)
, m_limit / 10));
int block_size = (std::min)(qe.peer->bandwidth_throttle(m_channel)
, m_limit / 10);
if (block_size < min_bandwidth_block_size)
{
block_size = min_bandwidth_block_size;
block_size = (std::min)(int(min_bandwidth_block_size), m_limit);
}
else if (block_size > max_bandwidth_block_size)
{
@ -399,7 +411,11 @@ private:
/ (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)
{
m_queue.push_front(qe);

View File

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

View File

@ -0,0 +1,80 @@
/*
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);
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);
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,7 +65,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/allocate_resources.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
@ -122,8 +121,16 @@ namespace libtorrent
msg_request,
msg_piece,
msg_cancel,
// DHT extension
msg_dht_port,
// extension protocol message
// FAST extension
msg_suggest_piece = 0xd,
msg_have_all,
msg_have_none,
msg_reject_request,
msg_allowed_fast,
// extension protocol message
msg_extended = 20,
num_supported_messages
@ -174,8 +181,17 @@ namespace libtorrent
void on_request(int received);
void on_piece(int received);
void on_cancel(int received);
// DHT extension
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_handshake();
@ -201,7 +217,16 @@ namespace libtorrent
void write_metadata(std::pair<int, int> req);
void write_metadata_request(std::pair<int, int> req);
void write_keepalive();
// DHT extension
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_metadata();
@ -325,6 +350,7 @@ namespace libtorrent
bool m_supports_extensions;
#endif
bool m_supports_dht_port;
bool m_supports_fast;
#ifndef TORRENT_DISABLE_ENCRYPTION
// this is set to true after the encryption method has been

View File

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

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_CONFIG_HPP_INCLUDED
#include <boost/config.hpp>
#include "libtorrent/assert.hpp"
#if defined(__GNUC__) && __GNUC__ >= 4

View File

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

View File

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

View File

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

View File

@ -0,0 +1,44 @@
/*
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,6 +131,15 @@ namespace libtorrent
virtual bool on_bitfield(std::vector<bool> const& bitfield)
{ 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)
{ return false; }

View File

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

View File

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

View File

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

View File

@ -73,6 +73,8 @@ namespace libtorrent
T header(char const* key) const;
std::string const& protocol() const { return m_protocol; }
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; }
buffer::const_interval get_body() const;
bool header_finished() const { return m_state == read_body; }
@ -85,6 +87,8 @@ namespace libtorrent
private:
int m_recv_pos;
int m_status_code;
std::string m_method;
std::string m_path;
std::string m_protocol;
std::string m_server_message;
@ -176,3 +180,4 @@ namespace libtorrent
#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/broadcast_socket.hpp"
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
@ -58,35 +59,26 @@ public:
, peer_callback_t const& cb);
~lsd();
void rebind(address const& listen_interface);
// void rebind(address const& listen_interface);
void announce(sha1_hash const& ih, int listen_port);
void close();
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 on_announce(asio::error_code const& e
void on_announce(udp::endpoint const& from, char* buffer
, std::size_t bytes_transferred);
void setup_receive();
// void setup_receive();
peer_callback_t m_callback;
// current 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
// multicast messages on
datagram_socket m_socket;
broadcast_socket m_socket;
// used to resend udp packets in case
// they time out

View File

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

View File

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

View File

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

View File

@ -56,10 +56,11 @@ namespace libtorrent
connecting = 0x80,
queued = 0x100,
on_parole = 0x200,
seed = 0x400
seed = 0x400,
optimistic_unchoke = 0x800
#ifndef TORRENT_DISABLE_ENCRYPTION
, rc4_encrypted = 0x800,
plaintext_encrypted = 0x1000
, rc4_encrypted = 0x100000,
plaintext_encrypted = 0x200000
#endif
};
@ -116,6 +117,11 @@ namespace libtorrent
// for yet
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
// the peer has sent to us
// that we haven't sent yet

View File

@ -35,7 +35,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <vector>
#include <bitset>
#include <cassert>
#include <utility>
#ifdef _MSC_VER
@ -52,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
@ -191,11 +191,33 @@ namespace libtorrent
// THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION!
// The last argument is the policy::peer pointer for the peer that
// we'll download from.
void pick_pieces(const std::vector<bool>& pieces
void pick_pieces(std::vector<bool> const& pieces
, std::vector<piece_block>& interesting_blocks
, int num_pieces, bool prefer_whole_pieces
, int num_pieces, int prefer_whole_pieces
, void* peer, piece_state_t speed
, bool rarest_first) const;
, bool rarest_first, bool on_parole
, 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
// peer pointer
@ -253,6 +275,8 @@ namespace libtorrent
#ifndef NDEBUG
// used in debug mode
void check_invariant(const torrent* t = 0) const;
void verify_pick(std::vector<piece_block> const& picked
, std::vector<bool> const& bitfield) const;
#endif
// functor that compares indices on downloading_pieces
@ -271,6 +295,10 @@ namespace libtorrent
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
{
piece_pos() {}
@ -320,9 +348,9 @@ namespace libtorrent
int priority(int limit) const
{
if (filtered() || have()) return 0;
if (downloading || filtered() || have()) return 0;
// pieces we are currently downloading have high priority
int prio = downloading ? (std::min)(1, int(peer_count)) : peer_count * 2;
int prio = peer_count * 2;
// if the peer_count is 0 or 1, the priority cannot be higher
if (prio <= 1) return prio;
if (prio >= limit * 2) prio = limit * 2;
@ -358,14 +386,6 @@ namespace libtorrent
void move(int vec_index, int elem_index);
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();
void erase_download_piece(std::vector<downloading_piece>::iterator i);

View File

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

View File

@ -53,6 +53,7 @@ POSSIBILITY OF SUCH DAMAGE.
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/alert.hpp"
@ -60,7 +61,6 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp"
#include "libtorrent/resource_request.hpp"
#include "libtorrent/storage.hpp"
#ifdef _MSC_VER
@ -141,22 +141,16 @@ namespace libtorrent
, fs::path const& save_path
, entry const& resume_data = entry()
, bool compact_mode = true
, int block_size = 16 * 1024
, storage_constructor_type sc = default_storage_constructor);
, bool paused = false
, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED;
// ==== deprecated, this is for backwards compatibility only
// instead, use one of the other add_torrent overloads
torrent_handle add_torrent(
entry const& e
boost::intrusive_ptr<torrent_info> ti
, fs::path const& save_path
, entry const& resume_data = entry()
, bool compact_mode = true
, int block_size = 16 * 1024
, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED
{
return add_torrent(torrent_info(e), save_path, resume_data
, compact_mode, block_size, sc);
}
, bool paused = false
, storage_constructor_type sc = default_storage_constructor);
torrent_handle add_torrent(
char const* tracker_url
@ -165,7 +159,7 @@ namespace libtorrent
, fs::path const& save_path
, entry const& resume_data = entry()
, bool compact_mode = true
, int block_size = 16 * 1024
, bool paused = false
, storage_constructor_type sc = default_storage_constructor);
session_proxy abort() { return session_proxy(m_impl); }
@ -243,6 +237,7 @@ namespace libtorrent
int upload_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_download_rate_limit(int bytes_per_second);
@ -265,12 +260,6 @@ namespace libtorrent
void stop_natpmp();
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:
// just a way to initialize boost.filesystem

View File

@ -105,9 +105,11 @@ namespace libtorrent
, send_redundant_have(false)
, lazy_bitfields(true)
, inactivity_timeout(600)
, unchoke_interval(20)
, unchoke_interval(15)
, optimistic_unchoke_multiplier(4)
, num_want(200)
, initial_picker_threshold(4)
, allowed_fast_set_size(10)
, max_outstanding_disk_bytes_per_connection(64 * 1024)
#ifndef TORRENT_DISABLE_DHT
, use_dht_as_fallback(true)
@ -241,6 +243,10 @@ namespace libtorrent
// the number of seconds between chokes/unchokes
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
// tracker in the ip= parameter.
address announce_ip;
@ -252,6 +258,10 @@ namespace libtorrent
// random pieces instead of rarest first.
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
// pending in the disk write queue before its download
// rate is being throttled. This prevents fast downloads

View File

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

View File

@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/limits.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/filesystem/path.hpp>
#ifdef _MSC_VER
@ -147,10 +148,11 @@ namespace libtorrent
};
typedef storage_interface* (&storage_constructor_type)(
torrent_info const&, fs::path const&
boost::intrusive_ptr<torrent_info const>, fs::path const&
, file_pool&);
TORRENT_EXPORT storage_interface* default_storage_constructor(torrent_info const& ti
TORRENT_EXPORT storage_interface* default_storage_constructor(
boost::intrusive_ptr<torrent_info const> ti
, fs::path const& path, file_pool& fp);
// returns true if the filesystem the path relies on supports
@ -169,7 +171,7 @@ namespace libtorrent
piece_manager(
boost::shared_ptr<void> const& torrent
, torrent_info const& ti
, boost::intrusive_ptr<torrent_info const> ti
, fs::path const& path
, file_pool& fp
, disk_io_thread& io
@ -199,7 +201,8 @@ namespace libtorrent
void async_read(
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);
void async_write(
peer_request const& r
@ -227,7 +230,7 @@ namespace libtorrent
{ return m_compact_mode; }
#ifndef NDEBUG
std::string name() const { return m_info.name(); }
std::string name() const { return m_info->name(); }
#endif
private:
@ -283,7 +286,7 @@ namespace libtorrent
// a bitmask representing the pieces we have
std::vector<bool> m_have_piece;
torrent_info const& m_info;
boost::intrusive_ptr<torrent_info const> m_info;
// slots that haven't had any file storage allocated
std::vector<int> m_unallocated_slots;
@ -313,12 +316,6 @@ namespace libtorrent
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 {
// the default initial state
state_none,
@ -333,6 +330,11 @@ namespace libtorrent
} m_state;
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;
// this maps a piece hash to piece index. It will be
@ -340,6 +342,8 @@ namespace libtorrent
// isn't needed)
std::multimap<sha1_hash, int> m_hash_to_piece;
// this map contains partial hashes for downloading
// pieces.
std::map<int, partial_hash> m_piece_hasher;
disk_io_thread& m_io_thread;

View File

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

View File

@ -62,13 +62,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/resource_request.hpp"
#include "libtorrent/piece_picker.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/escape_string.hpp"
#include "libtorrent/bandwidth_manager.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp"
namespace libtorrent
{
@ -98,13 +98,13 @@ namespace libtorrent
torrent(
aux::session_impl& ses
, aux::checker_impl& checker
, torrent_info const& tf
, boost::intrusive_ptr<torrent_info> tf
, fs::path const& save_path
, tcp::endpoint const& net_interface
, bool compact_mode
, int block_size
, session_settings const& s
, storage_constructor_type sc);
, storage_constructor_type sc
, bool paused);
// used with metadata-less torrents
// (the metadata is downloaded from the peers)
@ -118,8 +118,8 @@ namespace libtorrent
, tcp::endpoint const& net_interface
, bool compact_mode
, int block_size
, session_settings const& s
, storage_constructor_type sc);
, storage_constructor_type sc
, bool paused);
~torrent();
@ -154,10 +154,6 @@ namespace libtorrent
bool verify_resume_data(entry& rd, std::string& 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);
// debug purpose only
@ -254,6 +250,15 @@ namespace libtorrent
void remove_url_seed(std::string const& 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
// since incoming connections don't know what torrent
// they're a part of until they have received an info_hash.
@ -465,14 +470,14 @@ namespace libtorrent
bool is_seed() const
{
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
bool is_finished() const
{
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;
}
@ -494,7 +499,7 @@ namespace libtorrent
}
piece_manager& filesystem();
torrent_info const& torrent_file() const
{ return m_torrent_file; }
{ return *m_torrent_file; }
std::vector<announce_entry> const& trackers() const
{ return m_trackers; }
@ -516,11 +521,6 @@ namespace libtorrent
// --------------------------------------------
// 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_download_limit(tcp::endpoint ip, int limit);
@ -530,7 +530,9 @@ namespace libtorrent
int download_limit() const;
void set_max_uploads(int limit);
int max_uploads() const { return m_max_uploads; }
void set_max_connections(int limit);
int max_connections() const { return m_max_connections; }
void move_storage(fs::path const& save_path);
// unless this returns true, new connections must wait
@ -538,7 +540,7 @@ namespace libtorrent
bool ready_for_connections() const
{ return m_connections_initialized; }
bool valid_metadata() const
{ return m_torrent_file.is_valid(); }
{ return m_torrent_file->is_valid(); }
// parses the info section from the given
// bencoded tree and moves the torrent
@ -562,7 +564,7 @@ namespace libtorrent
void update_peer_interest();
torrent_info m_torrent_file;
boost::intrusive_ptr<torrent_info> m_torrent_file;
// is set to true when the torrent has
// been aborted.
@ -705,9 +707,9 @@ namespace libtorrent
// determine the timeout until next try.
int m_failed_trackers;
// this is a counter that is increased every
// second, and when it reaches 10, the policy::pulse()
// is called and the time scaler is reset to 0.
// this is a counter that is decreased every
// second, and when it reaches 0, the policy::pulse()
// is called and the time scaler is reset to 10.
int m_time_scaler;
// the bitmask that says which pieces we have
@ -774,6 +776,15 @@ namespace libtorrent
session_settings const& m_settings;
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
typedef std::list<boost::shared_ptr<torrent_plugin> > extension_list_t;

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED
#include <vector>
#include <set>
#ifdef _MSC_VER
#pragma warning(push, 1)
@ -273,7 +274,9 @@ namespace libtorrent
std::vector<announce_entry> const& trackers() const;
void replace_trackers(std::vector<announce_entry> const&) const;
void add_url_seed(std::string const& url);
void add_url_seed(std::string const& url) const;
void remove_url_seed(std::string const& url) const;
std::set<std::string> url_seeds() const;
bool has_metadata() const;
const torrent_info& get_torrent_info() const;

View File

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

View File

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

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