sync lt and asio 1615 and upload version # of plugin

This commit is contained in:
Marcos Pinto 2007-09-30 18:32:19 +00:00
parent c0d8bf2d7f
commit 3de1cb9938
45 changed files with 1048 additions and 579 deletions

View 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

View File

@ -450,7 +450,7 @@ public:
} }
endpoint_type endpoint; 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)) if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
return endpoint_type(); return endpoint_type();
endpoint.resize(addr_len); endpoint.resize(addr_len);
@ -468,7 +468,7 @@ public:
} }
endpoint_type endpoint; 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)) if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
return endpoint_type(); return endpoint_type();
endpoint.resize(addr_len); endpoint.resize(addr_len);
@ -1073,7 +1073,7 @@ public:
for (;;) for (;;)
{ {
// Try to complete the operation without blocking. // 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, int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags,
sender_endpoint.data(), &addr_len, ec); sender_endpoint.data(), &addr_len, ec);
@ -1144,7 +1144,7 @@ public:
} }
// Receive some data. // Receive some data.
socket_addr_len_type addr_len = sender_endpoint_.capacity(); std::size_t addr_len = sender_endpoint_.capacity();
asio::error_code ec; asio::error_code ec;
int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_, int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
sender_endpoint_.data(), &addr_len, ec); sender_endpoint_.data(), &addr_len, ec);
@ -1242,7 +1242,7 @@ public:
// Try to complete the operation without blocking. // Try to complete the operation without blocking.
asio::error_code ec; asio::error_code ec;
socket_holder new_socket; socket_holder new_socket;
socket_addr_len_type addr_len = 0; std::size_t addr_len = 0;
if (peer_endpoint) if (peer_endpoint)
{ {
addr_len = peer_endpoint->capacity(); addr_len = peer_endpoint->capacity();
@ -1327,7 +1327,7 @@ public:
// Accept the waiting connection. // Accept the waiting connection.
asio::error_code ec; asio::error_code ec;
socket_holder new_socket; socket_holder new_socket;
socket_addr_len_type addr_len = 0; std::size_t addr_len = 0;
if (peer_endpoint_) if (peer_endpoint_)
{ {
addr_len = peer_endpoint_->capacity(); addr_len = peer_endpoint_->capacity();

View File

@ -26,9 +26,6 @@
#include <cerrno> #include <cerrno>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
#include <new> #include <new>
#if defined(__MACH__) && defined(__APPLE__)
# include <AvailabilityMacros.h>
#endif // defined(__MACH__) && defined(__APPLE__)
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#include "asio/error.hpp" #include "asio/error.hpp"
@ -38,6 +35,10 @@ namespace asio {
namespace detail { namespace detail {
namespace socket_ops { 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) inline void clear_error(asio::error_code& ec)
{ {
errno = 0; errno = 0;
@ -60,15 +61,28 @@ inline ReturnType error_wrapper(ReturnType return_value,
return 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, 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); 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) if (new_s == invalid_socket)
return new_s; return new_s;
#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
int optval = 1; int optval = 1;
int result = error_wrapper(::setsockopt(new_s, int result = error_wrapper(::setsockopt(new_s,
SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); 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); ::close(new_s);
return invalid_socket; return invalid_socket;
} }
#endif
return new_s; 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, 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); 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) 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); 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, 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); 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) 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__) #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, inline int recv(socket_type s, buf* bufs, size_t count, int flags,
asio::error_code& ec) asio::error_code& ec)
{ {
@ -163,20 +212,15 @@ inline int recv(socket_type s, buf* bufs, size_t count, int flags,
return -1; return -1;
return bytes_transferred; return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg; msghdr msg = msghdr();
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = bufs; msg.msg_iov = bufs;
msg.msg_iovlen = count; msg.msg_iovlen = count;
msg.msg_control = 0;
msg.msg_controllen = 0;
msg.msg_flags = 0;
return error_wrapper(::recvmsg(s, &msg, flags), ec); return error_wrapper(::recvmsg(s, &msg, flags), ec);
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
} }
inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags, 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) asio::error_code& ec)
{ {
clear_error(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 recv_buf_count = static_cast<DWORD>(count);
DWORD bytes_transferred = 0; DWORD bytes_transferred = 0;
DWORD recv_flags = flags; DWORD recv_flags = flags;
int tmp_addrlen = (int)*addrlen;
int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count, 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) if (result != 0)
return -1; return -1;
return bytes_transferred; return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg; msghdr msg = msghdr();
#if defined(__MACH__) && defined(__APPLE__) \ init_msghdr_msg_name(msg.msg_name, addr);
&& (MAC_OS_X_VERSION_MAX_ALLOWED < 1040)
msg.msg_name = reinterpret_cast<char*>(addr);
#else
msg.msg_name = addr;
#endif
msg.msg_namelen = *addrlen; msg.msg_namelen = *addrlen;
msg.msg_iov = bufs; msg.msg_iov = bufs;
msg.msg_iovlen = count; 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); int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
*addrlen = msg.msg_namelen; *addrlen = msg.msg_namelen;
return result; return result;
@ -225,14 +263,9 @@ inline int send(socket_type s, const buf* bufs, size_t count, int flags,
return -1; return -1;
return bytes_transferred; return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg; msghdr msg = msghdr();
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = const_cast<buf*>(bufs); msg.msg_iov = const_cast<buf*>(bufs);
msg.msg_iovlen = count; msg.msg_iovlen = count;
msg.msg_control = 0;
msg.msg_controllen = 0;
msg.msg_flags = 0;
#if defined(__linux__) #if defined(__linux__)
flags |= MSG_NOSIGNAL; flags |= MSG_NOSIGNAL;
#endif // defined(__linux__) #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, 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) asio::error_code& ec)
{ {
clear_error(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 -1;
return bytes_transferred; return bytes_transferred;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
msghdr msg; msghdr msg = msghdr();
#if defined(__MACH__) && defined(__APPLE__) \ init_msghdr_msg_name(msg.msg_name, addr);
&& (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
msg.msg_namelen = addrlen; msg.msg_namelen = addrlen;
msg.msg_iov = const_cast<buf*>(bufs); msg.msg_iov = const_cast<buf*>(bufs);
msg.msg_iovlen = count; msg.msg_iovlen = count;
msg.msg_control = 0;
msg.msg_controllen = 0;
msg.msg_flags = 0;
#if defined(__linux__) #if defined(__linux__)
flags |= MSG_NOSIGNAL; flags |= MSG_NOSIGNAL;
#endif // defined(__linux__) #endif // defined(__linux__)
@ -316,8 +341,17 @@ inline socket_type socket(int af, int type, int protocol,
#endif #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, 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) 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; ec = asio::error::fault;
return -1; return -1;
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(__BORLANDC__)
clear_error(ec); clear_error(ec);
return error_wrapper(::setsockopt(s, level, optname, return error_wrapper(call_setsockopt(&msghdr::msg_namelen,
reinterpret_cast<const char*>(optval), static_cast<int>(optlen)), ec); s, level, optname, optval, optlen), ec);
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #endif // defined(__BORLANDC__)
clear_error(ec); }
return error_wrapper(::setsockopt(s, level, optname, optval,
static_cast<socklen_t>(optlen)), ec); template <typename SockLenType>
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) 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, 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; return -1;
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) #elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
clear_error(ec); clear_error(ec);
int tmp_optlen = static_cast<int>(*optlen); int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
int result = error_wrapper(::getsockopt(s, level, optname, s, level, optname, optval, optlen), ec);
reinterpret_cast<char*>(optval), &tmp_optlen), ec);
*optlen = static_cast<size_t>(tmp_optlen);
if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
&& ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
{ {
@ -412,10 +451,8 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
return result; return result;
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
clear_error(ec); clear_error(ec);
socklen_t tmp_optlen = static_cast<socklen_t>(*optlen); int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
int result = error_wrapper(::getsockopt(s, level, optname, s, level, optname, optval, optlen), ec);
optval, &tmp_optlen), ec);
*optlen = static_cast<size_t>(tmp_optlen);
#if defined(__linux__) #if defined(__linux__)
if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int) if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
&& (optname == SO_SNDBUF || optname == SO_RCVBUF)) && (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__) #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, 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); 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, 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); 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, 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( 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, std::size_t hostlen, char* serv, std::size_t servlen, int flags,
asio::error_code& ec) asio::error_code& ec)
{ {
@ -1595,7 +1654,7 @@ inline void freeaddrinfo(addrinfo_type* ai)
} }
inline asio::error_code getnameinfo(const socket_addr_type* addr, 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) char* serv, std::size_t servlen, int flags, asio::error_code& ec)
{ {
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@ -1608,7 +1667,7 @@ inline asio::error_code getnameinfo(const socket_addr_type* addr,
# else # else
// Building for Windows 2000 or earlier. // Building for Windows 2000 or earlier.
typedef int (WSAAPI *gni_t)(const socket_addr_type*, 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 (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
{ {
if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo")) 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 detail
} // namespace asio } // namespace asio
#undef ASIO_SOCKET_CALL
#include "asio/detail/pop_options.hpp" #include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SOCKET_OPS_HPP #endif // ASIO_DETAIL_SOCKET_OPS_HPP

View File

@ -52,7 +52,7 @@ public:
using namespace std; // For memset. using namespace std; // For memset.
sockaddr_in4_type addr; sockaddr_in4_type addr;
socket_addr_len_type addr_len = sizeof(addr); std::size_t addr_len = sizeof(addr);
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); addr.sin_addr.s_addr = inet_addr("127.0.0.1");

View File

@ -116,7 +116,6 @@ const int socket_error_retval = SOCKET_ERROR;
const int max_addr_v4_str_len = 256; const int max_addr_v4_str_len = 256;
const int max_addr_v6_str_len = 256; const int max_addr_v6_str_len = 256;
typedef sockaddr socket_addr_type; typedef sockaddr socket_addr_type;
typedef int socket_addr_len_type;
typedef in_addr in4_addr_type; typedef in_addr in4_addr_type;
typedef ip_mreq in4_mreq_type; typedef ip_mreq in4_mreq_type;
typedef sockaddr_in sockaddr_in4_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_v4_str_len = INET_ADDRSTRLEN;
const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
typedef sockaddr socket_addr_type; typedef sockaddr socket_addr_type;
typedef socklen_t socket_addr_len_type;
typedef in_addr in4_addr_type; typedef in_addr in4_addr_type;
typedef ip_mreq in4_mreq_type; typedef ip_mreq in4_mreq_type;
typedef sockaddr_in sockaddr_in4_type; typedef sockaddr_in sockaddr_in4_type;

View File

@ -135,9 +135,9 @@ public:
handler_base* last_waiter_; handler_base* last_waiter_;
// Storage for posted handlers. // Storage for posted handlers.
typedef boost::aligned_storage<64> handler_storage_type; typedef boost::aligned_storage<128> handler_storage_type;
#if defined(__BORLANDC__) #if defined(__BORLANDC__)
boost::aligned_storage<64> handler_storage_; boost::aligned_storage<128> handler_storage_;
#else #else
handler_storage_type handler_storage_; handler_storage_type handler_storage_;
#endif #endif
@ -235,7 +235,7 @@ public:
void* do_handler_allocate(std::size_t size) void* do_handler_allocate(std::size_t size)
{ {
#if defined(__BORLANDC__) #if defined(__BORLANDC__)
BOOST_ASSERT(size <= boost::aligned_storage<64>::size); BOOST_ASSERT(size <= boost::aligned_storage<128>::size);
#else #else
BOOST_ASSERT(size <= strand_impl::handler_storage_type::size); BOOST_ASSERT(size <= strand_impl::handler_storage_type::size);
#endif #endif

View File

@ -23,6 +23,7 @@
#include "asio/detail/event.hpp" #include "asio/detail/event.hpp"
#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/handler_queue.hpp"
#include "asio/detail/mutex.hpp" #include "asio/detail/mutex.hpp"
#include "asio/detail/service_base.hpp" #include "asio/detail/service_base.hpp"
#include "asio/detail/task_io_service_fwd.hpp" #include "asio/detail/task_io_service_fwd.hpp"
@ -42,12 +43,11 @@ public:
task_(use_service<Task>(io_service)), task_(use_service<Task>(io_service)),
task_interrupted_(true), task_interrupted_(true),
outstanding_work_(0), outstanding_work_(0),
handler_queue_(&task_handler_),
handler_queue_end_(&task_handler_),
stopped_(false), stopped_(false),
shutdown_(false), shutdown_(false),
first_idle_thread_(0) first_idle_thread_(0)
{ {
handler_queue_.push(&task_handler_);
} }
void init(size_t /*concurrency_hint*/) void init(size_t /*concurrency_hint*/)
@ -62,17 +62,16 @@ public:
lock.unlock(); lock.unlock();
// Destroy handler objects. // Destroy handler objects.
while (handler_queue_) while (!handler_queue_.empty())
{ {
handler_base* h = handler_queue_; handler_queue::handler* h = handler_queue_.front();
handler_queue_ = h->next_; handler_queue_.pop();
if (h != &task_handler_) if (h != &task_handler_)
h->destroy(); h->destroy();
} }
// Reset handler queue to initial state. // Reset handler queue to initial state.
handler_queue_ = &task_handler_; handler_queue_.push(&task_handler_);
handler_queue_end_ = &task_handler_;
} }
// Run the event loop until interrupted or no more work. // Run the event loop until interrupted or no more work.
@ -173,10 +172,7 @@ public:
void post(Handler handler) void post(Handler handler)
{ {
// Allocate and construct an operation to wrap the handler. // Allocate and construct an operation to wrap the handler.
typedef handler_wrapper<Handler> value_type; handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
typedef handler_alloc_traits<Handler, value_type> alloc_traits;
raw_handler_ptr<alloc_traits> raw_ptr(handler);
handler_ptr<alloc_traits> ptr(raw_ptr, handler);
asio::detail::mutex::scoped_lock lock(mutex_); asio::detail::mutex::scoped_lock lock(mutex_);
@ -185,15 +181,7 @@ public:
return; return;
// Add the handler to the end of the queue. // Add the handler to the end of the queue.
if (handler_queue_end_) handler_queue_.push(ptr.get());
{
handler_queue_end_->next_ = ptr.get();
handler_queue_end_ = ptr.get();
}
else
{
handler_queue_ = handler_queue_end_ = ptr.get();
}
ptr.release(); ptr.release();
// An undelivered handler is treated as unfinished work. // An undelivered handler is treated as unfinished work.
@ -227,18 +215,15 @@ private:
bool task_has_run = false; bool task_has_run = false;
while (!stopped_) while (!stopped_)
{ {
if (handler_queue_) if (!handler_queue_.empty())
{ {
// Prepare to execute first handler from queue. // Prepare to execute first handler from queue.
handler_base* h = handler_queue_; handler_queue::handler* h = handler_queue_.front();
handler_queue_ = h->next_; handler_queue_.pop();
if (handler_queue_ == 0)
handler_queue_end_ = 0;
h->next_ = 0;
if (h == &task_handler_) if (h == &task_handler_)
{ {
bool more_handlers = (handler_queue_ != 0); bool more_handlers = (!handler_queue_.empty());
task_interrupted_ = more_handlers || polling; task_interrupted_ = more_handlers || polling;
lock.unlock(); lock.unlock();
@ -263,7 +248,7 @@ private:
handler_cleanup c(lock, *this); handler_cleanup c(lock, *this);
// Invoke the handler. May throw an exception. // 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(); ec = asio::error_code();
return 1; 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. // Helper class to perform task-related operations on block exit.
class task_cleanup class task_cleanup
{ {
@ -433,20 +331,7 @@ private:
// Reinsert the task at the end of the handler queue. // Reinsert the task at the end of the handler queue.
lock_.lock(); lock_.lock();
task_io_service_.task_interrupted_ = true; task_io_service_.task_interrupted_ = true;
task_io_service_.task_handler_.next_ = 0; task_io_service_.handler_queue_.push(&task_io_service_.task_handler_);
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_;
}
} }
private: private:
@ -487,11 +372,11 @@ private:
// Handler object to represent the position of the task in the queue. // Handler object to represent the position of the task in the queue.
class task_handler class task_handler
: public handler_base : public handler_queue::handler
{ {
public: public:
task_handler() task_handler()
: handler_base(0, 0) : handler_queue::handler(0, 0)
{ {
} }
} task_handler_; } task_handler_;
@ -502,11 +387,8 @@ private:
// The count of unfinished work. // The count of unfinished work.
int outstanding_work_; int outstanding_work_;
// The start of a linked list of handlers that are ready to be delivered. // The queue of handlers that are ready to be delivered.
handler_base* handler_queue_; handler_queue handler_queue_;
// The end of a linked list of handlers that are ready to be delivered.
handler_base* handler_queue_end_;
// Flag to indicate that the dispatcher has been stopped. // Flag to indicate that the dispatcher has been stopped.
bool stopped_; bool stopped_;

View File

@ -561,7 +561,7 @@ public:
} }
endpoint_type endpoint; 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)) if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
return endpoint_type(); return endpoint_type();
endpoint.resize(addr_len); endpoint.resize(addr_len);
@ -600,7 +600,7 @@ public:
else else
{ {
endpoint_type endpoint; 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)) if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
return endpoint_type(); return endpoint_type();
endpoint.resize(addr_len); endpoint.resize(addr_len);
@ -1261,7 +1261,7 @@ public:
// Receive some data. // Receive some data.
DWORD bytes_transferred = 0; DWORD bytes_transferred = 0;
DWORD recv_flags = flags; 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, int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
&recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0); &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0);
if (result != 0) if (result != 0)
@ -1279,7 +1279,7 @@ public:
return 0; return 0;
} }
sender_endpoint.resize(endpoint_size); sender_endpoint.resize(static_cast<std::size_t>(endpoint_size));
ec = asio::error_code(); ec = asio::error_code();
return bytes_transferred; return bytes_transferred;
@ -1299,7 +1299,7 @@ public:
&receive_from_operation< &receive_from_operation<
MutableBufferSequence, Handler>::destroy_impl), MutableBufferSequence, Handler>::destroy_impl),
endpoint_(endpoint), endpoint_(endpoint),
endpoint_size_(endpoint.capacity()), endpoint_size_(static_cast<int>(endpoint.capacity())),
work_(io_service), work_(io_service),
buffers_(buffers), buffers_(buffers),
handler_(handler) handler_(handler)
@ -1463,7 +1463,7 @@ public:
{ {
asio::error_code ec; asio::error_code ec;
socket_holder new_socket; socket_holder new_socket;
socket_addr_len_type addr_len = 0; std::size_t addr_len = 0;
if (peer_endpoint) if (peer_endpoint)
{ {
addr_len = peer_endpoint->capacity(); addr_len = peer_endpoint->capacity();
@ -1618,7 +1618,8 @@ public:
GetAcceptExSockaddrs(handler_op->output_buffer(), 0, GetAcceptExSockaddrs(handler_op->output_buffer(), 0,
handler_op->address_length(), handler_op->address_length(), handler_op->address_length(), handler_op->address_length(),
&local_addr, &local_addr_length, &remote_addr, &remote_addr_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; last_error = WSAEINVAL;
} }
@ -1626,7 +1627,7 @@ public:
{ {
using namespace std; // For memcpy. using namespace std; // For memcpy.
memcpy(peer_endpoint.data(), remote_addr, remote_addr_length); 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));
} }
} }

View File

@ -54,6 +54,9 @@ namespace error
}; };
} // 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 to represent an error code value.
class error_code class error_code
{ {
@ -69,7 +72,7 @@ public:
} }
/// Construct with specific error code and category. /// Construct with specific error code and category.
error_code(value_type v, error::error_category c) error_code(value_type v, error_category c)
: value_(v), : value_(v),
category_(c) category_(c)
{ {
@ -89,7 +92,7 @@ public:
} }
/// Get the error category. /// Get the error category.
error::error_category category() const error_category category() const
{ {
return category_; return category_;
} }
@ -135,7 +138,7 @@ private:
value_type value_; value_type value_;
// The category associated with the error code. // The category associated with the error code.
error::error_category category_; error_category category_;
}; };
} // namespace asio } // namespace asio

