mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-08-16 15:12:30 +00:00
* Piece request messages didn't get read when they were the only
message in the buffer, it required an additional byte beyond the size of the request body. * More work on ClientInfo. * Bound 'k' to disconnecting a peer. Consider a better key. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@647 e378c898-3ddf-0310-93e7-cc216c733640
This commit is contained in:
@@ -241,6 +241,20 @@
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>k</term>
|
||||
<listitem><para>
|
||||
Disconnect peer.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>*</term>
|
||||
<listitem><para>
|
||||
Choke/Snubb peer.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</refsect2>
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2006, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// Wrapper for addrinfo with focus on zero-copy conversion to and from
|
||||
// the c-type and wrapper.
|
||||
//
|
||||
// Do use the wrapper on a pre-existing struct addrinfo, cast the
|
||||
// pointer rather than the base type.
|
||||
|
||||
#ifndef RAK_ADDRESS_INFO_H
|
||||
#define RAK_ADDRESS_INFO_H
|
||||
|
||||
#include <netdb.h>
|
||||
#include <rak/socket_address.h>
|
||||
|
||||
namespace rak {
|
||||
|
||||
class address_info {
|
||||
public:
|
||||
void clear() { std::memset(this, 0, sizeof(address_info)); }
|
||||
|
||||
int flags() const { return m_addrinfo.ai_flags; }
|
||||
void set_flags(int f) { m_addrinfo.ai_flags = f; }
|
||||
|
||||
int family() const { return m_addrinfo.ai_family; }
|
||||
void set_family(int f) { m_addrinfo.ai_family = f; }
|
||||
|
||||
int socket_type() const { return m_addrinfo.ai_socktype; }
|
||||
void set_socket_type(int t) { m_addrinfo.ai_socktype = t; }
|
||||
|
||||
int protocol() const { return m_addrinfo.ai_protocol; }
|
||||
void set_protocol(int p) { m_addrinfo.ai_protocol = p; }
|
||||
|
||||
size_t length() const { return m_addrinfo.ai_addrlen; }
|
||||
|
||||
socket_address* address() { return reinterpret_cast<socket_address*>(m_addrinfo.ai_addr); }
|
||||
|
||||
addrinfo* c_addrinfo() { return &m_addrinfo; }
|
||||
const addrinfo* c_addrinfo() const { return &m_addrinfo; }
|
||||
|
||||
address_info* next() { return reinterpret_cast<address_info*>(m_addrinfo.ai_next); }
|
||||
|
||||
static int get_address_info(const char* node, int domain, int type, address_info** ai);
|
||||
|
||||
static void free_address_info(address_info* ai) { ::freeaddrinfo(ai->c_addrinfo()); }
|
||||
|
||||
static const char* strerror(int err) { return gai_strerror(err); }
|
||||
|
||||
private:
|
||||
addrinfo m_addrinfo;
|
||||
};
|
||||
|
||||
inline int
|
||||
address_info::get_address_info(const char* node, int pfamily, int stype, address_info** ai) {
|
||||
address_info hints;
|
||||
hints.clear();
|
||||
hints.set_family(pfamily);
|
||||
hints.set_socket_type(stype);
|
||||
|
||||
return ::getaddrinfo(node, NULL, hints.c_addrinfo(), reinterpret_cast<addrinfo**>(ai));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -34,7 +34,7 @@
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// This file contains functors that wrap function points and member
|
||||
// This file contains functors that wrap function pointers and member
|
||||
// function pointers.
|
||||
//
|
||||
// 'fn' functors are polymorphic and derives from 'rak::function' and
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// libTorrent - BitTorrent library
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2006, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
// rak - Rakshasa's toolbox
|
||||
// Copyright (C) 2005-2006, Jari Sundell
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// In addition, as a special exception, the copyright holders give
|
||||
// permission to link the code of portions of this program with the
|
||||
// OpenSSL library under certain conditions as described in each
|
||||
// individual source file, and distribute linked combinations
|
||||
// including the two.
|
||||
//
|
||||
// You must obey the GNU General Public License in all respects for
|
||||
// all of the code used other than OpenSSL. If you modify file(s)
|
||||
// with this exception, you may extend this exception to your version
|
||||
// of the file(s), but you are not obligated to do so. If you do not
|
||||
// wish to do so, delete this exception statement from your version.
|
||||
// If you delete this exception statement from all source files in the
|
||||
// program, then also delete it here.
|
||||
//
|
||||
// Contact: Jari Sundell <jaris@ifi.uio.no>
|
||||
//
|
||||
// Skomakerveien 33
|
||||
// 3185 Skoppum, NORWAY
|
||||
|
||||
// Wrappers for the various sockaddr types with focus on zero-copy
|
||||
// casting between the original type and the wrapper class.
|
||||
//
|
||||
// The default ctor does not initialize any data.
|
||||
//
|
||||
// _n suffixes indicate that the argument or return value is in
|
||||
// network byte order, _h that they are in hardware byte order.
|
||||
|
||||
// Add define for inet6 scope id?
|
||||
|
||||
#ifndef RAK_SOCKET_ADDRESS_H
|
||||
#define RAK_SOCKET_ADDRESS_H
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
namespace rak {
|
||||
|
||||
class socket_address_inet;
|
||||
class socket_address_inet6;
|
||||
|
||||
class socket_address {
|
||||
public:
|
||||
static const sa_family_t af_local = AF_LOCAL;
|
||||
static const sa_family_t af_unix = AF_UNIX;
|
||||
static const sa_family_t af_file = AF_FILE;
|
||||
static const sa_family_t af_inet = AF_INET;
|
||||
static const sa_family_t af_inet6 = AF_INET6;
|
||||
static const sa_family_t af_unspec = AF_UNSPEC;
|
||||
|
||||
bool is_valid() const;
|
||||
bool is_bindable() const;
|
||||
bool is_address_any() const;
|
||||
|
||||
// Should we need to set AF_UNSPEC?
|
||||
void clear() { std::memset(this, 0, sizeof(socket_address)); set_family(); }
|
||||
|
||||
sa_family_t family() const { return m_sa.m_sockaddr.sa_family; }
|
||||
void set_family() { m_sa.m_sockaddr.sa_family = af_unspec; }
|
||||
|
||||
uint16_t port() const;
|
||||
void set_port(uint16_t p);
|
||||
|
||||
std::string address_str() const;
|
||||
bool address_c_str(char* buf, socklen_t size) const;
|
||||
|
||||
// Attemts to set it as an inet, then an inet6 address. It will
|
||||
// never set anything but net addresses, no local/unix.
|
||||
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
|
||||
bool set_address_c_str(const char* a);
|
||||
|
||||
socket_address_inet* sa_inet() { return reinterpret_cast<socket_address_inet*>(this); }
|
||||
socket_address_inet6* sa_inet6() { return reinterpret_cast<socket_address_inet6*>(this); }
|
||||
|
||||
const socket_address_inet* sa_inet() const { return reinterpret_cast<const socket_address_inet*>(this); }
|
||||
const socket_address_inet6* sa_inet6() const { return reinterpret_cast<const socket_address_inet6*>(this); }
|
||||
|
||||
sockaddr* c_sockaddr() { return &m_sa.m_sockaddr; }
|
||||
sockaddr_in* c_sockaddr_inet() { return &m_sa.m_sockaddrInet; }
|
||||
sockaddr_in6* c_sockaddr_inet6() { return &m_sa.m_sockaddrInet6; }
|
||||
|
||||
const sockaddr* c_sockaddr() const { return &m_sa.m_sockaddr; }
|
||||
const sockaddr_in* c_sockaddr_inet() const { return &m_sa.m_sockaddrInet; }
|
||||
const sockaddr_in6* c_sockaddr_inet6() const { return &m_sa.m_sockaddrInet6; }
|
||||
|
||||
// Copy a socket address which has the length 'length. Zero out any
|
||||
// extranous bytes and ensure it does not go beyond the size of this
|
||||
// struct.
|
||||
void copy(const socket_address& src, size_t length);
|
||||
|
||||
// The different families will be sorted according to the
|
||||
// sa_family_t's numeric value.
|
||||
bool operator == (const socket_address& rhs) const;
|
||||
bool operator < (const socket_address& rhs) const;
|
||||
|
||||
private:
|
||||
union sa_union {
|
||||
sockaddr m_sockaddr;
|
||||
sockaddr_in m_sockaddrInet;
|
||||
sockaddr_in6 m_sockaddrInet6;
|
||||
};
|
||||
|
||||
sa_union m_sa;
|
||||
};
|
||||
|
||||
// Remeber to set the AF_INET.
|
||||
|
||||
class socket_address_inet {
|
||||
public:
|
||||
bool is_any() const { return is_port_any() && is_address_any(); }
|
||||
bool is_valid() const { return !is_port_any() && !is_address_any(); }
|
||||
bool is_port_any() const { return port() == 0; }
|
||||
bool is_address_any() const { return m_sockaddr.sin_addr.s_addr == htonl(INADDR_ANY); }
|
||||
|
||||
void clear() { std::memset(this, 0, sizeof(socket_address_inet)); set_family(); }
|
||||
|
||||
uint16_t port() const { return ntohs(m_sockaddr.sin_port); }
|
||||
uint16_t port_n() const { return m_sockaddr.sin_port; }
|
||||
void set_port(uint16_t p) { m_sockaddr.sin_port = htons(p); }
|
||||
void set_port_n(uint16_t p) { m_sockaddr.sin_port = p; }
|
||||
|
||||
// Should address() return the uint32_t?
|
||||
in_addr address() const { return m_sockaddr.sin_addr; }
|
||||
uint32_t address_h() const { return ntohl(m_sockaddr.sin_addr.s_addr); }
|
||||
uint32_t address_n() const { return m_sockaddr.sin_addr.s_addr; }
|
||||
std::string address_str() const;
|
||||
bool address_c_str(char* buf, socklen_t size) const;
|
||||
|
||||
void set_address(in_addr a) { m_sockaddr.sin_addr = a; }
|
||||
void set_address_h(uint32_t a) { m_sockaddr.sin_addr.s_addr = htonl(a); }
|
||||
void set_address_n(uint32_t a) { m_sockaddr.sin_addr.s_addr = a; }
|
||||
bool set_address_str(const std::string& a) { return set_address_c_str(a.c_str()); }
|
||||
bool set_address_c_str(const char* a);
|
||||
|
||||
void set_address_any() { set_port(0); set_address_h(INADDR_ANY); }
|
||||
|
||||
sa_family_t family() const { return m_sockaddr.sin_family; }
|
||||
void set_family() { m_sockaddr.sin_family = AF_INET; }
|
||||
|
||||
sockaddr* c_sockaddr() { return reinterpret_cast<sockaddr*>(&m_sockaddr); }
|
||||
sockaddr_in* c_sockaddr_inet() { return &m_sockaddr; }
|
||||
|
||||
const sockaddr* c_sockaddr() const { return reinterpret_cast<const sockaddr*>(&m_sockaddr); }
|
||||
const sockaddr_in* c_sockaddr_inet() const { return &m_sockaddr; }
|
||||
|
||||
bool operator == (const socket_address_inet& rhs) const;
|
||||
bool operator < (const socket_address_inet& rhs) const;
|
||||
|
||||
private:
|
||||
struct sockaddr_in m_sockaddr;
|
||||
};
|
||||
|
||||
inline bool
|
||||
socket_address::is_valid() const {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return sa_inet()->is_valid();
|
||||
// case af_inet6:
|
||||
// return sa_inet6().is_valid();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address::is_bindable() const {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return !sa_inet()->is_address_any();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address::is_address_any() const {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return sa_inet()->is_address_any();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline uint16_t
|
||||
socket_address::port() const {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return sa_inet()->port();
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
socket_address::set_port(uint16_t p) {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return sa_inet()->set_port(p);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string
|
||||
socket_address::address_str() const {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return sa_inet()->address_str();
|
||||
default:
|
||||
return std::string();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address::address_c_str(char* buf, socklen_t size) const {
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return sa_inet()->address_c_str(buf, size);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address::set_address_c_str(const char* a) {
|
||||
if (sa_inet()->set_address_c_str(a)) {
|
||||
sa_inet()->set_family();
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
socket_address::copy(const socket_address& src, size_t length) {
|
||||
length = std::min(length, sizeof(socket_address));
|
||||
|
||||
// Does this get properly optimized?
|
||||
std::memset(this, 0, sizeof(socket_address));
|
||||
std::memcpy(this, &src, length);
|
||||
}
|
||||
|
||||
// Should we be able to compare af_unspec?
|
||||
|
||||
inline bool
|
||||
socket_address::operator == (const socket_address& rhs) const {
|
||||
if (family() != rhs.family())
|
||||
return false;
|
||||
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return *sa_inet() == *rhs.sa_inet();
|
||||
// case af_inet6:
|
||||
// return *sa_inet6() == *rhs.sa_inet6();
|
||||
default:
|
||||
throw std::logic_error("socket_address::operator == (rhs) invalid type comparison.");
|
||||
}
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address::operator < (const socket_address& rhs) const {
|
||||
if (family() != rhs.family())
|
||||
return family() < rhs.family();
|
||||
|
||||
switch (family()) {
|
||||
case af_inet:
|
||||
return *sa_inet() < *rhs.sa_inet();
|
||||
// case af_inet6:
|
||||
// return *sa_inet6() < *rhs.sa_inet6();
|
||||
default:
|
||||
throw std::logic_error("socket_address::operator < (rhs) invalid type comparison.");
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string
|
||||
socket_address_inet::address_str() const {
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
|
||||
if (!address_c_str(buf, INET_ADDRSTRLEN))
|
||||
return std::string();
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address_inet::address_c_str(char* buf, socklen_t size) const {
|
||||
return inet_ntop(family(), &m_sockaddr.sin_addr, buf, size);
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address_inet::set_address_c_str(const char* a) {
|
||||
return inet_pton(AF_INET, a, &m_sockaddr.sin_addr);
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address_inet::operator == (const socket_address_inet& rhs) const {
|
||||
return
|
||||
m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&
|
||||
m_sockaddr.sin_port == rhs.m_sockaddr.sin_port;
|
||||
}
|
||||
|
||||
inline bool
|
||||
socket_address_inet::operator < (const socket_address_inet& rhs) const {
|
||||
return
|
||||
m_sockaddr.sin_addr.s_addr < rhs.m_sockaddr.sin_addr.s_addr ||
|
||||
(m_sockaddr.sin_addr.s_addr == rhs.m_sockaddr.sin_addr.s_addr &&
|
||||
m_sockaddr.sin_port < rhs.m_sockaddr.sin_port);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -130,6 +130,19 @@ split_iterator(__UNUSED const Sequence& seq) {
|
||||
return split_iterator_t<Sequence>();
|
||||
}
|
||||
|
||||
// Could optimize this abit.
|
||||
inline char
|
||||
hexchar_to_value(char c) {
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
return 10 + c - 'A';
|
||||
|
||||
else
|
||||
return 10 + c - 'a';
|
||||
}
|
||||
|
||||
template <int pos, typename Value>
|
||||
inline char
|
||||
value_to_hexchar(Value v) {
|
||||
|
||||
@@ -75,8 +75,12 @@ public:
|
||||
using Base::push_back;
|
||||
using Base::pop_back;
|
||||
|
||||
// Use the range erase function, the single element erase gets
|
||||
// overloaded.
|
||||
using Base::erase;
|
||||
|
||||
iterator insert(iterator position, const value_type& x);
|
||||
iterator erase(iterator position);
|
||||
iterator erase(iterator position);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
+43
-29
@@ -38,6 +38,7 @@
|
||||
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <rak/string_manip.h>
|
||||
#include <torrent/exceptions.h>
|
||||
|
||||
#include "client_info.h"
|
||||
@@ -85,17 +86,17 @@ ClientInfo::ClientInfo() {
|
||||
insert(TYPE_AZUREUS, "SZ", "Shareaza");
|
||||
insert(TYPE_AZUREUS, "RT", "Retriever");
|
||||
|
||||
m_containers[TYPE_THREE_COMPACT].reserve(10);
|
||||
m_containers[TYPE_COMPACT].reserve(10);
|
||||
|
||||
insert(TYPE_THREE_COMPACT, "A", "ABC");
|
||||
insert(TYPE_THREE_COMPACT, "T", "BitTornado");
|
||||
insert(TYPE_THREE_COMPACT, "S", "Shadow's client");
|
||||
insert(TYPE_THREE_COMPACT, "U", "UPnP NAT Bit Torrent");
|
||||
insert(TYPE_THREE_COMPACT, "O", "Osprey Permaseed");
|
||||
insert(TYPE_COMPACT, "A", "ABC");
|
||||
insert(TYPE_COMPACT, "T", "BitTornado");
|
||||
insert(TYPE_COMPACT, "S", "Shadow's client");
|
||||
insert(TYPE_COMPACT, "U", "UPnP NAT Bit Torrent");
|
||||
insert(TYPE_COMPACT, "O", "Osprey Permaseed");
|
||||
|
||||
m_containers[TYPE_THREE_SPARSE].reserve(4);
|
||||
m_containers[TYPE_MAINLINE].reserve(4);
|
||||
|
||||
insert(TYPE_THREE_SPARSE, "M", "Mainline");
|
||||
insert(TYPE_MAINLINE, "M", "Mainline");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -108,21 +109,20 @@ ClientInfo::insert(Type t, const char* key, const char* name) {
|
||||
if (keySize != std::strlen(key))
|
||||
throw torrent::input_error("Client info key size not what was expected.");
|
||||
|
||||
// Check if it is already present.
|
||||
// Check if it is already present, not entirely optimal when
|
||||
// initializing but this only get run once.
|
||||
iterator itr = std::find_if(m_containers[t].begin(), m_containers[t].end(), client_info_equal(key, sizeof_key(t)));
|
||||
|
||||
if (itr == m_containers[t].end())
|
||||
itr = m_containers[t].insert(m_containers[t].end(), value_type());
|
||||
|
||||
value_type v;
|
||||
|
||||
std::memcpy(v.first, key, keySize);
|
||||
v.second = name;
|
||||
|
||||
m_containers[t].push_back(v);
|
||||
std::memcpy(itr->first, key, keySize);
|
||||
itr->second = name;
|
||||
}
|
||||
|
||||
char*
|
||||
ClientInfo::print(char* first, char* last, const char* id) {
|
||||
|
||||
// Start with an UDP0 test.
|
||||
|
||||
if (id[0] == '-' && id[7] == '-' &&
|
||||
std::isalpha(id[1]) && std::isalpha(id[2]) &&
|
||||
std::isxdigit(id[3]) && std::isxdigit(id[4]) && std::isxdigit(id[5]) && std::isxdigit(id[6])) {
|
||||
@@ -132,38 +132,52 @@ ClientInfo::print(char* first, char* last, const char* id) {
|
||||
client_info_equal(id + 1, sizeof_key(TYPE_AZUREUS)));
|
||||
|
||||
if (itr != m_containers[TYPE_AZUREUS].end())
|
||||
first = print_buffer(first, last, "%s %c.%c.%c.%c", itr->second, id[3], id[4], id[5], id[6]);
|
||||
first = print_buffer(first, last, "%s %hhu.%hhu.%hhu.%hhu", itr->second,
|
||||
rak::hexchar_to_value(id[3]), rak::hexchar_to_value(id[4]),
|
||||
rak::hexchar_to_value(id[5]), rak::hexchar_to_value(id[6]));
|
||||
|
||||
else
|
||||
first = print_buffer(first, last, "unknown %c%c %c.%c.%c.%c", id[1], id[2], id[3], id[4], id[5], id[6]);
|
||||
first = print_buffer(first, last, "unknown %c%c %hhu.%hhu.%hhu.%hhu", id[1], id[2],
|
||||
rak::hexchar_to_value(id[3]), rak::hexchar_to_value(id[4]),
|
||||
rak::hexchar_to_value(id[5]), rak::hexchar_to_value(id[6]));
|
||||
|
||||
} else if (std::isalpha(id[0]) && id[4] == '-' &&
|
||||
std::isxdigit(id[1]) && std::isxdigit(id[2]) && std::isxdigit(id[3])) {
|
||||
// TYPE_THREE_COMPACT.
|
||||
|
||||
iterator itr = std::find_if(m_containers[TYPE_THREE_COMPACT].begin(), m_containers[TYPE_THREE_COMPACT].end(),
|
||||
client_info_equal(id, sizeof_key(TYPE_THREE_COMPACT)));
|
||||
iterator itr = std::find_if(m_containers[TYPE_COMPACT].begin(), m_containers[TYPE_COMPACT].end(),
|
||||
client_info_equal(id, sizeof_key(TYPE_COMPACT)));
|
||||
|
||||
if (itr != m_containers[TYPE_THREE_COMPACT].end())
|
||||
first = print_buffer(first, last, "%s %c.%c.%c", itr->second, id[1], id[2], id[3]);
|
||||
if (itr != m_containers[TYPE_COMPACT].end())
|
||||
first = print_buffer(first, last, "%s %hhu.%hhu.%hhu", itr->second,
|
||||
rak::hexchar_to_value(id[1]), rak::hexchar_to_value(id[2]), rak::hexchar_to_value(id[3]));
|
||||
|
||||
else
|
||||
first = print_buffer(first, last, "unknown %c %c.%c.%c", id[0], id[1], id[2], id[3]);
|
||||
first = print_buffer(first, last, "unknown %c %hhu.%hhu.%hhu", id[0],
|
||||
rak::hexchar_to_value(id[1]), rak::hexchar_to_value(id[2]), rak::hexchar_to_value(id[3]));
|
||||
|
||||
} else if (std::isalpha(id[0]) && id[2] == '-' && id[4] == '-' && id[6] == '-' &&
|
||||
std::isxdigit(id[1]) && std::isxdigit(id[3]) && std::isxdigit(id[5])) {
|
||||
// TYPE_THREE_SPARSE.
|
||||
|
||||
iterator itr = std::find_if(m_containers[TYPE_THREE_SPARSE].begin(), m_containers[TYPE_THREE_SPARSE].end(),
|
||||
client_info_equal(id, sizeof_key(TYPE_THREE_SPARSE)));
|
||||
iterator itr = std::find_if(m_containers[TYPE_MAINLINE].begin(), m_containers[TYPE_MAINLINE].end(),
|
||||
client_info_equal(id, sizeof_key(TYPE_MAINLINE)));
|
||||
|
||||
if (itr != m_containers[TYPE_THREE_SPARSE].end())
|
||||
first = print_buffer(first, last, "%s %c.%c.%c", itr->second, id[1], id[3], id[5]);
|
||||
if (itr != m_containers[TYPE_MAINLINE].end())
|
||||
first = print_buffer(first, last, "%s %hhu.%hhu.%hhu", itr->second,
|
||||
rak::hexchar_to_value(id[1]), rak::hexchar_to_value(id[3]), rak::hexchar_to_value(id[5]));
|
||||
|
||||
else
|
||||
first = print_buffer(first, last, "unknown %c %c.%c.%c", id[0], id[1], id[3], id[5]);
|
||||
first = print_buffer(first, last, "unknown %c %hhu.%hhu.%hhu", id[0],
|
||||
rak::hexchar_to_value(id[1]), rak::hexchar_to_value(id[3]), rak::hexchar_to_value(id[5]));
|
||||
|
||||
|
||||
// And then the incompatible idiots that make life difficult for us
|
||||
// others. (There's '3' schemes to choose from already...)
|
||||
|
||||
// Well... fuck this... I don't feel like adding the rest of the
|
||||
// checks as they wouldn't be possible to remove/modify.
|
||||
|
||||
} else {
|
||||
first = print_buffer(first, last, "unknown");
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@ public:
|
||||
|
||||
typedef enum {
|
||||
TYPE_AZUREUS,
|
||||
TYPE_THREE_COMPACT,
|
||||
TYPE_THREE_SPARSE,
|
||||
TYPE_COMPACT,
|
||||
TYPE_MAINLINE,
|
||||
TYPE_MAXSIZE
|
||||
} Type;
|
||||
|
||||
@@ -67,10 +67,10 @@ public:
|
||||
|
||||
size_type sizeof_key(Type t) {
|
||||
switch (t) {
|
||||
case TYPE_AZUREUS: return 2;
|
||||
case TYPE_THREE_COMPACT: return 1;
|
||||
case TYPE_THREE_SPARSE: return 1;
|
||||
case TYPE_MAXSIZE: return 0;
|
||||
case TYPE_AZUREUS: return 2;
|
||||
case TYPE_COMPACT: return 1;
|
||||
case TYPE_MAINLINE: return 1;
|
||||
case TYPE_MAXSIZE: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <getopt.h>
|
||||
#include <stdexcept>
|
||||
#include <unistd.h>
|
||||
#include <sigc++/bind.h>
|
||||
|
||||
@@ -171,6 +171,16 @@ Download::receive_prev() {
|
||||
mark_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Download::receive_disconnect_peer() {
|
||||
if (m_focus == m_peers.end())
|
||||
return;
|
||||
|
||||
m_download->get_download().disconnect_peer(*m_focus);
|
||||
|
||||
mark_dirty();
|
||||
}
|
||||
|
||||
void
|
||||
Download::receive_peer_connected(torrent::Peer p) {
|
||||
m_peers.push_back(p);
|
||||
@@ -250,6 +260,8 @@ Download::bind_keys() {
|
||||
(*m_bindings)['+'] = sigc::mem_fun(*this, &Download::receive_next_priority);
|
||||
(*m_bindings)['-'] = sigc::mem_fun(*this, &Download::receive_prev_priority);
|
||||
|
||||
(*m_bindings)['k'] = sigc::mem_fun(*this, &Download::receive_disconnect_peer);
|
||||
|
||||
(*m_bindings)['t'] = sigc::bind(sigc::mem_fun(m_download->get_download(), &torrent::Download::tracker_manual_request), false);
|
||||
(*m_bindings)['T'] = sigc::bind(sigc::mem_fun(m_download->get_download(), &torrent::Download::tracker_manual_request), true);
|
||||
|
||||
|
||||
@@ -98,6 +98,8 @@ private:
|
||||
void receive_next();
|
||||
void receive_prev();
|
||||
|
||||
void receive_disconnect_peer();
|
||||
|
||||
void receive_peer_connected(torrent::Peer p);
|
||||
void receive_peer_disconnected(torrent::Peer p);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user