1
// libTorrent - BitTorrent library
2
// Copyright (C) 2005-2007, Jari Sundell
4
// This program is free software; you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation; either version 2 of the License, or
7
// (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public License
15
// along with this program; if not, write to the Free Software
16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
// In addition, as a special exception, the copyright holders give
19
// permission to link the code of portions of this program with the
20
// OpenSSL library under certain conditions as described in each
21
// individual source file, and distribute linked combinations
24
// You must obey the GNU General Public License in all respects for
25
// all of the code used other than OpenSSL. If you modify file(s)
26
// with this exception, you may extend this exception to your version
27
// of the file(s), but you are not obligated to do so. If you do not
28
// wish to do so, delete this exception statement from your version.
29
// If you delete this exception statement from all source files in the
30
// program, then also delete it here.
32
// Contact: Jari Sundell <jaris@ifi.uio.no>
35
// 3185 Skoppum, NORWAY
39
#include <rak/socket_address.h>
41
#include "torrent/exceptions.h"
42
#include "torrent/error.h"
43
#include "download/download_main.h"
44
#include "torrent/connection_manager.h"
45
#include "torrent/download_info.h"
46
#include "torrent/peer/peer_info.h"
47
#include "torrent/peer/client_list.h"
48
#include "torrent/peer/connection_list.h"
50
#include "peer_connection_base.h"
51
#include "handshake.h"
52
#include "handshake_manager.h"
58
ProtocolExtension HandshakeManager::DefaultExtensions = ProtocolExtension::make_default();
61
handshake_manager_delete_handshake(Handshake* h) {
62
h->deactivate_connection();
63
h->destroy_connection();
68
HandshakeManager::size_type
69
HandshakeManager::size_info(DownloadMain* info) const {
70
return std::count_if(base_type::begin(), base_type::end(), rak::equal(info, std::mem_fun(&Handshake::download)));
74
HandshakeManager::clear() {
75
std::for_each(base_type::begin(), base_type::end(), std::ptr_fun(&handshake_manager_delete_handshake));
80
HandshakeManager::erase(Handshake* handshake) {
81
iterator itr = std::find(base_type::begin(), base_type::end(), handshake);
83
if (itr == base_type::end())
84
throw internal_error("HandshakeManager::erase(...) could not find handshake.");
86
base_type::erase(itr);
89
struct handshake_manager_equal : std::binary_function<const rak::socket_address*, const Handshake*, bool> {
90
bool operator () (const rak::socket_address* sa1, const Handshake* p2) const {
91
return p2->peer_info() != NULL && *sa1 == *rak::socket_address::cast_from(p2->peer_info()->socket_address());
96
HandshakeManager::find(const rak::socket_address& sa) {
97
return std::find_if(base_type::begin(), base_type::end(), std::bind1st(handshake_manager_equal(), &sa)) != base_type::end();
101
HandshakeManager::erase_download(DownloadMain* info) {
102
iterator split = std::partition(base_type::begin(), base_type::end(), rak::not_equal(info, std::mem_fun(&Handshake::download)));
104
std::for_each(split, base_type::end(), std::ptr_fun(&handshake_manager_delete_handshake));
105
base_type::erase(split, base_type::end());
109
HandshakeManager::add_incoming(SocketFd fd, const rak::socket_address& sa) {
110
if (!manager->connection_manager()->can_connect() ||
111
!manager->connection_manager()->filter(sa.c_sockaddr()) ||
117
manager->connection_manager()->signal_handshake_log().emit(sa.c_sockaddr(), ConnectionManager::handshake_incoming, e_none, NULL);
118
manager->connection_manager()->inc_socket_count();
120
Handshake* h = new Handshake(fd, this, manager->connection_manager()->encryption_options());
121
h->initialize_incoming(sa);
123
base_type::push_back(h);
127
HandshakeManager::add_outgoing(const rak::socket_address& sa, DownloadMain* download) {
128
if (!manager->connection_manager()->can_connect() ||
129
!manager->connection_manager()->filter(sa.c_sockaddr()))
132
create_outgoing(sa, download, manager->connection_manager()->encryption_options());
136
HandshakeManager::create_outgoing(const rak::socket_address& sa, DownloadMain* download, int encryptionOptions) {
137
PeerInfo* peerInfo = download->peer_list()->connected(sa.c_sockaddr(),
138
PeerList::connect_keep_handshakes | PeerList::connect_filter_recent);
140
if (peerInfo == NULL || peerInfo->failed_counter() > max_failed)
144
const rak::socket_address* bindAddress = rak::socket_address::cast_from(manager->connection_manager()->bind_address());
145
const rak::socket_address* connectAddress = &sa;
147
if (rak::socket_address::cast_from(manager->connection_manager()->proxy_address())->is_valid()) {
148
connectAddress = rak::socket_address::cast_from(manager->connection_manager()->proxy_address());
149
encryptionOptions |= ConnectionManager::encryption_use_proxy;
152
if (!fd.open_stream() ||
154
(bindAddress->is_bindable() && !fd.bind(*bindAddress)) ||
155
!fd.connect(*connectAddress)) {
160
download->peer_list()->disconnected(peerInfo, 0);
166
if (encryptionOptions & ConnectionManager::encryption_use_proxy)
167
message = ConnectionManager::handshake_outgoing_proxy;
168
else if (encryptionOptions & (ConnectionManager::encryption_try_outgoing | ConnectionManager::encryption_require))
169
message = ConnectionManager::handshake_outgoing_encrypted;
171
message = ConnectionManager::handshake_outgoing;
173
manager->connection_manager()->signal_handshake_log().emit(sa.c_sockaddr(), message, e_none, &download->info()->hash());
174
manager->connection_manager()->inc_socket_count();
176
Handshake* handshake = new Handshake(fd, this, encryptionOptions);
177
handshake->initialize_outgoing(sa, download, peerInfo);
179
base_type::push_back(handshake);
183
HandshakeManager::receive_succeeded(Handshake* handshake) {
184
if (!handshake->is_active())
185
throw internal_error("HandshakeManager::receive_succeeded(...) called on an inactive handshake.");
188
handshake->deactivate_connection();
190
DownloadMain* download = handshake->download();
191
PeerConnectionBase* pcb;
193
if (download->info()->is_active() &&
195
// We need to make libtorrent more selective in the clients it
196
// connects to, and to move this somewhere else.
197
(!download->file_list()->is_done() || !handshake->bitfield()->is_all_set() || download->initial_seeding() != NULL) &&
199
(pcb = download->connection_list()->insert(handshake->peer_info(),
201
handshake->bitfield(),
202
handshake->encryption()->info(),
203
handshake->extensions())) != NULL) {
205
manager->client_list()->retrieve_id(&handshake->peer_info()->mutable_client_info(), handshake->peer_info()->id());
206
manager->connection_manager()->signal_handshake_log().emit(handshake->peer_info()->socket_address(),
207
ConnectionManager::handshake_success,
209
&download->info()->hash());
211
pcb->peer_chunks()->set_have_timer(handshake->initialized_time());
213
if (handshake->unread_size() != 0) {
214
if (handshake->unread_size() > PeerConnectionBase::ProtocolRead::buffer_size)
215
throw internal_error("HandshakeManager::receive_succeeded(...) Unread data won't fit PCB's read buffer.");
217
pcb->push_unread(handshake->unread_data(), handshake->unread_size());
221
handshake->release_connection();
226
if (!download->info()->is_active())
227
reason = e_handshake_inactive_download;
228
else if (download->file_list()->is_done() && handshake->bitfield()->is_all_set())
229
reason = e_handshake_unwanted_connection;
231
reason = e_handshake_duplicate;
233
manager->connection_manager()->signal_handshake_log().emit(handshake->peer_info()->socket_address(),
234
ConnectionManager::handshake_dropped,
236
&download->info()->hash());
237
handshake->destroy_connection();
244
HandshakeManager::receive_failed(Handshake* handshake, int message, int error) {
245
if (!handshake->is_active())
246
throw internal_error("HandshakeManager::receive_failed(...) called on an inactive handshake.");
248
const rak::socket_address* sa = handshake->socket_address();
251
handshake->deactivate_connection();
252
handshake->destroy_connection();
254
manager->connection_manager()->signal_handshake_log().emit(sa->c_sockaddr(),
257
handshake->download() != NULL ? &handshake->download()->info()->hash() : NULL);
258
if (handshake->encryption()->should_retry()) {
259
int retry_options = handshake->retry_options();
260
DownloadMain* download = handshake->download();
262
manager->connection_manager()->signal_handshake_log().emit(sa->c_sockaddr(),
263
retry_options & ConnectionManager::encryption_try_outgoing ?
264
ConnectionManager::handshake_retry_encrypted :
265
ConnectionManager::handshake_retry_plaintext,
267
&download->info()->hash());
269
create_outgoing(*sa, download, retry_options);
276
HandshakeManager::receive_timeout(Handshake* h) {
277
receive_failed(h, ConnectionManager::handshake_failed, h->state() == Handshake::CONNECTING ? e_handshake_network_unreachable : e_handshake_network_timeout);
281
HandshakeManager::setup_socket(SocketFd fd) {
282
if (!fd.set_nonblock())
285
ConnectionManager* m = manager->connection_manager();
287
if (m->priority() != ConnectionManager::iptos_default && !fd.set_priority(m->priority()))
290
if (m->send_buffer_size() != 0 && !fd.set_send_buffer_size(m->send_buffer_size()))
293
if (m->receive_buffer_size() != 0 && !fd.set_receive_buffer_size(m->receive_buffer_size()))