View File

@ -39,6 +39,11 @@
namespace asio { 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. /// Provides core I/O functionality.
/** /**
* The io_service class provides the core I/O functionality for users of the * The io_service class provides the core I/O functionality for users of the

View File

@ -268,7 +268,12 @@ std::basic_ostream<Elem, Traits>& operator<<(
asio::error_code ec; asio::error_code ec;
std::string s = addr.to_string(ec); std::string s = addr.to_string(ec);
if (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 else
for (std::string::iterator i = s.begin(); i != s.end(); ++i) for (std::string::iterator i = s.begin(); i != s.end(); ++i)
os << os.widen(*i); os << os.widen(*i);

View File

@ -386,7 +386,12 @@ std::basic_ostream<Elem, Traits>& operator<<(
asio::error_code ec; asio::error_code ec;
std::string s = addr.to_string(ec); std::string s = addr.to_string(ec);
if (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 else
for (std::string::iterator i = s.begin(); i != s.end(); ++i) for (std::string::iterator i = s.begin(); i != s.end(); ++i)
os << os.widen(*i); os << os.widen(*i);

View File

@ -61,14 +61,6 @@ public:
typedef asio::detail::socket_addr_type data_type; typedef asio::detail::socket_addr_type data_type;
#endif #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. /// Default constructor.
basic_endpoint() basic_endpoint()
: data_() : data_()
@ -190,7 +182,7 @@ public:
} }
/// Get the underlying size of the endpoint in the native type. /// Get the underlying size of the endpoint in the native type.
size_type size() const std::size_t size() const
{ {
if (is_v4(data_)) if (is_v4(data_))
return sizeof(asio::detail::sockaddr_in4_type); return sizeof(asio::detail::sockaddr_in4_type);
@ -199,9 +191,9 @@ public:
} }
/// Set the underlying size of the endpoint in the native type. /// 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); asio::system_error e(asio::error::invalid_argument);
boost::throw_exception(e); boost::throw_exception(e);
@ -209,7 +201,7 @@ public:
} }
/// Get the capacity of the endpoint in the native type. /// Get the capacity of the endpoint in the native type.
size_type capacity() const std::size_t capacity() const
{ {
return sizeof(data_); return sizeof(data_);
} }
@ -349,11 +341,23 @@ std::ostream& operator<<(std::ostream& os,
const basic_endpoint<InternetProtocol>& endpoint) const basic_endpoint<InternetProtocol>& endpoint)
{ {
const address& addr = endpoint.address(); const address& addr = endpoint.address();
if (addr.is_v4()) asio::error_code ec;
os << addr.to_string(); 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 else
os << '[' << addr.to_string() << ']'; {
os << ':' << endpoint.port(); if (addr.is_v4())
os << a;
else
os << '[' << a << ']';
os << ':' << endpoint.port();
}
return os; return os;
} }
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) #else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
@ -363,11 +367,23 @@ std::basic_ostream<Elem, Traits>& operator<<(
const basic_endpoint<InternetProtocol>& endpoint) const basic_endpoint<InternetProtocol>& endpoint)
{ {
const address& addr = endpoint.address(); const address& addr = endpoint.address();
if (addr.is_v4()) asio::error_code ec;
os << addr.to_string(); 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 else
os << '[' << addr.to_string() << ']'; {
os << ':' << endpoint.port(); if (addr.is_v4())
os << a;
else
os << '[' << a << ']';
os << ':' << endpoint.port();
}
return os; return os;
} }
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) #endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))

View File

@ -80,9 +80,7 @@ public:
{ {
using namespace std; // For memcpy. using namespace std; // For memcpy.
typename InternetProtocol::endpoint endpoint; typename InternetProtocol::endpoint endpoint;
endpoint.resize( endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen));
static_cast<asio::detail::socket_addr_len_type>(
address_info->ai_addrlen));
memcpy(endpoint.data(), address_info->ai_addr, memcpy(endpoint.data(), address_info->ai_addr,
address_info->ai_addrlen); address_info->ai_addrlen);
iter.values_->push_back( iter.values_->push_back(

View File

@ -37,7 +37,7 @@ template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
class boolean class boolean
{ {
public: public:
#if defined(__sun) #if defined(__sun) || defined(_AIX)
typedef unsigned char value_type; typedef unsigned char value_type;
#else #else
typedef int value_type; typedef int value_type;

View File

@ -168,6 +168,10 @@ namespace libtorrent
// thread started to run the main downloader loop // thread started to run the main downloader loop
struct session_impl: boost::noncopyable struct session_impl: boost::noncopyable
{ {
// the size of each allocation that is chained in the send buffer
enum { send_buffer_size = 200 };
#ifndef NDEBUG #ifndef NDEBUG
friend class ::libtorrent::peer_connection; friend class ::libtorrent::peer_connection;
#endif #endif
@ -329,6 +333,24 @@ namespace libtorrent
{ return m_dht_proxy; } { return m_dht_proxy; }
#endif #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_lsd();
void start_natpmp(); void start_natpmp();
void start_upnp(); void start_upnp();
@ -340,10 +362,24 @@ namespace libtorrent
// handles delayed alerts // handles delayed alerts
alert_manager m_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: // private:
void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); 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. // this is where all active sockets are stored.
// the selector can sleep while there's no activity on // the selector can sleep while there's no activity on
// them // them
@ -358,9 +394,6 @@ namespace libtorrent
// when they are destructed. // when they are destructed.
file_pool m_files; file_pool m_files;
// handles disk io requests asynchronously
disk_io_thread m_disk_thread;
// this is a list of half-open tcp connections // this is a list of half-open tcp connections
// (only outgoing connections) // (only outgoing connections)
// this has to be one of the last // this has to be one of the last
@ -507,9 +540,9 @@ namespace libtorrent
pe_settings m_pe_settings; pe_settings m_pe_settings;
#endif #endif
boost::shared_ptr<natpmp> m_natpmp; boost::intrusive_ptr<natpmp> m_natpmp;
boost::shared_ptr<upnp> m_upnp; boost::intrusive_ptr<upnp> m_upnp;
boost::shared_ptr<lsd> m_lsd; boost::intrusive_ptr<lsd> m_lsd;
// the timer used to fire the second_tick // the timer used to fire the second_tick
deadline_timer m_timer; deadline_timer m_timer;
@ -526,6 +559,10 @@ namespace libtorrent
// logger used to write bandwidth usage statistics // logger used to write bandwidth usage statistics
std::ofstream m_stats_logger; std::ofstream m_stats_logger;
int m_second_counter; 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 #endif
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
boost::shared_ptr<logger> create_log(std::string const& name boost::shared_ptr<logger> create_log(std::string const& name

View File

@ -208,7 +208,7 @@ namespace libtorrent
void write_cancel(peer_request const& r); void write_cancel(peer_request const& r);
void write_bitfield(std::vector<bool> const& bitfield); void write_bitfield(std::vector<bool> const& bitfield);
void write_have(int index); 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(); void write_handshake();
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void write_extensions(); void write_extensions();
@ -270,8 +270,17 @@ namespace libtorrent
// these functions encrypt the send buffer if m_rc4_encrypted // these functions encrypt the send buffer if m_rc4_encrypted
// is true, otherwise it passes the call to the // is true, otherwise it passes the call to the
// peer_connection functions of the same names // 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); 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(); void setup_send();
// Returns offset at which bytestream (src, src + src_size) // Returns offset at which bytestream (src, src + src_size)

View 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

View File

@ -94,6 +94,11 @@ namespace libtorrent
disk_io_thread(int block_size = 16 * 1024); disk_io_thread(int block_size = 16 * 1024);
~disk_io_thread(); ~disk_io_thread();
#ifdef TORRENT_STATS
int disk_allocations() const
{ return m_allocations; }
#endif
// aborts read operations // aborts read operations
void stop(boost::intrusive_ptr<piece_manager> s); void stop(boost::intrusive_ptr<piece_manager> s);
void add_job(disk_io_job const& j void add_job(disk_io_job const& j
@ -110,6 +115,7 @@ namespace libtorrent
void operator()(); void operator()();
char* allocate_buffer(); char* allocate_buffer();
void free_buffer(char* buf);
private: private:
@ -129,6 +135,9 @@ namespace libtorrent
#ifdef TORRENT_DISK_STATS #ifdef TORRENT_DISK_STATS
std::ofstream m_log; std::ofstream m_log;
#endif #endif
#ifdef TORRENT_STATS
int m_allocations;
#endif
// thread for performing blocking disk io operations // thread for performing blocking disk io operations
boost::thread m_disk_io_thread; boost::thread m_disk_io_thread;

View File

@ -69,13 +69,20 @@ namespace libtorrent
{ {
public: public:
http_parser(); http_parser();
template <class T> std::string const& header(char const* key) const
T 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; } std::string const& protocol() const { return m_protocol; }
int status_code() const { return m_status_code; } int status_code() const { return m_status_code; }
std::string const& method() const { return m_method; } std::string const& method() const { return m_method; }
std::string const& path() const { return m_path; } 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; buffer::const_interval get_body() const;
bool header_finished() const { return m_state == read_body; } bool header_finished() const { return m_state == read_body; }
bool finished() const { return m_finished; } bool finished() const { return m_finished; }
@ -103,15 +110,6 @@ namespace libtorrent
bool m_finished; 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 class TORRENT_EXPORT http_tracker_connection
: public tracker_connection : public tracker_connection
{ {

View File

@ -60,6 +60,12 @@ namespace libtorrent
delete static_cast<T const*>(s); 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; } int refcount() const { return m_refs; }
intrusive_ptr_base(): m_refs(0) {} intrusive_ptr_base(): m_refs(0) {}

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/broadcast_socket.hpp" #include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
@ -52,7 +53,7 @@ namespace libtorrent
typedef boost::function<void(tcp::endpoint, sha1_hash)> peer_callback_t; typedef boost::function<void(tcp::endpoint, sha1_hash)> peer_callback_t;
class lsd : boost::noncopyable class lsd : public intrusive_ptr_base<lsd>
{ {
public: public:
lsd(io_service& ios, address const& listen_interface lsd(io_service& ios, address const& listen_interface

View File

@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_NATPMP_HPP #define TORRENT_NATPMP_HPP
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include <boost/function.hpp> #include <boost/function.hpp>
@ -49,7 +50,7 @@ namespace libtorrent
// std::string: error message // std::string: error message
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t; typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;
class natpmp class natpmp : public intrusive_ptr_base<natpmp>
{ {
public: public:
natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb); natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb);

View File

@ -51,6 +51,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/array.hpp> #include <boost/array.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/pool/pool.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
@ -73,6 +74,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/socket_type.hpp" #include "libtorrent/socket_type.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/chained_buffer.hpp"
namespace libtorrent namespace libtorrent
{ {
@ -356,14 +358,23 @@ namespace libtorrent
virtual boost::optional<piece_block_progress> virtual boost::optional<piece_block_progress>
downloading_piece_progress() const downloading_piece_progress() const
{ {
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "downloading_piece_progress() dispatched to the base class!\n"; (*m_logger) << "downloading_piece_progress() dispatched to the base class!\n";
#endif #endif
return boost::optional<piece_block_progress>(); 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); 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(); void setup_send();
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
@ -376,6 +387,12 @@ namespace libtorrent
bool has_country() const { return m_country[0] != 0; } bool has_country() const { return m_country[0] != 0; }
#endif #endif
int send_buffer_size() const
{ return m_send_buffer.size(); }
int send_buffer_capacity() const
{ return m_send_buffer.capacity(); }
protected: protected:
virtual void get_specific_peer_info(peer_info& p) const = 0; 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_cancel(peer_request const& r) = 0;
virtual void write_have(int index) = 0; virtual void write_have(int index) = 0;
virtual void write_keepalive() = 0; virtual void write_keepalive() = 0;
virtual void write_piece(peer_request const& r, char const* buffer) = 0; virtual void write_piece(peer_request const& r, char* buffer) = 0;
virtual void write_reject_request(peer_request const& r) = 0; virtual void write_reject_request(peer_request const& r) = 0;
virtual void write_allow_fast(int piece) = 0; virtual void write_allow_fast(int piece) = 0;
@ -401,13 +418,6 @@ namespace libtorrent
virtual void on_sent(asio::error_code const& error virtual void on_sent(asio::error_code const& error
, std::size_t bytes_transferred) = 0; , 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 #ifndef TORRENT_DISABLE_ENCRYPTION
buffer::interval wr_recv_buffer() buffer::interval wr_recv_buffer()
{ {
@ -512,31 +522,13 @@ namespace libtorrent
int m_recv_pos; int m_recv_pos;
buffer m_recv_buffer; buffer m_recv_buffer;
// this is the buffer where data that is chained_buffer m_send_buffer;
// 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;
// the number of bytes we are currently reading // the number of bytes we are currently reading
// from disk, that will be added to the send // from disk, that will be added to the send
// buffer as soon as they complete // buffer as soon as they complete
int m_reading_bytes; 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 // timeouts
ptime m_last_receive; ptime m_last_receive;
ptime m_last_sent; ptime m_last_sent;

View File

@ -184,6 +184,9 @@ namespace libtorrent
std::pair<bool, float> check_files(std::vector<bool>& pieces std::pair<bool, float> check_files(std::vector<bool>& pieces
, int& num_pieces, boost::recursive_mutex& mutex); , 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; void write_resume_data(entry& rd) const;
bool verify_resume_data(entry& rd, std::string& error); bool verify_resume_data(entry& rd, std::string& error);

View File

@ -49,6 +49,8 @@ namespace libtorrent
std::strftime(str, 200, "%b %d %X", timeinfo); std::strftime(str, 200, "%b %d %X", timeinfo);
return str; return str;
} }
inline std::string log_time();
} }
#if (!defined (__MACH__) && !defined (_WIN32) && (!defined(_POSIX_MONOTONIC_CLOCK) \ #if (!defined (__MACH__) && !defined (_WIN32) && (!defined(_POSIX_MONOTONIC_CLOCK) \
@ -389,5 +391,6 @@ namespace libtorrent
#endif #endif
#endif #endif
#endif #endif

View File

@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/broadcast_socket.hpp" #include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/http_connection.hpp" #include "libtorrent/http_connection.hpp"
#include "libtorrent/connection_queue.hpp" #include "libtorrent/connection_queue.hpp"
#include "libtorrent/intrusive_ptr_base.hpp"
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
@ -62,7 +63,7 @@ namespace libtorrent
// std::string: error message // std::string: error message
typedef boost::function<void(int, int, std::string const&)> portmap_callback_t; typedef boost::function<void(int, int, std::string const&)> portmap_callback_t;
class upnp : boost::noncopyable class upnp : public intrusive_ptr_base<upnp>
{ {
public: public:
upnp(io_service& ios, connection_queue& cc upnp(io_service& ios, connection_queue& cc

View File

@ -122,7 +122,7 @@ namespace libtorrent
void write_request(peer_request const& r); void write_request(peer_request const& r);
void write_cancel(peer_request const& r) {} void write_cancel(peer_request const& r) {}
void write_have(int index) {} 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 write_keepalive() {}
void on_connected(); void on_connected();
void write_reject_request(peer_request const&) {} void write_reject_request(peer_request const&) {}

View File

@ -58,6 +58,7 @@ $(top_srcdir)/include/libtorrent/intrusive_ptr_base.hpp \
$(top_srcdir)/include/libtorrent/invariant_check.hpp \ $(top_srcdir)/include/libtorrent/invariant_check.hpp \
$(top_srcdir)/include/libtorrent/io.hpp \ $(top_srcdir)/include/libtorrent/io.hpp \
$(top_srcdir)/include/libtorrent/ip_filter.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/lsd.hpp \
$(top_srcdir)/include/libtorrent/peer.hpp \ $(top_srcdir)/include/libtorrent/peer.hpp \
$(top_srcdir)/include/libtorrent/peer_connection.hpp \ $(top_srcdir)/include/libtorrent/peer_connection.hpp \

View File

@ -251,12 +251,10 @@ namespace libtorrent
(*m_logger) << time_now_string() (*m_logger) << time_now_string()
<< " ==> DHT_PORT [ " << listen_port << " ]\n"; << " ==> DHT_PORT [ " << listen_port << " ]\n";
#endif #endif
buffer::interval packet = allocate_send_buffer(7); char msg[] = {0,0,0,3, msg_dht_port, 0, 0};
detail::write_uint32(3, packet.begin); char* ptr = msg + 5;
detail::write_uint8(msg_dht_port, packet.begin); detail::write_uint16(listen_port, ptr);
detail::write_uint16(listen_port, packet.begin); send_buffer(msg, sizeof(msg));
assert(packet.begin == packet.end);
setup_send();
} }
void bt_peer_connection::write_have_all() void bt_peer_connection::write_have_all()
@ -270,8 +268,8 @@ namespace libtorrent
(*m_logger) << time_now_string() (*m_logger) << time_now_string()
<< " ==> HAVE_ALL\n"; << " ==> HAVE_ALL\n";
#endif #endif
char buf[] = {0,0,0,1, msg_have_all}; char msg[] = {0,0,0,1, msg_have_all};
send_buffer(buf, buf + sizeof(buf)); send_buffer(msg, sizeof(msg));
} }
void bt_peer_connection::write_have_none() void bt_peer_connection::write_have_none()
@ -285,8 +283,8 @@ namespace libtorrent
(*m_logger) << time_now_string() (*m_logger) << time_now_string()
<< " ==> HAVE_NONE\n"; << " ==> HAVE_NONE\n";
#endif #endif
char buf[] = {0,0,0,1, msg_have_none}; char msg[] = {0,0,0,1, msg_have_none};
send_buffer(buf, buf + sizeof(buf)); send_buffer(msg, sizeof(msg));
} }
void bt_peer_connection::write_reject_request(peer_request const& r) 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(m_sent_handshake && m_sent_bitfield);
assert(associated_torrent().lock()->valid_metadata()); assert(associated_torrent().lock()->valid_metadata());
char buf[] = {0,0,0,13, msg_reject_request}; 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;
buffer::interval i = allocate_send_buffer(17); detail::write_int32(r.piece, ptr); // index
detail::write_int32(r.start, ptr); // begin
std::copy(buf, buf + 5, i.begin); detail::write_int32(r.length, ptr); // length
i.begin += 5; send_buffer(msg, sizeof(msg));
// index
detail::write_int32(r.piece, i.begin);
// begin
detail::write_int32(r.start, i.begin);
// length
detail::write_int32(r.length, i.begin);
assert(i.begin == i.end);
setup_send();
} }
void bt_peer_connection::write_allow_fast(int piece) void bt_peer_connection::write_allow_fast(int piece)
@ -321,11 +309,10 @@ namespace libtorrent
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
assert(associated_torrent().lock()->valid_metadata()); assert(associated_torrent().lock()->valid_metadata());
char buf[] = {0,0,0,5, msg_allowed_fast, 0, 0, 0, 0}; char msg[] = {0,0,0,5, msg_allowed_fast, 0, 0, 0, 0};
char* ptr = msg + 5;
char* ptr = buf + 5;
detail::write_int32(piece, ptr); 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 void bt_peer_connection::get_specific_peer_info(peer_info& p) const
@ -556,8 +543,8 @@ namespace libtorrent
assert(secret); assert(secret);
hasher h; hasher h;
const char keyA[] = "keyA"; static const char keyA[] = "keyA";
const char keyB[] = "keyB"; static const char keyB[] = "keyB";
// encryption rc4 longkeys // encryption rc4 longkeys
// outgoing connection : hash ('keyA',S,SKEY) // outgoing connection : hash ('keyA',S,SKEY)
@ -587,17 +574,16 @@ namespace libtorrent
#endif #endif
} }
void bt_peer_connection::send_buffer(char* begin, char* end) void bt_peer_connection::send_buffer(char* buf, int size)
{ {
assert (begin); assert(buf);
assert (end); assert(size > 0);
assert (end > begin); assert(!m_rc4_encrypted || m_encrypted);
assert (!m_rc4_encrypted || m_encrypted);
if (m_rc4_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) buffer::interval bt_peer_connection::allocate_send_buffer(int size)
@ -606,6 +592,7 @@ namespace libtorrent
if (m_rc4_encrypted) if (m_rc4_encrypted)
{ {
assert(m_enc_send_buffer.left() == 0);
m_enc_send_buffer = peer_connection::allocate_send_buffer(size); m_enc_send_buffer = peer_connection::allocate_send_buffer(size);
return m_enc_send_buffer; return m_enc_send_buffer;
} }
@ -620,24 +607,24 @@ namespace libtorrent
{ {
assert(!m_rc4_encrypted || m_encrypted); 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.begin);
assert (m_enc_send_buffer.end); assert(m_enc_send_buffer.end);
assert (m_enc_send_buffer.left() > 0);
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(); peer_connection::setup_send();
} }
int bt_peer_connection::get_syncoffset(char const* src, int src_size, 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(target_size >= src_size);
assert (src_size > 0); assert(src_size > 0);
assert (src); assert(src);
assert (target); assert(target);
int traverse_limit = target_size - src_size; int traverse_limit = target_size - src_size;
@ -1288,8 +1275,8 @@ namespace libtorrent
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
char buf[] = {0,0,0,0}; char msg[] = {0,0,0,0};
send_buffer(buf, buf + sizeof(buf)); send_buffer(msg, sizeof(msg));
} }
void bt_peer_connection::write_cancel(peer_request const& r) void bt_peer_connection::write_cancel(peer_request const& r)
@ -1299,22 +1286,12 @@ namespace libtorrent
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
assert(associated_torrent().lock()->valid_metadata()); assert(associated_torrent().lock()->valid_metadata());
char buf[] = {0,0,0,13, msg_cancel}; char msg[17] = {0,0,0,13, msg_cancel};
char* ptr = msg + 5;
buffer::interval i = allocate_send_buffer(17); detail::write_int32(r.piece, ptr); // index
detail::write_int32(r.start, ptr); // begin
std::copy(buf, buf + 5, i.begin); detail::write_int32(r.length, ptr); // length
i.begin += 5; send_buffer(msg, sizeof(msg));
// index
detail::write_int32(r.piece, i.begin);
// begin
detail::write_int32(r.start, i.begin);
// length
detail::write_int32(r.length, i.begin);
assert(i.begin == i.end);
setup_send();
} }
void bt_peer_connection::write_request(peer_request const& r) void bt_peer_connection::write_request(peer_request const& r)
@ -1324,22 +1301,13 @@ namespace libtorrent
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
assert(associated_torrent().lock()->valid_metadata()); 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); detail::write_int32(r.piece, ptr); // index
detail::write_int32(r.start, ptr); // begin
std::copy(buf, buf + 5, i.begin); detail::write_int32(r.length, ptr); // length
i.begin += 5; send_buffer(msg, sizeof(msg));
// index
detail::write_int32(r.piece, i.begin);
// begin
detail::write_int32(r.start, i.begin);
// length
detail::write_int32(r.length, i.begin);
assert(i.begin == i.end);
setup_send();
} }
void bt_peer_connection::write_bitfield(std::vector<bool> const& bitfield) void bt_peer_connection::write_bitfield(std::vector<bool> const& bitfield)
@ -1526,7 +1494,7 @@ namespace libtorrent
if (is_choked()) return; if (is_choked()) return;
char msg[] = {0,0,0,1,msg_choke}; 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() void bt_peer_connection::write_unchoke()
@ -1536,7 +1504,7 @@ namespace libtorrent
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
char msg[] = {0,0,0,1,msg_unchoke}; 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() void bt_peer_connection::write_interested()
@ -1546,7 +1514,7 @@ namespace libtorrent
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
char msg[] = {0,0,0,1,msg_interested}; 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() void bt_peer_connection::write_not_interested()
@ -1556,7 +1524,7 @@ namespace libtorrent
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
char msg[] = {0,0,0,1,msg_not_interested}; 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) void bt_peer_connection::write_have(int index)
@ -1567,34 +1535,39 @@ namespace libtorrent
assert(index < associated_torrent().lock()->torrent_file().num_pieces()); assert(index < associated_torrent().lock()->torrent_file().num_pieces());
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
const int packet_size = 9; char msg[] = {0,0,0,5,msg_have,0,0,0,0};
char msg[packet_size] = {0,0,0,5,msg_have};
char* ptr = msg + 5; char* ptr = msg + 5;
detail::write_int32(index, ptr); 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; INVARIANT_CHECK;
assert(m_sent_handshake && m_sent_bitfield); assert(m_sent_handshake && m_sent_bitfield);
const int packet_size = 4 + 5 + 4 + r.length;
boost::shared_ptr<torrent> t = associated_torrent().lock(); boost::shared_ptr<torrent> t = associated_torrent().lock();
assert(t); assert(t);
buffer::interval i = allocate_send_buffer(packet_size); 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));
detail::write_int32(packet_size-4, i.begin); append_send_buffer(buffer, r.length
detail::write_uint8(msg_piece, i.begin); , boost::bind(&session_impl::free_disk_buffer
detail::write_int32(r.piece, i.begin); , boost::ref(m_ses), _1));
detail::write_int32(r.start, i.begin);
/*
buffer::interval i = allocate_send_buffer(r.length);
std::memcpy(i.begin, buffer, r.length); std::memcpy(i.begin, buffer, r.length);
t->filesystem().free_buffer(buffer);
assert(i.begin + r.length == i.end); */
m_payloads.push_back(range(send_buffer_size() - r.length, r.length)); m_payloads.push_back(range(send_buffer_size() - r.length, r.length));
setup_send(); setup_send();
} }

