mirror of
https://github.com/codex-storage/deluge.git
synced 2025-02-26 10:05:19 +00:00
sync lt and asio 1615 and upload version # of plugin
This commit is contained in:
parent
c0d8bf2d7f
commit
3de1cb9938
219
libtorrent/include/libtorrent/asio/detail/handler_queue.hpp
Normal file
219
libtorrent/include/libtorrent/asio/detail/handler_queue.hpp
Normal file
@ -0,0 +1,219 @@
|
||||
//
|
||||
// handler_queue.hpp
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_HANDLER_QUEUE_HPP
|
||||
#define ASIO_DETAIL_HANDLER_QUEUE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class handler_queue
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// Base class for handlers in the queue.
|
||||
class handler
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
void invoke()
|
||||
{
|
||||
invoke_func_(this);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
destroy_func_(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef void (*invoke_func_type)(handler*);
|
||||
typedef void (*destroy_func_type)(handler*);
|
||||
|
||||
handler(invoke_func_type invoke_func,
|
||||
destroy_func_type destroy_func)
|
||||
: next_(0),
|
||||
invoke_func_(invoke_func),
|
||||
destroy_func_(destroy_func)
|
||||
{
|
||||
}
|
||||
|
||||
~handler()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class handler_queue;
|
||||
handler* next_;
|
||||
invoke_func_type invoke_func_;
|
||||
destroy_func_type destroy_func_;
|
||||
};
|
||||
|
||||
// Smart point to manager handler lifetimes.
|
||||
class scoped_ptr
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
explicit scoped_ptr(handler* h)
|
||||
: handler_(h)
|
||||
{
|
||||
}
|
||||
|
||||
~scoped_ptr()
|
||||
{
|
||||
if (handler_)
|
||||
handler_->destroy();
|
||||
}
|
||||
|
||||
handler* get() const
|
||||
{
|
||||
return handler_;
|
||||
}
|
||||
|
||||
handler* release()
|
||||
{
|
||||
handler* tmp = handler_;
|
||||
handler_ = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
handler* handler_;
|
||||
};
|
||||
|
||||
// Constructor.
|
||||
handler_queue()
|
||||
: front_(0),
|
||||
back_(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Wrap a handler to be pushed into the queue.
|
||||
template <typename Handler>
|
||||
static handler* wrap(Handler h)
|
||||
{
|
||||
// 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(h);
|
||||
handler_ptr<alloc_traits> ptr(raw_ptr, h);
|
||||
return ptr.release();
|
||||
}
|
||||
|
||||
// Get the handler at the front of the queue.
|
||||
handler* front()
|
||||
{
|
||||
return front_;
|
||||
}
|
||||
|
||||
// Pop a handler from the front of the queue.
|
||||
void pop()
|
||||
{
|
||||
if (front_)
|
||||
{
|
||||
handler* tmp = front_;
|
||||
front_ = front_->next_;
|
||||
if (front_ == 0)
|
||||
back_ = 0;
|
||||
tmp->next_= 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Push a handler on to the back of the queue.
|
||||
void push(handler* h)
|
||||
{
|
||||
h->next_ = 0;
|
||||
if (back_)
|
||||
{
|
||||
back_->next_ = h;
|
||||
back_ = h;
|
||||
}
|
||||
else
|
||||
{
|
||||
front_ = back_ = h;
|
||||
}
|
||||
}
|
||||
|
||||
// Whether the queue is empty.
|
||||
bool empty() const
|
||||
{
|
||||
return front_ == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
// Template wrapper for handlers.
|
||||
template <typename Handler>
|
||||
class handler_wrapper
|
||||
: public handler
|
||||
{
|
||||
public:
|
||||
handler_wrapper(Handler h)
|
||||
: handler(
|
||||
&handler_wrapper<Handler>::do_call,
|
||||
&handler_wrapper<Handler>::do_destroy),
|
||||
handler_(h)
|
||||
{
|
||||
}
|
||||
|
||||
static void do_call(handler* base)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
typedef handler_wrapper<Handler> this_type;
|
||||
this_type* h(static_cast<this_type*>(base));
|
||||
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made.
|
||||
Handler handler(h->handler_);
|
||||
|
||||
// Free the memory associated with the handler.
|
||||
ptr.reset();
|
||||
|
||||
// Make the upcall.
|
||||
asio_handler_invoke_helpers::invoke(handler, &handler);
|
||||
}
|
||||
|
||||
static void do_destroy(handler* base)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
typedef handler_wrapper<Handler> this_type;
|
||||
this_type* h(static_cast<this_type*>(base));
|
||||
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
// The front of the queue.
|
||||
handler* front_;
|
||||
|
||||
// The back of the queue.
|
||||
handler* back_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_HANDLER_QUEUE_HPP
|
@ -450,7 +450,7 @@ public:
|
||||
}
|
||||
|
||||
endpoint_type endpoint;
|
||||
socket_addr_len_type addr_len = endpoint.capacity();
|
||||
std::size_t addr_len = endpoint.capacity();
|
||||
if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
|
||||
return endpoint_type();
|
||||
endpoint.resize(addr_len);
|
||||
@ -468,7 +468,7 @@ public:
|
||||
}
|
||||
|
||||
endpoint_type endpoint;
|
||||
socket_addr_len_type addr_len = endpoint.capacity();
|
||||
std::size_t addr_len = endpoint.capacity();
|
||||
if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
|
||||
return endpoint_type();
|
||||
endpoint.resize(addr_len);
|
||||
@ -1073,7 +1073,7 @@ public:
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
socket_addr_len_type addr_len = sender_endpoint.capacity();
|
||||
std::size_t addr_len = sender_endpoint.capacity();
|
||||
int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags,
|
||||
sender_endpoint.data(), &addr_len, ec);
|
||||
|
||||
@ -1144,7 +1144,7 @@ public:
|
||||
}
|
||||
|
||||
// Receive some data.
|
||||
socket_addr_len_type addr_len = sender_endpoint_.capacity();
|
||||
std::size_t addr_len = sender_endpoint_.capacity();
|
||||
asio::error_code ec;
|
||||
int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
|
||||
sender_endpoint_.data(), &addr_len, ec);
|
||||
@ -1242,7 +1242,7 @@ public:
|
||||
// Try to complete the operation without blocking.
|
||||
asio::error_code ec;
|
||||
socket_holder new_socket;
|
||||
socket_addr_len_type addr_len = 0;
|
||||
std::size_t addr_len = 0;
|
||||
if (peer_endpoint)
|
||||
{
|
||||
addr_len = peer_endpoint->capacity();
|
||||
@ -1327,7 +1327,7 @@ public:
|
||||
// Accept the waiting connection.
|
||||
asio::error_code ec;
|
||||
socket_holder new_socket;
|
||||
socket_addr_len_type addr_len = 0;
|
||||
std::size_t addr_len = 0;
|
||||
if (peer_endpoint_)
|
||||
{
|
||||
addr_len = peer_endpoint_->capacity();
|
||||
|
@ -26,9 +26,6 @@
|
||||
#include <cerrno>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <new>
|
||||
#if defined(__MACH__) && defined(__APPLE__)
|
||||
# include <AvailabilityMacros.h>
|
||||
#endif // defined(__MACH__) && defined(__APPLE__)
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error.hpp"
|
||||
@ -38,6 +35,10 @@ namespace asio {
|
||||
namespace detail {
|
||||
namespace socket_ops {
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
struct msghdr { int msg_namelen; };
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
||||
inline void clear_error(asio::error_code& ec)
|
||||
{
|
||||
errno = 0;
|
||||
@ -60,15 +61,28 @@ inline ReturnType error_wrapper(ReturnType return_value,
|
||||
return return_value;
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline socket_type call_accept(SockLenType msghdr::*,
|
||||
socket_type s, socket_addr_type* addr, std::size_t* addrlen)
|
||||
{
|
||||
SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
|
||||
socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
|
||||
if (addrlen)
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline socket_type accept(socket_type s, socket_addr_type* addr,
|
||||
socket_addr_len_type* addrlen, asio::error_code& ec)
|
||||
std::size_t* addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
|
||||
socket_type new_s = error_wrapper(::accept(s, addr, addrlen), ec);
|
||||
|
||||
socket_type new_s = error_wrapper(call_accept(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
if (new_s == invalid_socket)
|
||||
return new_s;
|
||||
|
||||
#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
|
||||
int optval = 1;
|
||||
int result = error_wrapper(::setsockopt(new_s,
|
||||
SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
|
||||
@ -77,18 +91,23 @@ inline socket_type accept(socket_type s, socket_addr_type* addr,
|
||||
::close(new_s);
|
||||
return invalid_socket;
|
||||
}
|
||||
#endif
|
||||
|
||||
return new_s;
|
||||
#else
|
||||
return error_wrapper(::accept(s, addr, addrlen), ec);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_bind(SockLenType msghdr::*,
|
||||
socket_type s, const socket_addr_type* addr, std::size_t addrlen)
|
||||
{
|
||||
return ::bind(s, addr, (SockLenType)addrlen);
|
||||
}
|
||||
|
||||
inline int bind(socket_type s, const socket_addr_type* addr,
|
||||
socket_addr_len_type addrlen, asio::error_code& ec)
|
||||
std::size_t addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::bind(s, addr, addrlen), ec);
|
||||
return error_wrapper(call_bind(&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
}
|
||||
|
||||
inline int close(socket_type s, asio::error_code& ec)
|
||||
@ -107,11 +126,19 @@ inline int shutdown(socket_type s, int what, asio::error_code& ec)
|
||||
return error_wrapper(::shutdown(s, what), ec);
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_connect(SockLenType msghdr::*,
|
||||
socket_type s, const socket_addr_type* addr, std::size_t addrlen)
|
||||
{
|
||||
return ::connect(s, addr, (SockLenType)addrlen);
|
||||
}
|
||||
|
||||
inline int connect(socket_type s, const socket_addr_type* addr,
|
||||
socket_addr_len_type addrlen, asio::error_code& ec)
|
||||
std::size_t addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::connect(s, addr, addrlen), ec);
|
||||
return error_wrapper(call_connect(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
}
|
||||
|
||||
inline int listen(socket_type s, int backlog, asio::error_code& ec)
|
||||
@ -148,6 +175,28 @@ inline void init_buf(buf& b, const void* data, size_t size)
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
|
||||
{
|
||||
name = addr;
|
||||
}
|
||||
|
||||
inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
|
||||
{
|
||||
name = const_cast<socket_addr_type*>(addr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
|
||||
{
|
||||
name = reinterpret_cast<T>(addr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
|
||||
{
|
||||
name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
|
||||
}
|
||||
|
||||
inline int recv(socket_type s, buf* bufs, size_t count, int flags,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
@ -163,20 +212,15 @@ inline int recv(socket_type s, buf* bufs, size_t count, int flags,
|
||||
return -1;
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg;
|
||||
msg.msg_name = 0;
|
||||
msg.msg_namelen = 0;
|
||||
msghdr msg = msghdr();
|
||||
msg.msg_iov = bufs;
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
return error_wrapper(::recvmsg(s, &msg, flags), ec);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
|
||||
socket_addr_type* addr, socket_addr_len_type* addrlen,
|
||||
socket_addr_type* addr, std::size_t* addrlen,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
@ -185,25 +229,19 @@ inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
|
||||
DWORD recv_buf_count = static_cast<DWORD>(count);
|
||||
DWORD bytes_transferred = 0;
|
||||
DWORD recv_flags = flags;
|
||||
int tmp_addrlen = (int)*addrlen;
|
||||
int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
|
||||
&bytes_transferred, &recv_flags, addr, addrlen, 0, 0), ec);
|
||||
&bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
if (result != 0)
|
||||
return -1;
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg;
|
||||
#if defined(__MACH__) && defined(__APPLE__) \
|
||||
&& (MAC_OS_X_VERSION_MAX_ALLOWED < 1040)
|
||||
msg.msg_name = reinterpret_cast<char*>(addr);
|
||||
#else
|
||||
msg.msg_name = addr;
|
||||
#endif
|
||||
msghdr msg = msghdr();
|
||||
init_msghdr_msg_name(msg.msg_name, addr);
|
||||
msg.msg_namelen = *addrlen;
|
||||
msg.msg_iov = bufs;
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
|
||||
*addrlen = msg.msg_namelen;
|
||||
return result;
|
||||
@ -225,14 +263,9 @@ inline int send(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
return -1;
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg;
|
||||
msg.msg_name = 0;
|
||||
msg.msg_namelen = 0;
|
||||
msghdr msg = msghdr();
|
||||
msg.msg_iov = const_cast<buf*>(bufs);
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
#if defined(__linux__)
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif // defined(__linux__)
|
||||
@ -241,7 +274,7 @@ inline int send(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
}
|
||||
|
||||
inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
const socket_addr_type* addr, socket_addr_len_type addrlen,
|
||||
const socket_addr_type* addr, std::size_t addrlen,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
@ -255,19 +288,11 @@ inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
return -1;
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg;
|
||||
#if defined(__MACH__) && defined(__APPLE__) \
|
||||
&& (MAC_OS_X_VERSION_MAX_ALLOWED < 1040)
|
||||
msg.msg_name = reinterpret_cast<char*>(const_cast<socket_addr_type*>(addr));
|
||||
#else
|
||||
msg.msg_name = const_cast<socket_addr_type*>(addr);
|
||||
#endif
|
||||
msghdr msg = msghdr();
|
||||
init_msghdr_msg_name(msg.msg_name, addr);
|
||||
msg.msg_namelen = addrlen;
|
||||
msg.msg_iov = const_cast<buf*>(bufs);
|
||||
msg.msg_iovlen = count;
|
||||
msg.msg_control = 0;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_flags = 0;
|
||||
#if defined(__linux__)
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif // defined(__linux__)
|
||||
@ -316,8 +341,17 @@ inline socket_type socket(int af, int type, int protocol,
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_setsockopt(SockLenType msghdr::*,
|
||||
socket_type s, int level, int optname,
|
||||
const void* optval, std::size_t optlen)
|
||||
{
|
||||
return ::setsockopt(s, level, optname,
|
||||
(const char*)optval, (SockLenType)optlen);
|
||||
}
|
||||
|
||||
inline int setsockopt(socket_type s, int level, int optname,
|
||||
const void* optval, size_t optlen, asio::error_code& ec)
|
||||
const void* optval, std::size_t optlen, asio::error_code& ec)
|
||||
{
|
||||
if (level == custom_socket_option_level && optname == always_fail_option)
|
||||
{
|
||||
@ -342,15 +376,22 @@ inline int setsockopt(socket_type s, int level, int optname,
|
||||
}
|
||||
ec = asio::error::fault;
|
||||
return -1;
|
||||
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
#else // defined(__BORLANDC__)
|
||||
clear_error(ec);
|
||||
return error_wrapper(::setsockopt(s, level, optname,
|
||||
reinterpret_cast<const char*>(optval), static_cast<int>(optlen)), ec);
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
clear_error(ec);
|
||||
return error_wrapper(::setsockopt(s, level, optname, optval,
|
||||
static_cast<socklen_t>(optlen)), ec);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return error_wrapper(call_setsockopt(&msghdr::msg_namelen,
|
||||
s, level, optname, optval, optlen), ec);
|
||||
#endif // defined(__BORLANDC__)
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_getsockopt(SockLenType msghdr::*,
|
||||
socket_type s, int level, int optname,
|
||||
void* optval, std::size_t* optlen)
|
||||
{
|
||||
SockLenType tmp_optlen = (SockLenType)*optlen;
|
||||
int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
|
||||
*optlen = (std::size_t)tmp_optlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
||||
@ -394,10 +435,8 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
||||
return -1;
|
||||
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
clear_error(ec);
|
||||
int tmp_optlen = static_cast<int>(*optlen);
|
||||
int result = error_wrapper(::getsockopt(s, level, optname,
|
||||
reinterpret_cast<char*>(optval), &tmp_optlen), ec);
|
||||
*optlen = static_cast<size_t>(tmp_optlen);
|
||||
int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
|
||||
s, level, optname, optval, optlen), ec);
|
||||
if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
|
||||
&& ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
|
||||
{
|
||||
@ -412,10 +451,8 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
clear_error(ec);
|
||||
socklen_t tmp_optlen = static_cast<socklen_t>(*optlen);
|
||||
int result = error_wrapper(::getsockopt(s, level, optname,
|
||||
optval, &tmp_optlen), ec);
|
||||
*optlen = static_cast<size_t>(tmp_optlen);
|
||||
int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
|
||||
s, level, optname, optval, optlen), ec);
|
||||
#if defined(__linux__)
|
||||
if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
|
||||
&& (optname == SO_SNDBUF || optname == SO_RCVBUF))
|
||||
@ -432,18 +469,40 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_getpeername(SockLenType msghdr::*,
|
||||
socket_type s, socket_addr_type* addr, std::size_t* addrlen)
|
||||
{
|
||||
SockLenType tmp_addrlen = (SockLenType)*addrlen;
|
||||
int result = ::getpeername(s, addr, &tmp_addrlen);
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int getpeername(socket_type s, socket_addr_type* addr,
|
||||
socket_addr_len_type* addrlen, asio::error_code& ec)
|
||||
std::size_t* addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::getpeername(s, addr, addrlen), ec);
|
||||
return error_wrapper(call_getpeername(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
}
|
||||
|
||||
template <typename SockLenType>
|
||||
inline int call_getsockname(SockLenType msghdr::*,
|
||||
socket_type s, socket_addr_type* addr, std::size_t* addrlen)
|
||||
{
|
||||
SockLenType tmp_addrlen = (SockLenType)*addrlen;
|
||||
int result = ::getsockname(s, addr, &tmp_addrlen);
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int getsockname(socket_type s, socket_addr_type* addr,
|
||||
socket_addr_len_type* addrlen, asio::error_code& ec)
|
||||
std::size_t* addrlen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
return error_wrapper(::getsockname(s, addr, addrlen), ec);
|
||||
return error_wrapper(call_getsockname(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
}
|
||||
|
||||
inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
|
||||
@ -1373,7 +1432,7 @@ inline int getaddrinfo_emulation(const char* host, const char* service,
|
||||
}
|
||||
|
||||
inline asio::error_code getnameinfo_emulation(
|
||||
const socket_addr_type* sa, socket_addr_len_type salen, char* host,
|
||||
const socket_addr_type* sa, std::size_t salen, char* host,
|
||||
std::size_t hostlen, char* serv, std::size_t servlen, int flags,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
@ -1595,7 +1654,7 @@ inline void freeaddrinfo(addrinfo_type* ai)
|
||||
}
|
||||
|
||||
inline asio::error_code getnameinfo(const socket_addr_type* addr,
|
||||
socket_addr_len_type addrlen, char* host, std::size_t hostlen,
|
||||
std::size_t addrlen, char* host, std::size_t hostlen,
|
||||
char* serv, std::size_t servlen, int flags, asio::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
@ -1608,7 +1667,7 @@ inline asio::error_code getnameinfo(const socket_addr_type* addr,
|
||||
# else
|
||||
// Building for Windows 2000 or earlier.
|
||||
typedef int (WSAAPI *gni_t)(const socket_addr_type*,
|
||||
socket_addr_len_type, char*, std::size_t, char*, std::size_t, int);
|
||||
int, char*, std::size_t, char*, std::size_t, int);
|
||||
if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
|
||||
{
|
||||
if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
|
||||
@ -1662,6 +1721,8 @@ inline u_short_type host_to_network_short(u_short_type value)
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#undef ASIO_SOCKET_CALL
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_SOCKET_OPS_HPP
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
|
||||
using namespace std; // For memset.
|
||||
sockaddr_in4_type addr;
|
||||
socket_addr_len_type addr_len = sizeof(addr);
|
||||
std::size_t addr_len = sizeof(addr);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
@ -116,7 +116,6 @@ const int socket_error_retval = SOCKET_ERROR;
|
||||
const int max_addr_v4_str_len = 256;
|
||||
const int max_addr_v6_str_len = 256;
|
||||
typedef sockaddr socket_addr_type;
|
||||
typedef int socket_addr_len_type;
|
||||
typedef in_addr in4_addr_type;
|
||||
typedef ip_mreq in4_mreq_type;
|
||||
typedef sockaddr_in sockaddr_in4_type;
|
||||
@ -154,7 +153,6 @@ const int socket_error_retval = -1;
|
||||
const int max_addr_v4_str_len = INET_ADDRSTRLEN;
|
||||
const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
|
||||
typedef sockaddr socket_addr_type;
|
||||
typedef socklen_t socket_addr_len_type;
|
||||
typedef in_addr in4_addr_type;
|
||||
typedef ip_mreq in4_mreq_type;
|
||||
typedef sockaddr_in sockaddr_in4_type;
|
||||
|
@ -135,9 +135,9 @@ public:
|
||||
handler_base* last_waiter_;
|
||||
|
||||
// Storage for posted handlers.
|
||||
typedef boost::aligned_storage<64> handler_storage_type;
|
||||
typedef boost::aligned_storage<128> handler_storage_type;
|
||||
#if defined(__BORLANDC__)
|
||||
boost::aligned_storage<64> handler_storage_;
|
||||
boost::aligned_storage<128> handler_storage_;
|
||||
#else
|
||||
handler_storage_type handler_storage_;
|
||||
#endif
|
||||
@ -235,7 +235,7 @@ public:
|
||||
void* do_handler_allocate(std::size_t size)
|
||||
{
|
||||
#if defined(__BORLANDC__)
|
||||
BOOST_ASSERT(size <= boost::aligned_storage<64>::size);
|
||||
BOOST_ASSERT(size <= boost::aligned_storage<128>::size);
|
||||
#else
|
||||
BOOST_ASSERT(size <= strand_impl::handler_storage_type::size);
|
||||
#endif
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "asio/detail/event.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/handler_queue.hpp"
|
||||
#include "asio/detail/mutex.hpp"
|
||||
#include "asio/detail/service_base.hpp"
|
||||
#include "asio/detail/task_io_service_fwd.hpp"
|
||||
@ -42,12 +43,11 @@ public:
|
||||
task_(use_service<Task>(io_service)),
|
||||
task_interrupted_(true),
|
||||
outstanding_work_(0),
|
||||
handler_queue_(&task_handler_),
|
||||
handler_queue_end_(&task_handler_),
|
||||
stopped_(false),
|
||||
shutdown_(false),
|
||||
first_idle_thread_(0)
|
||||
{
|
||||
handler_queue_.push(&task_handler_);
|
||||
}
|
||||
|
||||
void init(size_t /*concurrency_hint*/)
|
||||
@ -62,17 +62,16 @@ public:
|
||||
lock.unlock();
|
||||
|
||||
// Destroy handler objects.
|
||||
while (handler_queue_)
|
||||
while (!handler_queue_.empty())
|
||||
{
|
||||
handler_base* h = handler_queue_;
|
||||
handler_queue_ = h->next_;
|
||||
handler_queue::handler* h = handler_queue_.front();
|
||||
handler_queue_.pop();
|
||||
if (h != &task_handler_)
|
||||
h->destroy();
|
||||
}
|
||||
|
||||
// Reset handler queue to initial state.
|
||||
handler_queue_ = &task_handler_;
|
||||
handler_queue_end_ = &task_handler_;
|
||||
handler_queue_.push(&task_handler_);
|
||||
}
|
||||
|
||||
// Run the event loop until interrupted or no more work.
|
||||
@ -173,10 +172,7 @@ public:
|
||||
void post(Handler handler)
|
||||
{
|
||||
// Allocate and construct an operation 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);
|
||||
handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
|
||||
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
@ -185,15 +181,7 @@ public:
|
||||
return;
|
||||
|
||||
// Add the handler to the end of the queue.
|
||||
if (handler_queue_end_)
|
||||
{
|
||||
handler_queue_end_->next_ = ptr.get();
|
||||
handler_queue_end_ = ptr.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
handler_queue_ = handler_queue_end_ = ptr.get();
|
||||
}
|
||||
handler_queue_.push(ptr.get());
|
||||
ptr.release();
|
||||
|
||||
// An undelivered handler is treated as unfinished work.
|
||||
@ -227,18 +215,15 @@ private:
|
||||
bool task_has_run = false;
|
||||
while (!stopped_)
|
||||
{
|
||||
if (handler_queue_)
|
||||
if (!handler_queue_.empty())
|
||||
{
|
||||
// Prepare to execute first handler from queue.
|
||||
handler_base* h = handler_queue_;
|
||||
handler_queue_ = h->next_;
|
||||
if (handler_queue_ == 0)
|
||||
handler_queue_end_ = 0;
|
||||
h->next_ = 0;
|
||||
handler_queue::handler* h = handler_queue_.front();
|
||||
handler_queue_.pop();
|
||||
|
||||
if (h == &task_handler_)
|
||||
{
|
||||
bool more_handlers = (handler_queue_ != 0);
|
||||
bool more_handlers = (!handler_queue_.empty());
|
||||
task_interrupted_ = more_handlers || polling;
|
||||
lock.unlock();
|
||||
|
||||
@ -263,7 +248,7 @@ private:
|
||||
handler_cleanup c(lock, *this);
|
||||
|
||||
// Invoke the handler. May throw an exception.
|
||||
h->call(); // call() deletes the handler object
|
||||
h->invoke(); // invoke() deletes the handler object
|
||||
|
||||
ec = asio::error_code();
|
||||
return 1;
|
||||
@ -330,93 +315,6 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
class task_cleanup;
|
||||
friend class task_cleanup;
|
||||
|
||||
// The base class for all handler wrappers. A function pointer is used
|
||||
// instead of virtual functions to avoid the associated overhead.
|
||||
class handler_base
|
||||
{
|
||||
public:
|
||||
typedef void (*call_func_type)(handler_base*);
|
||||
typedef void (*destroy_func_type)(handler_base*);
|
||||
|
||||
handler_base(call_func_type call_func, destroy_func_type destroy_func)
|
||||
: next_(0),
|
||||
call_func_(call_func),
|
||||
destroy_func_(destroy_func)
|
||||
{
|
||||
}
|
||||
|
||||
void call()
|
||||
{
|
||||
call_func_(this);
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
destroy_func_(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Prevent deletion through this type.
|
||||
~handler_base()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class task_io_service<Task>;
|
||||
friend class task_cleanup;
|
||||
handler_base* next_;
|
||||
call_func_type call_func_;
|
||||
destroy_func_type destroy_func_;
|
||||
};
|
||||
|
||||
// Template wrapper for handlers.
|
||||
template <typename Handler>
|
||||
class handler_wrapper
|
||||
: public handler_base
|
||||
{
|
||||
public:
|
||||
handler_wrapper(Handler handler)
|
||||
: handler_base(&handler_wrapper<Handler>::do_call,
|
||||
&handler_wrapper<Handler>::do_destroy),
|
||||
handler_(handler)
|
||||
{
|
||||
}
|
||||
|
||||
static void do_call(handler_base* base)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
typedef handler_wrapper<Handler> this_type;
|
||||
this_type* h(static_cast<this_type*>(base));
|
||||
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made.
|
||||
Handler handler(h->handler_);
|
||||
|
||||
// Free the memory associated with the handler.
|
||||
ptr.reset();
|
||||
|
||||
// Make the upcall.
|
||||
asio_handler_invoke_helpers::invoke(handler, &handler);
|
||||
}
|
||||
|
||||
static void do_destroy(handler_base* base)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
typedef handler_wrapper<Handler> this_type;
|
||||
this_type* h(static_cast<this_type*>(base));
|
||||
typedef handler_alloc_traits<Handler, this_type> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
// Helper class to perform task-related operations on block exit.
|
||||
class task_cleanup
|
||||
{
|
||||
@ -433,20 +331,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_)
|
||||
{
|
||||
task_io_service_.handler_queue_end_->next_
|
||||
= &task_io_service_.task_handler_;
|
||||
task_io_service_.handler_queue_end_
|
||||
= &task_io_service_.task_handler_;
|
||||
}
|
||||
else
|
||||
{
|
||||
task_io_service_.handler_queue_
|
||||
= task_io_service_.handler_queue_end_
|
||||
= &task_io_service_.task_handler_;
|
||||
}
|
||||
task_io_service_.handler_queue_.push(&task_io_service_.task_handler_);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -487,11 +372,11 @@ private:
|
||||
|
||||
// Handler object to represent the position of the task in the queue.
|
||||
class task_handler
|
||||
: public handler_base
|
||||
: public handler_queue::handler
|
||||
{
|
||||
public:
|
||||
task_handler()
|
||||
: handler_base(0, 0)
|
||||
: handler_queue::handler(0, 0)
|
||||
{
|
||||
}
|
||||
} task_handler_;
|
||||
@ -502,11 +387,8 @@ private:
|
||||
// The count of unfinished work.
|
||||
int outstanding_work_;
|
||||
|
||||
// The start of a linked list of handlers that are ready to be delivered.
|
||||
handler_base* handler_queue_;
|
||||
|
||||
// The end of a linked list of handlers that are ready to be delivered.
|
||||
handler_base* handler_queue_end_;
|
||||
// The queue of handlers that are ready to be delivered.
|
||||
handler_queue handler_queue_;
|
||||
|
||||
// Flag to indicate that the dispatcher has been stopped.
|
||||
bool stopped_;
|
||||
|
@ -561,7 +561,7 @@ public:
|
||||
}
|
||||
|
||||
endpoint_type endpoint;
|
||||
socket_addr_len_type addr_len = endpoint.capacity();
|
||||
std::size_t addr_len = endpoint.capacity();
|
||||
if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
|
||||
return endpoint_type();
|
||||
endpoint.resize(addr_len);
|
||||
@ -600,7 +600,7 @@ public:
|
||||
else
|
||||
{
|
||||
endpoint_type endpoint;
|
||||
socket_addr_len_type addr_len = endpoint.capacity();
|
||||
std::size_t addr_len = endpoint.capacity();
|
||||
if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
|
||||
return endpoint_type();
|
||||
endpoint.resize(addr_len);
|
||||
@ -1261,7 +1261,7 @@ public:
|
||||
// Receive some data.
|
||||
DWORD bytes_transferred = 0;
|
||||
DWORD recv_flags = flags;
|
||||
int endpoint_size = sender_endpoint.capacity();
|
||||
int endpoint_size = static_cast<int>(sender_endpoint.capacity());
|
||||
int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
|
||||
&recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0);
|
||||
if (result != 0)
|
||||
@ -1279,7 +1279,7 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
sender_endpoint.resize(endpoint_size);
|
||||
sender_endpoint.resize(static_cast<std::size_t>(endpoint_size));
|
||||
|
||||
ec = asio::error_code();
|
||||
return bytes_transferred;
|
||||
@ -1299,7 +1299,7 @@ public:
|
||||
&receive_from_operation<
|
||||
MutableBufferSequence, Handler>::destroy_impl),
|
||||
endpoint_(endpoint),
|
||||
endpoint_size_(endpoint.capacity()),
|
||||
endpoint_size_(static_cast<int>(endpoint.capacity())),
|
||||
work_(io_service),
|
||||
buffers_(buffers),
|
||||
handler_(handler)
|
||||
@ -1463,7 +1463,7 @@ public:
|
||||
{
|
||||
asio::error_code ec;
|
||||
socket_holder new_socket;
|
||||
socket_addr_len_type addr_len = 0;
|
||||
std::size_t addr_len = 0;
|
||||
if (peer_endpoint)
|
||||
{
|
||||
addr_len = peer_endpoint->capacity();
|
||||
@ -1618,7 +1618,8 @@ public:
|
||||
GetAcceptExSockaddrs(handler_op->output_buffer(), 0,
|
||||
handler_op->address_length(), handler_op->address_length(),
|
||||
&local_addr, &local_addr_length, &remote_addr, &remote_addr_length);
|
||||
if (remote_addr_length > peer_endpoint.capacity())
|
||||
if (static_cast<std::size_t>(remote_addr_length)
|
||||
> peer_endpoint.capacity())
|
||||
{
|
||||
last_error = WSAEINVAL;
|
||||
}
|
||||
@ -1626,7 +1627,7 @@ public:
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
|
||||
peer_endpoint.resize(remote_addr_length);
|
||||
peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,9 @@ namespace error
|
||||
};
|
||||
} // namespace error
|
||||
|
||||
/// Bring error category type into the asio namespace.
|
||||
typedef asio::error::error_category error_category;
|
||||
|
||||
/// Class to represent an error code value.
|
||||
class error_code
|
||||
{
|
||||
@ -69,7 +72,7 @@ public:
|
||||
}
|
||||
|
||||
/// Construct with specific error code and category.
|
||||
error_code(value_type v, error::error_category c)
|
||||
error_code(value_type v, error_category c)
|
||||
: value_(v),
|
||||
category_(c)
|
||||
{
|
||||
@ -89,7 +92,7 @@ public:
|
||||
}
|
||||
|
||||
/// Get the error category.
|
||||
error::error_category category() const
|
||||
error_category category() const
|
||||
{
|
||||
return category_;
|
||||
}
|
||||
@ -135,7 +138,7 @@ private:
|
||||
value_type value_;
|
||||
|
||||
// The category associated with the error code.
|
||||
error::error_category category_;
|
||||
error_category category_;
|
||||
};
|
||||
|
||||
} // namespace asio
|
||||
|
@ -39,6 +39,11 @@
|
||||
|
||||
namespace asio {
|
||||
|
||||
class io_service;
|
||||
template <typename Service> Service& use_service(io_service& ios);
|
||||
template <typename Service> void add_service(io_service& ios, Service* svc);
|
||||
template <typename Service> bool has_service(io_service& ios);
|
||||
|
||||
/// Provides core I/O functionality.
|
||||
/**
|
||||
* The io_service class provides the core I/O functionality for users of the
|
||||
|
@ -268,7 +268,12 @@ std::basic_ostream<Elem, Traits>& operator<<(
|
||||
asio::error_code ec;
|
||||
std::string s = addr.to_string(ec);
|
||||
if (ec)
|
||||
os.setstate(std::ios_base::failbit);
|
||||
{
|
||||
if (os.exceptions() & std::ios::failbit)
|
||||
asio::detail::throw_error(ec);
|
||||
else
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
else
|
||||
for (std::string::iterator i = s.begin(); i != s.end(); ++i)
|
||||
os << os.widen(*i);
|
||||
|
@ -386,7 +386,12 @@ std::basic_ostream<Elem, Traits>& operator<<(
|
||||
asio::error_code ec;
|
||||
std::string s = addr.to_string(ec);
|
||||
if (ec)
|
||||
os.setstate(std::ios_base::failbit);
|
||||
{
|
||||
if (os.exceptions() & std::ios::failbit)
|
||||
asio::detail::throw_error(ec);
|
||||
else
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
else
|
||||
for (std::string::iterator i = s.begin(); i != s.end(); ++i)
|
||||
os << os.widen(*i);
|
||||
|
@ -61,14 +61,6 @@ public:
|
||||
typedef asio::detail::socket_addr_type data_type;
|
||||
#endif
|
||||
|
||||
/// The type for the size of the endpoint structure. This type is dependent on
|
||||
/// the underlying implementation of the socket layer.
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
typedef implementation_defined size_type;
|
||||
#else
|
||||
typedef asio::detail::socket_addr_len_type size_type;
|
||||
#endif
|
||||
|
||||
/// Default constructor.
|
||||
basic_endpoint()
|
||||
: data_()
|
||||
@ -190,7 +182,7 @@ public:
|
||||
}
|
||||
|
||||
/// Get the underlying size of the endpoint in the native type.
|
||||
size_type size() const
|
||||
std::size_t size() const
|
||||
{
|
||||
if (is_v4(data_))
|
||||
return sizeof(asio::detail::sockaddr_in4_type);
|
||||
@ -199,9 +191,9 @@ public:
|
||||
}
|
||||
|
||||
/// Set the underlying size of the endpoint in the native type.
|
||||
void resize(size_type size)
|
||||
void resize(std::size_t size)
|
||||
{
|
||||
if (size > size_type(sizeof(data_)))
|
||||
if (size > sizeof(data_))
|
||||
{
|
||||
asio::system_error e(asio::error::invalid_argument);
|
||||
boost::throw_exception(e);
|
||||
@ -209,7 +201,7 @@ public:
|
||||
}
|
||||
|
||||
/// Get the capacity of the endpoint in the native type.
|
||||
size_type capacity() const
|
||||
std::size_t capacity() const
|
||||
{
|
||||
return sizeof(data_);
|
||||
}
|
||||
@ -349,11 +341,23 @@ std::ostream& operator<<(std::ostream& os,
|
||||
const basic_endpoint<InternetProtocol>& endpoint)
|
||||
{
|
||||
const address& addr = endpoint.address();
|
||||
if (addr.is_v4())
|
||||
os << addr.to_string();
|
||||
asio::error_code ec;
|
||||
std::string a = addr.to_string(ec);
|
||||
if (ec)
|
||||
{
|
||||
if (os.exceptions() & std::ios::failbit)
|
||||
asio::detail::throw_error(ec);
|
||||
else
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
else
|
||||
os << '[' << addr.to_string() << ']';
|
||||
os << ':' << endpoint.port();
|
||||
{
|
||||
if (addr.is_v4())
|
||||
os << a;
|
||||
else
|
||||
os << '[' << a << ']';
|
||||
os << ':' << endpoint.port();
|
||||
}
|
||||
return os;
|
||||
}
|
||||
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
@ -363,11 +367,23 @@ std::basic_ostream<Elem, Traits>& operator<<(
|
||||
const basic_endpoint<InternetProtocol>& endpoint)
|
||||
{
|
||||
const address& addr = endpoint.address();
|
||||
if (addr.is_v4())
|
||||
os << addr.to_string();
|
||||
asio::error_code ec;
|
||||
std::string a = addr.to_string(ec);
|
||||
if (ec)
|
||||
{
|
||||
if (os.exceptions() & std::ios::failbit)
|
||||
asio::detail::throw_error(ec);
|
||||
else
|
||||
os.setstate(std::ios_base::failbit);
|
||||
}
|
||||
else
|
||||
os << '[' << addr.to_string() << ']';
|
||||
os << ':' << endpoint.port();
|
||||
{
|
||||
if (addr.is_v4())
|
||||
os << a;
|
||||
else
|
||||
os << '[' << a << ']';
|
||||
os << ':' << endpoint.port();
|
||||
}
|
||||
return os;
|
||||
}
|
||||
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
|
||||
|
@ -80,9 +80,7 @@ public:
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
typename InternetProtocol::endpoint endpoint;
|
||||
endpoint.resize(
|
||||
static_cast<asio::detail::socket_addr_len_type>(
|
||||
address_info->ai_addrlen));
|
||||
endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen));
|
||||
memcpy(endpoint.data(), address_info->ai_addr,
|
||||
address_info->ai_addrlen);
|
||||
iter.values_->push_back(
|
||||
|
@ -37,7 +37,7 @@ template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
|
||||
class boolean
|
||||
{
|
||||
public:
|
||||
#if defined(__sun)
|
||||
#if defined(__sun) || defined(_AIX)
|
||||
typedef unsigned char value_type;
|
||||
#else
|
||||
typedef int value_type;
|
||||
|
@ -168,6 +168,10 @@ namespace libtorrent
|
||||
// thread started to run the main downloader loop
|
||||
struct session_impl: boost::noncopyable
|
||||
{
|
||||
|
||||
// the size of each allocation that is chained in the send buffer
|
||||
enum { send_buffer_size = 200 };
|
||||
|
||||
#ifndef NDEBUG
|
||||
friend class ::libtorrent::peer_connection;
|
||||
#endif
|
||||
@ -329,6 +333,24 @@ namespace libtorrent
|
||||
{ return m_dht_proxy; }
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
void log_buffer_usage()
|
||||
{
|
||||
int send_buffer_capacity = 0;
|
||||
int used_send_buffer = 0;
|
||||
for (connection_map::const_iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end; ++i)
|
||||
{
|
||||
send_buffer_capacity += i->second->send_buffer_capacity();
|
||||
used_send_buffer += i->second->send_buffer_size();
|
||||
}
|
||||
assert(send_buffer_capacity >= used_send_buffer);
|
||||
m_buffer_usage_logger << log_time() << " send_buffer_size: " << send_buffer_capacity << std::endl;
|
||||
m_buffer_usage_logger << log_time() << " used_send_buffer: " << used_send_buffer << std::endl;
|
||||
m_buffer_usage_logger << log_time() << " send_buffer_utilization: "
|
||||
<< (used_send_buffer * 100.f / send_buffer_capacity) << std::endl;
|
||||
}
|
||||
#endif
|
||||
void start_lsd();
|
||||
void start_natpmp();
|
||||
void start_upnp();
|
||||
@ -339,11 +361,25 @@ namespace libtorrent
|
||||
|
||||
// handles delayed alerts
|
||||
alert_manager m_alerts;
|
||||
|
||||
std::pair<char*, int> allocate_buffer(int size);
|
||||
void free_buffer(char* buf, int size);
|
||||
void free_disk_buffer(char* buf);
|
||||
|
||||
// private:
|
||||
|
||||
void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih);
|
||||
|
||||
// handles disk io requests asynchronously
|
||||
// peers have pointers into the disk buffer
|
||||
// pool, and must be destructed before this
|
||||
// object.
|
||||
disk_io_thread m_disk_thread;
|
||||
|
||||
// this pool is used to allocate and recycle send
|
||||
// buffers from.
|
||||
boost::pool<> m_send_buffers;
|
||||
|
||||
// this is where all active sockets are stored.
|
||||
// the selector can sleep while there's no activity on
|
||||
// them
|
||||
@ -358,9 +394,6 @@ namespace libtorrent
|
||||
// when they are destructed.
|
||||
file_pool m_files;
|
||||
|
||||
// handles disk io requests asynchronously
|
||||
disk_io_thread m_disk_thread;
|
||||
|
||||
// this is a list of half-open tcp connections
|
||||
// (only outgoing connections)
|
||||
// this has to be one of the last
|
||||
@ -507,9 +540,9 @@ namespace libtorrent
|
||||
pe_settings m_pe_settings;
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<natpmp> m_natpmp;
|
||||
boost::shared_ptr<upnp> m_upnp;
|
||||
boost::shared_ptr<lsd> m_lsd;
|
||||
boost::intrusive_ptr<natpmp> m_natpmp;
|
||||
boost::intrusive_ptr<upnp> m_upnp;
|
||||
boost::intrusive_ptr<lsd> m_lsd;
|
||||
|
||||
// the timer used to fire the second_tick
|
||||
deadline_timer m_timer;
|
||||
@ -526,6 +559,10 @@ namespace libtorrent
|
||||
// logger used to write bandwidth usage statistics
|
||||
std::ofstream m_stats_logger;
|
||||
int m_second_counter;
|
||||
// used to log send buffer usage statistics
|
||||
std::ofstream m_buffer_usage_logger;
|
||||
// the number of send buffers that are allocated
|
||||
int m_buffer_allocations;
|
||||
#endif
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
boost::shared_ptr<logger> create_log(std::string const& name
|
||||
|
@ -208,7 +208,7 @@ namespace libtorrent
|
||||
void write_cancel(peer_request const& r);
|
||||
void write_bitfield(std::vector<bool> const& bitfield);
|
||||
void write_have(int index);
|
||||
void write_piece(peer_request const& r, char const* buffer);
|
||||
void write_piece(peer_request const& r, char* buffer);
|
||||
void write_handshake();
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
void write_extensions();
|
||||
@ -270,8 +270,17 @@ namespace libtorrent
|
||||
// these functions encrypt the send buffer if m_rc4_encrypted
|
||||
// is true, otherwise it passes the call to the
|
||||
// peer_connection functions of the same names
|
||||
void send_buffer(char* begin, char* end);
|
||||
void send_buffer(char* buf, int size);
|
||||
buffer::interval allocate_send_buffer(int size);
|
||||
template <class Destructor>
|
||||
void append_send_buffer(char* buffer, int size, Destructor const& destructor)
|
||||
{
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
if (m_rc4_encrypted)
|
||||
m_RC4_handler->encrypt(buffer, size);
|
||||
#endif
|
||||
peer_connection::append_send_buffer(buffer, size, destructor);
|
||||
}
|
||||
void setup_send();
|
||||
|
||||
// Returns offset at which bytestream (src, src + src_size)
|
||||
|
192
libtorrent/include/libtorrent/chained_buffer.hpp
Normal file
192
libtorrent/include/libtorrent/chained_buffer.hpp
Normal file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
|
||||
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_CHAINED_BUFFER_HPP_INCLUDED
|
||||
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <asio.hpp>
|
||||
#include <list>
|
||||
#include <cstring>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
struct chained_buffer
|
||||
{
|
||||
chained_buffer(): m_bytes(0), m_capacity(0) {}
|
||||
|
||||
struct buffer_t
|
||||
{
|
||||
boost::function<void(char*)> free; // destructs the buffer
|
||||
char* buf; // the first byte of the buffer
|
||||
int size; // the total size of the buffer
|
||||
|
||||
char* start; // the first byte to send/receive in the buffer
|
||||
int used_size; // this is the number of bytes to send/receive
|
||||
};
|
||||
|
||||
bool empty() const { return m_bytes == 0; }
|
||||
int size() const { return m_bytes; }
|
||||
int capacity() const { return m_capacity; }
|
||||
|
||||
void pop_front(int bytes_to_pop)
|
||||
{
|
||||
assert(bytes_to_pop <= m_bytes);
|
||||
while (bytes_to_pop > 0 && !m_vec.empty())
|
||||
{
|
||||
buffer_t& b = m_vec.front();
|
||||
if (b.used_size > bytes_to_pop)
|
||||
{
|
||||
b.start += bytes_to_pop;
|
||||
b.used_size -= bytes_to_pop;
|
||||
m_bytes -= bytes_to_pop;
|
||||
assert(m_bytes <= m_capacity);
|
||||
assert(m_bytes >= 0);
|
||||
assert(m_capacity >= 0);
|
||||
break;
|
||||
}
|
||||
|
||||
b.free(b.buf);
|
||||
m_bytes -= b.used_size;
|
||||
m_capacity -= b.size;
|
||||
bytes_to_pop -= b.used_size;
|
||||
assert(m_bytes >= 0);
|
||||
assert(m_capacity >= 0);
|
||||
assert(m_bytes <= m_capacity);
|
||||
m_vec.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
template <class D>
|
||||
void append_buffer(char* buffer, int size, int used_size, D const& destructor)
|
||||
{
|
||||
assert(size >= used_size);
|
||||
buffer_t b;
|
||||
b.buf = buffer;
|
||||
b.size = size;
|
||||
b.start = buffer;
|
||||
b.used_size = used_size;
|
||||
b.free = destructor;
|
||||
m_vec.push_back(b);
|
||||
|
||||
m_bytes += used_size;
|
||||
m_capacity += size;
|
||||
assert(m_bytes <= m_capacity);
|
||||
}
|
||||
|
||||
// returns the number of bytes available at the
|
||||
// end of the last chained buffer.
|
||||
int space_in_last_buffer()
|
||||
{
|
||||
if (m_vec.empty()) return 0;
|
||||
buffer_t& b = m_vec.back();
|
||||
return b.size - b.used_size - (b.start - b.buf);
|
||||
}
|
||||
|
||||
// tries to copy the given buffer to the end of the
|
||||
// last chained buffer. If there's not enough room
|
||||
// it returns false
|
||||
bool append(char const* buf, int size)
|
||||
{
|
||||
char* insert = allocate_appendix(size);
|
||||
if (insert == 0) return false;
|
||||
std::memcpy(insert, buf, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
// tries to allocate memory from the end
|
||||
// of the last buffer. If there isn't
|
||||
// enough room, returns 0
|
||||
char* allocate_appendix(int size)
|
||||
{
|
||||
if (m_vec.empty()) return 0;
|
||||
buffer_t& b = m_vec.back();
|
||||
char* insert = b.start + b.used_size;
|
||||
if (insert + size > b.buf + b.size) return 0;
|
||||
b.used_size += size;
|
||||
m_bytes += size;
|
||||
assert(m_bytes <= m_capacity);
|
||||
return insert;
|
||||
}
|
||||
|
||||
std::list<asio::const_buffer> const& build_iovec(int to_send)
|
||||
{
|
||||
m_tmp_vec.clear();
|
||||
|
||||
for (std::list<buffer_t>::iterator i = m_vec.begin()
|
||||
, end(m_vec.end()); to_send > 0 && i != end; ++i)
|
||||
{
|
||||
if (i->used_size > to_send)
|
||||
{
|
||||
assert(to_send > 0);
|
||||
m_tmp_vec.push_back(asio::const_buffer(i->start, to_send));
|
||||
break;
|
||||
}
|
||||
assert(i->used_size > 0);
|
||||
m_tmp_vec.push_back(asio::const_buffer(i->start, i->used_size));
|
||||
to_send -= i->used_size;
|
||||
}
|
||||
return m_tmp_vec;
|
||||
}
|
||||
|
||||
~chained_buffer()
|
||||
{
|
||||
for (std::list<buffer_t>::iterator i = m_vec.begin()
|
||||
, end(m_vec.end()); i != end; ++i)
|
||||
{
|
||||
i->free(i->buf);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// this is the list of all the buffers we want to
|
||||
// send
|
||||
std::list<buffer_t> m_vec;
|
||||
|
||||
// this is the number of bytes in the send buf.
|
||||
// this will always be equal to the sum of the
|
||||
// size of all buffers in vec
|
||||
int m_bytes;
|
||||
|
||||
// the total size of all buffers in the chain
|
||||
// including unused space
|
||||
int m_capacity;
|
||||
|
||||
// this is the vector of buffers used when
|
||||
// invoking the async write call
|
||||
std::list<asio::const_buffer> m_tmp_vec;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -94,6 +94,11 @@ namespace libtorrent
|
||||
disk_io_thread(int block_size = 16 * 1024);
|
||||
~disk_io_thread();
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
int disk_allocations() const
|
||||
{ return m_allocations; }
|
||||
#endif
|
||||
|
||||
// aborts read operations
|
||||
void stop(boost::intrusive_ptr<piece_manager> s);
|
||||
void add_job(disk_io_job const& j
|
||||
@ -110,6 +115,7 @@ namespace libtorrent
|
||||
void operator()();
|
||||
|
||||
char* allocate_buffer();
|
||||
void free_buffer(char* buf);
|
||||
|
||||
private:
|
||||
|
||||
@ -129,6 +135,9 @@ namespace libtorrent
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
std::ofstream m_log;
|
||||
#endif
|
||||
#ifdef TORRENT_STATS
|
||||
int m_allocations;
|
||||
#endif
|
||||
|
||||
// thread for performing blocking disk io operations
|
||||
boost::thread m_disk_io_thread;
|
||||
|
@ -69,13 +69,20 @@ namespace libtorrent
|
||||
{
|
||||
public:
|
||||
http_parser();
|
||||
template <class T>
|
||||
T header(char const* key) const;
|
||||
std::string const& header(char const* key) const
|
||||
{
|
||||
static std::string empty;
|
||||
std::map<std::string, std::string>::const_iterator i
|
||||
= m_header.find(key);
|
||||
if (i == m_header.end()) return empty;
|
||||
return i->second;
|
||||
}
|
||||
|
||||
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; }
|
||||
std::string const& message() const { return m_server_message; }
|
||||
buffer::const_interval get_body() const;
|
||||
bool header_finished() const { return m_state == read_body; }
|
||||
bool finished() const { return m_finished; }
|
||||
@ -103,15 +110,6 @@ namespace libtorrent
|
||||
bool m_finished;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T http_parser::header(char const* key) const
|
||||
{
|
||||
std::map<std::string, std::string>::const_iterator i
|
||||
= m_header.find(key);
|
||||
if (i == m_header.end()) return T();
|
||||
return boost::lexical_cast<T>(i->second);
|
||||
}
|
||||
|
||||
class TORRENT_EXPORT http_tracker_connection
|
||||
: public tracker_connection
|
||||
{
|
||||
|
@ -60,6 +60,12 @@ namespace libtorrent
|
||||
delete static_cast<T const*>(s);
|
||||
}
|
||||
|
||||
boost::intrusive_ptr<T> self()
|
||||
{ return boost::intrusive_ptr<T>((T*)this); }
|
||||
|
||||
boost::intrusive_ptr<const T> self() const
|
||||
{ return boost::intrusive_ptr<const T>((T const*)this); }
|
||||
|
||||
int refcount() const { return m_refs; }
|
||||
|
||||
intrusive_ptr_base(): m_refs(0) {}
|
||||
|
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/broadcast_socket.hpp"
|
||||
#include "libtorrent/intrusive_ptr_base.hpp"
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
@ -52,7 +53,7 @@ namespace libtorrent
|
||||
|
||||
typedef boost::function<void(tcp::endpoint, sha1_hash)> peer_callback_t;
|
||||
|
||||
class lsd : boost::noncopyable
|
||||
class lsd : public intrusive_ptr_base<lsd>
|
||||
{
|
||||
public:
|
||||
lsd(io_service& ios, address const& listen_interface
|
||||
|
@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#define TORRENT_NATPMP_HPP
|
||||
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/intrusive_ptr_base.hpp"
|
||||
|
||||
#include <boost/function.hpp>
|
||||
|
||||
@ -49,7 +50,7 @@ namespace libtorrent
|
||||
// std::string: error message
|
||||
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;
|
||||
|
||||
class natpmp
|
||||
class natpmp : public intrusive_ptr_base<natpmp>
|
||||
{
|
||||
public:
|
||||
natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb);
|
||||
|
@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/pool/pool.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
@ -73,6 +74,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libtorrent/socket_type.hpp"
|
||||
#include "libtorrent/intrusive_ptr_base.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
#include "libtorrent/chained_buffer.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
@ -356,14 +358,23 @@ namespace libtorrent
|
||||
virtual boost::optional<piece_block_progress>
|
||||
downloading_piece_progress() const
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "downloading_piece_progress() dispatched to the base class!\n";
|
||||
#endif
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "downloading_piece_progress() dispatched to the base class!\n";
|
||||
#endif
|
||||
return boost::optional<piece_block_progress>();
|
||||
}
|
||||
|
||||
void send_buffer(char const* begin, char const* end);
|
||||
void send_buffer(char const* begin, int size);
|
||||
buffer::interval allocate_send_buffer(int size);
|
||||
template <class Destructor>
|
||||
void append_send_buffer(char* buffer, int size, Destructor const& destructor)
|
||||
{
|
||||
m_send_buffer.append_buffer(buffer, size, size, destructor);
|
||||
#ifdef TORRENT_STATS
|
||||
m_ses.m_buffer_usage_logger << log_time() << " append_send_buffer: " << size << std::endl;
|
||||
m_ses.log_buffer_usage();
|
||||
#endif
|
||||
}
|
||||
void setup_send();
|
||||
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
@ -376,6 +387,12 @@ namespace libtorrent
|
||||
bool has_country() const { return m_country[0] != 0; }
|
||||
#endif
|
||||
|
||||
int send_buffer_size() const
|
||||
{ return m_send_buffer.size(); }
|
||||
|
||||
int send_buffer_capacity() const
|
||||
{ return m_send_buffer.capacity(); }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void get_specific_peer_info(peer_info& p) const = 0;
|
||||
@ -388,7 +405,7 @@ namespace libtorrent
|
||||
virtual void write_cancel(peer_request const& r) = 0;
|
||||
virtual void write_have(int index) = 0;
|
||||
virtual void write_keepalive() = 0;
|
||||
virtual void write_piece(peer_request const& r, char const* buffer) = 0;
|
||||
virtual void write_piece(peer_request const& r, char* buffer) = 0;
|
||||
|
||||
virtual void write_reject_request(peer_request const& r) = 0;
|
||||
virtual void write_allow_fast(int piece) = 0;
|
||||
@ -401,13 +418,6 @@ namespace libtorrent
|
||||
virtual void on_sent(asio::error_code const& error
|
||||
, std::size_t bytes_transferred) = 0;
|
||||
|
||||
int send_buffer_size() const
|
||||
{
|
||||
return (int)m_send_buffer[0].size()
|
||||
+ (int)m_send_buffer[1].size()
|
||||
- m_write_pos;
|
||||
}
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
buffer::interval wr_recv_buffer()
|
||||
{
|
||||
@ -512,31 +522,13 @@ namespace libtorrent
|
||||
int m_recv_pos;
|
||||
buffer m_recv_buffer;
|
||||
|
||||
// this is the buffer where data that is
|
||||
// to be sent is stored until it gets
|
||||
// consumed by send(). Since asio requires
|
||||
// the memory buffer that is given to async.
|
||||
// operations to remain valid until the operation
|
||||
// finishes, there has to be two buffers. While
|
||||
// waiting for a async_write operation on one
|
||||
// buffer, the other is used to write data to
|
||||
// be queued up.
|
||||
buffer m_send_buffer[2];
|
||||
// the current send buffer is the one to write to.
|
||||
// (m_current_send_buffer + 1) % 2 is the
|
||||
// buffer we're currently waiting for.
|
||||
int m_current_send_buffer;
|
||||
chained_buffer m_send_buffer;
|
||||
|
||||
// the number of bytes we are currently reading
|
||||
// from disk, that will be added to the send
|
||||
// buffer as soon as they complete
|
||||
int m_reading_bytes;
|
||||
|
||||
// if the sending buffer doesn't finish in one send
|
||||
// operation, this is the position within that buffer
|
||||
// where the next operation should continue
|
||||
int m_write_pos;
|
||||
|
||||
// timeouts
|
||||
ptime m_last_receive;
|
||||
ptime m_last_sent;
|
||||
|
@ -184,6 +184,9 @@ namespace libtorrent
|
||||
std::pair<bool, float> check_files(std::vector<bool>& pieces
|
||||
, int& num_pieces, boost::recursive_mutex& mutex);
|
||||
|
||||
// frees a buffer that was returned from a read operation
|
||||
void free_buffer(char* buf);
|
||||
|
||||
void write_resume_data(entry& rd) const;
|
||||
bool verify_resume_data(entry& rd, std::string& error);
|
||||
|
||||
|
@ -49,6 +49,8 @@ namespace libtorrent
|
||||
std::strftime(str, 200, "%b %d %X", timeinfo);
|
||||
return str;
|
||||
}
|
||||
|
||||
inline std::string log_time();
|
||||
}
|
||||
|
||||
#if (!defined (__MACH__) && !defined (_WIN32) && (!defined(_POSIX_MONOTONIC_CLOCK) \
|
||||
@ -389,5 +391,6 @@ namespace libtorrent
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "libtorrent/broadcast_socket.hpp"
|
||||
#include "libtorrent/http_connection.hpp"
|
||||
#include "libtorrent/connection_queue.hpp"
|
||||
#include "libtorrent/intrusive_ptr_base.hpp"
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
@ -62,7 +63,7 @@ namespace libtorrent
|
||||
// std::string: error message
|
||||
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;
|
||||
|
||||
class upnp : boost::noncopyable
|
||||
class upnp : public intrusive_ptr_base<upnp>
|
||||
{
|
||||
public:
|
||||
upnp(io_service& ios, connection_queue& cc
|
||||
|
@ -122,7 +122,7 @@ namespace libtorrent
|
||||
void write_request(peer_request const& r);
|
||||
void write_cancel(peer_request const& r) {}
|
||||
void write_have(int index) {}
|
||||
void write_piece(peer_request const& r, char const* buffer) { assert(false); }
|
||||
void write_piece(peer_request const& r, char* buffer) { assert(false); }
|
||||
void write_keepalive() {}
|
||||
void on_connected();
|
||||
void write_reject_request(peer_request const&) {}
|
||||
|
@ -58,6 +58,7 @@ $(top_srcdir)/include/libtorrent/intrusive_ptr_base.hpp \
|
||||
$(top_srcdir)/include/libtorrent/invariant_check.hpp \
|
||||
$(top_srcdir)/include/libtorrent/io.hpp \
|
||||
$(top_srcdir)/include/libtorrent/ip_filter.hpp \
|
||||
$(top_srcdir)/include/libtorrent/chained_buffer.hpp \
|
||||
$(top_srcdir)/include/libtorrent/lsd.hpp \
|
||||
$(top_srcdir)/include/libtorrent/peer.hpp \
|
||||
$(top_srcdir)/include/libtorrent/peer_connection.hpp \
|
||||
|
@ -251,12 +251,10 @@ namespace libtorrent
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> DHT_PORT [ " << listen_port << " ]\n";
|
||||
#endif
|
||||
buffer::interval packet = allocate_send_buffer(7);
|
||||
detail::write_uint32(3, packet.begin);
|
||||
detail::write_uint8(msg_dht_port, packet.begin);
|
||||
detail::write_uint16(listen_port, packet.begin);
|
||||
assert(packet.begin == packet.end);
|
||||
setup_send();
|
||||
char msg[] = {0,0,0,3, msg_dht_port, 0, 0};
|
||||
char* ptr = msg + 5;
|
||||
detail::write_uint16(listen_port, ptr);
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_have_all()
|
||||
@ -270,8 +268,8 @@ namespace libtorrent
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> HAVE_ALL\n";
|
||||
#endif
|
||||
char buf[] = {0,0,0,1, msg_have_all};
|
||||
send_buffer(buf, buf + sizeof(buf));
|
||||
char msg[] = {0,0,0,1, msg_have_all};
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_have_none()
|
||||
@ -285,8 +283,8 @@ namespace libtorrent
|
||||
(*m_logger) << time_now_string()
|
||||
<< " ==> HAVE_NONE\n";
|
||||
#endif
|
||||
char buf[] = {0,0,0,1, msg_have_none};
|
||||
send_buffer(buf, buf + sizeof(buf));
|
||||
char msg[] = {0,0,0,1, msg_have_none};
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_reject_request(peer_request const& r)
|
||||
@ -296,22 +294,12 @@ namespace libtorrent
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
assert(associated_torrent().lock()->valid_metadata());
|
||||
|
||||
char buf[] = {0,0,0,13, msg_reject_request};
|
||||
|
||||
buffer::interval i = allocate_send_buffer(17);
|
||||
|
||||
std::copy(buf, buf + 5, i.begin);
|
||||
i.begin += 5;
|
||||
|
||||
// index
|
||||
detail::write_int32(r.piece, i.begin);
|
||||
// begin
|
||||
detail::write_int32(r.start, i.begin);
|
||||
// length
|
||||
detail::write_int32(r.length, i.begin);
|
||||
assert(i.begin == i.end);
|
||||
|
||||
setup_send();
|
||||
char msg[] = {0,0,0,13, msg_reject_request,0,0,0,0, 0,0,0,0, 0,0,0,0};
|
||||
char* ptr = msg + 5;
|
||||
detail::write_int32(r.piece, ptr); // index
|
||||
detail::write_int32(r.start, ptr); // begin
|
||||
detail::write_int32(r.length, ptr); // length
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_allow_fast(int piece)
|
||||
@ -321,11 +309,10 @@ namespace libtorrent
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
assert(associated_torrent().lock()->valid_metadata());
|
||||
|
||||
char buf[] = {0,0,0,5, msg_allowed_fast, 0, 0, 0, 0};
|
||||
|
||||
char* ptr = buf + 5;
|
||||
char msg[] = {0,0,0,5, msg_allowed_fast, 0, 0, 0, 0};
|
||||
char* ptr = msg + 5;
|
||||
detail::write_int32(piece, ptr);
|
||||
send_buffer(buf, buf + sizeof(buf));
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::get_specific_peer_info(peer_info& p) const
|
||||
@ -556,8 +543,8 @@ namespace libtorrent
|
||||
assert(secret);
|
||||
|
||||
hasher h;
|
||||
const char keyA[] = "keyA";
|
||||
const char keyB[] = "keyB";
|
||||
static const char keyA[] = "keyA";
|
||||
static const char keyB[] = "keyB";
|
||||
|
||||
// encryption rc4 longkeys
|
||||
// outgoing connection : hash ('keyA',S,SKEY)
|
||||
@ -587,17 +574,16 @@ namespace libtorrent
|
||||
#endif
|
||||
}
|
||||
|
||||
void bt_peer_connection::send_buffer(char* begin, char* end)
|
||||
void bt_peer_connection::send_buffer(char* buf, int size)
|
||||
{
|
||||
assert (begin);
|
||||
assert (end);
|
||||
assert (end > begin);
|
||||
assert (!m_rc4_encrypted || m_encrypted);
|
||||
assert(buf);
|
||||
assert(size > 0);
|
||||
assert(!m_rc4_encrypted || m_encrypted);
|
||||
|
||||
if (m_rc4_encrypted)
|
||||
m_RC4_handler->encrypt(begin, end - begin);
|
||||
m_RC4_handler->encrypt(buf, size);
|
||||
|
||||
peer_connection::send_buffer(begin, end);
|
||||
peer_connection::send_buffer(buf, size);
|
||||
}
|
||||
|
||||
buffer::interval bt_peer_connection::allocate_send_buffer(int size)
|
||||
@ -606,6 +592,7 @@ namespace libtorrent
|
||||
|
||||
if (m_rc4_encrypted)
|
||||
{
|
||||
assert(m_enc_send_buffer.left() == 0);
|
||||
m_enc_send_buffer = peer_connection::allocate_send_buffer(size);
|
||||
return m_enc_send_buffer;
|
||||
}
|
||||
@ -620,24 +607,24 @@ namespace libtorrent
|
||||
{
|
||||
assert(!m_rc4_encrypted || m_encrypted);
|
||||
|
||||
if (m_rc4_encrypted)
|
||||
if (m_rc4_encrypted && m_enc_send_buffer.left())
|
||||
{
|
||||
assert (m_enc_send_buffer.begin);
|
||||
assert (m_enc_send_buffer.end);
|
||||
assert (m_enc_send_buffer.left() > 0);
|
||||
assert(m_enc_send_buffer.begin);
|
||||
assert(m_enc_send_buffer.end);
|
||||
|
||||
m_RC4_handler->encrypt (m_enc_send_buffer.begin, m_enc_send_buffer.left());
|
||||
m_RC4_handler->encrypt(m_enc_send_buffer.begin, m_enc_send_buffer.left());
|
||||
m_enc_send_buffer.end = m_enc_send_buffer.begin;
|
||||
}
|
||||
peer_connection::setup_send();
|
||||
}
|
||||
|
||||
int bt_peer_connection::get_syncoffset(char const* src, int src_size,
|
||||
char const* target, int target_size) const
|
||||
char const* target, int target_size) const
|
||||
{
|
||||
assert (target_size >= src_size);
|
||||
assert (src_size > 0);
|
||||
assert (src);
|
||||
assert (target);
|
||||
assert(target_size >= src_size);
|
||||
assert(src_size > 0);
|
||||
assert(src);
|
||||
assert(target);
|
||||
|
||||
int traverse_limit = target_size - src_size;
|
||||
|
||||
@ -1288,8 +1275,8 @@ namespace libtorrent
|
||||
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
|
||||
char buf[] = {0,0,0,0};
|
||||
send_buffer(buf, buf + sizeof(buf));
|
||||
char msg[] = {0,0,0,0};
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_cancel(peer_request const& r)
|
||||
@ -1299,22 +1286,12 @@ namespace libtorrent
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
assert(associated_torrent().lock()->valid_metadata());
|
||||
|
||||
char buf[] = {0,0,0,13, msg_cancel};
|
||||
|
||||
buffer::interval i = allocate_send_buffer(17);
|
||||
|
||||
std::copy(buf, buf + 5, i.begin);
|
||||
i.begin += 5;
|
||||
|
||||
// index
|
||||
detail::write_int32(r.piece, i.begin);
|
||||
// begin
|
||||
detail::write_int32(r.start, i.begin);
|
||||
// length
|
||||
detail::write_int32(r.length, i.begin);
|
||||
assert(i.begin == i.end);
|
||||
|
||||
setup_send();
|
||||
char msg[17] = {0,0,0,13, msg_cancel};
|
||||
char* ptr = msg + 5;
|
||||
detail::write_int32(r.piece, ptr); // index
|
||||
detail::write_int32(r.start, ptr); // begin
|
||||
detail::write_int32(r.length, ptr); // length
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_request(peer_request const& r)
|
||||
@ -1324,22 +1301,13 @@ namespace libtorrent
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
assert(associated_torrent().lock()->valid_metadata());
|
||||
|
||||
char buf[] = {0,0,0,13, msg_request};
|
||||
char msg[17] = {0,0,0,13, msg_request};
|
||||
char* ptr = msg + 5;
|
||||
|
||||
buffer::interval i = allocate_send_buffer(17);
|
||||
|
||||
std::copy(buf, buf + 5, i.begin);
|
||||
i.begin += 5;
|
||||
|
||||
// index
|
||||
detail::write_int32(r.piece, i.begin);
|
||||
// begin
|
||||
detail::write_int32(r.start, i.begin);
|
||||
// length
|
||||
detail::write_int32(r.length, i.begin);
|
||||
assert(i.begin == i.end);
|
||||
|
||||
setup_send();
|
||||
detail::write_int32(r.piece, ptr); // index
|
||||
detail::write_int32(r.start, ptr); // begin
|
||||
detail::write_int32(r.length, ptr); // length
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_bitfield(std::vector<bool> const& bitfield)
|
||||
@ -1526,7 +1494,7 @@ namespace libtorrent
|
||||
|
||||
if (is_choked()) return;
|
||||
char msg[] = {0,0,0,1,msg_choke};
|
||||
send_buffer(msg, msg + sizeof(msg));
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_unchoke()
|
||||
@ -1536,7 +1504,7 @@ namespace libtorrent
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
|
||||
char msg[] = {0,0,0,1,msg_unchoke};
|
||||
send_buffer(msg, msg + sizeof(msg));
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_interested()
|
||||
@ -1546,7 +1514,7 @@ namespace libtorrent
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
|
||||
char msg[] = {0,0,0,1,msg_interested};
|
||||
send_buffer(msg, msg + sizeof(msg));
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_not_interested()
|
||||
@ -1556,7 +1524,7 @@ namespace libtorrent
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
|
||||
char msg[] = {0,0,0,1,msg_not_interested};
|
||||
send_buffer(msg, msg + sizeof(msg));
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_have(int index)
|
||||
@ -1567,34 +1535,39 @@ namespace libtorrent
|
||||
assert(index < associated_torrent().lock()->torrent_file().num_pieces());
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
|
||||
const int packet_size = 9;
|
||||
char msg[packet_size] = {0,0,0,5,msg_have};
|
||||
char msg[] = {0,0,0,5,msg_have,0,0,0,0};
|
||||
char* ptr = msg + 5;
|
||||
detail::write_int32(index, ptr);
|
||||
send_buffer(msg, msg + packet_size);
|
||||
send_buffer(msg, sizeof(msg));
|
||||
}
|
||||
|
||||
void bt_peer_connection::write_piece(peer_request const& r, char const* buffer)
|
||||
void bt_peer_connection::write_piece(peer_request const& r, char* buffer)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(m_sent_handshake && m_sent_bitfield);
|
||||
|
||||
const int packet_size = 4 + 5 + 4 + r.length;
|
||||
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
assert(t);
|
||||
|
||||
buffer::interval i = allocate_send_buffer(packet_size);
|
||||
|
||||
detail::write_int32(packet_size-4, i.begin);
|
||||
detail::write_uint8(msg_piece, i.begin);
|
||||
detail::write_int32(r.piece, i.begin);
|
||||
detail::write_int32(r.start, i.begin);
|
||||
char msg[4 + 1 + 4 + 4];
|
||||
char* ptr = msg;
|
||||
assert(r.length <= 16 * 1024);
|
||||
detail::write_int32(r.length + 1 + 4 + 4, ptr);
|
||||
detail::write_uint8(msg_piece, ptr);
|
||||
detail::write_int32(r.piece, ptr);
|
||||
detail::write_int32(r.start, ptr);
|
||||
send_buffer(msg, sizeof(msg));
|
||||
|
||||
append_send_buffer(buffer, r.length
|
||||
, boost::bind(&session_impl::free_disk_buffer
|
||||
, boost::ref(m_ses), _1));
|
||||
|
||||
/*
|
||||
buffer::interval i = allocate_send_buffer(r.length);
|
||||
std::memcpy(i.begin, buffer, r.length);
|
||||
|
||||
assert(i.begin + r.length == i.end);
|
||||
|
||||
t->filesystem().free_buffer(buffer);
|
||||
*/
|
||||
m_payloads.push_back(range(send_buffer_size() - r.length, r.length));
|
||||
setup_send();
|
||||
}
|
||||
|
@ -37,18 +37,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
|
||||
#include "libtorrent/time.hpp"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string log_time()
|
||||
{
|
||||
using namespace libtorrent;
|
||||
static ptime start = time_now();
|
||||
return boost::lexical_cast<std::string>(
|
||||
total_milliseconds(time_now() - start));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -64,7 +52,9 @@ namespace libtorrent
|
||||
#endif
|
||||
, m_disk_io_thread(boost::ref(*this))
|
||||
{
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
m_allocations = 0;
|
||||
#endif
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log.open("disk_io_thread.log", std::ios::trunc);
|
||||
#endif
|
||||
@ -188,9 +178,21 @@ namespace libtorrent
|
||||
char* disk_io_thread::allocate_buffer()
|
||||
{
|
||||
boost::mutex::scoped_lock l(m_mutex);
|
||||
#ifdef TORRENT_STATS
|
||||
++m_allocations;
|
||||
#endif
|
||||
return (char*)m_pool.ordered_malloc();
|
||||
}
|
||||
|
||||
void disk_io_thread::free_buffer(char* buf)
|
||||
{
|
||||
boost::mutex::scoped_lock l(m_mutex);
|
||||
#ifdef TORRENT_STATS
|
||||
--m_allocations;
|
||||
#endif
|
||||
m_pool.ordered_free(buf);
|
||||
}
|
||||
|
||||
void disk_io_thread::operator()()
|
||||
{
|
||||
for (;;)
|
||||
@ -225,10 +227,14 @@ namespace libtorrent
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log << log_time() << " read " << j.buffer_size << std::endl;
|
||||
#endif
|
||||
free_buffer = false;
|
||||
if (j.buffer == 0)
|
||||
{
|
||||
l.lock();
|
||||
j.buffer = (char*)m_pool.ordered_malloc();
|
||||
#ifdef TORRENT_STATS
|
||||
++m_allocations;
|
||||
#endif
|
||||
l.unlock();
|
||||
assert(j.buffer_size <= m_block_size);
|
||||
if (j.buffer == 0)
|
||||
@ -238,10 +244,6 @@ namespace libtorrent
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
free_buffer = false;
|
||||
}
|
||||
ret = j.storage->read_impl(j.buffer, j.piece, j.offset
|
||||
, j.buffer_size);
|
||||
|
||||
@ -301,6 +303,9 @@ namespace libtorrent
|
||||
{
|
||||
l.lock();
|
||||
m_pool.ordered_free(j.buffer);
|
||||
#ifdef TORRENT_STATS
|
||||
--m_allocations;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ void http_connection::on_read(asio::error_code const& e
|
||||
if (code >= 300 && code < 400)
|
||||
{
|
||||
// attempt a redirect
|
||||
std::string url = m_parser.header<std::string>("location");
|
||||
std::string const& url = m_parser.header("location");
|
||||
if (url.empty())
|
||||
{
|
||||
// missing location header
|
||||
|
@ -679,7 +679,7 @@ namespace libtorrent
|
||||
|
||||
if (m_parser.header_finished())
|
||||
{
|
||||
int cl = m_parser.header<int>("content-length");
|
||||
int cl = atoi(m_parser.header("content-length").c_str());
|
||||
if (cl > m_settings.tracker_maximum_response_length)
|
||||
{
|
||||
fail(-1, "content-length is greater than maximum response length");
|
||||
@ -718,7 +718,7 @@ namespace libtorrent
|
||||
return;
|
||||
}
|
||||
|
||||
std::string location = m_parser.header<std::string>("location");
|
||||
std::string location = m_parser.header("location");
|
||||
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
|
||||
@ -763,7 +763,7 @@ namespace libtorrent
|
||||
|
||||
buffer::const_interval buf(&m_buffer[0] + m_parser.body_start(), &m_buffer[0] + m_recv_pos);
|
||||
|
||||
std::string content_encoding = m_parser.header<std::string>("content-encoding");
|
||||
std::string content_encoding = m_parser.header("content-encoding");
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
if (cb) cb->debug_log("content-encoding: \"" + content_encoding + "\"");
|
||||
|
@ -58,7 +58,7 @@ lsd::lsd(io_service& ios, address const& listen_interface
|
||||
: m_callback(cb)
|
||||
, m_retry_count(0)
|
||||
, m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143"), 6771)
|
||||
, bind(&lsd::on_announce, this, _1, _2, _3))
|
||||
, bind(&lsd::on_announce, self(), _1, _2, _3))
|
||||
, m_broadcast_timer(ios)
|
||||
, m_disabled(false)
|
||||
{
|
||||
@ -96,7 +96,7 @@ void lsd::announce(sha1_hash const& ih, int listen_port)
|
||||
#endif
|
||||
|
||||
m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
|
||||
m_broadcast_timer.async_wait(bind(&lsd::resend_announce, this, _1, msg));
|
||||
m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
|
||||
}
|
||||
|
||||
void lsd::resend_announce(asio::error_code const& e, std::string msg) try
|
||||
@ -111,7 +111,7 @@ void lsd::resend_announce(asio::error_code const& e, std::string msg) try
|
||||
return;
|
||||
|
||||
m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
|
||||
m_broadcast_timer.async_wait(bind(&lsd::resend_announce, this, _1, msg));
|
||||
m_broadcast_timer.async_wait(bind(&lsd::resend_announce, self(), _1, msg));
|
||||
}
|
||||
catch (std::exception&)
|
||||
{}
|
||||
@ -121,48 +121,53 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
|
||||
{
|
||||
using namespace libtorrent::detail;
|
||||
|
||||
char* p = buffer;
|
||||
char* end = buffer + bytes_transferred;
|
||||
char* line = std::find(p, end, '\n');
|
||||
for (char* i = p; i < line; ++i) *i = std::tolower(*i);
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: " << std::string(p, line) << std::endl;
|
||||
#endif
|
||||
if (line == end || (line - p >= 9 && std::memcmp("bt-search", p, 9)))
|
||||
http_parser p;
|
||||
|
||||
p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred));
|
||||
|
||||
if (!p.header_finished())
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " *** assumed 'bt-search', ignoring" << std::endl;
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: incomplete HTTP message\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
p = line + 1;
|
||||
int port = 0;
|
||||
sha1_hash ih(0);
|
||||
while (p != end)
|
||||
|
||||
if (p.method() != "bt-search")
|
||||
{
|
||||
line = std::find(p, end, '\n');
|
||||
if (line == end) break;
|
||||
*line = 0;
|
||||
for (char* i = p; i < line; ++i) *i = std::tolower(*i);
|
||||
if (line - p >= 5 && memcmp(p, "port:", 5) == 0)
|
||||
{
|
||||
p += 5;
|
||||
while (*p == ' ') ++p;
|
||||
port = atoi(p);
|
||||
}
|
||||
else if (line - p >= 9 && memcmp(p, "infohash:", 9) == 0)
|
||||
{
|
||||
p += 9;
|
||||
while (*p == ' ') ++p;
|
||||
if (line - p > 40) p[40] = 0;
|
||||
try { ih = boost::lexical_cast<sha1_hash>(p); }
|
||||
catch (std::exception&) {}
|
||||
}
|
||||
p = line + 1;
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
std::string const& port_str = p.header("port");
|
||||
if (port_str.empty())
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
std::string const& ih_str = p.header("infohash");
|
||||
if (ih_str.empty())
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
m_log << time_now_string()
|
||||
<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
sha1_hash ih(0);
|
||||
std::istringstream ih_sstr(ih_str);
|
||||
ih_sstr >> ih;
|
||||
int port = atoi(port_str.c_str());
|
||||
|
||||
if (!ih.is_all_zeros() && port != 0)
|
||||
{
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
|
@ -161,7 +161,7 @@ void natpmp::update_mapping(int i, int port)
|
||||
m_retry_count = 0;
|
||||
send_map_request(i);
|
||||
m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
|
||||
, m_remote, bind(&natpmp::on_reply, this, _1, _2));
|
||||
, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,7 +194,7 @@ void natpmp::send_map_request(int i) try
|
||||
// linear back-off instead of exponential
|
||||
++m_retry_count;
|
||||
m_send_timer.expires_from_now(milliseconds(250 * m_retry_count));
|
||||
m_send_timer.async_wait(bind(&natpmp::resend_request, this, i, _1));
|
||||
m_send_timer.async_wait(bind(&natpmp::resend_request, self(), i, _1));
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
@ -227,7 +227,7 @@ void natpmp::on_reply(asio::error_code const& e
|
||||
if (m_remote != m_nat_endpoint)
|
||||
{
|
||||
m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
|
||||
, m_remote, bind(&natpmp::on_reply, this, _1, _2));
|
||||
, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -346,7 +346,7 @@ void natpmp::update_expiration_timer()
|
||||
if (min_index >= 0)
|
||||
{
|
||||
m_refresh_timer.expires_from_now(min_expire - now);
|
||||
m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, this, _1, min_index));
|
||||
m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, self(), _1, min_index));
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,7 +369,7 @@ void natpmp::refresh_mapping(int i)
|
||||
m_retry_count = 0;
|
||||
send_map_request(i);
|
||||
m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
|
||||
, m_remote, bind(&natpmp::on_reply, this, _1, _2));
|
||||
, m_remote, bind(&natpmp::on_reply, self(), _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,9 +81,7 @@ namespace libtorrent
|
||||
, m_last_unchoke(min_time())
|
||||
, m_packet_size(0)
|
||||
, m_recv_pos(0)
|
||||
, m_current_send_buffer(0)
|
||||
, m_reading_bytes(0)
|
||||
, m_write_pos(0)
|
||||
, m_last_receive(time_now())
|
||||
, m_last_sent(time_now())
|
||||
, m_socket(s)
|
||||
@ -161,9 +159,7 @@ namespace libtorrent
|
||||
, m_last_unchoke(min_time())
|
||||
, m_packet_size(0)
|
||||
, m_recv_pos(0)
|
||||
, m_current_send_buffer(0)
|
||||
, m_reading_bytes(0)
|
||||
, m_write_pos(0)
|
||||
, m_last_receive(time_now())
|
||||
, m_last_sent(time_now())
|
||||
, m_socket(s)
|
||||
@ -2082,8 +2078,7 @@ namespace libtorrent
|
||||
p.remote_dl_rate = 0;
|
||||
}
|
||||
|
||||
p.send_buffer_size = int(m_send_buffer[0].capacity()
|
||||
+ m_send_buffer[1].capacity());
|
||||
p.send_buffer_size = m_send_buffer.capacity();
|
||||
}
|
||||
|
||||
void peer_connection::cut_receive_buffer(int size, int packet_size)
|
||||
@ -2386,8 +2381,7 @@ namespace libtorrent
|
||||
shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
||||
if (m_bandwidth_limit[upload_channel].quota_left() == 0
|
||||
&& (!m_send_buffer[m_current_send_buffer].empty()
|
||||
|| !m_send_buffer[(m_current_send_buffer + 1) & 1].empty())
|
||||
&& !m_send_buffer.empty()
|
||||
&& !m_connecting
|
||||
&& t
|
||||
&& !m_ignore_bandwidth_limits)
|
||||
@ -2415,32 +2409,21 @@ namespace libtorrent
|
||||
|
||||
assert(!m_writing);
|
||||
|
||||
int sending_buffer = (m_current_send_buffer + 1) & 1;
|
||||
if (m_send_buffer[sending_buffer].empty())
|
||||
{
|
||||
// this means we have to swap buffer, because there's no
|
||||
// previous buffer we're still waiting for.
|
||||
std::swap(m_current_send_buffer, sending_buffer);
|
||||
m_write_pos = 0;
|
||||
}
|
||||
|
||||
// send the actual buffer
|
||||
if (!m_send_buffer[sending_buffer].empty())
|
||||
if (!m_send_buffer.empty())
|
||||
{
|
||||
int amount_to_send = (int)m_send_buffer[sending_buffer].size() - m_write_pos;
|
||||
int amount_to_send = m_send_buffer.size();
|
||||
int quota_left = m_bandwidth_limit[upload_channel].quota_left();
|
||||
if (!m_ignore_bandwidth_limits && amount_to_send > quota_left)
|
||||
amount_to_send = quota_left;
|
||||
|
||||
assert(amount_to_send > 0);
|
||||
|
||||
assert(m_write_pos < (int)m_send_buffer[sending_buffer].size());
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "async_write " << amount_to_send << " bytes\n";
|
||||
#endif
|
||||
m_socket->async_write_some(asio::buffer(
|
||||
&m_send_buffer[sending_buffer][m_write_pos], amount_to_send)
|
||||
, bind(&peer_connection::on_send_data, self(), _1, _2));
|
||||
std::list<asio::const_buffer> const& vec = m_send_buffer.build_iovec(amount_to_send);
|
||||
m_socket->async_write_some(vec, bind(&peer_connection::on_send_data, self(), _1, _2));
|
||||
|
||||
m_writing = true;
|
||||
}
|
||||
@ -2511,10 +2494,32 @@ namespace libtorrent
|
||||
m_recv_buffer.resize(m_packet_size);
|
||||
}
|
||||
|
||||
void peer_connection::send_buffer(char const* begin, char const* end)
|
||||
void peer_connection::send_buffer(char const* buf, int size)
|
||||
{
|
||||
buffer& buf = m_send_buffer[m_current_send_buffer];
|
||||
buf.insert(buf.end(), begin, end);
|
||||
int free_space = m_send_buffer.space_in_last_buffer();
|
||||
if (free_space > size) free_space = size;
|
||||
if (free_space > 0)
|
||||
{
|
||||
m_send_buffer.append(buf, free_space);
|
||||
size -= free_space;
|
||||
buf += free_space;
|
||||
#ifdef TORRENT_STATS
|
||||
m_ses.m_buffer_usage_logger << log_time() << " send_buffer: "
|
||||
<< free_space << std::endl;
|
||||
m_ses.log_buffer_usage();
|
||||
#endif
|
||||
}
|
||||
if (size <= 0) return;
|
||||
|
||||
std::pair<char*, int> buffer = m_ses.allocate_buffer(size);
|
||||
assert(buffer.second >= size);
|
||||
std::memcpy(buffer.first, buf, size);
|
||||
m_send_buffer.append_buffer(buffer.first, buffer.second, size
|
||||
, bind(&session_impl::free_buffer, boost::ref(m_ses), _1, buffer.second));
|
||||
#ifdef TORRENT_STATS
|
||||
m_ses.m_buffer_usage_logger << log_time() << " send_buffer_alloc: " << size << std::endl;
|
||||
m_ses.log_buffer_usage();
|
||||
#endif
|
||||
setup_send();
|
||||
}
|
||||
|
||||
@ -2522,10 +2527,29 @@ namespace libtorrent
|
||||
// return value is destructed
|
||||
buffer::interval peer_connection::allocate_send_buffer(int size)
|
||||
{
|
||||
buffer& buf = m_send_buffer[m_current_send_buffer];
|
||||
buf.resize(buf.size() + size);
|
||||
buffer::interval ret(&buf[0] + buf.size() - size, &buf[0] + buf.size());
|
||||
return ret;
|
||||
char* insert = m_send_buffer.allocate_appendix(size);
|
||||
if (insert == 0)
|
||||
{
|
||||
std::pair<char*, int> buffer = m_ses.allocate_buffer(size);
|
||||
assert(buffer.second >= size);
|
||||
m_send_buffer.append_buffer(buffer.first, buffer.second, size
|
||||
, bind(&session_impl::free_buffer, boost::ref(m_ses), _1, buffer.second));
|
||||
buffer::interval ret(buffer.first, buffer.first + size);
|
||||
#ifdef TORRENT_STATS
|
||||
m_ses.m_buffer_usage_logger << log_time() << " allocate_buffer_alloc: " << size << std::endl;
|
||||
m_ses.log_buffer_usage();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef TORRENT_STATS
|
||||
m_ses.m_buffer_usage_logger << log_time() << " allocate_buffer: " << size << std::endl;
|
||||
m_ses.log_buffer_usage();
|
||||
#endif
|
||||
buffer::interval ret(insert, insert + size);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -2647,8 +2671,7 @@ namespace libtorrent
|
||||
|
||||
// if we have requests or pending data to be sent or announcements to be made
|
||||
// we want to send data
|
||||
return (!m_send_buffer[m_current_send_buffer].empty()
|
||||
|| !m_send_buffer[(m_current_send_buffer + 1) & 1].empty())
|
||||
return !m_send_buffer.empty()
|
||||
&& (m_bandwidth_limit[upload_channel].quota_left() > 0
|
||||
|| m_ignore_bandwidth_limits)
|
||||
&& !m_connecting;
|
||||
@ -2763,6 +2786,9 @@ namespace libtorrent
|
||||
INVARIANT_CHECK;
|
||||
|
||||
assert(m_writing);
|
||||
|
||||
m_send_buffer.pop_front(bytes_transferred);
|
||||
|
||||
m_writing = false;
|
||||
|
||||
if (!m_ignore_bandwidth_limits)
|
||||
@ -2772,9 +2798,6 @@ namespace libtorrent
|
||||
(*m_logger) << "wrote " << bytes_transferred << " bytes\n";
|
||||
#endif
|
||||
|
||||
m_write_pos += bytes_transferred;
|
||||
|
||||
|
||||
if (error)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
@ -2787,34 +2810,11 @@ namespace libtorrent
|
||||
assert(!m_connecting);
|
||||
assert(bytes_transferred > 0);
|
||||
|
||||
int sending_buffer = (m_current_send_buffer + 1) & 1;
|
||||
|
||||
assert(int(m_send_buffer[sending_buffer].size()) >= m_write_pos);
|
||||
if (int(m_send_buffer[sending_buffer].size()) == m_write_pos)
|
||||
{
|
||||
m_send_buffer[sending_buffer].clear();
|
||||
m_write_pos = 0;
|
||||
}
|
||||
|
||||
m_last_sent = time_now();
|
||||
|
||||
on_sent(error, bytes_transferred);
|
||||
fill_send_buffer();
|
||||
|
||||
if (m_choked)
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (int(m_send_buffer[i].size()) < 64
|
||||
&& int(m_send_buffer[i].capacity()) > 128)
|
||||
{
|
||||
buffer tmp(m_send_buffer[i]);
|
||||
tmp.swap(m_send_buffer[i]);
|
||||
assert(m_send_buffer[i].capacity() == m_send_buffer[i].size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setup_send();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
@ -2876,8 +2876,6 @@ namespace libtorrent
|
||||
}
|
||||
}
|
||||
*/
|
||||
assert(m_write_pos <= int(m_send_buffer[
|
||||
(m_current_send_buffer + 1) & 1].size()));
|
||||
|
||||
// extremely expensive invariant check
|
||||
/*
|
||||
|
@ -1426,16 +1426,16 @@ namespace libtorrent
|
||||
int nonempty_connections = 0;
|
||||
|
||||
std::set<address> unique_test;
|
||||
std::set<tcp::endpoint> unique_test2;
|
||||
// std::set<tcp::endpoint> unique_test2;
|
||||
for (const_iterator i = m_peers.begin();
|
||||
i != m_peers.end(); ++i)
|
||||
{
|
||||
peer const& p = *i;
|
||||
if (!m_torrent->settings().allow_multiple_connections_per_ip)
|
||||
assert(unique_test.find(p.ip.address()) == unique_test.end());
|
||||
assert(unique_test2.find(p.ip) == unique_test2.end());
|
||||
unique_test.insert(p.ip.address());
|
||||
unique_test2.insert(p.ip);
|
||||
// if (!m_torrent->settings().allow_multiple_connections_per_ip)
|
||||
// assert(unique_test.find(p.ip.address()) == unique_test.end());
|
||||
// assert(unique_test2.find(p.ip) == unique_test2.end());
|
||||
// unique_test.insert(p.ip.address());
|
||||
// unique_test2.insert(p.ip);
|
||||
++total_connections;
|
||||
if (!p.connection)
|
||||
{
|
||||
|
@ -83,6 +83,14 @@ using libtorrent::aux::session_impl;
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
std::string log_time()
|
||||
{
|
||||
static const ptime start = time_now();
|
||||
char ret[200];
|
||||
std::sprintf(ret, "%d", total_milliseconds(time_now() - start));
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace aux
|
||||
{
|
||||
filesystem_init::filesystem_init()
|
||||
|
@ -507,7 +507,8 @@ namespace detail
|
||||
std::pair<int, int> listen_port_range
|
||||
, fingerprint const& cl_fprint
|
||||
, char const* listen_interface)
|
||||
: m_strand(m_io_service)
|
||||
: m_send_buffers(send_buffer_size)
|
||||
, m_strand(m_io_service)
|
||||
, m_files(40)
|
||||
, m_half_open(m_io_service)
|
||||
, m_download_channel(m_io_service, peer_connection::download_channel)
|
||||
@ -546,7 +547,7 @@ namespace detail
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
m_stats_logger.open("session_stats.log");
|
||||
m_stats_logger.open("session_stats.log", std::ios::trunc);
|
||||
m_stats_logger <<
|
||||
"1. second\n"
|
||||
"2. upload rate\n"
|
||||
@ -555,7 +556,9 @@ namespace detail
|
||||
"5. seeding torrents\n"
|
||||
"6. peers\n"
|
||||
"7. connecting peers\n"
|
||||
"8. disk block buffers\n"
|
||||
"\n";
|
||||
m_buffer_usage_logger.open("buffer_stats.log", std::ios::trunc);
|
||||
m_second_counter = 0;
|
||||
#endif
|
||||
|
||||
@ -999,7 +1002,8 @@ namespace detail
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_mutex);
|
||||
|
||||
INVARIANT_CHECK;
|
||||
// too expensive
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
if (e)
|
||||
{
|
||||
@ -1031,7 +1035,7 @@ namespace detail
|
||||
else
|
||||
++downloading_torrents;
|
||||
}
|
||||
int num_connections = 0;
|
||||
int num_complete_connections = 0;
|
||||
int num_half_open = 0;
|
||||
for (connection_map::iterator i = m_connections.begin()
|
||||
, end(m_connections.end()); i != end; ++i)
|
||||
@ -1039,7 +1043,7 @@ namespace detail
|
||||
if (i->second->is_connecting())
|
||||
++num_half_open;
|
||||
else
|
||||
++num_connections;
|
||||
++num_complete_connections;
|
||||
}
|
||||
|
||||
m_stats_logger
|
||||
@ -1048,8 +1052,9 @@ namespace detail
|
||||
<< m_stat.download_rate() << "\t"
|
||||
<< downloading_torrents << "\t"
|
||||
<< seeding_torrents << "\t"
|
||||
<< num_connections << "\t"
|
||||
<< num_complete_connections << "\t"
|
||||
<< num_half_open << "\t"
|
||||
<< m_disk_thread.disk_allocations() << "\t"
|
||||
<< std::endl;
|
||||
#endif
|
||||
|
||||
@ -2195,9 +2200,9 @@ namespace detail
|
||||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_lsd.reset(new lsd(m_io_service
|
||||
m_lsd = new lsd(m_io_service
|
||||
, m_listen_interface.address()
|
||||
, bind(&session_impl::on_lsd_peer, this, _1, _2)));
|
||||
, bind(&session_impl::on_lsd_peer, this, _1, _2));
|
||||
}
|
||||
|
||||
void session_impl::start_natpmp()
|
||||
@ -2206,10 +2211,10 @@ namespace detail
|
||||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_natpmp.reset(new natpmp(m_io_service
|
||||
m_natpmp = new natpmp(m_io_service
|
||||
, m_listen_interface.address()
|
||||
, bind(&session_impl::on_port_mapping
|
||||
, this, _1, _2, _3)));
|
||||
, this, _1, _2, _3));
|
||||
|
||||
m_natpmp->set_mappings(m_listen_interface.port(),
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
@ -2224,11 +2229,11 @@ namespace detail
|
||||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_upnp.reset(new upnp(m_io_service, m_half_open
|
||||
m_upnp = new upnp(m_io_service, m_half_open
|
||||
, m_listen_interface.address()
|
||||
, m_settings.user_agent
|
||||
, bind(&session_impl::on_port_mapping
|
||||
, this, _1, _2, _3)));
|
||||
, this, _1, _2, _3));
|
||||
|
||||
m_upnp->set_mappings(m_listen_interface.port(),
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
@ -2240,7 +2245,7 @@ namespace detail
|
||||
void session_impl::stop_lsd()
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
m_lsd.reset();
|
||||
m_lsd = 0;
|
||||
}
|
||||
|
||||
void session_impl::stop_natpmp()
|
||||
@ -2248,7 +2253,7 @@ namespace detail
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
if (m_natpmp.get())
|
||||
m_natpmp->close();
|
||||
m_natpmp.reset();
|
||||
m_natpmp = 0;
|
||||
}
|
||||
|
||||
void session_impl::stop_upnp()
|
||||
@ -2256,9 +2261,38 @@ namespace detail
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
if (m_upnp.get())
|
||||
m_upnp->close();
|
||||
m_upnp.reset();
|
||||
m_upnp = 0;
|
||||
}
|
||||
|
||||
void session_impl::free_disk_buffer(char* buf)
|
||||
{
|
||||
m_disk_thread.free_buffer(buf);
|
||||
}
|
||||
|
||||
std::pair<char*, int> session_impl::allocate_buffer(int size)
|
||||
{
|
||||
int num_buffers = (size + send_buffer_size - 1) / send_buffer_size;
|
||||
#ifdef TORRENT_STATS
|
||||
m_buffer_allocations += num_buffers;
|
||||
m_buffer_usage_logger << log_time() << " protocol_buffer: "
|
||||
<< (m_buffer_allocations * send_buffer_size) << std::endl;
|
||||
#endif
|
||||
return std::make_pair((char*)m_send_buffers.ordered_malloc(num_buffers)
|
||||
, num_buffers * send_buffer_size);
|
||||
}
|
||||
|
||||
void session_impl::free_buffer(char* buf, int size)
|
||||
{
|
||||
assert(size % send_buffer_size == 0);
|
||||
int num_buffers = size / send_buffer_size;
|
||||
#ifdef TORRENT_STATS
|
||||
m_buffer_allocations -= num_buffers;
|
||||
assert(m_buffer_allocations >= 0);
|
||||
m_buffer_usage_logger << log_time() << " protocol_buffer: "
|
||||
<< (m_buffer_allocations * send_buffer_size) << std::endl;
|
||||
#endif
|
||||
m_send_buffers.ordered_free(buf, num_buffers);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void session_impl::check_invariant() const
|
||||
|
@ -1065,6 +1065,11 @@ namespace libtorrent
|
||||
return m_storage->verify_resume_data(rd, error);
|
||||
}
|
||||
|
||||
void piece_manager::free_buffer(char* buf)
|
||||
{
|
||||
m_io_thread.free_buffer(buf);
|
||||
}
|
||||
|
||||
void piece_manager::async_release_files(
|
||||
boost::function<void(int, disk_io_job const&)> const& handler)
|
||||
{
|
||||
|
@ -1464,9 +1464,6 @@ namespace libtorrent
|
||||
m_policy->connection_closed(*p);
|
||||
p->set_peer_info(0);
|
||||
m_connections.erase(i);
|
||||
#ifndef NDEBUG
|
||||
m_policy->check_invariant();
|
||||
#endif
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
@ -2940,4 +2937,3 @@ namespace libtorrent
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -901,4 +901,3 @@ namespace libtorrent
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ upnp::upnp(io_service& ios, connection_queue& cc
|
||||
, m_io_service(ios)
|
||||
, m_strand(ios)
|
||||
, m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250"), 1900)
|
||||
, m_strand.wrap(bind(&upnp::on_reply, this, _1, _2, _3)), false)
|
||||
, m_strand.wrap(bind(&upnp::on_reply, self(), _1, _2, _3)), false)
|
||||
, m_broadcast_timer(ios)
|
||||
, m_refresh_timer(ios)
|
||||
, m_disabled(false)
|
||||
@ -119,7 +119,7 @@ void upnp::discover_device() try
|
||||
++m_retry_count;
|
||||
m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
|
||||
m_broadcast_timer.async_wait(m_strand.wrap(bind(&upnp::resend_request
|
||||
, this, _1)));
|
||||
, self(), _1)));
|
||||
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
@ -203,7 +203,7 @@ try
|
||||
try
|
||||
{
|
||||
d.upnp_connection.reset(new http_connection(m_io_service
|
||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, this, _1, _2
|
||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2
|
||||
, boost::ref(d)))));
|
||||
d.upnp_connection->get(d.url);
|
||||
}
|
||||
@ -300,7 +300,7 @@ try
|
||||
return;
|
||||
}
|
||||
|
||||
std::string url = p.header<std::string>("location");
|
||||
std::string url = p.header("location");
|
||||
if (url.empty())
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
@ -393,7 +393,7 @@ try
|
||||
try
|
||||
{
|
||||
d.upnp_connection.reset(new http_connection(m_io_service
|
||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, this, _1, _2
|
||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2
|
||||
, boost::ref(d)))));
|
||||
d.upnp_connection->get(d.url);
|
||||
}
|
||||
@ -480,9 +480,9 @@ void upnp::map_port(rootdevice& d, int i)
|
||||
assert(d.service_namespace);
|
||||
|
||||
d.upnp_connection.reset(new http_connection(m_io_service
|
||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, this, _1, _2
|
||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, self(), _1, _2
|
||||
, boost::ref(d), i)), true
|
||||
, bind(&upnp::create_port_mapping, this, _1, boost::ref(d), i)));
|
||||
, bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i)));
|
||||
|
||||
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
||||
, seconds(10));
|
||||
@ -523,9 +523,9 @@ void upnp::unmap_port(rootdevice& d, int i)
|
||||
return;
|
||||
}
|
||||
d.upnp_connection.reset(new http_connection(m_io_service
|
||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, this, _1, _2
|
||||
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, self(), _1, _2
|
||||
, boost::ref(d), i)), true
|
||||
, bind(&upnp::delete_port_mapping, this, boost::ref(d), i)));
|
||||
, bind(&upnp::delete_port_mapping, self(), boost::ref(d), i)));
|
||||
|
||||
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
|
||||
, seconds(10));
|
||||
@ -851,7 +851,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
||||
|| next_expire > d.mapping[mapping].expires)
|
||||
{
|
||||
m_refresh_timer.expires_at(d.mapping[mapping].expires);
|
||||
m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, this, _1)));
|
||||
m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, self(), _1)));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -962,7 +962,7 @@ void upnp::on_expire(asio::error_code const& e) try
|
||||
if (next_expire != max_time())
|
||||
{
|
||||
m_refresh_timer.expires_at(next_expire);
|
||||
m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, this, _1)));
|
||||
m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, self(), _1)));
|
||||
}
|
||||
}
|
||||
catch (std::exception&)
|
||||
|
@ -297,7 +297,7 @@ namespace libtorrent
|
||||
(*m_logger) << request << "\n";
|
||||
#endif
|
||||
|
||||
send_buffer(request.c_str(), request.c_str() + request.size());
|
||||
send_buffer(request.c_str(), request.size());
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
@ -387,7 +387,7 @@ namespace libtorrent
|
||||
{
|
||||
// this means we got a redirection request
|
||||
// look for the location header
|
||||
std::string location = m_parser.header<std::string>("location");
|
||||
std::string location = m_parser.header("location");
|
||||
|
||||
if (location.empty())
|
||||
{
|
||||
@ -423,7 +423,7 @@ namespace libtorrent
|
||||
throw std::runtime_error("redirecting to " + location);
|
||||
}
|
||||
|
||||
std::string server_version = m_parser.header<std::string>("server");
|
||||
std::string const& server_version = m_parser.header("server");
|
||||
if (!server_version.empty())
|
||||
{
|
||||
m_server_string = "URL seed @ ";
|
||||
@ -445,7 +445,7 @@ namespace libtorrent
|
||||
size_type range_end;
|
||||
if (m_parser.status_code() == 206)
|
||||
{
|
||||
std::stringstream range_str(m_parser.header<std::string>("content-range"));
|
||||
std::stringstream range_str(m_parser.header("content-range"));
|
||||
char dummy;
|
||||
std::string bytes;
|
||||
range_str >> bytes >> range_start >> dummy >> range_end;
|
||||
@ -461,7 +461,7 @@ namespace libtorrent
|
||||
else
|
||||
{
|
||||
range_start = 0;
|
||||
range_end = m_parser.header<size_type>("content-length");
|
||||
range_end = atol(m_parser.header("content-length").c_str());
|
||||
if (range_end == -1)
|
||||
{
|
||||
// we should not try this server again.
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
plugin_name = _("Move Torrent")
|
||||
plugin_author = "Marcos Pinto"
|
||||
plugin_version = "0.1"
|
||||
plugin_version = "0.2"
|
||||
plugin_description = _("This plugin allows users to move the torrent to a \
|
||||
different directory without having to remove and re-add the torrent. This \
|
||||
feature can be found by right-clicking on a torrent.\nFurthermore, it \
|
||||
|
Loading…
x
Reference in New Issue
Block a user