View File

@ -37,18 +37,6 @@ POSSIBILITY OF SUCH DAMAGE.
#ifdef TORRENT_DISK_STATS #ifdef TORRENT_DISK_STATS
#include "libtorrent/time.hpp" #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 #endif
@ -64,7 +52,9 @@ namespace libtorrent
#endif #endif
, m_disk_io_thread(boost::ref(*this)) , m_disk_io_thread(boost::ref(*this))
{ {
#ifdef TORRENT_STATS
m_allocations = 0;
#endif
#ifdef TORRENT_DISK_STATS #ifdef TORRENT_DISK_STATS
m_log.open("disk_io_thread.log", std::ios::trunc); m_log.open("disk_io_thread.log", std::ios::trunc);
#endif #endif
@ -188,9 +178,21 @@ namespace libtorrent
char* disk_io_thread::allocate_buffer() char* disk_io_thread::allocate_buffer()
{ {
boost::mutex::scoped_lock l(m_mutex); boost::mutex::scoped_lock l(m_mutex);
#ifdef TORRENT_STATS
++m_allocations;
#endif
return (char*)m_pool.ordered_malloc(); 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()() void disk_io_thread::operator()()
{ {
for (;;) for (;;)
@ -225,10 +227,14 @@ namespace libtorrent
#ifdef TORRENT_DISK_STATS #ifdef TORRENT_DISK_STATS
m_log << log_time() << " read " << j.buffer_size << std::endl; m_log << log_time() << " read " << j.buffer_size << std::endl;
#endif #endif
free_buffer = false;
if (j.buffer == 0) if (j.buffer == 0)
{ {
l.lock(); l.lock();
j.buffer = (char*)m_pool.ordered_malloc(); j.buffer = (char*)m_pool.ordered_malloc();
#ifdef TORRENT_STATS
++m_allocations;
#endif
l.unlock(); l.unlock();
assert(j.buffer_size <= m_block_size); assert(j.buffer_size <= m_block_size);
if (j.buffer == 0) if (j.buffer == 0)
@ -238,10 +244,6 @@ namespace libtorrent
break; break;
} }
} }
else
{
free_buffer = false;
}
ret = j.storage->read_impl(j.buffer, j.piece, j.offset ret = j.storage->read_impl(j.buffer, j.piece, j.offset
, j.buffer_size); , j.buffer_size);
@ -301,6 +303,9 @@ namespace libtorrent
{ {
l.lock(); l.lock();
m_pool.ordered_free(j.buffer); m_pool.ordered_free(j.buffer);
#ifdef TORRENT_STATS
--m_allocations;
#endif
} }
} }
} }

View File

@ -263,7 +263,7 @@ void http_connection::on_read(asio::error_code const& e
if (code >= 300 && code < 400) if (code >= 300 && code < 400)
{ {
// attempt a redirect // attempt a redirect
std::string url = m_parser.header<std::string>("location"); std::string const& url = m_parser.header("location");
if (url.empty()) if (url.empty())
{ {
// missing location header // missing location header

View File

@ -679,7 +679,7 @@ namespace libtorrent
if (m_parser.header_finished()) 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) if (cl > m_settings.tracker_maximum_response_length)
{ {
fail(-1, "content-length is greater than maximum response length"); fail(-1, "content-length is greater than maximum response length");
@ -718,7 +718,7 @@ namespace libtorrent
return; return;
} }
std::string location = m_parser.header<std::string>("location"); std::string location = m_parser.header("location");
boost::shared_ptr<request_callback> cb = requester(); 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); 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 defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
if (cb) cb->debug_log("content-encoding: \"" + content_encoding + "\""); if (cb) cb->debug_log("content-encoding: \"" + content_encoding + "\"");

View File

@ -58,7 +58,7 @@ lsd::lsd(io_service& ios, address const& listen_interface
: m_callback(cb) : m_callback(cb)
, m_retry_count(0) , m_retry_count(0)
, m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143"), 6771) , 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_broadcast_timer(ios)
, m_disabled(false) , m_disabled(false)
{ {
@ -96,7 +96,7 @@ void lsd::announce(sha1_hash const& ih, int listen_port)
#endif #endif
m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); 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 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; return;
m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); 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&) catch (std::exception&)
{} {}
@ -121,48 +121,53 @@ void lsd::on_announce(udp::endpoint const& from, char* buffer
{ {
using namespace libtorrent::detail; using namespace libtorrent::detail;
char* p = buffer; http_parser p;
char* end = buffer + bytes_transferred;
char* line = std::find(p, end, '\n'); p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred));
for (char* i = p; i < line; ++i) *i = std::tolower(*i);
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) if (!p.header_finished())
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)))
{ {
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
m_log << time_now_string() m_log << time_now_string()
<< " *** assumed 'bt-search', ignoring" << std::endl; << " <== announce: incomplete HTTP message\n";
#endif #endif
return; return;
} }
p = line + 1;
int port = 0; if (p.method() != "bt-search")
sha1_hash ih(0);
while (p != end)
{ {
line = std::find(p, end, '\n'); #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
if (line == end) break; m_log << time_now_string()
*line = 0; << " <== announce: invalid HTTP method: " << p.method() << std::endl;
for (char* i = p; i < line; ++i) *i = std::tolower(*i); #endif
if (line - p >= 5 && memcmp(p, "port:", 5) == 0) return;
{
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;
} }
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 (!ih.is_all_zeros() && port != 0)
{ {
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)

View File

@ -161,7 +161,7 @@ void natpmp::update_mapping(int i, int port)
m_retry_count = 0; m_retry_count = 0;
send_map_request(i); send_map_request(i);
m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) 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 // linear back-off instead of exponential
++m_retry_count; ++m_retry_count;
m_send_timer.expires_from_now(milliseconds(250 * 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) catch (std::exception& e)
{ {
@ -227,7 +227,7 @@ void natpmp::on_reply(asio::error_code const& e
if (m_remote != m_nat_endpoint) if (m_remote != m_nat_endpoint)
{ {
m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) 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; return;
} }
@ -346,7 +346,7 @@ void natpmp::update_expiration_timer()
if (min_index >= 0) if (min_index >= 0)
{ {
m_refresh_timer.expires_from_now(min_expire - now); 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; m_retry_count = 0;
send_map_request(i); send_map_request(i);
m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) 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));
} }
} }

View File

@ -81,9 +81,7 @@ namespace libtorrent
, m_last_unchoke(min_time()) , m_last_unchoke(min_time())
, m_packet_size(0) , m_packet_size(0)
, m_recv_pos(0) , m_recv_pos(0)
, m_current_send_buffer(0)
, m_reading_bytes(0) , m_reading_bytes(0)
, m_write_pos(0)
, m_last_receive(time_now()) , m_last_receive(time_now())
, m_last_sent(time_now()) , m_last_sent(time_now())
, m_socket(s) , m_socket(s)
@ -161,9 +159,7 @@ namespace libtorrent
, m_last_unchoke(min_time()) , m_last_unchoke(min_time())
, m_packet_size(0) , m_packet_size(0)
, m_recv_pos(0) , m_recv_pos(0)
, m_current_send_buffer(0)
, m_reading_bytes(0) , m_reading_bytes(0)
, m_write_pos(0)
, m_last_receive(time_now()) , m_last_receive(time_now())
, m_last_sent(time_now()) , m_last_sent(time_now())
, m_socket(s) , m_socket(s)
@ -2082,8 +2078,7 @@ namespace libtorrent
p.remote_dl_rate = 0; p.remote_dl_rate = 0;
} }
p.send_buffer_size = int(m_send_buffer[0].capacity() p.send_buffer_size = m_send_buffer.capacity();
+ m_send_buffer[1].capacity());
} }
void peer_connection::cut_receive_buffer(int size, int packet_size) void peer_connection::cut_receive_buffer(int size, int packet_size)
@ -2386,8 +2381,7 @@ namespace libtorrent
shared_ptr<torrent> t = m_torrent.lock(); shared_ptr<torrent> t = m_torrent.lock();
if (m_bandwidth_limit[upload_channel].quota_left() == 0 if (m_bandwidth_limit[upload_channel].quota_left() == 0
&& (!m_send_buffer[m_current_send_buffer].empty() && !m_send_buffer.empty()
|| !m_send_buffer[(m_current_send_buffer + 1) & 1].empty())
&& !m_connecting && !m_connecting
&& t && t
&& !m_ignore_bandwidth_limits) && !m_ignore_bandwidth_limits)
@ -2415,32 +2409,21 @@ namespace libtorrent
assert(!m_writing); 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 // 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(); int quota_left = m_bandwidth_limit[upload_channel].quota_left();
if (!m_ignore_bandwidth_limits && amount_to_send > quota_left) if (!m_ignore_bandwidth_limits && amount_to_send > quota_left)
amount_to_send = quota_left; amount_to_send = quota_left;
assert(amount_to_send > 0); assert(amount_to_send > 0);
assert(m_write_pos < (int)m_send_buffer[sending_buffer].size());
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "async_write " << amount_to_send << " bytes\n"; (*m_logger) << "async_write " << amount_to_send << " bytes\n";
#endif #endif
m_socket->async_write_some(asio::buffer( std::list<asio::const_buffer> const& vec = m_send_buffer.build_iovec(amount_to_send);
&m_send_buffer[sending_buffer][m_write_pos], amount_to_send) m_socket->async_write_some(vec, bind(&peer_connection::on_send_data, self(), _1, _2));
, bind(&peer_connection::on_send_data, self(), _1, _2));
m_writing = true; m_writing = true;
} }
@ -2511,10 +2494,32 @@ namespace libtorrent
m_recv_buffer.resize(m_packet_size); 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]; int free_space = m_send_buffer.space_in_last_buffer();
buf.insert(buf.end(), begin, end); 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(); setup_send();
} }
@ -2522,10 +2527,29 @@ namespace libtorrent
// return value is destructed // return value is destructed
buffer::interval peer_connection::allocate_send_buffer(int size) buffer::interval peer_connection::allocate_send_buffer(int size)
{ {
buffer& buf = m_send_buffer[m_current_send_buffer]; char* insert = m_send_buffer.allocate_appendix(size);
buf.resize(buf.size() + size); if (insert == 0)
buffer::interval ret(&buf[0] + buf.size() - size, &buf[0] + buf.size()); {
return ret; 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> template<class T>
@ -2647,8 +2671,7 @@ namespace libtorrent
// if we have requests or pending data to be sent or announcements to be made // if we have requests or pending data to be sent or announcements to be made
// we want to send data // we want to send data
return (!m_send_buffer[m_current_send_buffer].empty() return !m_send_buffer.empty()
|| !m_send_buffer[(m_current_send_buffer + 1) & 1].empty())
&& (m_bandwidth_limit[upload_channel].quota_left() > 0 && (m_bandwidth_limit[upload_channel].quota_left() > 0
|| m_ignore_bandwidth_limits) || m_ignore_bandwidth_limits)
&& !m_connecting; && !m_connecting;
@ -2763,6 +2786,9 @@ namespace libtorrent
INVARIANT_CHECK; INVARIANT_CHECK;
assert(m_writing); assert(m_writing);
m_send_buffer.pop_front(bytes_transferred);
m_writing = false; m_writing = false;
if (!m_ignore_bandwidth_limits) if (!m_ignore_bandwidth_limits)
@ -2772,9 +2798,6 @@ namespace libtorrent
(*m_logger) << "wrote " << bytes_transferred << " bytes\n"; (*m_logger) << "wrote " << bytes_transferred << " bytes\n";
#endif #endif
m_write_pos += bytes_transferred;
if (error) if (error)
{ {
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
@ -2787,34 +2810,11 @@ namespace libtorrent
assert(!m_connecting); assert(!m_connecting);
assert(bytes_transferred > 0); 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(); m_last_sent = time_now();
on_sent(error, bytes_transferred); on_sent(error, bytes_transferred);
fill_send_buffer(); 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(); setup_send();
} }
catch (std::exception& e) 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 // extremely expensive invariant check
/* /*

View File

@ -1426,16 +1426,16 @@ namespace libtorrent
int nonempty_connections = 0; int nonempty_connections = 0;
std::set<address> unique_test; std::set<address> unique_test;
std::set<tcp::endpoint> unique_test2; // std::set<tcp::endpoint> unique_test2;
for (const_iterator i = m_peers.begin(); for (const_iterator i = m_peers.begin();
i != m_peers.end(); ++i) i != m_peers.end(); ++i)
{ {
peer const& p = *i; peer const& p = *i;
if (!m_torrent->settings().allow_multiple_connections_per_ip) // if (!m_torrent->settings().allow_multiple_connections_per_ip)
assert(unique_test.find(p.ip.address()) == unique_test.end()); // assert(unique_test.find(p.ip.address()) == unique_test.end());
assert(unique_test2.find(p.ip) == unique_test2.end()); // assert(unique_test2.find(p.ip) == unique_test2.end());
unique_test.insert(p.ip.address()); // unique_test.insert(p.ip.address());
unique_test2.insert(p.ip); // unique_test2.insert(p.ip);
++total_connections; ++total_connections;
if (!p.connection) if (!p.connection)
{ {

View File

@ -83,6 +83,14 @@ using libtorrent::aux::session_impl;
namespace libtorrent 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 namespace aux
{ {
filesystem_init::filesystem_init() filesystem_init::filesystem_init()

View File

@ -507,7 +507,8 @@ namespace detail
std::pair<int, int> listen_port_range std::pair<int, int> listen_port_range
, fingerprint const& cl_fprint , fingerprint const& cl_fprint
, char const* listen_interface) , char const* listen_interface)
: m_strand(m_io_service) : m_send_buffers(send_buffer_size)
, m_strand(m_io_service)
, m_files(40) , m_files(40)
, m_half_open(m_io_service) , m_half_open(m_io_service)
, m_download_channel(m_io_service, peer_connection::download_channel) , m_download_channel(m_io_service, peer_connection::download_channel)
@ -546,7 +547,7 @@ namespace detail
#endif #endif
#ifdef TORRENT_STATS #ifdef TORRENT_STATS
m_stats_logger.open("session_stats.log"); m_stats_logger.open("session_stats.log", std::ios::trunc);
m_stats_logger << m_stats_logger <<
"1. second\n" "1. second\n"
"2. upload rate\n" "2. upload rate\n"
@ -555,7 +556,9 @@ namespace detail
"5. seeding torrents\n" "5. seeding torrents\n"
"6. peers\n" "6. peers\n"
"7. connecting peers\n" "7. connecting peers\n"
"8. disk block buffers\n"
"\n"; "\n";
m_buffer_usage_logger.open("buffer_stats.log", std::ios::trunc);
m_second_counter = 0; m_second_counter = 0;
#endif #endif
@ -999,7 +1002,8 @@ namespace detail
{ {
session_impl::mutex_t::scoped_lock l(m_mutex); session_impl::mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK; // too expensive
// INVARIANT_CHECK;
if (e) if (e)
{ {
@ -1031,7 +1035,7 @@ namespace detail
else else
++downloading_torrents; ++downloading_torrents;
} }
int num_connections = 0; int num_complete_connections = 0;
int num_half_open = 0; int num_half_open = 0;
for (connection_map::iterator i = m_connections.begin() for (connection_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i) , end(m_connections.end()); i != end; ++i)
@ -1039,7 +1043,7 @@ namespace detail
if (i->second->is_connecting()) if (i->second->is_connecting())
++num_half_open; ++num_half_open;
else else
++num_connections; ++num_complete_connections;
} }
m_stats_logger m_stats_logger
@ -1048,8 +1052,9 @@ namespace detail
<< m_stat.download_rate() << "\t" << m_stat.download_rate() << "\t"
<< downloading_torrents << "\t" << downloading_torrents << "\t"
<< seeding_torrents << "\t" << seeding_torrents << "\t"
<< num_connections << "\t" << num_complete_connections << "\t"
<< num_half_open << "\t" << num_half_open << "\t"
<< m_disk_thread.disk_allocations() << "\t"
<< std::endl; << std::endl;
#endif #endif
@ -2195,9 +2200,9 @@ namespace detail
INVARIANT_CHECK; INVARIANT_CHECK;
m_lsd.reset(new lsd(m_io_service m_lsd = new lsd(m_io_service
, m_listen_interface.address() , 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() void session_impl::start_natpmp()
@ -2206,10 +2211,10 @@ namespace detail
INVARIANT_CHECK; INVARIANT_CHECK;
m_natpmp.reset(new natpmp(m_io_service m_natpmp = new natpmp(m_io_service
, m_listen_interface.address() , m_listen_interface.address()
, bind(&session_impl::on_port_mapping , bind(&session_impl::on_port_mapping
, this, _1, _2, _3))); , this, _1, _2, _3));
m_natpmp->set_mappings(m_listen_interface.port(), m_natpmp->set_mappings(m_listen_interface.port(),
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
@ -2224,11 +2229,11 @@ namespace detail
INVARIANT_CHECK; 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_listen_interface.address()
, m_settings.user_agent , m_settings.user_agent
, bind(&session_impl::on_port_mapping , bind(&session_impl::on_port_mapping
, this, _1, _2, _3))); , this, _1, _2, _3));
m_upnp->set_mappings(m_listen_interface.port(), m_upnp->set_mappings(m_listen_interface.port(),
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
@ -2240,7 +2245,7 @@ namespace detail
void session_impl::stop_lsd() void session_impl::stop_lsd()
{ {
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
m_lsd.reset(); m_lsd = 0;
} }
void session_impl::stop_natpmp() void session_impl::stop_natpmp()
@ -2248,7 +2253,7 @@ namespace detail
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
if (m_natpmp.get()) if (m_natpmp.get())
m_natpmp->close(); m_natpmp->close();
m_natpmp.reset(); m_natpmp = 0;
} }
void session_impl::stop_upnp() void session_impl::stop_upnp()
@ -2256,9 +2261,38 @@ namespace detail
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
if (m_upnp.get()) if (m_upnp.get())
m_upnp->close(); 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 #ifndef NDEBUG
void session_impl::check_invariant() const void session_impl::check_invariant() const

View File

@ -1065,6 +1065,11 @@ namespace libtorrent
return m_storage->verify_resume_data(rd, error); 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( void piece_manager::async_release_files(
boost::function<void(int, disk_io_job const&)> const& handler) boost::function<void(int, disk_io_job const&)> const& handler)
{ {

View File

@ -1464,9 +1464,6 @@ namespace libtorrent
m_policy->connection_closed(*p); m_policy->connection_closed(*p);
p->set_peer_info(0); p->set_peer_info(0);
m_connections.erase(i); m_connections.erase(i);
#ifndef NDEBUG
m_policy->check_invariant();
#endif
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -2940,4 +2937,3 @@ namespace libtorrent
} }

View File

@ -901,4 +901,3 @@ namespace libtorrent
} }
} }

View File

@ -70,7 +70,7 @@ upnp::upnp(io_service& ios, connection_queue& cc
, m_io_service(ios) , m_io_service(ios)
, m_strand(ios) , m_strand(ios)
, m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250"), 1900) , 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_broadcast_timer(ios)
, m_refresh_timer(ios) , m_refresh_timer(ios)
, m_disabled(false) , m_disabled(false)
@ -119,7 +119,7 @@ void upnp::discover_device() try
++m_retry_count; ++m_retry_count;
m_broadcast_timer.expires_from_now(milliseconds(250 * 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 m_broadcast_timer.async_wait(m_strand.wrap(bind(&upnp::resend_request
, this, _1))); , self(), _1)));
#ifdef TORRENT_UPNP_LOGGING #ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string() m_log << time_now_string()
@ -203,7 +203,7 @@ try
try try
{ {
d.upnp_connection.reset(new http_connection(m_io_service 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))))); , boost::ref(d)))));
d.upnp_connection->get(d.url); d.upnp_connection->get(d.url);
} }
@ -300,7 +300,7 @@ try
return; return;
} }
std::string url = p.header<std::string>("location"); std::string url = p.header("location");
if (url.empty()) if (url.empty())
{ {
#ifdef TORRENT_UPNP_LOGGING #ifdef TORRENT_UPNP_LOGGING
@ -393,7 +393,7 @@ try
try try
{ {
d.upnp_connection.reset(new http_connection(m_io_service 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))))); , boost::ref(d)))));
d.upnp_connection->get(d.url); d.upnp_connection->get(d.url);
} }
@ -480,9 +480,9 @@ void upnp::map_port(rootdevice& d, int i)
assert(d.service_namespace); assert(d.service_namespace);
d.upnp_connection.reset(new http_connection(m_io_service 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 , 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) d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
, seconds(10)); , seconds(10));
@ -523,9 +523,9 @@ void upnp::unmap_port(rootdevice& d, int i)
return; return;
} }
d.upnp_connection.reset(new http_connection(m_io_service 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 , 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) d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
, seconds(10)); , seconds(10));
@ -851,7 +851,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|| next_expire > d.mapping[mapping].expires) || next_expire > d.mapping[mapping].expires)
{ {
m_refresh_timer.expires_at(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 else
@ -962,7 +962,7 @@ void upnp::on_expire(asio::error_code const& e) try
if (next_expire != max_time()) if (next_expire != max_time())
{ {
m_refresh_timer.expires_at(next_expire); 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&) catch (std::exception&)

View File

@ -297,7 +297,7 @@ namespace libtorrent
(*m_logger) << request << "\n"; (*m_logger) << request << "\n";
#endif #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 // this means we got a redirection request
// look for the location header // look for the location header
std::string location = m_parser.header<std::string>("location"); std::string location = m_parser.header("location");
if (location.empty()) if (location.empty())
{ {
@ -423,7 +423,7 @@ namespace libtorrent
throw std::runtime_error("redirecting to " + location); 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()) if (!server_version.empty())
{ {
m_server_string = "URL seed @ "; m_server_string = "URL seed @ ";
@ -445,7 +445,7 @@ namespace libtorrent
size_type range_end; size_type range_end;
if (m_parser.status_code() == 206) 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; char dummy;
std::string bytes; std::string bytes;
range_str >> bytes >> range_start >> dummy >> range_end; range_str >> bytes >> range_start >> dummy >> range_end;
@ -461,7 +461,7 @@ namespace libtorrent
else else
{ {
range_start = 0; 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) if (range_end == -1)
{ {
// we should not try this server again. // we should not try this server again.

View File

@ -18,7 +18,7 @@
plugin_name = _("Move Torrent") plugin_name = _("Move Torrent")
plugin_author = "Marcos Pinto" plugin_author = "Marcos Pinto"
plugin_version = "0.1" plugin_version = "0.2"
plugin_description = _("This plugin allows users to move the torrent to a \ plugin_description = _("This plugin allows users to move the torrent to a \
different directory without having to remove and re-add the torrent. This \ different directory without having to remove and re-add the torrent. This \
feature can be found by right-clicking on a torrent.\nFurthermore, it \ feature can be found by right-clicking on a torrent.\nFurthermore, it \