From 1b5ce85e40de5b5d1f40f14723a9fb54a2970d31 Mon Sep 17 00:00:00 2001 From: Marcos Pinto Date: Fri, 25 May 2007 20:25:48 +0000 Subject: [PATCH] libtorrent dir seems corrupt beyond repair....just deleting and reupping --- libtorrent/include/libtorrent/alert.hpp | 164 - libtorrent/include/libtorrent/alert_types.hpp | 300 -- .../include/libtorrent/allocate_resources.hpp | 78 - libtorrent/include/libtorrent/asio.hpp | 73 - .../libtorrent/asio/basic_datagram_socket.hpp | 803 ----- .../libtorrent/asio/basic_deadline_timer.hpp | 399 --- .../libtorrent/asio/basic_io_object.hpp | 75 - .../libtorrent/asio/basic_resolver.hpp | 252 -- .../include/libtorrent/asio/basic_socket.hpp | 972 ------ .../libtorrent/asio/basic_socket_acceptor.hpp | 824 ----- .../libtorrent/asio/basic_socket_iostream.hpp | 146 - .../asio/basic_socket_streambuf.hpp | 284 -- .../libtorrent/asio/basic_stream_socket.hpp | 718 ----- .../libtorrent/asio/basic_streambuf.hpp | 200 -- libtorrent/include/libtorrent/asio/buffer.hpp | 782 ----- .../libtorrent/asio/buffered_read_stream.hpp | 407 --- .../asio/buffered_read_stream_fwd.hpp | 29 - .../libtorrent/asio/buffered_stream.hpp | 243 -- .../libtorrent/asio/buffered_stream_fwd.hpp | 29 - .../libtorrent/asio/buffered_write_stream.hpp | 361 --- .../asio/buffered_write_stream_fwd.hpp | 29 - .../libtorrent/asio/completion_condition.hpp | 101 - .../asio/datagram_socket_service.hpp | 320 -- .../libtorrent/asio/deadline_timer.hpp | 37 - .../asio/deadline_timer_service.hpp | 164 - .../libtorrent/asio/detail/bind_handler.hpp | 349 --- .../asio/detail/buffer_resize_guard.hpp | 70 - .../asio/detail/buffered_stream_storage.hpp | 127 - .../libtorrent/asio/detail/call_stack.hpp | 90 - .../asio/detail/const_buffers_iterator.hpp | 151 - .../asio/detail/consuming_buffers.hpp | 205 -- .../asio/detail/deadline_timer_service.hpp | 199 -- .../libtorrent/asio/detail/epoll_reactor.hpp | 613 ---- .../asio/detail/epoll_reactor_fwd.hpp | 47 - .../include/libtorrent/asio/detail/event.hpp | 50 - .../libtorrent/asio/detail/fd_set_adapter.hpp | 41 - .../asio/detail/handler_alloc_helpers.hpp | 256 -- .../asio/detail/handler_invoke_helpers.hpp | 47 - .../libtorrent/asio/detail/hash_map.hpp | 209 -- .../libtorrent/asio/detail/io_control.hpp | 137 - .../libtorrent/asio/detail/kqueue_reactor.hpp | 620 ---- .../asio/detail/kqueue_reactor_fwd.hpp | 41 - .../asio/detail/local_free_on_block_exit.hpp | 59 - .../include/libtorrent/asio/detail/mutex.hpp | 50 - .../libtorrent/asio/detail/noncopyable.hpp | 55 - .../libtorrent/asio/detail/null_event.hpp | 68 - .../libtorrent/asio/detail/null_mutex.hpp | 66 - .../asio/detail/null_signal_blocker.hpp | 63 - .../libtorrent/asio/detail/null_thread.hpp | 68 - .../libtorrent/asio/detail/null_tss_ptr.hpp | 70 - .../asio/detail/old_win_sdk_compat.hpp | 317 -- .../asio/detail/pipe_select_interrupter.hpp | 104 - .../libtorrent/asio/detail/pop_options.hpp | 88 - .../libtorrent/asio/detail/posix_event.hpp | 111 - .../asio/detail/posix_fd_set_adapter.hpp | 72 - .../libtorrent/asio/detail/posix_mutex.hpp | 100 - .../asio/detail/posix_signal_blocker.hpp | 90 - .../libtorrent/asio/detail/posix_thread.hpp | 127 - .../libtorrent/asio/detail/posix_tss_ptr.hpp | 86 - .../libtorrent/asio/detail/push_options.hpp | 106 - .../asio/detail/reactive_socket_service.hpp | 1486 --------- .../asio/detail/reactor_op_queue.hpp | 384 --- .../asio/detail/resolver_service.hpp | 357 --- .../libtorrent/asio/detail/scoped_lock.hpp | 79 - .../asio/detail/select_interrupter.hpp | 41 - .../libtorrent/asio/detail/select_reactor.hpp | 456 --- .../asio/detail/select_reactor_fwd.hpp | 31 - .../libtorrent/asio/detail/service_base.hpp | 49 - .../libtorrent/asio/detail/service_id.hpp | 37 - .../asio/detail/service_registry.hpp | 198 -- .../asio/detail/service_registry_fwd.hpp | 30 - .../libtorrent/asio/detail/signal_blocker.hpp | 50 - .../libtorrent/asio/detail/signal_init.hpp | 51 - .../libtorrent/asio/detail/socket_holder.hpp | 95 - .../libtorrent/asio/detail/socket_ops.hpp | 1592 ---------- .../libtorrent/asio/detail/socket_option.hpp | 298 -- .../asio/detail/socket_select_interrupter.hpp | 184 -- .../libtorrent/asio/detail/socket_types.hpp | 178 -- .../libtorrent/asio/detail/strand_service.hpp | 526 ---- .../asio/detail/task_io_service.hpp | 538 ---- .../asio/detail/task_io_service_fwd.hpp | 31 - .../include/libtorrent/asio/detail/thread.hpp | 50 - .../libtorrent/asio/detail/throw_error.hpp | 44 - .../libtorrent/asio/detail/timer_queue.hpp | 347 --- .../asio/detail/timer_queue_base.hpp | 56 - .../libtorrent/asio/detail/tss_ptr.hpp | 65 - .../libtorrent/asio/detail/win_event.hpp | 90 - .../asio/detail/win_fd_set_adapter.hpp | 84 - .../asio/detail/win_iocp_io_service.hpp | 424 --- .../asio/detail/win_iocp_io_service_fwd.hpp | 46 - .../asio/detail/win_iocp_operation.hpp | 81 - .../asio/detail/win_iocp_socket_service.hpp | 1963 ------------ .../detail/win_local_free_on_block_exit.hpp | 59 - .../libtorrent/asio/detail/win_mutex.hpp | 146 - .../asio/detail/win_signal_blocker.hpp | 67 - .../libtorrent/asio/detail/win_thread.hpp | 123 - .../libtorrent/asio/detail/win_tss_ptr.hpp | 87 - .../libtorrent/asio/detail/winsock_init.hpp | 118 - .../asio/detail/wrapped_handler.hpp | 187 -- libtorrent/include/libtorrent/asio/error.hpp | 367 --- .../include/libtorrent/asio/error_code.hpp | 139 - .../include/libtorrent/asio/error_handler.hpp | 120 - .../libtorrent/asio/handler_alloc_hook.hpp | 88 - .../libtorrent/asio/handler_invoke_hook.hpp | 69 - .../libtorrent/asio/impl/error_code.ipp | 98 - .../libtorrent/asio/impl/io_service.ipp | 213 -- .../include/libtorrent/asio/impl/read.ipp | 314 -- .../libtorrent/asio/impl/read_until.ipp | 750 ----- .../include/libtorrent/asio/impl/write.ipp | 279 -- .../include/libtorrent/asio/io_service.hpp | 501 --- .../include/libtorrent/asio/ip/address.hpp | 277 -- .../include/libtorrent/asio/ip/address_v4.hpp | 283 -- .../include/libtorrent/asio/ip/address_v6.hpp | 401 --- .../libtorrent/asio/ip/basic_endpoint.hpp | 368 --- .../libtorrent/asio/ip/basic_resolver.hpp | 245 -- .../asio/ip/basic_resolver_entry.hpp | 95 - .../asio/ip/basic_resolver_iterator.hpp | 154 - .../asio/ip/basic_resolver_query.hpp | 149 - .../asio/ip/detail/socket_option.hpp | 530 ---- .../include/libtorrent/asio/ip/host_name.hpp | 62 - .../include/libtorrent/asio/ip/multicast.hpp | 181 -- .../asio/ip/resolver_query_base.hpp | 107 - .../libtorrent/asio/ip/resolver_service.hpp | 140 - libtorrent/include/libtorrent/asio/ip/tcp.hpp | 158 - libtorrent/include/libtorrent/asio/ip/udp.hpp | 116 - .../libtorrent/asio/is_read_buffered.hpp | 62 - .../libtorrent/asio/is_write_buffered.hpp | 62 - .../include/libtorrent/asio/placeholders.hpp | 107 - libtorrent/include/libtorrent/asio/read.hpp | 516 --- .../include/libtorrent/asio/read_until.hpp | 452 --- .../libtorrent/asio/resolver_service.hpp | 126 - .../asio/socket_acceptor_service.hpp | 222 -- .../include/libtorrent/asio/socket_base.hpp | 515 --- libtorrent/include/libtorrent/asio/ssl.hpp | 26 - .../libtorrent/asio/ssl/basic_context.hpp | 434 --- .../include/libtorrent/asio/ssl/context.hpp | 35 - .../libtorrent/asio/ssl/context_base.hpp | 164 - .../libtorrent/asio/ssl/context_service.hpp | 175 -- .../ssl/detail/openssl_context_service.hpp | 379 --- .../asio/ssl/detail/openssl_init.hpp | 127 - .../asio/ssl/detail/openssl_operation.hpp | 482 --- .../ssl/detail/openssl_stream_service.hpp | 504 --- .../asio/ssl/detail/openssl_types.hpp | 29 - .../include/libtorrent/asio/ssl/stream.hpp | 490 --- .../libtorrent/asio/ssl/stream_base.hpp | 60 - .../libtorrent/asio/ssl/stream_service.hpp | 186 -- libtorrent/include/libtorrent/asio/strand.hpp | 166 - .../libtorrent/asio/stream_socket_service.hpp | 283 -- .../include/libtorrent/asio/streambuf.hpp | 31 - .../include/libtorrent/asio/system_error.hpp | 117 - .../libtorrent/asio/system_exception.hpp | 198 -- libtorrent/include/libtorrent/asio/thread.hpp | 91 - .../include/libtorrent/asio/time_traits.hpp | 78 - libtorrent/include/libtorrent/asio/write.hpp | 515 --- .../aux_/allocate_resources_impl.hpp | 328 -- .../include/libtorrent/aux_/session_impl.hpp | 532 ---- .../include/libtorrent/bandwidth_manager.hpp | 228 -- libtorrent/include/libtorrent/bencode.hpp | 299 -- .../include/libtorrent/bt_peer_connection.hpp | 276 -- libtorrent/include/libtorrent/buffer.hpp | 447 --- libtorrent/include/libtorrent/config.hpp | 66 - .../include/libtorrent/connection_queue.hpp | 96 - libtorrent/include/libtorrent/debug.hpp | 81 - libtorrent/include/libtorrent/entry.hpp | 276 -- .../include/libtorrent/escape_string.hpp | 46 - libtorrent/include/libtorrent/extensions.hpp | 176 -- .../include/libtorrent/extensions/logger.hpp | 54 - .../extensions/metadata_transfer.hpp | 55 - .../include/libtorrent/extensions/ut_pex.hpp | 54 - libtorrent/include/libtorrent/file.hpp | 131 - libtorrent/include/libtorrent/file_pool.hpp | 103 - libtorrent/include/libtorrent/fingerprint.hpp | 93 - libtorrent/include/libtorrent/hasher.hpp | 121 - .../include/libtorrent/http_connection.hpp | 154 - libtorrent/include/libtorrent/http_stream.hpp | 193 -- .../libtorrent/http_tracker_connection.hpp | 178 -- .../include/libtorrent/identify_client.hpp | 58 - .../libtorrent/instantiate_connection.hpp | 49 - .../include/libtorrent/invariant_check.hpp | 78 - libtorrent/include/libtorrent/io.hpp | 153 - libtorrent/include/libtorrent/ip_filter.hpp | 276 -- .../libtorrent/kademlia/closest_nodes.hpp | 117 - .../libtorrent/kademlia/dht_tracker.hpp | 159 - .../include/libtorrent/kademlia/find_data.hpp | 128 - .../include/libtorrent/kademlia/logging.hpp | 146 - .../include/libtorrent/kademlia/node.hpp | 259 -- .../libtorrent/kademlia/node_entry.hpp | 63 - .../include/libtorrent/kademlia/node_id.hpp | 60 - .../libtorrent/kademlia/packet_iterator.hpp | 95 - .../include/libtorrent/kademlia/refresh.hpp | 214 -- .../libtorrent/kademlia/routing_table.hpp | 248 -- .../libtorrent/kademlia/rpc_manager.hpp | 140 - .../kademlia/traversal_algorithm.hpp | 162 - libtorrent/include/libtorrent/lsd.hpp | 105 - libtorrent/include/libtorrent/natpmp.hpp | 150 - libtorrent/include/libtorrent/pch.hpp | 96 - libtorrent/include/libtorrent/peer.hpp | 63 - .../include/libtorrent/peer_connection.hpp | 699 ----- libtorrent/include/libtorrent/peer_id.hpp | 184 -- libtorrent/include/libtorrent/peer_info.hpp | 131 - .../include/libtorrent/peer_request.hpp | 49 - .../libtorrent/piece_block_progress.hpp | 57 - .../include/libtorrent/piece_picker.hpp | 414 --- libtorrent/include/libtorrent/policy.hpp | 232 -- .../include/libtorrent/random_sample.hpp | 74 - .../include/libtorrent/resource_request.hpp | 99 - libtorrent/include/libtorrent/session.hpp | 267 -- .../include/libtorrent/session_settings.hpp | 247 -- .../include/libtorrent/session_status.hpp | 69 - libtorrent/include/libtorrent/size_type.hpp | 52 - libtorrent/include/libtorrent/socket.hpp | 162 - libtorrent/include/libtorrent/socket_type.hpp | 46 - .../include/libtorrent/socks5_stream.hpp | 195 -- libtorrent/include/libtorrent/stat.hpp | 193 -- libtorrent/include/libtorrent/storage.hpp | 205 -- libtorrent/include/libtorrent/time.hpp | 383 --- libtorrent/include/libtorrent/torrent.hpp | 771 ----- .../include/libtorrent/torrent_handle.hpp | 376 --- .../include/libtorrent/torrent_info.hpp | 269 -- .../include/libtorrent/tracker_manager.hpp | 258 -- .../libtorrent/udp_tracker_connection.hpp | 122 - libtorrent/include/libtorrent/upnp.hpp | 237 -- libtorrent/include/libtorrent/utf8.hpp | 161 - .../include/libtorrent/variant_stream.hpp | 716 ----- libtorrent/include/libtorrent/version.hpp | 41 - .../libtorrent/web_peer_connection.hpp | 179 -- libtorrent/include/libtorrent/xml_parse.hpp | 99 - libtorrent/src/Makefile.am | 94 - libtorrent/src/Makefile.in | 672 ---- libtorrent/src/alert.cpp | 126 - libtorrent/src/allocate_resources.cpp | 225 -- libtorrent/src/bandwidth_manager.cpp | 249 -- libtorrent/src/bt_peer_connection.cpp | 1378 -------- libtorrent/src/connection_queue.cpp | 169 - libtorrent/src/entry.cpp | 344 -- libtorrent/src/escape_string.cpp | 150 - libtorrent/src/file.cpp | 347 --- libtorrent/src/file_pool.cpp | 134 - libtorrent/src/file_win.cpp | 366 --- libtorrent/src/http_connection.cpp | 384 --- libtorrent/src/http_stream.cpp | 162 - libtorrent/src/http_tracker_connection.cpp | 921 ------ libtorrent/src/identify_client.cpp | 351 --- libtorrent/src/instantiate_connection.cpp | 78 - libtorrent/src/ip_filter.cpp | 82 - libtorrent/src/kademlia/closest_nodes.cpp | 132 - libtorrent/src/kademlia/dht_tracker.cpp | 974 ------ libtorrent/src/kademlia/find_data.cpp | 142 - libtorrent/src/kademlia/node.cpp | 497 --- libtorrent/src/kademlia/node_id.cpp | 99 - libtorrent/src/kademlia/refresh.cpp | 174 -- libtorrent/src/kademlia/routing_table.cpp | 448 --- libtorrent/src/kademlia/rpc_manager.cpp | 430 --- .../src/kademlia/traversal_algorithm.cpp | 184 -- libtorrent/src/logger.cpp | 230 -- libtorrent/src/lsd.cpp | 250 -- libtorrent/src/metadata_transfer.cpp | 568 ---- libtorrent/src/natpmp.cpp | 393 --- libtorrent/src/peer_connection.cpp | 2566 --------------- libtorrent/src/piece_picker.cpp | 1446 --------- libtorrent/src/policy.cpp | 1435 --------- libtorrent/src/session.cpp | 368 --- libtorrent/src/session_impl.cpp | 2063 ------------ libtorrent/src/sha1.cpp | 317 -- libtorrent/src/socks5_stream.cpp | 315 -- libtorrent/src/stat.cpp | 93 - libtorrent/src/storage.cpp | 2325 -------------- libtorrent/src/torrent.cpp | 2768 ----------------- libtorrent/src/torrent_handle.cpp | 774 ----- libtorrent/src/torrent_info.cpp | 856 ----- libtorrent/src/tracker_manager.cpp | 599 ---- libtorrent/src/udp_tracker_connection.cpp | 552 ---- libtorrent/src/upnp.cpp | 1038 ------- libtorrent/src/ut_pex.cpp | 345 -- libtorrent/src/web_peer_connection.cpp | 692 ----- 275 files changed, 79404 deletions(-) delete mode 100644 libtorrent/include/libtorrent/alert.hpp delete mode 100644 libtorrent/include/libtorrent/alert_types.hpp delete mode 100644 libtorrent/include/libtorrent/allocate_resources.hpp delete mode 100644 libtorrent/include/libtorrent/asio.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_deadline_timer.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_io_object.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_resolver.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_socket.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_socket_acceptor.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_socket_iostream.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_socket_streambuf.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_stream_socket.hpp delete mode 100644 libtorrent/include/libtorrent/asio/basic_streambuf.hpp delete mode 100644 libtorrent/include/libtorrent/asio/buffer.hpp delete mode 100644 libtorrent/include/libtorrent/asio/buffered_read_stream.hpp delete mode 100644 libtorrent/include/libtorrent/asio/buffered_read_stream_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/buffered_stream.hpp delete mode 100644 libtorrent/include/libtorrent/asio/buffered_stream_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/buffered_write_stream.hpp delete mode 100644 libtorrent/include/libtorrent/asio/buffered_write_stream_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/completion_condition.hpp delete mode 100644 libtorrent/include/libtorrent/asio/datagram_socket_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/deadline_timer.hpp delete mode 100644 libtorrent/include/libtorrent/asio/deadline_timer_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/bind_handler.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/buffer_resize_guard.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/buffered_stream_storage.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/call_stack.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/const_buffers_iterator.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/consuming_buffers.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/epoll_reactor.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/epoll_reactor_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/event.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/fd_set_adapter.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/handler_alloc_helpers.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/handler_invoke_helpers.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/hash_map.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/io_control.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/kqueue_reactor.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/kqueue_reactor_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/local_free_on_block_exit.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/mutex.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/noncopyable.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/null_event.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/null_mutex.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/null_signal_blocker.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/null_thread.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/null_tss_ptr.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/old_win_sdk_compat.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/pop_options.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/posix_event.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/posix_mutex.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/posix_signal_blocker.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/posix_thread.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/posix_tss_ptr.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/push_options.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/resolver_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/scoped_lock.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/select_interrupter.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/select_reactor.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/select_reactor_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/service_base.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/service_id.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/service_registry.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/service_registry_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/signal_blocker.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/signal_init.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/socket_holder.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/socket_ops.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/socket_option.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/socket_select_interrupter.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/socket_types.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/strand_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/task_io_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/task_io_service_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/thread.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/throw_error.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/timer_queue.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/timer_queue_base.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/tss_ptr.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_event.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_iocp_io_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_iocp_io_service_fwd.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_iocp_operation.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_local_free_on_block_exit.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_mutex.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_signal_blocker.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_thread.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/win_tss_ptr.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/winsock_init.hpp delete mode 100644 libtorrent/include/libtorrent/asio/detail/wrapped_handler.hpp delete mode 100644 libtorrent/include/libtorrent/asio/error.hpp delete mode 100644 libtorrent/include/libtorrent/asio/error_code.hpp delete mode 100644 libtorrent/include/libtorrent/asio/error_handler.hpp delete mode 100644 libtorrent/include/libtorrent/asio/handler_alloc_hook.hpp delete mode 100644 libtorrent/include/libtorrent/asio/handler_invoke_hook.hpp delete mode 100644 libtorrent/include/libtorrent/asio/impl/error_code.ipp delete mode 100644 libtorrent/include/libtorrent/asio/impl/io_service.ipp delete mode 100644 libtorrent/include/libtorrent/asio/impl/read.ipp delete mode 100644 libtorrent/include/libtorrent/asio/impl/read_until.ipp delete mode 100644 libtorrent/include/libtorrent/asio/impl/write.ipp delete mode 100644 libtorrent/include/libtorrent/asio/io_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/address.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/address_v4.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/address_v6.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/basic_endpoint.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/basic_resolver.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/basic_resolver_entry.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/basic_resolver_iterator.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/basic_resolver_query.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/host_name.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/multicast.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/resolver_query_base.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/resolver_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/tcp.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ip/udp.hpp delete mode 100644 libtorrent/include/libtorrent/asio/is_read_buffered.hpp delete mode 100644 libtorrent/include/libtorrent/asio/is_write_buffered.hpp delete mode 100644 libtorrent/include/libtorrent/asio/placeholders.hpp delete mode 100644 libtorrent/include/libtorrent/asio/read.hpp delete mode 100644 libtorrent/include/libtorrent/asio/read_until.hpp delete mode 100644 libtorrent/include/libtorrent/asio/resolver_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/socket_acceptor_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/socket_base.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/basic_context.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/context.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/context_base.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/context_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/detail/openssl_context_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/detail/openssl_init.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/detail/openssl_types.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/stream.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/stream_base.hpp delete mode 100644 libtorrent/include/libtorrent/asio/ssl/stream_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/strand.hpp delete mode 100644 libtorrent/include/libtorrent/asio/stream_socket_service.hpp delete mode 100644 libtorrent/include/libtorrent/asio/streambuf.hpp delete mode 100644 libtorrent/include/libtorrent/asio/system_error.hpp delete mode 100644 libtorrent/include/libtorrent/asio/system_exception.hpp delete mode 100644 libtorrent/include/libtorrent/asio/thread.hpp delete mode 100644 libtorrent/include/libtorrent/asio/time_traits.hpp delete mode 100644 libtorrent/include/libtorrent/asio/write.hpp delete mode 100644 libtorrent/include/libtorrent/aux_/allocate_resources_impl.hpp delete mode 100644 libtorrent/include/libtorrent/aux_/session_impl.hpp delete mode 100644 libtorrent/include/libtorrent/bandwidth_manager.hpp delete mode 100644 libtorrent/include/libtorrent/bencode.hpp delete mode 100644 libtorrent/include/libtorrent/bt_peer_connection.hpp delete mode 100644 libtorrent/include/libtorrent/buffer.hpp delete mode 100644 libtorrent/include/libtorrent/config.hpp delete mode 100644 libtorrent/include/libtorrent/connection_queue.hpp delete mode 100644 libtorrent/include/libtorrent/debug.hpp delete mode 100644 libtorrent/include/libtorrent/entry.hpp delete mode 100644 libtorrent/include/libtorrent/escape_string.hpp delete mode 100644 libtorrent/include/libtorrent/extensions.hpp delete mode 100644 libtorrent/include/libtorrent/extensions/logger.hpp delete mode 100644 libtorrent/include/libtorrent/extensions/metadata_transfer.hpp delete mode 100644 libtorrent/include/libtorrent/extensions/ut_pex.hpp delete mode 100644 libtorrent/include/libtorrent/file.hpp delete mode 100644 libtorrent/include/libtorrent/file_pool.hpp delete mode 100644 libtorrent/include/libtorrent/fingerprint.hpp delete mode 100644 libtorrent/include/libtorrent/hasher.hpp delete mode 100644 libtorrent/include/libtorrent/http_connection.hpp delete mode 100644 libtorrent/include/libtorrent/http_stream.hpp delete mode 100644 libtorrent/include/libtorrent/http_tracker_connection.hpp delete mode 100644 libtorrent/include/libtorrent/identify_client.hpp delete mode 100644 libtorrent/include/libtorrent/instantiate_connection.hpp delete mode 100644 libtorrent/include/libtorrent/invariant_check.hpp delete mode 100644 libtorrent/include/libtorrent/io.hpp delete mode 100644 libtorrent/include/libtorrent/ip_filter.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/closest_nodes.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/dht_tracker.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/find_data.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/logging.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/node.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/node_entry.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/node_id.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/packet_iterator.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/refresh.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/routing_table.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/rpc_manager.hpp delete mode 100644 libtorrent/include/libtorrent/kademlia/traversal_algorithm.hpp delete mode 100644 libtorrent/include/libtorrent/lsd.hpp delete mode 100644 libtorrent/include/libtorrent/natpmp.hpp delete mode 100644 libtorrent/include/libtorrent/pch.hpp delete mode 100644 libtorrent/include/libtorrent/peer.hpp delete mode 100644 libtorrent/include/libtorrent/peer_connection.hpp delete mode 100644 libtorrent/include/libtorrent/peer_id.hpp delete mode 100644 libtorrent/include/libtorrent/peer_info.hpp delete mode 100644 libtorrent/include/libtorrent/peer_request.hpp delete mode 100644 libtorrent/include/libtorrent/piece_block_progress.hpp delete mode 100644 libtorrent/include/libtorrent/piece_picker.hpp delete mode 100644 libtorrent/include/libtorrent/policy.hpp delete mode 100644 libtorrent/include/libtorrent/random_sample.hpp delete mode 100644 libtorrent/include/libtorrent/resource_request.hpp delete mode 100644 libtorrent/include/libtorrent/session.hpp delete mode 100644 libtorrent/include/libtorrent/session_settings.hpp delete mode 100644 libtorrent/include/libtorrent/session_status.hpp delete mode 100644 libtorrent/include/libtorrent/size_type.hpp delete mode 100644 libtorrent/include/libtorrent/socket.hpp delete mode 100644 libtorrent/include/libtorrent/socket_type.hpp delete mode 100644 libtorrent/include/libtorrent/socks5_stream.hpp delete mode 100644 libtorrent/include/libtorrent/stat.hpp delete mode 100644 libtorrent/include/libtorrent/storage.hpp delete mode 100644 libtorrent/include/libtorrent/time.hpp delete mode 100644 libtorrent/include/libtorrent/torrent.hpp delete mode 100644 libtorrent/include/libtorrent/torrent_handle.hpp delete mode 100644 libtorrent/include/libtorrent/torrent_info.hpp delete mode 100644 libtorrent/include/libtorrent/tracker_manager.hpp delete mode 100644 libtorrent/include/libtorrent/udp_tracker_connection.hpp delete mode 100644 libtorrent/include/libtorrent/upnp.hpp delete mode 100644 libtorrent/include/libtorrent/utf8.hpp delete mode 100644 libtorrent/include/libtorrent/variant_stream.hpp delete mode 100644 libtorrent/include/libtorrent/version.hpp delete mode 100644 libtorrent/include/libtorrent/web_peer_connection.hpp delete mode 100644 libtorrent/include/libtorrent/xml_parse.hpp delete mode 100644 libtorrent/src/Makefile.am delete mode 100644 libtorrent/src/Makefile.in delete mode 100644 libtorrent/src/alert.cpp delete mode 100644 libtorrent/src/allocate_resources.cpp delete mode 100644 libtorrent/src/bandwidth_manager.cpp delete mode 100644 libtorrent/src/bt_peer_connection.cpp delete mode 100644 libtorrent/src/connection_queue.cpp delete mode 100644 libtorrent/src/entry.cpp delete mode 100644 libtorrent/src/escape_string.cpp delete mode 100644 libtorrent/src/file.cpp delete mode 100644 libtorrent/src/file_pool.cpp delete mode 100644 libtorrent/src/file_win.cpp delete mode 100644 libtorrent/src/http_connection.cpp delete mode 100644 libtorrent/src/http_stream.cpp delete mode 100644 libtorrent/src/http_tracker_connection.cpp delete mode 100644 libtorrent/src/identify_client.cpp delete mode 100644 libtorrent/src/instantiate_connection.cpp delete mode 100644 libtorrent/src/ip_filter.cpp delete mode 100644 libtorrent/src/kademlia/closest_nodes.cpp delete mode 100644 libtorrent/src/kademlia/dht_tracker.cpp delete mode 100644 libtorrent/src/kademlia/find_data.cpp delete mode 100644 libtorrent/src/kademlia/node.cpp delete mode 100644 libtorrent/src/kademlia/node_id.cpp delete mode 100644 libtorrent/src/kademlia/refresh.cpp delete mode 100644 libtorrent/src/kademlia/routing_table.cpp delete mode 100644 libtorrent/src/kademlia/rpc_manager.cpp delete mode 100644 libtorrent/src/kademlia/traversal_algorithm.cpp delete mode 100644 libtorrent/src/logger.cpp delete mode 100644 libtorrent/src/lsd.cpp delete mode 100644 libtorrent/src/metadata_transfer.cpp delete mode 100644 libtorrent/src/natpmp.cpp delete mode 100644 libtorrent/src/peer_connection.cpp delete mode 100644 libtorrent/src/piece_picker.cpp delete mode 100644 libtorrent/src/policy.cpp delete mode 100644 libtorrent/src/session.cpp delete mode 100644 libtorrent/src/session_impl.cpp delete mode 100644 libtorrent/src/sha1.cpp delete mode 100644 libtorrent/src/socks5_stream.cpp delete mode 100644 libtorrent/src/stat.cpp delete mode 100644 libtorrent/src/storage.cpp delete mode 100644 libtorrent/src/torrent.cpp delete mode 100644 libtorrent/src/torrent_handle.cpp delete mode 100644 libtorrent/src/torrent_info.cpp delete mode 100644 libtorrent/src/tracker_manager.cpp delete mode 100644 libtorrent/src/udp_tracker_connection.cpp delete mode 100644 libtorrent/src/upnp.cpp delete mode 100644 libtorrent/src/ut_pex.cpp delete mode 100644 libtorrent/src/web_peer_connection.cpp diff --git a/libtorrent/include/libtorrent/alert.hpp b/libtorrent/include/libtorrent/alert.hpp deleted file mode 100644 index b6b6711dc..000000000 --- a/libtorrent/include/libtorrent/alert.hpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg, Daniel Wallin -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_ALERT_HPP_INCLUDED -#define TORRENT_ALERT_HPP_INCLUDED - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/time.hpp" -#include "libtorrent/config.hpp" - -#ifndef TORRENT_MAX_ALERT_TYPES -#define TORRENT_MAX_ALERT_TYPES 15 -#endif - -namespace libtorrent { - - class TORRENT_EXPORT alert - { - public: - enum severity_t { debug, info, warning, critical, fatal, none }; - - alert(severity_t severity, const std::string& msg); - virtual ~alert(); - - // a timestamp is automatically created in the constructor - ptime timestamp() const; - - std::string const& msg() const; - - severity_t severity() const; - - virtual std::auto_ptr clone() const = 0; - - private: - std::string m_msg; - severity_t m_severity; - ptime m_timestamp; - }; - - class TORRENT_EXPORT alert_manager - { - public: - alert_manager(); - ~alert_manager(); - - void post_alert(const alert& alert_); - bool pending() const; - std::auto_ptr get(); - - void set_severity(alert::severity_t severity); - bool should_post(alert::severity_t severity) const; - - private: - std::queue m_alerts; - alert::severity_t m_severity; - mutable boost::mutex m_mutex; - }; - - struct TORRENT_EXPORT unhandled_alert : std::exception - { - unhandled_alert() {} - }; - - namespace detail { - - struct void_; - - template - void handle_alert_dispatch( - const std::auto_ptr& alert_, const Handler& handler - , const std::type_info& typeid_ - , BOOST_PP_ENUM_BINARY_PARAMS(TORRENT_MAX_ALERT_TYPES, T, *p)) - { - if (typeid_ == typeid(T0)) - handler(*static_cast(alert_.get())); - else - handle_alert_dispatch(alert_, handler, typeid_ - , BOOST_PP_ENUM_SHIFTED_PARAMS( - TORRENT_MAX_ALERT_TYPES, p), (void_*)0); - } - - template - void handle_alert_dispatch( - const std::auto_ptr& alert_ - , const Handler& handler - , const std::type_info& typeid_ - , BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void_* BOOST_PP_INTERCEPT)) - { - throw unhandled_alert(); - } - - } // namespace detail - - template - struct TORRENT_EXPORT handle_alert - { - template - handle_alert(const std::auto_ptr& alert_ - , const Handler& handler) - { - #define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT(T, n)*)0 - - detail::handle_alert_dispatch(alert_, handler, typeid(*alert_) - , BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALERT_POINTER_TYPE, _)); - - #undef ALERT_POINTER_TYPE - } - }; - -} // namespace libtorrent - -#endif // TORRENT_ALERT_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/alert_types.hpp b/libtorrent/include/libtorrent/alert_types.hpp deleted file mode 100644 index e3e23ad05..000000000 --- a/libtorrent/include/libtorrent/alert_types.hpp +++ /dev/null @@ -1,300 +0,0 @@ -/* - -Copyright (c) 2003, 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_ALERT_TYPES_HPP_INCLUDED -#define TORRENT_ALERT_TYPES_HPP_INCLUDED - -#include "libtorrent/alert.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - struct TORRENT_EXPORT torrent_alert: alert - { - torrent_alert(torrent_handle const& h, alert::severity_t s - , std::string const& msg) - : alert(s, msg) - , handle(h) - {} - - torrent_handle handle; - }; - - struct TORRENT_EXPORT tracker_alert: torrent_alert - { - tracker_alert(torrent_handle const& h - , int times - , int status - , std::string const& msg) - : torrent_alert(h, alert::warning, msg) - , times_in_row(times) - , status_code(status) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_alert(*this)); } - - int times_in_row; - int status_code; - }; - - struct TORRENT_EXPORT tracker_warning_alert: torrent_alert - { - tracker_warning_alert(torrent_handle const& h - , std::string const& msg) - : torrent_alert(h, alert::warning, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_warning_alert(*this)); } - }; - - - - struct TORRENT_EXPORT tracker_reply_alert: torrent_alert - { - tracker_reply_alert(torrent_handle const& h - , int np - , std::string const& msg) - : torrent_alert(h, alert::info, msg) - , num_peers(np) - {} - - int num_peers; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_reply_alert(*this)); } - }; - - struct TORRENT_EXPORT tracker_announce_alert: torrent_alert - { - tracker_announce_alert(torrent_handle const& h, std::string const& msg) - : torrent_alert(h, alert::info, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new tracker_announce_alert(*this)); } - }; - - struct TORRENT_EXPORT hash_failed_alert: torrent_alert - { - hash_failed_alert( - torrent_handle const& h - , int index - , std::string const& msg) - : torrent_alert(h, alert::info, msg) - , piece_index(index) - { assert(index >= 0);} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new hash_failed_alert(*this)); } - - int piece_index; - }; - - struct TORRENT_EXPORT peer_ban_alert: torrent_alert - { - peer_ban_alert(tcp::endpoint const& pip, torrent_handle h, std::string const& msg) - : torrent_alert(h, alert::info, msg) - , ip(pip) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_ban_alert(*this)); } - - tcp::endpoint ip; - }; - - struct TORRENT_EXPORT peer_error_alert: alert - { - peer_error_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg) - : alert(alert::debug, msg) - , ip(pip) - , pid(pid_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_error_alert(*this)); } - - tcp::endpoint ip; - peer_id pid; - }; - - struct TORRENT_EXPORT invalid_request_alert: torrent_alert - { - invalid_request_alert( - peer_request const& r - , torrent_handle const& h - , tcp::endpoint const& sender - , peer_id const& pid_ - , std::string const& msg) - : torrent_alert(h, alert::debug, msg) - , ip(sender) - , request(r) - , pid(pid_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new invalid_request_alert(*this)); } - - tcp::endpoint ip; - peer_request request; - peer_id pid; - }; - - struct TORRENT_EXPORT torrent_finished_alert: torrent_alert - { - torrent_finished_alert( - const torrent_handle& h - , const std::string& msg) - : torrent_alert(h, alert::warning, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new torrent_finished_alert(*this)); } - }; - - struct TORRENT_EXPORT url_seed_alert: torrent_alert - { - url_seed_alert( - torrent_handle const& h - , const std::string& url_ - , const std::string& msg) - : torrent_alert(h, alert::warning, msg) - , url(url_) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new url_seed_alert(*this)); } - - std::string url; - }; - - struct TORRENT_EXPORT file_error_alert: torrent_alert - { - file_error_alert( - const torrent_handle& h - , const std::string& msg) - : torrent_alert(h, alert::fatal, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new file_error_alert(*this)); } - }; - - struct TORRENT_EXPORT metadata_failed_alert: torrent_alert - { - metadata_failed_alert( - const torrent_handle& h - , const std::string& msg) - : torrent_alert(h, alert::info, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new metadata_failed_alert(*this)); } - }; - - struct TORRENT_EXPORT metadata_received_alert: torrent_alert - { - metadata_received_alert( - const torrent_handle& h - , const std::string& msg) - : torrent_alert(h, alert::info, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new metadata_received_alert(*this)); } - }; - - struct TORRENT_EXPORT listen_failed_alert: alert - { - listen_failed_alert( - const std::string& msg) - : alert(alert::fatal, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new listen_failed_alert(*this)); } - }; - - struct TORRENT_EXPORT portmap_error_alert: alert - { - portmap_error_alert(const std::string& msg) - : alert(alert::warning, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new portmap_error_alert(*this)); } - }; - - struct TORRENT_EXPORT portmap_alert: alert - { - portmap_alert(const std::string& msg) - : alert(alert::info, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new portmap_alert(*this)); } - }; - - struct TORRENT_EXPORT fastresume_rejected_alert: torrent_alert - { - fastresume_rejected_alert(torrent_handle const& h - , std::string const& msg) - : torrent_alert(h, alert::warning, msg) - {} - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new fastresume_rejected_alert(*this)); } - }; - - struct TORRENT_EXPORT peer_blocked_alert: alert - { - peer_blocked_alert(address const& ip_ - , std::string const& msg) - : alert(alert::info, msg) - , ip(ip_) - {} - - address ip; - - virtual std::auto_ptr clone() const - { return std::auto_ptr(new peer_blocked_alert(*this)); } - }; - -} - - -#endif diff --git a/libtorrent/include/libtorrent/allocate_resources.hpp b/libtorrent/include/libtorrent/allocate_resources.hpp deleted file mode 100644 index 3d8237914..000000000 --- a/libtorrent/include/libtorrent/allocate_resources.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - -Copyright (c) 2003, Magnus Jonsson -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_ALLOCATE_RESOURCES_HPP_INCLUDED -#define TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED - -#include -#include - -#include - -#include "libtorrent/resource_request.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/session.hpp" - -namespace libtorrent -{ - class peer_connection; - class torrent; - - int saturated_add(int a, int b); - - // Function to allocate a limited resource fairly among many consumers. - // It takes into account the current use, and the consumer's desired use. - // Should be invoked periodically to allow it adjust to the situation (make - // sure "used" is updated between calls!). - // If resources = std::numeric_limits::max() it means there is an infinite - // supply of resources (so everyone can get what they want). - - void allocate_resources( - int resources - , std::map >& torrents - , resource_request torrent::* res); - - void allocate_resources( - int resources - , std::map& connections - , resource_request peer_connection::* res); - - // Used for global limits. - void allocate_resources( - int resources - , std::vector& _sessions - , resource_request session::* res); -} - - -#endif diff --git a/libtorrent/include/libtorrent/asio.hpp b/libtorrent/include/libtorrent/asio.hpp deleted file mode 100644 index dfad4a6d5..000000000 --- a/libtorrent/include/libtorrent/asio.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// -// asio.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_HPP -#define ASIO_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/basic_datagram_socket.hpp" -#include "asio/basic_deadline_timer.hpp" -#include "asio/basic_io_object.hpp" -#include "asio/basic_socket_acceptor.hpp" -#include "asio/basic_socket_iostream.hpp" -#include "asio/basic_socket_streambuf.hpp" -#include "asio/basic_stream_socket.hpp" -#include "asio/basic_streambuf.hpp" -#include "asio/buffer.hpp" -#include "asio/buffered_read_stream_fwd.hpp" -#include "asio/buffered_read_stream.hpp" -#include "asio/buffered_stream_fwd.hpp" -#include "asio/buffered_stream.hpp" -#include "asio/buffered_write_stream_fwd.hpp" -#include "asio/buffered_write_stream.hpp" -#include "asio/completion_condition.hpp" -#include "asio/datagram_socket_service.hpp" -#include "asio/deadline_timer_service.hpp" -#include "asio/deadline_timer.hpp" -#include "asio/error.hpp" -#include "asio/error_code.hpp" -#include "asio/handler_alloc_hook.hpp" -#include "asio/handler_invoke_hook.hpp" -#include "asio/io_service.hpp" -#include "asio/ip/address.hpp" -#include "asio/ip/address_v4.hpp" -#include "asio/ip/address_v6.hpp" -#include "asio/ip/basic_endpoint.hpp" -#include "asio/ip/basic_resolver.hpp" -#include "asio/ip/basic_resolver_entry.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" -#include "asio/ip/basic_resolver_query.hpp" -#include "asio/ip/host_name.hpp" -#include "asio/ip/multicast.hpp" -#include "asio/ip/resolver_query_base.hpp" -#include "asio/ip/resolver_service.hpp" -#include "asio/ip/tcp.hpp" -#include "asio/ip/udp.hpp" -#include "asio/ip/unicast.hpp" -#include "asio/ip/v6_only.hpp" -#include "asio/is_read_buffered.hpp" -#include "asio/is_write_buffered.hpp" -#include "asio/placeholders.hpp" -#include "asio/read.hpp" -#include "asio/read_until.hpp" -#include "asio/socket_acceptor_service.hpp" -#include "asio/socket_base.hpp" -#include "asio/strand.hpp" -#include "asio/stream_socket_service.hpp" -#include "asio/streambuf.hpp" -#include "asio/system_error.hpp" -#include "asio/thread.hpp" -#include "asio/time_traits.hpp" -#include "asio/write.hpp" - -#endif // ASIO_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp b/libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp deleted file mode 100644 index 1a521628f..000000000 --- a/libtorrent/include/libtorrent/asio/basic_datagram_socket.hpp +++ /dev/null @@ -1,803 +0,0 @@ -// -// basic_datagram_socket.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_BASIC_DATAGRAM_SOCKET_HPP -#define ASIO_BASIC_DATAGRAM_SOCKET_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/datagram_socket_service.hpp" -#include "asio/error.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides datagram-oriented socket functionality. -/** - * The basic_datagram_socket class template provides asynchronous and blocking - * datagram-oriented socket functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template > -class basic_datagram_socket - : public basic_socket -{ -public: - /// The native representation of a socket. - typedef typename DatagramSocketService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct a basic_datagram_socket without opening it. - /** - * This constructor creates a datagram socket without opening it. The open() - * function must be called before data can be sent or received on the socket. - * - * @param io_service The io_service object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - */ - explicit basic_datagram_socket(asio::io_service& io_service) - : basic_socket(io_service) - { - } - - /// Construct and open a basic_datagram_socket. - /** - * This constructor creates and opens a datagram socket. - * - * @param io_service The io_service object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_datagram_socket(asio::io_service& io_service, - const protocol_type& protocol) - : basic_socket(io_service, protocol) - { - } - - /// Construct a basic_datagram_socket, opening it and binding it to the given - /// local endpoint. - /** - * This constructor creates a datagram socket and automatically opens it bound - * to the specified endpoint on the local machine. The protocol used is the - * protocol associated with the given endpoint. - * - * @param io_service The io_service object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param endpoint An endpoint on the local machine to which the datagram - * socket will be bound. - * - * @throws asio::system_error Thrown on failure. - */ - basic_datagram_socket(asio::io_service& io_service, - const endpoint_type& endpoint) - : basic_socket(io_service, endpoint) - { - } - - /// Construct a basic_datagram_socket on an existing native socket. - /** - * This constructor creates a datagram socket object to hold an existing - * native socket. - * - * @param io_service The io_service object that the datagram socket will use - * to dispatch handlers for any asynchronous operations performed on the - * socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_socket The new underlying socket implementation. - * - * @throws asio::system_error Thrown on failure. - */ - basic_datagram_socket(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_socket) - : basic_socket( - io_service, protocol, native_socket) - { - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One ore more data buffers to be sent on the socket. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected datagram socket. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code socket.send(asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.send(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One ore more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected datagram socket. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.send( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes sent. - * - * @note The send operation can only be used with a connected socket. Use - * the send_to function to send data on an unconnected datagram socket. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.send(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous send on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_send operation can only be used with a connected socket. - * Use the async_send_to function to send data on an unconnected datagram - * socket. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_send(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send(const ConstBufferSequence& buffers, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous send on a connected socket. - /** - * This function is used to send data on the datagram socket. The function - * call will block until the data has been sent successfully or an error - * occurs. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_send operation can only be used with a connected socket. - * Use the async_send_to function to send data on an unconnected datagram - * socket. - */ - template - void async_send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, flags, handler); - } - - /// Send a datagram to the specified endpoint. - /** - * This function is used to send a datagram to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * asio::ip::udp::endpoint destination( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.send_to(asio::buffer(data, size), destination); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination) - { - asio::error_code ec; - std::size_t s = this->service.send_to( - this->implementation, buffers, destination, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send a datagram to the specified endpoint. - /** - * This function is used to send a datagram to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @param flags Flags specifying how the send call is to be made. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.send_to( - this->implementation, buffers, destination, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send a datagram to the specified endpoint. - /** - * This function is used to send a datagram to the specified remote endpoint. - * The function call will block until the data has been sent successfully or - * an error occurs. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * - * @param destination The remote endpoint to which the data will be sent. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes sent. - */ - template - std::size_t send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - asio::error_code& ec) - { - return this->service.send_to(this->implementation, - buffers, destination, flags, ec); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send a datagram to the specified - * remote endpoint. The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param destination The remote endpoint to which the data will be sent. - * Copies will be made of the endpoint as required. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * asio::ip::udp::endpoint destination( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.async_send_to( - * asio::buffer(data, size), destination, handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, WriteHandler handler) - { - this->service.async_send_to(this->implementation, buffers, destination, 0, - handler); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send a datagram to the specified - * remote endpoint. The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent to the remote endpoint. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param destination The remote endpoint to which the data will be sent. - * Copies will be made of the endpoint as required. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_send_to(const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - WriteHandler handler) - { - this->service.async_send_to(this->implementation, buffers, destination, - flags, handler); - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the datagram socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected datagram - * socket. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code socket.receive(asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.receive( - this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the datagram socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected datagram - * socket. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.receive( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the datagram socket. The function - * call will block until data has been received successfully or an error - * occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes received. - * - * @note The receive operation can only be used with a connected socket. Use - * the receive_from function to receive data on an unconnected datagram - * socket. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.receive(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous receive on a connected socket. - /** - * This function is used to asynchronously receive data from the datagram - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_receive operation can only be used with a connected socket. - * Use the async_receive_from function to receive data on an unconnected - * datagram socket. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.async_receive(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous receive on a connected socket. - /** - * This function is used to asynchronously receive data from the datagram - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The async_receive operation can only be used with a connected socket. - * Use the async_receive_from function to receive data on an unconnected - * datagram socket. - */ - template - void async_receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, flags, handler); - } - - /// Receive a datagram with the endpoint of the sender. - /** - * This function is used to receive a datagram. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * asio::ip::udp::endpoint sender_endpoint; - * socket.receive_from( - * asio::buffer(data, size), sender_endpoint); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint) - { - asio::error_code ec; - std::size_t s = this->service.receive_from( - this->implementation, buffers, sender_endpoint, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive a datagram with the endpoint of the sender. - /** - * This function is used to receive a datagram. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.receive_from( - this->implementation, buffers, sender_endpoint, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive a datagram with the endpoint of the sender. - /** - * This function is used to receive a datagram. The function call will block - * until data has been received successfully or an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes received. - */ - template - std::size_t receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - asio::error_code& ec) - { - return this->service.receive_from(this->implementation, buffers, - sender_endpoint, flags, ec); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive a datagram. The function - * call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. Ownership of the sender_endpoint object - * is retained by the caller, which must guarantee that it is valid until the - * handler is called. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::system_error& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code socket.async_receive_from( - * asio::buffer(data, size), 0, sender_endpoint, handler); @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, ReadHandler handler) - { - this->service.async_receive_from(this->implementation, buffers, - sender_endpoint, 0, handler); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive a datagram. The function - * call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param sender_endpoint An endpoint object that receives the endpoint of - * the remote sender of the datagram. Ownership of the sender_endpoint object - * is retained by the caller, which must guarantee that it is valid until the - * handler is called. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_receive_from(const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - ReadHandler handler) - { - this->service.async_receive_from(this->implementation, buffers, - sender_endpoint, flags, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_DATAGRAM_SOCKET_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_deadline_timer.hpp b/libtorrent/include/libtorrent/asio/basic_deadline_timer.hpp deleted file mode 100644 index a630c67bc..000000000 --- a/libtorrent/include/libtorrent/asio/basic_deadline_timer.hpp +++ /dev/null @@ -1,399 +0,0 @@ -// -// basic_deadline_timer.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_BASIC_DEADLINE_TIMER_HPP -#define ASIO_BASIC_DEADLINE_TIMER_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_io_object.hpp" -#include "asio/deadline_timer_service.hpp" -#include "asio/error.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides waitable timer functionality. -/** - * The basic_deadline_timer class template provides the ability to perform a - * blocking or asynchronous wait for a timer to expire. - * - * Most applications will use the asio::deadline_timer typedef. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @sa @ref deadline_timer_reset - * - * @par Examples - * Performing a blocking wait: - * @code - * // Construct a timer without setting an expiry time. - * asio::deadline_timer timer(io_service); - * - * // Set an expiry time relative to now. - * timer.expires_from_now(boost::posix_time::seconds(5)); - * - * // Wait for the timer to expire. - * timer.wait(); - * @endcode - * - * @par - * Performing an asynchronous wait: - * @code - * void handler(const asio::error_code& error) - * { - * if (!error) - * { - * // Timer expired. - * } - * } - * - * ... - * - * // Construct a timer with an absolute expiry time. - * asio::deadline_timer timer(io_service, - * boost::posix_time::time_from_string("2005-12-07 23:59:59.000")); - * - * // Start an asynchronous wait. - * timer.async_wait(handler); - * @endcode - */ -template , - typename TimerService = deadline_timer_service > -class basic_deadline_timer - : public basic_io_object -{ -public: - /// The time traits type. - typedef TimeTraits traits_type; - - /// The time type. - typedef typename traits_type::time_type time_type; - - /// The duration type. - typedef typename traits_type::duration_type duration_type; - - /// Constructor. - /** - * This constructor creates a timer without setting an expiry time. The - * expires_at() or expires_from_now() functions must be called to set an - * expiry time before the timer can be waited on. - * - * @param io_service The io_service object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. - */ - explicit basic_deadline_timer(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Constructor to set a particular expiry time as an absolute time. - /** - * This constructor creates a timer and sets the expiry time. - * - * @param io_service The io_service object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. - * - * @param expiry_time The expiry time to be used for the timer, expressed - * as an absolute time. - */ - basic_deadline_timer(asio::io_service& io_service, - const time_type& expiry_time) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.expires_at(this->implementation, expiry_time, ec); - asio::detail::throw_error(ec); - } - - /// Constructor to set a particular expiry time relative to now. - /** - * This constructor creates a timer and sets the expiry time. - * - * @param io_service The io_service object that the timer will use to dispatch - * handlers for any asynchronous operations performed on the timer. - * - * @param expiry_time The expiry time to be used for the timer, relative to - * now. - */ - basic_deadline_timer(asio::io_service& io_service, - const duration_type& expiry_time) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.expires_from_now(this->implementation, expiry_time, ec); - asio::detail::throw_error(ec); - } - - /// Cancel any asynchronous operations that are waiting on the timer. - /** - * This function forces the completion of any pending asynchronous wait - * operations against the timer. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * Cancelling the timer does not change the expiry time. - * - * @return The number of asynchronous operations that were cancelled. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t cancel() - { - asio::error_code ec; - std::size_t s = this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Cancel any asynchronous operations that are waiting on the timer. - /** - * This function forces the completion of any pending asynchronous wait - * operations against the timer. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * Cancelling the timer does not change the expiry time. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of asynchronous operations that were cancelled. - */ - std::size_t cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - - /// Get the timer's expiry time as an absolute time. - /** - * This function may be used to obtain the timer's current expiry time. - * Whether the timer has expired or not does not affect this value. - */ - time_type expires_at() const - { - return this->service.expires_at(this->implementation); - } - - /// Set the timer's expiry time as an absolute time. - /** - * This function sets the expiry time. Any pending asynchronous wait - * operations will be cancelled. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * See @ref deadline_timer_reset for more information on altering the expiry - * time of an active timer. - * - * @param expiry_time The expiry time to be used for the timer. - * - * @return The number of asynchronous operations that were cancelled. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t expires_at(const time_type& expiry_time) - { - asio::error_code ec; - std::size_t s = this->service.expires_at( - this->implementation, expiry_time, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Set the timer's expiry time as an absolute time. - /** - * This function sets the expiry time. Any pending asynchronous wait - * operations will be cancelled. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * See @ref deadline_timer_reset for more information on altering the expiry - * time of an active timer. - * - * @param expiry_time The expiry time to be used for the timer. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of asynchronous operations that were cancelled. - */ - std::size_t expires_at(const time_type& expiry_time, - asio::error_code& ec) - { - return this->service.expires_at(this->implementation, expiry_time, ec); - } - - /// Get the timer's expiry time relative to now. - /** - * This function may be used to obtain the timer's current expiry time. - * Whether the timer has expired or not does not affect this value. - */ - duration_type expires_from_now() const - { - return this->service.expires_from_now(this->implementation); - } - - /// Set the timer's expiry time relative to now. - /** - * This function sets the expiry time. Any pending asynchronous wait - * operations will be cancelled. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * See @ref deadline_timer_reset for more information on altering the expiry - * time of an active timer. - * - * @param expiry_time The expiry time to be used for the timer. - * - * @return The number of asynchronous operations that were cancelled. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t expires_from_now(const duration_type& expiry_time) - { - asio::error_code ec; - std::size_t s = this->service.expires_from_now( - this->implementation, expiry_time, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Set the timer's expiry time relative to now. - /** - * This function sets the expiry time. Any pending asynchronous wait - * operations will be cancelled. The handler for each cancelled operation will - * be invoked with the asio::error::operation_aborted error code. - * - * See @ref deadline_timer_reset for more information on altering the expiry - * time of an active timer. - * - * @param expiry_time The expiry time to be used for the timer. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of asynchronous operations that were cancelled. - */ - std::size_t expires_from_now(const duration_type& expiry_time, - asio::error_code& ec) - { - return this->service.expires_from_now( - this->implementation, expiry_time, ec); - } - - /// Perform a blocking wait on the timer. - /** - * This function is used to wait for the timer to expire. This function - * blocks and does not return until the timer has expired. - * - * @throws asio::system_error Thrown on failure. - */ - void wait() - { - asio::error_code ec; - this->service.wait(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Perform a blocking wait on the timer. - /** - * This function is used to wait for the timer to expire. This function - * blocks and does not return until the timer has expired. - * - * @param ec Set to indicate what error occurred, if any. - */ - void wait(asio::error_code& ec) - { - this->service.wait(this->implementation, ec); - } - - /// Start an asynchronous wait on the timer. - /** - * This function may be used to initiate an asynchronous wait against the - * timer. It always returns immediately. - * - * For each call to async_wait(), the supplied handler will be called exactly - * once. The handler will be called when: - * - * @li The timer has expired. - * - * @li The timer was cancelled, in which case the handler is passed the error - * code asio::error::operation_aborted. - * - * @param handler The handler to be called when the timer expires. Copies - * will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_wait(WaitHandler handler) - { - this->service.async_wait(this->implementation, handler); - } -}; - -/** - * @page deadline_timer_reset Changing an active deadline_timer's expiry time - * - * Changing the expiry time of a timer while there are pending asynchronous - * waits causes those wait operations to be cancelled. To ensure that the action - * associated with the timer is performed only once, use something like this: - * used: - * - * @code - * void on_some_event() - * { - * if (my_timer.expires_from_now(seconds(5)) > 0) - * { - * // We managed to cancel the timer. Start new asynchronous wait. - * my_timer.async_wait(on_timeout); - * } - * else - * { - * // Too late, timer has already expired! - * } - * } - * - * void on_timeout(const asio::error_code& e) - * { - * if (e != asio::error::operation_aborted) - * { - * // Timer was not cancelled, take necessary action. - * } - * } - * @endcode - * - * @li The asio::basic_deadline_timer::expires_from_now() function - * cancels any pending asynchronous waits, and returns the number of - * asynchronous waits that were cancelled. If it returns 0 then you were too - * late and the wait handler has already been executed, or will soon be - * executed. If it returns 1 then the wait handler was successfully cancelled. - * - * @li If a wait handler is cancelled, the asio::error_code passed to - * it contains the value asio::error::operation_aborted. - * - * @sa asio::basic_deadline_timer - */ - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_DEADLINE_TIMER_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_io_object.hpp b/libtorrent/include/libtorrent/asio/basic_io_object.hpp deleted file mode 100644 index 9291ff5da..000000000 --- a/libtorrent/include/libtorrent/asio/basic_io_object.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// basic_io_object.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_BASIC_IO_OBJECT_HPP -#define ASIO_BASIC_IO_OBJECT_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/io_service.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Base class for all I/O objects. -template -class basic_io_object - : private noncopyable -{ -public: - /// The type of the service that will be used to provide I/O operations. - typedef IoObjectService service_type; - - /// The underlying implementation type of I/O object. - typedef typename service_type::implementation_type implementation_type; - - /// Get the io_service associated with the object. - /** - * This function may be used to obtain the io_service object that the I/O - * object uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that the I/O object will use - * to dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& io_service() - { - return service.io_service(); - } - -protected: - /// Construct a basic_io_object. - explicit basic_io_object(asio::io_service& io_service) - : service(asio::use_service(io_service)) - { - service.construct(implementation); - } - - /// Protected destructor to prevent deletion through this type. - ~basic_io_object() - { - service.destroy(implementation); - } - - // The backend service implementation. - service_type& service; - - // The underlying native implementation. - implementation_type implementation; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_IO_OBJECT_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_resolver.hpp b/libtorrent/include/libtorrent/asio/basic_resolver.hpp deleted file mode 100644 index 5df89d545..000000000 --- a/libtorrent/include/libtorrent/asio/basic_resolver.hpp +++ /dev/null @@ -1,252 +0,0 @@ -// -// basic_resolver.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2006 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_BASIC_RESOLVER_HPP -#define ASIO_BASIC_RESOLVER_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/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/error_handler.hpp" -#include "asio/resolver_service.hpp" - -namespace asio { - -/// Provides endpoint resolution functionality. -/** - * The basic_resolver class template provides the ability to resolve a query - * to a list of endpoints. - * - * @par Thread Safety: - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * Async_Object, Error_Source. - */ -template > -class basic_resolver - : public basic_io_object -{ -public: - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// The query type. - typedef typename Protocol::resolver_query query; - - /// The iterator type. - typedef typename Protocol::resolver_iterator iterator; - - /// The type used for reporting errors. - typedef asio::error error_type; - - /// Constructor. - /** - * This constructor creates a basic_resolver. - * - * @param io_service The io_service object that the resolver will use to - * dispatch handlers for any asynchronous operations performed on the timer. - */ - explicit basic_resolver(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Cancel any asynchronous operations that are waiting on the resolver. - /** - * This function forces the completion of any pending asynchronous - * operations on the host resolver. The handler for each cancelled operation - * will be invoked with the asio::error::operation_aborted error code. - */ - void cancel() - { - return this->service.cancel(this->implementation); - } - - /// Resolve a query to a list of entries. - /** - * This function is used to resolve a query into a list of endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. - * - * @throws asio::error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful call to this function is guaranteed to return at least - * one entry. - */ - iterator resolve(const query& q) - { - return this->service.resolve(this->implementation, q, throw_error()); - } - - /// Resolve a query to a list of entries. - /** - * This function is used to resolve a query into a list of endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @param error_handler A handler to be called when the operation completes, - * to indicate whether or not an error has occurred. Copies will be made of - * the handler as required. The function signature of the handler must be: - * @code void error_handler( - * const asio::error& error // Result of operation. - * ); @endcode - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful call to this function is guaranteed to return at least - * one entry. - */ - template - iterator resolve(const query& q, Error_Handler error_handler) - { - return this->service.resolve(this->implementation, q, error_handler); - } - - /// Asynchronously resolve a query to a list of entries. - /** - * This function is used to asynchronously resolve a query into a list of - * endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can be used to - * // traverse the list of endpoint entries. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful resolve operation is guaranteed to pass at least one - * entry to the handler. - */ - template - void async_resolve(const query& q, Handler handler) - { - return this->service.async_resolve(this->implementation, q, handler); - } - - /// Resolve an endpoint to a list of entries. - /** - * This function is used to resolve an endpoint into a list of endpoint - * entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. - * - * @throws asio::error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful call to this function is guaranteed to return at least - * one entry. - */ - iterator resolve(const endpoint_type& e) - { - return this->service.resolve(this->implementation, e, throw_error()); - } - - /// Resolve an endpoint to a list of entries. - /** - * This function is used to resolve an endpoint into a list of endpoint - * entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @param error_handler A handler to be called when the operation completes, - * to indicate whether or not an error has occurred. Copies will be made of - * the handler as required. The function signature of the handler must be: - * @code void error_handler( - * const asio::error& error // Result of operation. - * ); @endcode - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful call to this function is guaranteed to return at least - * one entry. - */ - template - iterator resolve(const endpoint_type& e, Error_Handler error_handler) - { - return this->service.resolve(this->implementation, e, error_handler); - } - - /// Asynchronously resolve an endpoint to a list of entries. - /** - * This function is used to asynchronously resolve an endpoint into a list of - * endpoint entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can be used to - * // traverse the list of endpoint entries. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note A default constructed iterator represents the end of the list. - * - * @note A successful resolve operation is guaranteed to pass at least one - * entry to the handler. - */ - template - void async_resolve(const endpoint_type& e, Handler handler) - { - return this->service.async_resolve(this->implementation, e, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_RESOLVER_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_socket.hpp b/libtorrent/include/libtorrent/asio/basic_socket.hpp deleted file mode 100644 index b0dc52e48..000000000 --- a/libtorrent/include/libtorrent/asio/basic_socket.hpp +++ /dev/null @@ -1,972 +0,0 @@ -// -// basic_socket.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_BASIC_SOCKET_HPP -#define ASIO_BASIC_SOCKET_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/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/socket_base.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides socket functionality. -/** - * The basic_socket class template provides functionality that is common to both - * stream-oriented and datagram-oriented sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_socket - : public basic_io_object, - public socket_base -{ -public: - /// The native representation of a socket. - typedef typename SocketService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// A basic_socket is always the lowest layer. - typedef basic_socket lowest_layer_type; - - /// Construct a basic_socket without opening it. - /** - * This constructor creates a socket without opening it. - * - * @param io_service The io_service object that the socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - */ - explicit basic_socket(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Construct and open a basic_socket. - /** - * This constructor creates and opens a socket. - * - * @param io_service The io_service object that the socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket(asio::io_service& io_service, - const protocol_type& protocol) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, protocol, ec); - asio::detail::throw_error(ec); - } - - /// Construct a basic_socket, opening it and binding it to the given local - /// endpoint. - /** - * This constructor creates a socket and automatically opens it bound to the - * specified endpoint on the local machine. The protocol used is the protocol - * associated with the given endpoint. - * - * @param io_service The io_service object that the socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param endpoint An endpoint on the local machine to which the socket will - * be bound. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket(asio::io_service& io_service, - const endpoint_type& endpoint) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, endpoint.protocol(), ec); - asio::detail::throw_error(ec); - this->service.bind(this->implementation, endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Construct a basic_socket on an existing native socket. - /** - * This constructor creates a socket object to hold an existing native socket. - * - * @param io_service The io_service object that the socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_socket A native socket. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_socket) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.assign(this->implementation, protocol, native_socket, ec); - asio::detail::throw_error(ec); - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * layers. Since a basic_socket cannot contain any further layers, it simply - * returns a reference to itself. - * - * @return A reference to the lowest layer in the stack of layers. Ownership - * is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return *this; - } - - /// Open the socket using the specified protocol. - /** - * This function opens the socket so that it will use the specified protocol. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * socket.open(asio::ip::tcp::v4()); - * @endcode - */ - void open(const protocol_type& protocol = protocol_type()) - { - asio::error_code ec; - this->service.open(this->implementation, protocol, ec); - asio::detail::throw_error(ec); - } - - /// Open the socket using the specified protocol. - /** - * This function opens the socket so that it will use the specified protocol. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * asio::error_code ec; - * socket.open(asio::ip::tcp::v4(), ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code open(const protocol_type& protocol, - asio::error_code& ec) - { - return this->service.open(this->implementation, protocol, ec); - } - - /// Assign an existing native socket to the socket. - /* - * This function opens the socket to hold an existing native socket. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param native_socket A native socket. - * - * @throws asio::system_error Thrown on failure. - */ - void assign(const protocol_type& protocol, const native_type& native_socket) - { - asio::error_code ec; - this->service.assign(this->implementation, protocol, native_socket, ec); - asio::detail::throw_error(ec); - } - - /// Assign an existing native socket to the socket. - /* - * This function opens the socket to hold an existing native socket. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param native_socket A native socket. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code assign(const protocol_type& protocol, - const native_type& native_socket, asio::error_code& ec) - { - return this->service.assign(this->implementation, - protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open() const - { - return this->service.is_open(this->implementation); - } - - /// Close the socket. - /** - * This function is used to close the socket. Any asynchronous send, receive - * or connect operations will be cancelled immediately, and will complete - * with the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void close() - { - asio::error_code ec; - this->service.close(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Close the socket. - /** - * This function is used to close the socket. Any asynchronous send, receive - * or connect operations will be cancelled immediately, and will complete - * with the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::error_code ec; - * socket.close(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code close(asio::error_code& ec) - { - return this->service.close(this->implementation, ec); - } - - /// Get the native socket representation. - /** - * This function may be used to obtain the underlying representation of the - * socket. This is intended to allow access to native socket functionality - * that is not otherwise provided. - */ - native_type native() - { - return this->service.native(this->implementation); - } - - /// Cancel all asynchronous operations associated with the socket. - /** - * This function causes all outstanding asynchronous connect, send and receive - * operations to finish immediately, and the handlers for cancelled operations - * will be passed the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void cancel() - { - asio::error_code ec; - this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Cancel all asynchronous operations associated with the socket. - /** - * This function causes all outstanding asynchronous connect, send and receive - * operations to finish immediately, and the handlers for cancelled operations - * will be passed the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - /** - * This function is used to check whether the socket input is currently - * positioned at the out-of-band data mark. - * - * @return A bool indicating whether the socket is at the out-of-band data - * mark. - * - * @throws asio::system_error Thrown on failure. - */ - bool at_mark() const - { - asio::error_code ec; - bool b = this->service.at_mark(this->implementation, ec); - asio::detail::throw_error(ec); - return b; - } - - /// Determine whether the socket is at the out-of-band data mark. - /** - * This function is used to check whether the socket input is currently - * positioned at the out-of-band data mark. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return A bool indicating whether the socket is at the out-of-band data - * mark. - */ - bool at_mark(asio::error_code& ec) const - { - return this->service.at_mark(this->implementation, ec); - } - - /// Determine the number of bytes available for reading. - /** - * This function is used to determine the number of bytes that may be read - * without blocking. - * - * @return The number of bytes that may be read without blocking, or 0 if an - * error occurs. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t available() const - { - asio::error_code ec; - std::size_t s = this->service.available(this->implementation, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Determine the number of bytes available for reading. - /** - * This function is used to determine the number of bytes that may be read - * without blocking. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of bytes that may be read without blocking, or 0 if an - * error occurs. - */ - std::size_t available(asio::error_code& ec) const - { - return this->service.available(this->implementation, ec); - } - - /// Bind the socket to the given local endpoint. - /** - * This function binds the socket to the specified endpoint on the local - * machine. - * - * @param endpoint An endpoint on the local machine to which the socket will - * be bound. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * socket.open(asio::ip::tcp::v4()); - * socket.bind(asio::ip::tcp::endpoint( - * asio::ip::tcp::v4(), 12345)); - * @endcode - */ - void bind(const endpoint_type& endpoint) - { - asio::error_code ec; - this->service.bind(this->implementation, endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Bind the socket to the given local endpoint. - /** - * This function binds the socket to the specified endpoint on the local - * machine. - * - * @param endpoint An endpoint on the local machine to which the socket will - * be bound. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * socket.open(asio::ip::tcp::v4()); - * asio::error_code ec; - * socket.bind(asio::ip::tcp::endpoint( - * asio::ip::tcp::v4(), 12345), ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code bind(const endpoint_type& endpoint, - asio::error_code& ec) - { - return this->service.bind(this->implementation, endpoint, ec); - } - - /// Connect the socket to the specified endpoint. - /** - * This function is used to connect a socket to the specified remote endpoint. - * The function call will block until the connection is successfully made or - * an error occurs. - * - * The socket is automatically opened if it is not already open. If the - * connect fails, and the socket was automatically opened, the socket is - * returned to the closed state. - * - * @param peer_endpoint The remote endpoint to which the socket will be - * connected. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.connect(endpoint); - * @endcode - */ - void connect(const endpoint_type& peer_endpoint) - { - asio::error_code ec; - if (!is_open()) - { - this->service.open(this->implementation, peer_endpoint.protocol(), ec); - asio::detail::throw_error(ec); - } - this->service.connect(this->implementation, peer_endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Connect the socket to the specified endpoint. - /** - * This function is used to connect a socket to the specified remote endpoint. - * The function call will block until the connection is successfully made or - * an error occurs. - * - * The socket is automatically opened if it is not already open. If the - * connect fails, and the socket was automatically opened, the socket is - * returned to the closed state. - * - * @param peer_endpoint The remote endpoint to which the socket will be - * connected. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * asio::error_code ec; - * socket.connect(endpoint, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code connect(const endpoint_type& peer_endpoint, - asio::error_code& ec) - { - if (!is_open()) - { - if (this->service.open(this->implementation, - peer_endpoint.protocol(), ec)) - { - return ec; - } - } - - return this->service.connect(this->implementation, peer_endpoint, ec); - } - - /// Start an asynchronous connect. - /** - * This function is used to asynchronously connect a socket to the specified - * remote endpoint. The function call always returns immediately. - * - * The socket is automatically opened if it is not already open. If the - * connect fails, and the socket was automatically opened, the socket is - * returned to the closed state. - * - * @param peer_endpoint The remote endpoint to which the socket will be - * connected. Copies will be made of the endpoint object as required. - * - * @param handler The handler to be called when the connection operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * @code - * void connect_handler(const asio::error_code& error) - * { - * if (!error) - * { - * // Connect succeeded. - * } - * } - * - * ... - * - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint( - * asio::ip::address::from_string("1.2.3.4"), 12345); - * socket.async_connect(endpoint, connect_handler); - * @endcode - */ - template - void async_connect(const endpoint_type& peer_endpoint, ConnectHandler handler) - { - if (!is_open()) - { - asio::error_code ec; - if (this->service.open(this->implementation, - peer_endpoint.protocol(), ec)) - { - this->io_service().post(asio::detail::bind_handler(handler, ec)); - return; - } - } - - this->service.async_connect(this->implementation, peer_endpoint, handler); - } - - /// Set an option on the socket. - /** - * This function is used to set an option on the socket. - * - * @param option The new option value to be set on the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @sa SettableSocketOption @n - * asio::socket_base::broadcast @n - * asio::socket_base::do_not_route @n - * asio::socket_base::keep_alive @n - * asio::socket_base::linger @n - * asio::socket_base::receive_buffer_size @n - * asio::socket_base::receive_low_watermark @n - * asio::socket_base::reuse_address @n - * asio::socket_base::send_buffer_size @n - * asio::socket_base::send_low_watermark @n - * asio::ip::multicast::join_group @n - * asio::ip::multicast::leave_group @n - * asio::ip::multicast::enable_loopback @n - * asio::ip::multicast::outbound_interface @n - * asio::ip::multicast::hops @n - * asio::ip::tcp::no_delay - * - * @par Example - * Setting the IPPROTO_TCP/TCP_NODELAY option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::no_delay option(true); - * socket.set_option(option); - * @endcode - */ - template - void set_option(const SettableSocketOption& option) - { - asio::error_code ec; - this->service.set_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Set an option on the socket. - /** - * This function is used to set an option on the socket. - * - * @param option The new option value to be set on the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa SettableSocketOption @n - * asio::socket_base::broadcast @n - * asio::socket_base::do_not_route @n - * asio::socket_base::keep_alive @n - * asio::socket_base::linger @n - * asio::socket_base::receive_buffer_size @n - * asio::socket_base::receive_low_watermark @n - * asio::socket_base::reuse_address @n - * asio::socket_base::send_buffer_size @n - * asio::socket_base::send_low_watermark @n - * asio::ip::multicast::join_group @n - * asio::ip::multicast::leave_group @n - * asio::ip::multicast::enable_loopback @n - * asio::ip::multicast::outbound_interface @n - * asio::ip::multicast::hops @n - * asio::ip::tcp::no_delay - * - * @par Example - * Setting the IPPROTO_TCP/TCP_NODELAY option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::no_delay option(true); - * asio::error_code ec; - * socket.set_option(option, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - template - asio::error_code set_option(const SettableSocketOption& option, - asio::error_code& ec) - { - return this->service.set_option(this->implementation, option, ec); - } - - /// Get an option from the socket. - /** - * This function is used to get the current value of an option on the socket. - * - * @param option The option value to be obtained from the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @sa GettableSocketOption @n - * asio::socket_base::broadcast @n - * asio::socket_base::do_not_route @n - * asio::socket_base::keep_alive @n - * asio::socket_base::linger @n - * asio::socket_base::receive_buffer_size @n - * asio::socket_base::receive_low_watermark @n - * asio::socket_base::reuse_address @n - * asio::socket_base::send_buffer_size @n - * asio::socket_base::send_low_watermark @n - * asio::ip::multicast::join_group @n - * asio::ip::multicast::leave_group @n - * asio::ip::multicast::enable_loopback @n - * asio::ip::multicast::outbound_interface @n - * asio::ip::multicast::hops @n - * asio::ip::tcp::no_delay - * - * @par Example - * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::socket::keep_alive option; - * socket.get_option(option); - * bool is_set = option.get(); - * @endcode - */ - template - void get_option(GettableSocketOption& option) const - { - asio::error_code ec; - this->service.get_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Get an option from the socket. - /** - * This function is used to get the current value of an option on the socket. - * - * @param option The option value to be obtained from the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa GettableSocketOption @n - * asio::socket_base::broadcast @n - * asio::socket_base::do_not_route @n - * asio::socket_base::keep_alive @n - * asio::socket_base::linger @n - * asio::socket_base::receive_buffer_size @n - * asio::socket_base::receive_low_watermark @n - * asio::socket_base::reuse_address @n - * asio::socket_base::send_buffer_size @n - * asio::socket_base::send_low_watermark @n - * asio::ip::multicast::join_group @n - * asio::ip::multicast::leave_group @n - * asio::ip::multicast::enable_loopback @n - * asio::ip::multicast::outbound_interface @n - * asio::ip::multicast::hops @n - * asio::ip::tcp::no_delay - * - * @par Example - * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::socket::keep_alive option; - * asio::error_code ec; - * socket.get_option(option, ec); - * if (ec) - * { - * // An error occurred. - * } - * bool is_set = option.get(); - * @endcode - */ - template - asio::error_code get_option(GettableSocketOption& option, - asio::error_code& ec) const - { - return this->service.get_option(this->implementation, option, ec); - } - - /// Perform an IO control command on the socket. - /** - * This function is used to execute an IO control command on the socket. - * - * @param command The IO control command to be performed on the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @sa IoControlCommand @n - * asio::socket_base::bytes_readable @n - * asio::socket_base::non_blocking_io - * - * @par Example - * Getting the number of bytes ready to read: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::socket::bytes_readable command; - * socket.io_control(command); - * std::size_t bytes_readable = command.get(); - * @endcode - */ - template - void io_control(IoControlCommand& command) - { - asio::error_code ec; - this->service.io_control(this->implementation, command, ec); - asio::detail::throw_error(ec); - } - - /// Perform an IO control command on the socket. - /** - * This function is used to execute an IO control command on the socket. - * - * @param command The IO control command to be performed on the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa IoControlCommand @n - * asio::socket_base::bytes_readable @n - * asio::socket_base::non_blocking_io - * - * @par Example - * Getting the number of bytes ready to read: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::socket::bytes_readable command; - * asio::error_code ec; - * socket.io_control(command, ec); - * if (ec) - * { - * // An error occurred. - * } - * std::size_t bytes_readable = command.get(); - * @endcode - */ - template - asio::error_code io_control(IoControlCommand& command, - asio::error_code& ec) - { - return this->service.io_control(this->implementation, command, ec); - } - - /// Get the local endpoint of the socket. - /** - * This function is used to obtain the locally bound endpoint of the socket. - * - * @returns An object that represents the local endpoint of the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::endpoint endpoint = socket.local_endpoint(); - * @endcode - */ - endpoint_type local_endpoint() const - { - asio::error_code ec; - endpoint_type ep = this->service.local_endpoint(this->implementation, ec); - asio::detail::throw_error(ec); - return ep; - } - - /// Get the local endpoint of the socket. - /** - * This function is used to obtain the locally bound endpoint of the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns An object that represents the local endpoint of the socket. - * Returns a default-constructed endpoint object if an error occurred. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::error_code ec; - * asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - endpoint_type local_endpoint(asio::error_code& ec) const - { - return this->service.local_endpoint(this->implementation, ec); - } - - /// Get the remote endpoint of the socket. - /** - * This function is used to obtain the remote endpoint of the socket. - * - * @returns An object that represents the remote endpoint of the socket. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(); - * @endcode - */ - endpoint_type remote_endpoint() const - { - asio::error_code ec; - endpoint_type ep = this->service.remote_endpoint(this->implementation, ec); - asio::detail::throw_error(ec); - return ep; - } - - /// Get the remote endpoint of the socket. - /** - * This function is used to obtain the remote endpoint of the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns An object that represents the remote endpoint of the socket. - * Returns a default-constructed endpoint object if an error occurred. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::error_code ec; - * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - endpoint_type remote_endpoint(asio::error_code& ec) const - { - return this->service.remote_endpoint(this->implementation, ec); - } - - /// Disable sends or receives on the socket. - /** - * This function is used to disable send operations, receive operations, or - * both. - * - * @param what Determines what types of operation will no longer be allowed. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * Shutting down the send side of the socket: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * socket.shutdown(asio::ip::tcp::socket::shutdown_send); - * @endcode - */ - void shutdown(shutdown_type what) - { - asio::error_code ec; - this->service.shutdown(this->implementation, what, ec); - asio::detail::throw_error(ec); - } - - /// Disable sends or receives on the socket. - /** - * This function is used to disable send operations, receive operations, or - * both. - * - * @param what Determines what types of operation will no longer be allowed. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * Shutting down the send side of the socket: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::error_code ec; - * socket.shutdown(asio::ip::tcp::socket::shutdown_send, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code shutdown(shutdown_type what, - asio::error_code& ec) - { - return this->service.shutdown(this->implementation, what, ec); - } - -protected: - /// Protected destructor to prevent deletion through this type. - ~basic_socket() - { - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SOCKET_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_socket_acceptor.hpp b/libtorrent/include/libtorrent/asio/basic_socket_acceptor.hpp deleted file mode 100644 index a2d6a0356..000000000 --- a/libtorrent/include/libtorrent/asio/basic_socket_acceptor.hpp +++ /dev/null @@ -1,824 +0,0 @@ -// -// basic_socket_acceptor.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_BASIC_SOCKET_ACCEPTOR_HPP -#define ASIO_BASIC_SOCKET_ACCEPTOR_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/basic_io_object.hpp" -#include "asio/basic_socket.hpp" -#include "asio/error.hpp" -#include "asio/socket_acceptor_service.hpp" -#include "asio/socket_base.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides the ability to accept new connections. -/** - * The basic_socket_acceptor class template is used for accepting new socket - * connections. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Example - * Opening a socket acceptor with the SO_REUSEADDR option enabled: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port); - * acceptor.open(endpoint.protocol()); - * acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true)); - * acceptor.bind(endpoint); - * acceptor.listen(); - * @endcode - */ -template > -class basic_socket_acceptor - : public basic_io_object, - public socket_base -{ -public: - /// The native representation of an acceptor. - typedef typename SocketAcceptorService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct an acceptor without opening it. - /** - * This constructor creates an acceptor without opening it to listen for new - * connections. The open() function must be called before the acceptor can - * accept new socket connections. - * - * @param io_service The io_service object that the acceptor will use to - * dispatch handlers for any asynchronous operations performed on the - * acceptor. - */ - explicit basic_socket_acceptor(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Construct an open acceptor. - /** - * This constructor creates an acceptor and automatically opens it. - * - * @param io_service The io_service object that the acceptor will use to - * dispatch handlers for any asynchronous operations performed on the - * acceptor. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket_acceptor(asio::io_service& io_service, - const protocol_type& protocol) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, protocol, ec); - asio::detail::throw_error(ec); - } - - /// Construct an acceptor opened on the given endpoint. - /** - * This constructor creates an acceptor and automatically opens it to listen - * for new connections on the specified endpoint. - * - * @param io_service The io_service object that the acceptor will use to - * dispatch handlers for any asynchronous operations performed on the - * acceptor. - * - * @param endpoint An endpoint on the local machine on which the acceptor - * will listen for new connections. - * - * @param reuse_addr Whether the constructor should set the socket option - * socket_base::reuse_address. - * - * @throws asio::system_error Thrown on failure. - * - * @note This constructor is equivalent to the following code: - * @code - * basic_socket_acceptor acceptor(io_service); - * acceptor.open(endpoint.protocol()); - * if (reuse_addr) - * acceptor.set_option(socket_base::reuse_address(true)); - * acceptor.bind(endpoint); - * acceptor.listen(listen_backlog); - * @endcode - */ - basic_socket_acceptor(asio::io_service& io_service, - const endpoint_type& endpoint, bool reuse_addr = true) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.open(this->implementation, endpoint.protocol(), ec); - asio::detail::throw_error(ec); - if (reuse_addr) - { - this->service.set_option(this->implementation, - socket_base::reuse_address(true), ec); - asio::detail::throw_error(ec); - } - this->service.bind(this->implementation, endpoint, ec); - asio::detail::throw_error(ec); - this->service.listen(this->implementation, - socket_base::max_connections, ec); - asio::detail::throw_error(ec); - } - - /// Construct a basic_socket_acceptor on an existing native acceptor. - /** - * This constructor creates an acceptor object to hold an existing native - * acceptor. - * - * @param io_service The io_service object that the acceptor will use to - * dispatch handlers for any asynchronous operations performed on the - * acceptor. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_acceptor A native acceptor. - * - * @throws asio::system_error Thrown on failure. - */ - basic_socket_acceptor(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_acceptor) - : basic_io_object(io_service) - { - asio::error_code ec; - this->service.assign(this->implementation, protocol, native_acceptor, ec); - asio::detail::throw_error(ec); - } - - /// Open the acceptor using the specified protocol. - /** - * This function opens the socket acceptor so that it will use the specified - * protocol. - * - * @param protocol An object specifying which protocol is to be used. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * acceptor.open(asio::ip::tcp::v4()); - * @endcode - */ - void open(const protocol_type& protocol = protocol_type()) - { - asio::error_code ec; - this->service.open(this->implementation, protocol, ec); - asio::detail::throw_error(ec); - } - - /// Open the acceptor using the specified protocol. - /** - * This function opens the socket acceptor so that it will use the specified - * protocol. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * asio::error_code ec; - * acceptor.open(asio::ip::tcp::v4(), ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code open(const protocol_type& protocol, - asio::error_code& ec) - { - return this->service.open(this->implementation, protocol, ec); - } - - /// Assigns an existing native acceptor to the acceptor. - /* - * This function opens the acceptor to hold an existing native acceptor. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param native_acceptor A native acceptor. - * - * @throws asio::system_error Thrown on failure. - */ - void assign(const protocol_type& protocol, const native_type& native_acceptor) - { - asio::error_code ec; - this->service.assign(this->implementation, protocol, native_acceptor, ec); - asio::detail::throw_error(ec); - } - - /// Assigns an existing native acceptor to the acceptor. - /* - * This function opens the acceptor to hold an existing native acceptor. - * - * @param protocol An object specifying which protocol is to be used. - * - * @param native_acceptor A native acceptor. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code assign(const protocol_type& protocol, - const native_type& native_acceptor, asio::error_code& ec) - { - return this->service.assign(this->implementation, - protocol, native_acceptor, ec); - } - - /// Determine whether the acceptor is open. - bool is_open() const - { - return this->service.is_open(this->implementation); - } - - /// Bind the acceptor to the given local endpoint. - /** - * This function binds the socket acceptor to the specified endpoint on the - * local machine. - * - * @param endpoint An endpoint on the local machine to which the socket - * acceptor will be bound. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * acceptor.open(asio::ip::tcp::v4()); - * acceptor.bind(asio::ip::tcp::endpoint(12345)); - * @endcode - */ - void bind(const endpoint_type& endpoint) - { - asio::error_code ec; - this->service.bind(this->implementation, endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Bind the acceptor to the given local endpoint. - /** - * This function binds the socket acceptor to the specified endpoint on the - * local machine. - * - * @param endpoint An endpoint on the local machine to which the socket - * acceptor will be bound. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * acceptor.open(asio::ip::tcp::v4()); - * asio::error_code ec; - * acceptor.bind(asio::ip::tcp::endpoint(12345), ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code bind(const endpoint_type& endpoint, - asio::error_code& ec) - { - return this->service.bind(this->implementation, endpoint, ec); - } - - /// Place the acceptor into the state where it will listen for new - /// connections. - /** - * This function puts the socket acceptor into the state where it may accept - * new connections. - * - * @param backlog The maximum length of the queue of pending connections. - * - * @throws asio::system_error Thrown on failure. - */ - void listen(int backlog = socket_base::max_connections) - { - asio::error_code ec; - this->service.listen(this->implementation, backlog, ec); - asio::detail::throw_error(ec); - } - - /// Place the acceptor into the state where it will listen for new - /// connections. - /** - * This function puts the socket acceptor into the state where it may accept - * new connections. - * - * @param backlog The maximum length of the queue of pending connections. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::error_code ec; - * acceptor.listen(asio::socket_base::max_connections, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code listen(int backlog, asio::error_code& ec) - { - return this->service.listen(this->implementation, backlog, ec); - } - - /// Close the acceptor. - /** - * This function is used to close the acceptor. Any asynchronous accept - * operations will be cancelled immediately. - * - * A subsequent call to open() is required before the acceptor can again be - * used to again perform socket accept operations. - * - * @throws asio::system_error Thrown on failure. - */ - void close() - { - asio::error_code ec; - this->service.close(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Close the acceptor. - /** - * This function is used to close the acceptor. Any asynchronous accept - * operations will be cancelled immediately. - * - * A subsequent call to open() is required before the acceptor can again be - * used to again perform socket accept operations. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::error_code ec; - * acceptor.close(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - asio::error_code close(asio::error_code& ec) - { - return this->service.close(this->implementation, ec); - } - - /// Get the native acceptor representation. - /** - * This function may be used to obtain the underlying representation of the - * acceptor. This is intended to allow access to native acceptor functionality - * that is not otherwise provided. - */ - native_type native() - { - return this->service.native(this->implementation); - } - - /// Cancel all asynchronous operations associated with the acceptor. - /** - * This function causes all outstanding asynchronous connect, send and receive - * operations to finish immediately, and the handlers for cancelled operations - * will be passed the asio::error::operation_aborted error. - * - * @throws asio::system_error Thrown on failure. - */ - void cancel() - { - asio::error_code ec; - this->service.cancel(this->implementation, ec); - asio::detail::throw_error(ec); - } - - /// Cancel all asynchronous operations associated with the acceptor. - /** - * This function causes all outstanding asynchronous connect, send and receive - * operations to finish immediately, and the handlers for cancelled operations - * will be passed the asio::error::operation_aborted error. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code cancel(asio::error_code& ec) - { - return this->service.cancel(this->implementation, ec); - } - - /// Set an option on the acceptor. - /** - * This function is used to set an option on the acceptor. - * - * @param option The new option value to be set on the acceptor. - * - * @throws asio::system_error Thrown on failure. - * - * @sa SettableSocketOption @n - * asio::socket_base::reuse_address - * asio::socket_base::enable_connection_aborted - * - * @par Example - * Setting the SOL_SOCKET/SO_REUSEADDR option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::acceptor::reuse_address option(true); - * acceptor.set_option(option); - * @endcode - */ - template - void set_option(const SettableSocketOption& option) - { - asio::error_code ec; - this->service.set_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Set an option on the acceptor. - /** - * This function is used to set an option on the acceptor. - * - * @param option The new option value to be set on the acceptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa SettableSocketOption @n - * asio::socket_base::reuse_address - * asio::socket_base::enable_connection_aborted - * - * @par Example - * Setting the SOL_SOCKET/SO_REUSEADDR option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::acceptor::reuse_address option(true); - * asio::error_code ec; - * acceptor.set_option(option, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - template - asio::error_code set_option(const SettableSocketOption& option, - asio::error_code& ec) - { - return this->service.set_option(this->implementation, option, ec); - } - - /// Get an option from the acceptor. - /** - * This function is used to get the current value of an option on the - * acceptor. - * - * @param option The option value to be obtained from the acceptor. - * - * @throws asio::system_error Thrown on failure. - * - * @sa GettableSocketOption @n - * asio::socket_base::reuse_address - * - * @par Example - * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::acceptor::reuse_address option; - * acceptor.get_option(option); - * bool is_set = option.get(); - * @endcode - */ - template - void get_option(GettableSocketOption& option) - { - asio::error_code ec; - this->service.get_option(this->implementation, option, ec); - asio::detail::throw_error(ec); - } - - /// Get an option from the acceptor. - /** - * This function is used to get the current value of an option on the - * acceptor. - * - * @param option The option value to be obtained from the acceptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @sa GettableSocketOption @n - * asio::socket_base::reuse_address - * - * @par Example - * Getting the value of the SOL_SOCKET/SO_REUSEADDR option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::acceptor::reuse_address option; - * asio::error_code ec; - * acceptor.get_option(option, ec); - * if (ec) - * { - * // An error occurred. - * } - * bool is_set = option.get(); - * @endcode - */ - template - asio::error_code get_option(GettableSocketOption& option, - asio::error_code& ec) - { - return this->service.get_option(this->implementation, option, ec); - } - - /// Get the local endpoint of the acceptor. - /** - * This function is used to obtain the locally bound endpoint of the acceptor. - * - * @returns An object that represents the local endpoint of the acceptor. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(); - * @endcode - */ - endpoint_type local_endpoint() const - { - asio::error_code ec; - endpoint_type ep = this->service.local_endpoint(this->implementation, ec); - asio::detail::throw_error(ec); - return ep; - } - - /// Get the local endpoint of the acceptor. - /** - * This function is used to obtain the locally bound endpoint of the acceptor. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns An object that represents the local endpoint of the acceptor. - * Returns a default-constructed endpoint object if an error occurred and the - * error handler did not throw an exception. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::error_code ec; - * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - endpoint_type local_endpoint(asio::error_code& ec) const - { - return this->service.local_endpoint(this->implementation, ec); - } - - /// Accept a new connection. - /** - * This function is used to accept a new connection from a peer into the - * given socket. The function call will block until a new connection has been - * accepted successfully or an error occurs. - * - * @param peer The socket into which the new connection will be accepted. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::socket socket(io_service); - * acceptor.accept(socket); - * @endcode - */ - template - void accept(basic_socket& peer) - { - asio::error_code ec; - this->service.accept(this->implementation, peer, 0, ec); - asio::detail::throw_error(ec); - } - - /// Accept a new connection. - /** - * This function is used to accept a new connection from a peer into the - * given socket. The function call will block until a new connection has been - * accepted successfully or an error occurs. - * - * @param peer The socket into which the new connection will be accepted. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::soocket socket(io_service); - * asio::error_code ec; - * acceptor.accept(socket, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - template - asio::error_code accept( - basic_socket& peer, - asio::error_code& ec) - { - return this->service.accept(this->implementation, peer, 0, ec); - } - - /// Start an asynchronous accept. - /** - * This function is used to asynchronously accept a new connection into a - * socket. The function call always returns immediately. - * - * @param peer The socket into which the new connection will be accepted. - * Ownership of the peer object is retained by the caller, which must - * guarantee that it is valid until the handler is called. - * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * @code - * void accept_handler(const asio::error_code& error) - * { - * if (!error) - * { - * // Accept succeeded. - * } - * } - * - * ... - * - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::socket socket(io_service); - * acceptor.async_accept(socket, accept_handler); - * @endcode - */ - template - void async_accept(basic_socket& peer, - AcceptHandler handler) - { - this->service.async_accept(this->implementation, peer, 0, handler); - } - - /// Accept a new connection and obtain the endpoint of the peer - /** - * This function is used to accept a new connection from a peer into the - * given socket, and additionally provide the endpoint of the remote peer. - * The function call will block until a new connection has been accepted - * successfully or an error occurs. - * - * @param peer The socket into which the new connection will be accepted. - * - * @param peer_endpoint An endpoint object which will receive the endpoint of - * the remote peer. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint; - * acceptor.accept(socket, endpoint); - * @endcode - */ - template - void accept(basic_socket& peer, - endpoint_type& peer_endpoint) - { - asio::error_code ec; - this->service.accept(this->implementation, peer, &peer_endpoint, ec); - asio::detail::throw_error(ec); - } - - /// Accept a new connection and obtain the endpoint of the peer - /** - * This function is used to accept a new connection from a peer into the - * given socket, and additionally provide the endpoint of the remote peer. - * The function call will block until a new connection has been accepted - * successfully or an error occurs. - * - * @param peer The socket into which the new connection will be accepted. - * - * @param peer_endpoint An endpoint object which will receive the endpoint of - * the remote peer. - * - * @param ec Set to indicate what error occurred, if any. - * - * @par Example - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::ip::tcp::socket socket(io_service); - * asio::ip::tcp::endpoint endpoint; - * asio::error_code ec; - * acceptor.accept(socket, endpoint, ec); - * if (ec) - * { - * // An error occurred. - * } - * @endcode - */ - template - asio::error_code accept( - basic_socket& peer, - endpoint_type& peer_endpoint, asio::error_code& ec) - { - return this->service.accept(this->implementation, peer, &peer_endpoint, ec); - } - - /// Start an asynchronous accept. - /** - * This function is used to asynchronously accept a new connection into a - * socket, and additionally obtain the endpoint of the remote peer. The - * function call always returns immediately. - * - * @param peer The socket into which the new connection will be accepted. - * Ownership of the peer object is retained by the caller, which must - * guarantee that it is valid until the handler is called. - * - * @param peer_endpoint An endpoint object into which the endpoint of the - * remote peer will be written. Ownership of the peer_endpoint object is - * retained by the caller, which must guarantee that it is valid until the - * handler is called. - * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ - template - void async_accept(basic_socket& peer, - endpoint_type& peer_endpoint, AcceptHandler handler) - { - this->service.async_accept(this->implementation, - peer, &peer_endpoint, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_socket_iostream.hpp b/libtorrent/include/libtorrent/asio/basic_socket_iostream.hpp deleted file mode 100644 index c48da7b62..000000000 --- a/libtorrent/include/libtorrent/asio/basic_socket_iostream.hpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// basic_socket_iostream.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_BASIC_SOCKET_IOSTREAM_HPP -#define ASIO_BASIC_SOCKET_IOSTREAM_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/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket_streambuf.hpp" -#include "asio/stream_socket_service.hpp" - -#if !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY) -#define ASIO_SOCKET_IOSTREAM_MAX_ARITY 5 -#endif // !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY) - -// A macro that should expand to: -// template -// explicit basic_socket_iostream(T1 x1, ..., Tn xn) -// : basic_iostream(&this->boost::base_from_member< -// basic_socket_streambuf >::member) -// { -// if (rdbuf()->connect(x1, ..., xn) == 0) -// this->setstate(std::ios_base::failbit); -// } -// This macro should only persist within this file. - -#define ASIO_PRIVATE_CTR_DEF(z, n, data) \ - template \ - explicit basic_socket_iostream(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ - : std::basic_iostream(&this->boost::base_from_member< \ - basic_socket_streambuf >::member) \ - { \ - if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \ - this->setstate(std::ios_base::failbit); \ - } \ - /**/ - -// A macro that should expand to: -// template -// void connect(T1 x1, ..., Tn xn) -// { -// if (rdbuf()->connect(x1, ..., xn) == 0) -// this->setstate(std::ios_base::failbit); -// } -// This macro should only persist within this file. - -#define ASIO_PRIVATE_CONNECT_DEF(z, n, data) \ - template \ - void connect(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ - { \ - if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \ - this->setstate(std::ios_base::failbit); \ - } \ - /**/ - -namespace asio { - -/// Iostream interface for a socket. -template > -class basic_socket_iostream - : public boost::base_from_member< - basic_socket_streambuf >, - public std::basic_iostream -{ -public: - /// Construct a basic_socket_iostream without establishing a connection. - basic_socket_iostream() - : std::basic_iostream(&this->boost::base_from_member< - basic_socket_streambuf >::member) - { - } - -#if defined(GENERATING_DOCUMENTATION) - /// Establish a connection to an endpoint corresponding to a resolver query. - /** - * This constructor automatically establishes a connection based on the - * supplied resolver query parameters. The arguments are used to construct - * a resolver query object. - */ - template - explicit basic_socket_iostream(T1 t1, ..., TN tn); -#else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(ASIO_SOCKET_IOSTREAM_MAX_ARITY), - ASIO_PRIVATE_CTR_DEF, _ ) -#endif - -#if defined(GENERATING_DOCUMENTATION) - /// Establish a connection to an endpoint corresponding to a resolver query. - /** - * This function automatically establishes a connection based on the supplied - * resolver query parameters. The arguments are used to construct a resolver - * query object. - */ - template - void connect(T1 t1, ..., TN tn); -#else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(ASIO_SOCKET_IOSTREAM_MAX_ARITY), - ASIO_PRIVATE_CONNECT_DEF, _ ) -#endif - - /// Close the connection. - void close() - { - if (rdbuf()->close() == 0) - this->setstate(std::ios_base::failbit); - } - - /// Return a pointer to the underlying streambuf. - basic_socket_streambuf* rdbuf() const - { - return const_cast*>( - &this->boost::base_from_member< - basic_socket_streambuf >::member); - } -}; - -} // namespace asio - -#undef ASIO_PRIVATE_CTR_DEF -#undef ASIO_PRIVATE_CONNECT_DEF - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_socket_streambuf.hpp b/libtorrent/include/libtorrent/asio/basic_socket_streambuf.hpp deleted file mode 100644 index 2c4189c52..000000000 --- a/libtorrent/include/libtorrent/asio/basic_socket_streambuf.hpp +++ /dev/null @@ -1,284 +0,0 @@ -// -// basic_socket_streambuf.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_BASIC_SOCKET_STREAMBUF_HPP -#define ASIO_BASIC_SOCKET_STREAMBUF_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/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/io_service.hpp" -#include "asio/stream_socket_service.hpp" -#include "asio/detail/throw_error.hpp" - -#if !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY) -#define ASIO_SOCKET_STREAMBUF_MAX_ARITY 5 -#endif // !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY) - -// A macro that should expand to: -// template -// basic_socket_streambuf* connect( -// T1 x1, ..., Tn xn) -// { -// init_buffers(); -// asio::error_code ec; -// this->basic_socket::close(ec); -// typedef typename Protocol::resolver_query resolver_query; -// resolver_query query(x1, ..., xn); -// resolve_and_connect(query, ec); -// return !ec ? this : 0; -// } -// This macro should only persist within this file. - -#define ASIO_PRIVATE_CONNECT_DEF( z, n, data ) \ - template \ - basic_socket_streambuf* connect( \ - BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \ - { \ - init_buffers(); \ - asio::error_code ec; \ - this->basic_socket::close(ec); \ - typedef typename Protocol::resolver_query resolver_query; \ - resolver_query query(BOOST_PP_ENUM_PARAMS(n, x)); \ - resolve_and_connect(query, ec); \ - return !ec ? this : 0; \ - } \ - /**/ - -namespace asio { - -/// Iostream streambuf for a socket. -template > -class basic_socket_streambuf - : public std::streambuf, - private boost::base_from_member, - public basic_socket -{ -public: - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct a basic_socket_streambuf without establishing a connection. - basic_socket_streambuf() - : basic_socket( - boost::base_from_member::member), - unbuffered_(false) - { - init_buffers(); - } - - /// Destructor flushes buffered data. - virtual ~basic_socket_streambuf() - { - if (pptr() != pbase()) - overflow(traits_type::eof()); - } - - /// Establish a connection. - /** - * This function establishes a connection to the specified endpoint. - * - * @return \c this if a connection was successfully established, a null - * pointer otherwise. - */ - basic_socket_streambuf* connect( - const endpoint_type& endpoint) - { - init_buffers(); - asio::error_code ec; - this->basic_socket::close(ec); - this->basic_socket::connect(endpoint, ec); - return !ec ? this : 0; - } - -#if defined(GENERATING_DOCUMENTATION) - /// Establish a connection. - /** - * This function automatically establishes a connection based on the supplied - * resolver query parameters. The arguments are used to construct a resolver - * query object. - * - * @return \c this if a connection was successfully established, a null - * pointer otherwise. - */ - template - basic_socket_streambuf* connect( - T1 t1, ..., TN tn); -#else - BOOST_PP_REPEAT_FROM_TO( - 1, BOOST_PP_INC(ASIO_SOCKET_STREAMBUF_MAX_ARITY), - ASIO_PRIVATE_CONNECT_DEF, _ ) -#endif - - /// Close the connection. - /** - * @return \c this if a connection was successfully established, a null - * pointer otherwise. - */ - basic_socket_streambuf* close() - { - asio::error_code ec; - sync(); - this->basic_socket::close(ec); - if (!ec) - init_buffers(); - return !ec ? this : 0; - } - -protected: - int_type underflow() - { - if (gptr() == egptr()) - { - asio::error_code ec; - std::size_t bytes_transferred = this->service.receive( - this->implementation, - asio::buffer(asio::buffer(get_buffer_) + putback_max), - 0, ec); - if (ec) - return traits_type::eof(); - setg(get_buffer_.begin(), get_buffer_.begin() + putback_max, - get_buffer_.begin() + putback_max + bytes_transferred); - return traits_type::to_int_type(*gptr()); - } - else - { - return traits_type::eof(); - } - } - - int_type overflow(int_type c) - { - if (unbuffered_) - { - if (traits_type::eq_int_type(c, traits_type::eof())) - { - // Nothing to do. - return traits_type::not_eof(c); - } - else - { - // Send the single character immediately. - asio::error_code ec; - char_type ch = traits_type::to_char_type(c); - this->service.send(this->implementation, - asio::buffer(&ch, sizeof(char_type)), 0, ec); - if (ec) - return traits_type::eof(); - return c; - } - } - else - { - // Send all data in the output buffer. - asio::const_buffer buffer = - asio::buffer(pbase(), pptr() - pbase()); - while (asio::buffer_size(buffer) > 0) - { - asio::error_code ec; - std::size_t bytes_transferred = this->service.send( - this->implementation, asio::buffer(buffer), - 0, ec); - if (ec) - return traits_type::eof(); - buffer = buffer + bytes_transferred; - } - setp(put_buffer_.begin(), put_buffer_.end()); - - // If the new character is eof then our work here is done. - if (traits_type::eq_int_type(c, traits_type::eof())) - return traits_type::not_eof(c); - - // Add the new character to the output buffer. - *pptr() = traits_type::to_char_type(c); - pbump(1); - return c; - } - } - - int sync() - { - return overflow(traits_type::eof()); - } - - std::streambuf* setbuf(char_type* s, std::streamsize n) - { - if (pptr() == pbase() && s == 0 && n == 0) - { - unbuffered_ = true; - setp(0, 0); - return this; - } - - return 0; - } - -private: - void init_buffers() - { - setg(get_buffer_.begin(), - get_buffer_.begin() + putback_max, - get_buffer_.begin() + putback_max); - if (unbuffered_) - setp(0, 0); - else - setp(put_buffer_.begin(), put_buffer_.end()); - } - - void resolve_and_connect(const typename Protocol::resolver_query& query, - asio::error_code& ec) - { - typedef typename Protocol::resolver resolver_type; - typedef typename Protocol::resolver_iterator iterator_type; - resolver_type resolver( - boost::base_from_member::member); - iterator_type i = resolver.resolve(query, ec); - if (!ec) - { - iterator_type end; - ec = asio::error::host_not_found; - while (ec && i != end) - { - this->basic_socket::close(); - this->basic_socket::connect(*i, ec); - ++i; - } - } - } - - enum { putback_max = 8 }; - enum { buffer_size = 512 }; - boost::array get_buffer_; - boost::array put_buffer_; - bool unbuffered_; -}; - -} // namespace asio - -#undef ASIO_PRIVATE_CONNECT_DEF - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_stream_socket.hpp b/libtorrent/include/libtorrent/asio/basic_stream_socket.hpp deleted file mode 100644 index 59889dc33..000000000 --- a/libtorrent/include/libtorrent/asio/basic_stream_socket.hpp +++ /dev/null @@ -1,718 +0,0 @@ -// -// basic_stream_socket.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_BASIC_STREAM_SOCKET_HPP -#define ASIO_BASIC_STREAM_SOCKET_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_socket.hpp" -#include "asio/error.hpp" -#include "asio/stream_socket_service.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -/// Provides stream-oriented socket functionality. -/** - * The basic_stream_socket class template provides asynchronous and blocking - * stream-oriented socket functionality. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template > -class basic_stream_socket - : public basic_socket -{ -public: - /// The native representation of a socket. - typedef typename StreamSocketService::native_type native_type; - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// Construct a basic_stream_socket without opening it. - /** - * This constructor creates a stream socket without opening it. The socket - * needs to be opened and then connected or accepted before data can be sent - * or received on it. - * - * @param io_service The io_service object that the stream socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - */ - explicit basic_stream_socket(asio::io_service& io_service) - : basic_socket(io_service) - { - } - - /// Construct and open a basic_stream_socket. - /** - * This constructor creates and opens a stream socket. The socket needs to be - * connected or accepted before data can be sent or received on it. - * - * @param io_service The io_service object that the stream socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @throws asio::system_error Thrown on failure. - */ - basic_stream_socket(asio::io_service& io_service, - const protocol_type& protocol) - : basic_socket(io_service, protocol) - { - } - - /// Construct a basic_stream_socket, opening it and binding it to the given - /// local endpoint. - /** - * This constructor creates a stream socket and automatically opens it bound - * to the specified endpoint on the local machine. The protocol used is the - * protocol associated with the given endpoint. - * - * @param io_service The io_service object that the stream socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param endpoint An endpoint on the local machine to which the stream - * socket will be bound. - * - * @throws asio::system_error Thrown on failure. - */ - basic_stream_socket(asio::io_service& io_service, - const endpoint_type& endpoint) - : basic_socket(io_service, endpoint) - { - } - - /// Construct a basic_stream_socket on an existing native socket. - /** - * This constructor creates a stream socket object to hold an existing native - * socket. - * - * @param io_service The io_service object that the stream socket will use to - * dispatch handlers for any asynchronous operations performed on the socket. - * - * @param protocol An object specifying protocol parameters to be used. - * - * @param native_socket The new underlying socket implementation. - * - * @throws asio::system_error Thrown on failure. - */ - basic_stream_socket(asio::io_service& io_service, - const protocol_type& protocol, const native_type& native_socket) - : basic_socket( - io_service, protocol, native_socket) - { - } - - /// Send some data on the socket. - /** - * This function is used to send data on the stream socket. The function - * call will block until one or more bytes of the data has been sent - * successfully, or an until error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref write function if you need to ensure that all data - * is written before the blocking operation completes. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.send(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.send( - this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on the socket. - /** - * This function is used to send data on the stream socket. The function - * call will block until one or more bytes of the data has been sent - * successfully, or an until error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @returns The number of bytes sent. - * - * @throws asio::system_error Thrown on failure. - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref write function if you need to ensure that all data - * is written before the blocking operation completes. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.send(asio::buffer(data, size), 0); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.send( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Send some data on the socket. - /** - * This function is used to send data on the stream socket. The function - * call will block until one or more bytes of the data has been sent - * successfully, or an until error occurs. - * - * @param buffers One or more data buffers to be sent on the socket. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes sent. Returns 0 if an error occurred. - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref write function if you need to ensure that all data - * is written before the blocking operation completes. - */ - template - std::size_t send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.send(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send data on the stream socket. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_send(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send(const ConstBufferSequence& buffers, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous send. - /** - * This function is used to asynchronously send data on the stream socket. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be sent on the socket. Although - * the buffers object may be copied as necessary, ownership of the underlying - * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. - * - * @param flags Flags specifying how the send call is to be made. - * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The send operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To send a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_send(asio::buffer(data, size), 0, handler); - * @endcode - * See the @ref buffer documentation for information on sending multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_send(const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, flags, handler); - } - - /// Receive some data on the socket. - /** - * This function is used to receive data on the stream socket. The function - * call will block until one or more bytes of data has been received - * successfully, or until an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.receive(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.receive(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on the socket. - /** - * This function is used to receive data on the stream socket. The function - * call will block until one or more bytes of data has been received - * successfully, or until an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @returns The number of bytes received. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.receive(asio::buffer(data, size), 0); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags) - { - asio::error_code ec; - std::size_t s = this->service.receive( - this->implementation, buffers, flags, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Receive some data on a connected socket. - /** - * This function is used to receive data on the stream socket. The function - * call will block until one or more bytes of data has been received - * successfully, or until an error occurs. - * - * @param buffers One or more buffers into which the data will be received. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes received. Returns 0 if an error occurred. - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - */ - template - std::size_t receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return this->service.receive(this->implementation, buffers, flags, ec); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive data from the stream - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref async_read function if you need to ensure - * that the requested amount of data is received before the asynchronous - * operation completes. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.async_receive(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive(const MutableBufferSequence& buffers, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, 0, handler); - } - - /// Start an asynchronous receive. - /** - * This function is used to asynchronously receive data from the stream - * socket. The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be received. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param flags Flags specifying how the receive call is to be made. - * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The receive operation may not receive all of the requested number of - * bytes. Consider using the @ref async_read function if you need to ensure - * that the requested amount of data is received before the asynchronous - * operation completes. - * - * @par Example - * To receive into a single data buffer use the @ref buffer function as - * follows: - * @code - * socket.async_receive(asio::buffer(data, size), 0, handler); - * @endcode - * See the @ref buffer documentation for information on receiving into - * multiple buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_receive(const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, flags, handler); - } - - /// Write some data to the socket. - /** - * This function is used to write data to the stream socket. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the socket. - * - * @returns The number of bytes written. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * socket.write_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.send(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Write some data to the socket. - /** - * This function is used to write data to the stream socket. The function call - * will block until one or more bytes of the data has been written - * successfully, or until an error occurs. - * - * @param buffers One or more data buffers to be written to the socket. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that - * all data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.send(this->implementation, buffers, 0, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write data to the stream socket. - * The function call always returns immediately. - * - * @param buffers One or more data buffers to be written to the socket. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The write operation may not transmit all of the data to the peer. - * Consider using the @ref async_write function if you need to ensure that all - * data is written before the asynchronous operation completes. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_write_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - this->service.async_send(this->implementation, buffers, 0, handler); - } - - /// Read some data from the socket. - /** - * This function is used to read data from the stream socket. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. An error code of - * asio::error::eof indicates that the connection was closed by the - * peer. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * socket.read_some(asio::buffer(data, size)); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = this->service.receive(this->implementation, buffers, 0, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Read some data from the socket. - /** - * This function is used to read data from the stream socket. The function - * call will block until one or more bytes of data has been read successfully, - * or until an error occurs. - * - * @param buffers One or more buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that - * the requested amount of data is read before the blocking operation - * completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return this->service.receive(this->implementation, buffers, 0, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read data from the stream socket. - * The function call always returns immediately. - * - * @param buffers One or more buffers into which the data will be read. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note The read operation may not read all of the requested number of bytes. - * Consider using the @ref async_read function if you need to ensure that the - * requested amount of data is read before the asynchronous operation - * completes. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * socket.async_read_some(asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - this->service.async_receive(this->implementation, buffers, 0, handler); - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_STREAM_SOCKET_HPP diff --git a/libtorrent/include/libtorrent/asio/basic_streambuf.hpp b/libtorrent/include/libtorrent/asio/basic_streambuf.hpp deleted file mode 100644 index 016445e0f..000000000 --- a/libtorrent/include/libtorrent/asio/basic_streambuf.hpp +++ /dev/null @@ -1,200 +0,0 @@ -// -// basic_streambuf.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_BASIC_STREAMBUF_HPP -#define ASIO_BASIC_STREAMBUF_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/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Automatically resizable buffer class based on std::streambuf. -template > -class basic_streambuf - : public std::streambuf, - private noncopyable -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The type used to represent the get area as a list of buffers. - typedef implementation_defined const_buffers_type; - - /// The type used to represent the put area as a list of buffers. - typedef implementation_defined mutable_buffers_type; -#else - typedef asio::const_buffers_1 const_buffers_type; - typedef asio::mutable_buffers_1 mutable_buffers_type; -#endif - - /// Construct a buffer with a specified maximum size. - explicit basic_streambuf( - std::size_t max_size = (std::numeric_limits::max)(), - const Allocator& allocator = Allocator()) - : max_size_(max_size), - buffer_(allocator) - { - std::size_t pend = (std::min)(max_size_, buffer_delta); - buffer_.resize((std::max)(pend, 1)); - setg(&buffer_[0], &buffer_[0], &buffer_[0]); - setp(&buffer_[0], &buffer_[0] + pend); - } - - /// Return the size of the get area in characters. - std::size_t size() const - { - return pptr() - gptr(); - } - - /// Return the maximum size of the buffer. - std::size_t max_size() const - { - return max_size_; - } - - /// Get a list of buffers that represents the get area. - const_buffers_type data() const - { - return asio::buffer(asio::const_buffer(gptr(), - (pptr() - gptr()) * sizeof(char_type))); - } - - /// Get a list of buffers that represents the put area, with the given size. - mutable_buffers_type prepare(std::size_t size) - { - reserve(size); - return asio::buffer(asio::mutable_buffer( - pptr(), size * sizeof(char_type))); - } - - /// Move the start of the put area by the specified number of characters. - void commit(std::size_t n) - { - if (pptr() + n > epptr()) - n = epptr() - pptr(); - pbump(static_cast(n)); - } - - /// Move the start of the get area by the specified number of characters. - void consume(std::size_t n) - { - while (n > 0) - { - sbumpc(); - --n; - } - } - -protected: - enum { buffer_delta = 128 }; - - int_type underflow() - { - if (gptr() < pptr()) - { - setg(&buffer_[0], gptr(), pptr()); - return traits_type::to_int_type(*gptr()); - } - else - { - return traits_type::eof(); - } - } - - int_type overflow(int_type c) - { - if (!traits_type::eq_int_type(c, traits_type::eof())) - { - if (pptr() == epptr()) - { - std::size_t buffer_size = pptr() - gptr(); - if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta) - { - reserve(max_size_ - buffer_size); - } - else - { - reserve(buffer_delta); - } - } - - *pptr() = traits_type::to_char_type(c); - pbump(1); - return c; - } - - return traits_type::not_eof(c); - } - - void reserve(std::size_t n) - { - // Get current stream positions as offsets. - std::size_t gnext = gptr() - &buffer_[0]; - std::size_t gend = egptr() - &buffer_[0]; - std::size_t pnext = pptr() - &buffer_[0]; - std::size_t pend = epptr() - &buffer_[0]; - - // Check if there is already enough space in the put area. - if (n <= pend - pnext) - { - return; - } - - // Shift existing contents of get area to start of buffer. - if (gnext > 0) - { - std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend); - gend -= gnext; - pnext -= gnext; - } - - // Ensure buffer is large enough to hold at least the specified size. - if (n > pend - pnext) - { - if (n <= max_size_ && pnext <= max_size_ - n) - { - buffer_.resize((std::max)(pnext + n, 1)); - } - else - { - throw std::length_error("asio::streambuf too long"); - } - } - - // Update stream positions. - setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend); - setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n); - } - -private: - std::size_t max_size_; - std::vector buffer_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BASIC_STREAMBUF_HPP diff --git a/libtorrent/include/libtorrent/asio/buffer.hpp b/libtorrent/include/libtorrent/asio/buffer.hpp deleted file mode 100644 index 69214fdb1..000000000 --- a/libtorrent/include/libtorrent/asio/buffer.hpp +++ /dev/null @@ -1,782 +0,0 @@ -// -// buffer.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_BUFFER_HPP -#define ASIO_BUFFER_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/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_MSVC) -# if defined(_HAS_ITERATOR_DEBUGGING) -# if !defined(ASIO_DISABLE_BUFFER_DEBUGGING) -# define ASIO_ENABLE_BUFFER_DEBUGGING -# endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING) -# endif // defined(_HAS_ITERATOR_DEBUGGING) -#endif // defined(BOOST_MSVC) - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) -# include "asio/detail/push_options.hpp" -# include -# include "asio/detail/pop_options.hpp" -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - -namespace asio { - -class mutable_buffer; -class const_buffer; - -namespace detail { -void* buffer_cast_helper(const mutable_buffer&); -const void* buffer_cast_helper(const const_buffer&); -std::size_t buffer_size_helper(const mutable_buffer&); -std::size_t buffer_size_helper(const const_buffer&); -} // namespace detail - -/// Holds a buffer that can be modified. -/** - * The mutable_buffer class provides a safe representation of a buffer that can - * be modified. It does not own the underlying data, and so is cheap to copy or - * assign. - */ -class mutable_buffer -{ -public: - /// Construct an empty buffer. - mutable_buffer() - : data_(0), - size_(0) - { - } - - /// Construct a buffer to represent a given memory range. - mutable_buffer(void* data, std::size_t size) - : data_(data), - size_(size) - { - } - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - mutable_buffer(void* data, std::size_t size, - boost::function debug_check) - : data_(data), - size_(size), - debug_check_(debug_check) - { - } - - const boost::function& get_debug_check() const - { - return debug_check_; - } -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - -private: - friend void* asio::detail::buffer_cast_helper( - const mutable_buffer& b); - friend std::size_t asio::detail::buffer_size_helper( - const mutable_buffer& b); - - void* data_; - std::size_t size_; - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - boost::function debug_check_; -#endif // ASIO_ENABLE_BUFFER_DEBUGGING -}; - -namespace detail { - -inline void* buffer_cast_helper(const mutable_buffer& b) -{ -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - if (b.debug_check_) - b.debug_check_(); -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - return b.data_; -} - -inline std::size_t buffer_size_helper(const mutable_buffer& b) -{ - return b.size_; -} - -} // namespace detail - -/// Cast a non-modifiable buffer to a specified pointer to POD type. -/** - * @relates mutable_buffer - */ -template -inline PointerToPodType buffer_cast(const mutable_buffer& b) -{ - return static_cast(detail::buffer_cast_helper(b)); -} - -/// Get the number of bytes in a non-modifiable buffer. -/** - * @relates mutable_buffer - */ -inline std::size_t buffer_size(const mutable_buffer& b) -{ - return detail::buffer_size_helper(b); -} - -/// Create a new modifiable buffer that is offset from the start of another. -/** - * @relates mutable_buffer - */ -inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start) -{ - if (start > buffer_size(b)) - return mutable_buffer(); - char* new_data = buffer_cast(b) + start; - std::size_t new_size = buffer_size(b) - start; - return mutable_buffer(new_data, new_size -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - ); -} - -/// Create a new modifiable buffer that is offset from the start of another. -/** - * @relates mutable_buffer - */ -inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b) -{ - if (start > buffer_size(b)) - return mutable_buffer(); - char* new_data = buffer_cast(b) + start; - std::size_t new_size = buffer_size(b) - start; - return mutable_buffer(new_data, new_size -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - ); -} - -/// Adapts a single modifiable buffer so that it meets the requirements of the -/// MutableBufferSequence concept. -class mutable_buffers_1 - : public mutable_buffer -{ -public: - /// The type for each element in the list of buffers. - typedef mutable_buffer value_type; - - /// A random-access iterator type that may be used to read elements. - typedef const mutable_buffer* const_iterator; - - /// Construct to represent a single modifiable buffer. - explicit mutable_buffers_1(const mutable_buffer& b) - : mutable_buffer(b) - { - } - - /// Get a random-access iterator to the first element. - const_iterator begin() const - { - return this; - } - - /// Get a random-access iterator for one past the last element. - const_iterator end() const - { - return begin() + 1; - } -}; - -/// Holds a buffer that cannot be modified. -/** - * The const_buffer class provides a safe representation of a buffer that cannot - * be modified. It does not own the underlying data, and so is cheap to copy or - * assign. - */ -class const_buffer -{ -public: - /// Construct an empty buffer. - const_buffer() - : data_(0), - size_(0) - { - } - - /// Construct a buffer to represent a given memory range. - const_buffer(const void* data, std::size_t size) - : data_(data), - size_(size) - { - } - - /// Construct a non-modifiable buffer from a modifiable one. - const_buffer(const mutable_buffer& b) - : data_(asio::detail::buffer_cast_helper(b)), - size_(asio::detail::buffer_size_helper(b)) -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , debug_check_(b.get_debug_check()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - { - } - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - const_buffer(const void* data, std::size_t size, - boost::function debug_check) - : data_(data), - size_(size), - debug_check_(debug_check) - { - } - - const boost::function& get_debug_check() const - { - return debug_check_; - } -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - -private: - friend const void* asio::detail::buffer_cast_helper( - const const_buffer& b); - friend std::size_t asio::detail::buffer_size_helper( - const const_buffer& b); - - const void* data_; - std::size_t size_; - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - boost::function debug_check_; -#endif // ASIO_ENABLE_BUFFER_DEBUGGING -}; - -namespace detail { - -inline const void* buffer_cast_helper(const const_buffer& b) -{ -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - if (b.debug_check_) - b.debug_check_(); -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - return b.data_; -} - -inline std::size_t buffer_size_helper(const const_buffer& b) -{ - return b.size_; -} - -} // namespace detail - -/// Cast a non-modifiable buffer to a specified pointer to POD type. -/** - * @relates const_buffer - */ -template -inline PointerToPodType buffer_cast(const const_buffer& b) -{ - return static_cast(detail::buffer_cast_helper(b)); -} - -/// Get the number of bytes in a non-modifiable buffer. -/** - * @relates const_buffer - */ -inline std::size_t buffer_size(const const_buffer& b) -{ - return detail::buffer_size_helper(b); -} - -/// Create a new non-modifiable buffer that is offset from the start of another. -/** - * @relates const_buffer - */ -inline const_buffer operator+(const const_buffer& b, std::size_t start) -{ - if (start > buffer_size(b)) - return const_buffer(); - const char* new_data = buffer_cast(b) + start; - std::size_t new_size = buffer_size(b) - start; - return const_buffer(new_data, new_size -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - ); -} - -/// Create a new non-modifiable buffer that is offset from the start of another. -/** - * @relates const_buffer - */ -inline const_buffer operator+(std::size_t start, const const_buffer& b) -{ - if (start > buffer_size(b)) - return const_buffer(); - const char* new_data = buffer_cast(b) + start; - std::size_t new_size = buffer_size(b) - start; - return const_buffer(new_data, new_size -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - ); -} - -/// Adapts a single non-modifiable buffer so that it meets the requirements of -/// the ConstBufferSequence concept. -class const_buffers_1 - : public const_buffer -{ -public: - /// The type for each element in the list of buffers. - typedef const_buffer value_type; - - /// A random-access iterator type that may be used to read elements. - typedef const const_buffer* const_iterator; - - /// Construct to represent a single non-modifiable buffer. - explicit const_buffers_1(const const_buffer& b) - : const_buffer(b) - { - } - - /// Get a random-access iterator to the first element. - const_iterator begin() const - { - return this; - } - - /// Get a random-access iterator for one past the last element. - const_iterator end() const - { - return begin() + 1; - } -}; - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) -namespace detail { - -template -class buffer_debug_check -{ -public: - buffer_debug_check(Iterator iter) - : iter_(iter) - { - } - - void operator()() - { - *iter_; - } - -private: - Iterator iter_; -}; - -} // namespace detail -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - -/** @defgroup buffer asio::buffer - * - * @brief The asio::buffer function is used to create a buffer object to - * represent raw memory, an array of POD elements, or a vector of POD elements. - * - * The simplest use case involves reading or writing a single buffer of a - * specified size: - * - * @code sock.write(asio::buffer(data, size)); @endcode - * - * In the above example, the return value of asio::buffer meets the - * requirements of the ConstBufferSequence concept so that it may be directly - * passed to the socket's write function. A buffer created for modifiable - * memory also meets the requirements of the MutableBufferSequence concept. - * - * An individual buffer may be created from a builtin array, std::vector or - * boost::array of POD elements. This helps prevent buffer overruns by - * automatically determining the size of the buffer: - * - * @code char d1[128]; - * size_t bytes_transferred = sock.read(asio::buffer(d1)); - * - * std::vector d2(128); - * bytes_transferred = sock.read(asio::buffer(d2)); - * - * boost::array d3; - * bytes_transferred = sock.read(asio::buffer(d3)); @endcode - * - * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple - * buffer objects may be assigned into a container that supports the - * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts: - * - * @code - * char d1[128]; - * std::vector d2(128); - * boost::array d3; - * - * boost::array bufs1 = { - * asio::buffer(d1), - * asio::buffer(d2), - * asio::buffer(d3) }; - * bytes_transferred = sock.read(bufs1); - * - * std::vector bufs2; - * bufs2.push_back(asio::buffer(d1)); - * bufs2.push_back(asio::buffer(d2)); - * bufs2.push_back(asio::buffer(d3)); - * bytes_transferred = sock.write(bufs2); @endcode - */ -/*@{*/ - -/// Create a new modifiable buffer from an existing buffer. -inline mutable_buffers_1 buffer(const mutable_buffer& b) -{ - return mutable_buffers_1(b); -} - -/// Create a new modifiable buffer from an existing buffer. -inline mutable_buffers_1 buffer(const mutable_buffer& b, - std::size_t max_size_in_bytes) -{ - return mutable_buffers_1( - mutable_buffer(buffer_cast(b), - buffer_size(b) < max_size_in_bytes - ? buffer_size(b) : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer from an existing buffer. -inline const_buffers_1 buffer(const const_buffer& b) -{ - return const_buffers_1(b); -} - -/// Create a new non-modifiable buffer from an existing buffer. -inline const_buffers_1 buffer(const const_buffer& b, - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(buffer_cast(b), - buffer_size(b) < max_size_in_bytes - ? buffer_size(b) : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , b.get_debug_check() -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new modifiable buffer that represents the given memory range. -inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes) -{ - return mutable_buffers_1(mutable_buffer(data, size_in_bytes)); -} - -/// Create a new non-modifiable buffer that represents the given memory range. -inline const_buffers_1 buffer(const void* data, - std::size_t size_in_bytes) -{ - return const_buffers_1(const_buffer(data, size_in_bytes)); -} - -/// Create a new modifiable buffer that represents the given POD array. -template -inline mutable_buffers_1 buffer(PodType (&data)[N]) -{ - return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType))); -} - -/// Create a new modifiable buffer that represents the given POD array. -template -inline mutable_buffers_1 buffer(PodType (&data)[N], - std::size_t max_size_in_bytes) -{ - return mutable_buffers_1( - mutable_buffer(data, - N * sizeof(PodType) < max_size_in_bytes - ? N * sizeof(PodType) : max_size_in_bytes)); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -template -inline const_buffers_1 buffer(const PodType (&data)[N]) -{ - return const_buffers_1(const_buffer(data, N * sizeof(PodType))); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -template -inline const_buffers_1 buffer(const PodType (&data)[N], - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data, - N * sizeof(PodType) < max_size_in_bytes - ? N * sizeof(PodType) : max_size_in_bytes)); -} - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) - -// Borland C++ thinks the overloads: -// -// unspecified buffer(boost::array& array ...); -// -// and -// -// unspecified buffer(boost::array& array ...); -// -// are ambiguous. This will be worked around by using a buffer_types traits -// class that contains typedefs for the appropriate buffer and container -// classes, based on whether PodType is const or non-const. - -namespace detail { - -template -struct buffer_types_base; - -template <> -struct buffer_types_base -{ - typedef mutable_buffer buffer_type; - typedef mutable_buffers_1 container_type; -}; - -template <> -struct buffer_types_base -{ - typedef const_buffer buffer_type; - typedef const_buffers_1 container_type; -}; - -template -struct buffer_types - : public buffer_types_base::value> -{ -}; - -} // namespace detail - -template -inline typename detail::buffer_types::container_type -buffer(boost::array& data) -{ - typedef typename asio::detail::buffer_types::buffer_type - buffer_type; - typedef typename asio::detail::buffer_types::container_type - container_type; - return container_type( - buffer_type(data.c_array(), data.size() * sizeof(PodType))); -} - -template -inline typename detail::buffer_types::container_type -buffer(boost::array& data, std::size_t max_size_in_bytes) -{ - typedef typename asio::detail::buffer_types::buffer_type - buffer_type; - typedef typename asio::detail::buffer_types::container_type - container_type; - return container_type( - buffer_type(data.c_array(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) - -/// Create a new modifiable buffer that represents the given POD array. -template -inline mutable_buffers_1 buffer(boost::array& data) -{ - return mutable_buffers_1( - mutable_buffer(data.c_array(), data.size() * sizeof(PodType))); -} - -/// Create a new modifiable buffer that represents the given POD array. -template -inline mutable_buffers_1 buffer(boost::array& data, - std::size_t max_size_in_bytes) -{ - return mutable_buffers_1( - mutable_buffer(data.c_array(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -template -inline const_buffers_1 buffer(boost::array& data) -{ - return const_buffers_1( - const_buffer(data.data(), data.size() * sizeof(PodType))); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -template -inline const_buffers_1 buffer(boost::array& data, - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) - -/// Create a new non-modifiable buffer that represents the given POD array. -template -inline const_buffers_1 buffer(const boost::array& data) -{ - return const_buffers_1( - const_buffer(data.data(), data.size() * sizeof(PodType))); -} - -/// Create a new non-modifiable buffer that represents the given POD array. -template -inline const_buffers_1 buffer(const boost::array& data, - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data.data(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -/// Create a new modifiable buffer that represents the given POD vector. -/** - * @note The buffer is invalidated by any vector operation that would also - * invalidate iterators. - */ -template -inline mutable_buffers_1 buffer(std::vector& data) -{ - return mutable_buffers_1( - mutable_buffer(&data[0], data.size() * sizeof(PodType) -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector::iterator - >(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new modifiable buffer that represents the given POD vector. -/** - * @note The buffer is invalidated by any vector operation that would also - * invalidate iterators. - */ -template -inline mutable_buffers_1 buffer(std::vector& data, - std::size_t max_size_in_bytes) -{ - return mutable_buffers_1( - mutable_buffer(&data[0], - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector::iterator - >(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer that represents the given POD vector. -/** - * @note The buffer is invalidated by any vector operation that would also - * invalidate iterators. - */ -template -inline const_buffers_1 buffer( - const std::vector& data) -{ - return const_buffers_1( - const_buffer(&data[0], data.size() * sizeof(PodType) -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector::const_iterator - >(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer that represents the given POD vector. -/** - * @note The buffer is invalidated by any vector operation that would also - * invalidate iterators. - */ -template -inline const_buffers_1 buffer( - const std::vector& data, std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(&data[0], - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check< - typename std::vector::const_iterator - >(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer that represents the given string. -/** - * @note The buffer is invalidated by any non-const operation called on the - * given string object. - */ -inline const_buffers_1 buffer(const std::string& data) -{ - return const_buffers_1(const_buffer(data.data(), data.size() -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/// Create a new non-modifiable buffer that represents the given string. -/** - * @note The buffer is invalidated by any non-const operation called on the - * given string object. - */ -inline const_buffers_1 buffer(const std::string& data, - std::size_t max_size_in_bytes) -{ - return const_buffers_1( - const_buffer(data.data(), - data.size() < max_size_in_bytes - ? data.size() : max_size_in_bytes -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - , detail::buffer_debug_check(data.begin()) -#endif // ASIO_ENABLE_BUFFER_DEBUGGING - )); -} - -/*@}*/ - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFER_HPP diff --git a/libtorrent/include/libtorrent/asio/buffered_read_stream.hpp b/libtorrent/include/libtorrent/asio/buffered_read_stream.hpp deleted file mode 100644 index 5cf5d688e..000000000 --- a/libtorrent/include/libtorrent/asio/buffered_read_stream.hpp +++ /dev/null @@ -1,407 +0,0 @@ -// -// buffered_read_stream.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_BUFFERED_READ_STREAM_HPP -#define ASIO_BUFFERED_READ_STREAM_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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_read_stream_fwd.hpp" -#include "asio/buffer.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/buffer_resize_guard.hpp" -#include "asio/detail/buffered_stream_storage.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Adds buffering to the read-related operations of a stream. -/** - * The buffered_read_stream class template can be used to add buffering to the - * synchronous and asynchronous read operations of a stream. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, Sync_Read_Stream, SyncWriteStream. - */ -template -class buffered_read_stream - : private noncopyable -{ -public: - /// The type of the next layer. - typedef typename boost::remove_reference::type next_layer_type; - - /// The type of the lowest layer. - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - -#if defined(GENERATING_DOCUMENTATION) - /// The default buffer size. - static const std::size_t default_buffer_size = implementation_defined; -#else - BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024); -#endif - - /// Construct, passing the specified argument to initialise the next layer. - template - explicit buffered_read_stream(Arg& a) - : next_layer_(a), - storage_(default_buffer_size) - { - } - - /// Construct, passing the specified argument to initialise the next layer. - template - buffered_read_stream(Arg& a, std::size_t buffer_size) - : next_layer_(a), - storage_(buffer_size) - { - } - - /// Get a reference to the next layer. - next_layer_type& next_layer() - { - return next_layer_; - } - - /// Get a reference to the lowest layer. - lowest_layer_type& lowest_layer() - { - return next_layer_.lowest_layer(); - } - - /// Get the io_service associated with the object. - asio::io_service& io_service() - { - return next_layer_.io_service(); - } - - /// Close the stream. - void close() - { - next_layer_.close(); - } - - /// Close the stream. - asio::error_code close(asio::error_code& ec) - { - return next_layer_.close(ec); - } - - /// Write the given data to the stream. Returns the number of bytes written. - /// Throws an exception on failure. - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - return next_layer_.write_some(buffers); - } - - /// Write the given data to the stream. Returns the number of bytes written, - /// or 0 if an error occurred. - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return next_layer_.write_some(buffers, ec); - } - - /// Start an asynchronous write. The data being written must be valid for the - /// lifetime of the asynchronous operation. - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - next_layer_.async_write_some(buffers, handler); - } - - /// Fill the buffer with some data. Returns the number of bytes placed in the - /// buffer as a result of the operation. Throws an exception on failure. - std::size_t fill() - { - detail::buffer_resize_guard - resize_guard(storage_); - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - storage_.resize(previous_size + next_layer_.read_some(buffer( - storage_.data() + previous_size, - storage_.size() - previous_size))); - resize_guard.commit(); - return storage_.size() - previous_size; - } - - /// Fill the buffer with some data. Returns the number of bytes placed in the - /// buffer as a result of the operation, or 0 if an error occurred. - std::size_t fill(asio::error_code& ec) - { - detail::buffer_resize_guard - resize_guard(storage_); - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - storage_.resize(previous_size + next_layer_.read_some(buffer( - storage_.data() + previous_size, - storage_.size() - previous_size), - ec)); - resize_guard.commit(); - return storage_.size() - previous_size; - } - - template - class fill_handler - { - public: - fill_handler(asio::io_service& io_service, - detail::buffered_stream_storage& storage, - std::size_t previous_size, ReadHandler handler) - : io_service_(io_service), - storage_(storage), - previous_size_(previous_size), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - storage_.resize(previous_size_ + bytes_transferred); - io_service_.dispatch(detail::bind_handler( - handler_, ec, bytes_transferred)); - } - - private: - asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - std::size_t previous_size_; - ReadHandler handler_; - }; - - /// Start an asynchronous fill. - template - void async_fill(ReadHandler handler) - { - std::size_t previous_size = storage_.size(); - storage_.resize(storage_.capacity()); - next_layer_.async_read_some( - buffer( - storage_.data() + previous_size, - storage_.size() - previous_size), - fill_handler(io_service(), - storage_, previous_size, handler)); - } - - /// Read some data from the stream. Returns the number of bytes read. Throws - /// an exception on failure. - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - if (storage_.empty()) - fill(); - return copy(buffers); - } - - /// Read some data from the stream. Returns the number of bytes read or 0 if - /// an error occurred. - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - ec = asio::error_code(); - if (storage_.empty() && !fill(ec)) - return 0; - return copy(buffers); - } - - template - class read_some_handler - { - public: - read_some_handler(asio::io_service& io_service, - detail::buffered_stream_storage& storage, - const MutableBufferSequence& buffers, ReadHandler handler) - : io_service_(io_service), - storage_(storage), - buffers_(buffers), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, std::size_t) - { - if (ec || storage_.empty()) - { - std::size_t length = 0; - io_service_.dispatch(detail::bind_handler(handler_, ec, length)); - } - else - { - using namespace std; // For memcpy. - - std::size_t bytes_avail = storage_.size(); - std::size_t bytes_copied = 0; - - typename MutableBufferSequence::const_iterator iter = buffers_.begin(); - typename MutableBufferSequence::const_iterator end = buffers_.end(); - for (; iter != end && bytes_avail > 0; ++iter) - { - std::size_t max_length = buffer_size(*iter); - std::size_t length = (max_length < bytes_avail) - ? max_length : bytes_avail; - memcpy(buffer_cast(*iter), - storage_.data() + bytes_copied, length); - bytes_copied += length; - bytes_avail -= length; - } - - storage_.consume(bytes_copied); - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied)); - } - } - - private: - asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - MutableBufferSequence buffers_; - ReadHandler handler_; - }; - - /// Start an asynchronous read. The buffer into which the data will be read - /// must be valid for the lifetime of the asynchronous operation. - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - if (storage_.empty()) - { - async_fill(read_some_handler( - io_service(), storage_, buffers, handler)); - } - else - { - std::size_t length = copy(buffers); - io_service().post(detail::bind_handler( - handler, asio::error_code(), length)); - } - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read. - /// Throws an exception on failure. - template - std::size_t peek(const MutableBufferSequence& buffers) - { - if (storage_.empty()) - fill(); - return peek_copy(buffers); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read, - /// or 0 if an error occurred. - template - std::size_t peek(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - ec = asio::error_code(); - if (storage_.empty() && !fill(ec)) - return 0; - return peek_copy(buffers); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail() - { - return storage_.size(); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail(asio::error_code& ec) - { - ec = asio::error_code(); - return storage_.size(); - } - -private: - /// Copy data out of the internal buffer to the specified target buffer. - /// Returns the number of bytes copied. - template - std::size_t copy(const MutableBufferSequence& buffers) - { - using namespace std; // For memcpy. - - std::size_t bytes_avail = storage_.size(); - std::size_t bytes_copied = 0; - - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - for (; iter != end && bytes_avail > 0; ++iter) - { - std::size_t max_length = buffer_size(*iter); - std::size_t length = (max_length < bytes_avail) - ? max_length : bytes_avail; - memcpy(buffer_cast(*iter), storage_.data() + bytes_copied, length); - bytes_copied += length; - bytes_avail -= length; - } - - storage_.consume(bytes_copied); - return bytes_copied; - } - - /// Copy data from the internal buffer to the specified target buffer, without - /// removing the data from the internal buffer. Returns the number of bytes - /// copied. - template - std::size_t peek_copy(const MutableBufferSequence& buffers) - { - using namespace std; // For memcpy. - - std::size_t bytes_avail = storage_.size(); - std::size_t bytes_copied = 0; - - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - for (; iter != end && bytes_avail > 0; ++iter) - { - std::size_t max_length = buffer_size(*iter); - std::size_t length = (max_length < bytes_avail) - ? max_length : bytes_avail; - memcpy(buffer_cast(*iter), storage_.data() + bytes_copied, length); - bytes_copied += length; - bytes_avail -= length; - } - - return bytes_copied; - } - - /// The next layer. - Stream next_layer_; - - // The data in the buffer. - detail::buffered_stream_storage storage_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_READ_STREAM_HPP diff --git a/libtorrent/include/libtorrent/asio/buffered_read_stream_fwd.hpp b/libtorrent/include/libtorrent/asio/buffered_read_stream_fwd.hpp deleted file mode 100644 index df4270366..000000000 --- a/libtorrent/include/libtorrent/asio/buffered_read_stream_fwd.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// buffered_read_stream_fwd.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_BUFFERED_READ_STREAM_FWD_HPP -#define ASIO_BUFFERED_READ_STREAM_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -template -class buffered_read_stream; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_READ_STREAM_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/buffered_stream.hpp b/libtorrent/include/libtorrent/asio/buffered_stream.hpp deleted file mode 100644 index b6901a6d4..000000000 --- a/libtorrent/include/libtorrent/asio/buffered_stream.hpp +++ /dev/null @@ -1,243 +0,0 @@ -// -// buffered_stream.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_BUFFERED_STREAM_HPP -#define ASIO_BUFFERED_STREAM_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_read_stream.hpp" -#include "asio/buffered_write_stream.hpp" -#include "asio/buffered_stream_fwd.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Adds buffering to the read- and write-related operations of a stream. -/** - * The buffered_stream class template can be used to add buffering to the - * synchronous and asynchronous read and write operations of a stream. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template -class buffered_stream - : private noncopyable -{ -public: - /// The type of the next layer. - typedef typename boost::remove_reference::type next_layer_type; - - /// The type of the lowest layer. - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - - /// Construct, passing the specified argument to initialise the next layer. - template - explicit buffered_stream(Arg& a) - : inner_stream_impl_(a), - stream_impl_(inner_stream_impl_) - { - } - - /// Construct, passing the specified argument to initialise the next layer. - template - explicit buffered_stream(Arg& a, std::size_t read_buffer_size, - std::size_t write_buffer_size) - : inner_stream_impl_(a, write_buffer_size), - stream_impl_(inner_stream_impl_, read_buffer_size) - { - } - - /// Get a reference to the next layer. - next_layer_type& next_layer() - { - return stream_impl_.next_layer().next_layer(); - } - - /// Get a reference to the lowest layer. - lowest_layer_type& lowest_layer() - { - return stream_impl_.lowest_layer(); - } - - /// Get the io_service associated with the object. - asio::io_service& io_service() - { - return stream_impl_.io_service(); - } - - /// Close the stream. - void close() - { - stream_impl_.close(); - } - - /// Close the stream. - asio::error_code close(asio::error_code& ec) - { - return stream_impl_.close(ec); - } - - /// Flush all data from the buffer to the next layer. Returns the number of - /// bytes written to the next layer on the last write operation. Throws an - /// exception on failure. - std::size_t flush() - { - return stream_impl_.next_layer().flush(); - } - - /// Flush all data from the buffer to the next layer. Returns the number of - /// bytes written to the next layer on the last write operation, or 0 if an - /// error occurred. - std::size_t flush(asio::error_code& ec) - { - return stream_impl_.next_layer().flush(ec); - } - - /// Start an asynchronous flush. - template - void async_flush(WriteHandler handler) - { - return stream_impl_.next_layer().async_flush(handler); - } - - /// Write the given data to the stream. Returns the number of bytes written. - /// Throws an exception on failure. - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - return stream_impl_.write_some(buffers); - } - - /// Write the given data to the stream. Returns the number of bytes written, - /// or 0 if an error occurred. - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return stream_impl_.write_some(buffers, ec); - } - - /// Start an asynchronous write. The data being written must be valid for the - /// lifetime of the asynchronous operation. - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - stream_impl_.async_write_some(buffers, handler); - } - - /// Fill the buffer with some data. Returns the number of bytes placed in the - /// buffer as a result of the operation. Throws an exception on failure. - std::size_t fill() - { - return stream_impl_.fill(); - } - - /// Fill the buffer with some data. Returns the number of bytes placed in the - /// buffer as a result of the operation, or 0 if an error occurred. - std::size_t fill(asio::error_code& ec) - { - return stream_impl_.fill(ec); - } - - /// Start an asynchronous fill. - template - void async_fill(ReadHandler handler) - { - stream_impl_.async_fill(handler); - } - - /// Read some data from the stream. Returns the number of bytes read. Throws - /// an exception on failure. - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - return stream_impl_.read_some(buffers); - } - - /// Read some data from the stream. Returns the number of bytes read or 0 if - /// an error occurred. - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return stream_impl_.read_some(buffers, ec); - } - - /// Start an asynchronous read. The buffer into which the data will be read - /// must be valid for the lifetime of the asynchronous operation. - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - stream_impl_.async_read_some(buffers, handler); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read. - /// Throws an exception on failure. - template - std::size_t peek(const MutableBufferSequence& buffers) - { - return stream_impl_.peek(buffers); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read, - /// or 0 if an error occurred. - template - std::size_t peek(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return stream_impl_.peek(buffers, ec); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail() - { - return stream_impl_.in_avail(); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail(asio::error_code& ec) - { - return stream_impl_.in_avail(ec); - } - -private: - // The buffered write stream. - typedef buffered_write_stream write_stream_type; - write_stream_type inner_stream_impl_; - - // The buffered read stream. - typedef buffered_read_stream read_stream_type; - read_stream_type stream_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_STREAM_HPP diff --git a/libtorrent/include/libtorrent/asio/buffered_stream_fwd.hpp b/libtorrent/include/libtorrent/asio/buffered_stream_fwd.hpp deleted file mode 100644 index 10d1c384e..000000000 --- a/libtorrent/include/libtorrent/asio/buffered_stream_fwd.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// buffered_stream_fwd.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_BUFFERED_STREAM_FWD_HPP -#define ASIO_BUFFERED_STREAM_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -template -class buffered_stream; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_STREAM_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/buffered_write_stream.hpp b/libtorrent/include/libtorrent/asio/buffered_write_stream.hpp deleted file mode 100644 index ffe3a2ee7..000000000 --- a/libtorrent/include/libtorrent/asio/buffered_write_stream.hpp +++ /dev/null @@ -1,361 +0,0 @@ -// -// buffered_write_stream.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_BUFFERED_WRITE_STREAM_HPP -#define ASIO_BUFFERED_WRITE_STREAM_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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_write_stream_fwd.hpp" -#include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/write.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/buffered_stream_storage.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { - -/// Adds buffering to the write-related operations of a stream. -/** - * The buffered_write_stream class template can be used to add buffering to the - * synchronous and asynchronous write operations of a stream. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template -class buffered_write_stream - : private noncopyable -{ -public: - /// The type of the next layer. - typedef typename boost::remove_reference::type next_layer_type; - - /// The type of the lowest layer. - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - -#if defined(GENERATING_DOCUMENTATION) - /// The default buffer size. - static const std::size_t default_buffer_size = implementation_defined; -#else - BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024); -#endif - - /// Construct, passing the specified argument to initialise the next layer. - template - explicit buffered_write_stream(Arg& a) - : next_layer_(a), - storage_(default_buffer_size) - { - } - - /// Construct, passing the specified argument to initialise the next layer. - template - buffered_write_stream(Arg& a, std::size_t buffer_size) - : next_layer_(a), - storage_(buffer_size) - { - } - - /// Get a reference to the next layer. - next_layer_type& next_layer() - { - return next_layer_; - } - - /// Get a reference to the lowest layer. - lowest_layer_type& lowest_layer() - { - return next_layer_.lowest_layer(); - } - - /// Get the io_service associated with the object. - asio::io_service& io_service() - { - return next_layer_.io_service(); - } - - /// Close the stream. - void close() - { - next_layer_.close(); - } - - /// Close the stream. - asio::error_code close(asio::error_code& ec) - { - return next_layer_.close(ec); - } - - /// Flush all data from the buffer to the next layer. Returns the number of - /// bytes written to the next layer on the last write operation. Throws an - /// exception on failure. - std::size_t flush() - { - std::size_t bytes_written = write(next_layer_, - buffer(storage_.data(), storage_.size())); - storage_.consume(bytes_written); - return bytes_written; - } - - /// Flush all data from the buffer to the next layer. Returns the number of - /// bytes written to the next layer on the last write operation, or 0 if an - /// error occurred. - std::size_t flush(asio::error_code& ec) - { - std::size_t bytes_written = write(next_layer_, - buffer(storage_.data(), storage_.size()), - transfer_all(), ec); - storage_.consume(bytes_written); - return bytes_written; - } - - template - class flush_handler - { - public: - flush_handler(asio::io_service& io_service, - detail::buffered_stream_storage& storage, WriteHandler handler) - : io_service_(io_service), - storage_(storage), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_written) - { - storage_.consume(bytes_written); - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_written)); - } - - private: - asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - WriteHandler handler_; - }; - - /// Start an asynchronous flush. - template - void async_flush(WriteHandler handler) - { - async_write(next_layer_, buffer(storage_.data(), storage_.size()), - flush_handler(io_service(), storage_, handler)); - } - - /// Write the given data to the stream. Returns the number of bytes written. - /// Throws an exception on failure. - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - if (storage_.size() == storage_.capacity()) - flush(); - return copy(buffers); - } - - /// Write the given data to the stream. Returns the number of bytes written, - /// or 0 if an error occurred and the error handler did not throw. - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - ec = asio::error_code(); - if (storage_.size() == storage_.capacity() && !flush(ec)) - return 0; - return copy(buffers); - } - - template - class write_some_handler - { - public: - write_some_handler(asio::io_service& io_service, - detail::buffered_stream_storage& storage, - const ConstBufferSequence& buffers, WriteHandler handler) - : io_service_(io_service), - storage_(storage), - buffers_(buffers), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, std::size_t) - { - if (ec) - { - std::size_t length = 0; - io_service_.dispatch(detail::bind_handler(handler_, ec, length)); - } - else - { - using namespace std; // For memcpy. - - std::size_t orig_size = storage_.size(); - std::size_t space_avail = storage_.capacity() - orig_size; - std::size_t bytes_copied = 0; - - typename ConstBufferSequence::const_iterator iter = buffers_.begin(); - typename ConstBufferSequence::const_iterator end = buffers_.end(); - for (; iter != end && space_avail > 0; ++iter) - { - std::size_t bytes_avail = buffer_size(*iter); - std::size_t length = (bytes_avail < space_avail) - ? bytes_avail : space_avail; - storage_.resize(orig_size + bytes_copied + length); - memcpy(storage_.data() + orig_size + bytes_copied, - buffer_cast(*iter), length); - bytes_copied += length; - space_avail -= length; - } - - io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied)); - } - } - - private: - asio::io_service& io_service_; - detail::buffered_stream_storage& storage_; - ConstBufferSequence buffers_; - WriteHandler handler_; - }; - - /// Start an asynchronous write. The data being written must be valid for the - /// lifetime of the asynchronous operation. - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - if (storage_.size() == storage_.capacity()) - { - async_flush(write_some_handler( - io_service(), storage_, buffers, handler)); - } - else - { - std::size_t bytes_copied = copy(buffers); - io_service().post(detail::bind_handler( - handler, asio::error_code(), bytes_copied)); - } - } - - /// Read some data from the stream. Returns the number of bytes read. Throws - /// an exception on failure. - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - return next_layer_.read_some(buffers); - } - - /// Read some data from the stream. Returns the number of bytes read or 0 if - /// an error occurred. - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return next_layer_.read_some(buffers, ec); - } - - /// Start an asynchronous read. The buffer into which the data will be read - /// must be valid for the lifetime of the asynchronous operation. - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - next_layer_.async_read_some(buffers, handler); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read. - /// Throws an exception on failure. - template - std::size_t peek(const MutableBufferSequence& buffers) - { - return next_layer_.peek(buffers); - } - - /// Peek at the incoming data on the stream. Returns the number of bytes read, - /// or 0 if an error occurred. - template - std::size_t peek(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return next_layer_.peek(buffers, ec); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail() - { - return next_layer_.in_avail(); - } - - /// Determine the amount of data that may be read without blocking. - std::size_t in_avail(asio::error_code& ec) - { - return next_layer_.in_avail(ec); - } - -private: - /// Copy data into the internal buffer from the specified source buffer. - /// Returns the number of bytes copied. - template - std::size_t copy(const ConstBufferSequence& buffers) - { - using namespace std; // For memcpy. - - std::size_t orig_size = storage_.size(); - std::size_t space_avail = storage_.capacity() - orig_size; - std::size_t bytes_copied = 0; - - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - for (; iter != end && space_avail > 0; ++iter) - { - std::size_t bytes_avail = buffer_size(*iter); - std::size_t length = (bytes_avail < space_avail) - ? bytes_avail : space_avail; - storage_.resize(orig_size + bytes_copied + length); - memcpy(storage_.data() + orig_size + bytes_copied, - buffer_cast(*iter), length); - bytes_copied += length; - space_avail -= length; - } - - return bytes_copied; - } - - /// The next layer. - Stream next_layer_; - - // The data in the buffer. - detail::buffered_stream_storage storage_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_WRITE_STREAM_HPP diff --git a/libtorrent/include/libtorrent/asio/buffered_write_stream_fwd.hpp b/libtorrent/include/libtorrent/asio/buffered_write_stream_fwd.hpp deleted file mode 100644 index 84cf36e3a..000000000 --- a/libtorrent/include/libtorrent/asio/buffered_write_stream_fwd.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// buffered_write_stream_fwd.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_BUFFERED_WRITE_STREAM_FWD_HPP -#define ASIO_BUFFERED_WRITE_STREAM_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -template -class buffered_write_stream; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_BUFFERED_WRITE_STREAM_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/completion_condition.hpp b/libtorrent/include/libtorrent/asio/completion_condition.hpp deleted file mode 100644 index 42696d599..000000000 --- a/libtorrent/include/libtorrent/asio/completion_condition.hpp +++ /dev/null @@ -1,101 +0,0 @@ -// -// completion_condition.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_COMPLETION_CONDITION_HPP -#define ASIO_COMPLETION_CONDITION_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { - -namespace detail { - -class transfer_all_t -{ -public: - typedef bool result_type; - - template - bool operator()(const Error& err, std::size_t) - { - return !!err; - } -}; - -class transfer_at_least_t -{ -public: - typedef bool result_type; - - explicit transfer_at_least_t(std::size_t minimum) - : minimum_(minimum) - { - } - - template - bool operator()(const Error& err, std::size_t bytes_transferred) - { - return !!err || bytes_transferred >= minimum_; - } - -private: - std::size_t minimum_; -}; - -} // namespace detail - -/** - * @defgroup completion_condition Completion Condition Function Objects - * - * Function objects used for determining when a read or write operation should - * complete. - */ -/*@{*/ - -/// Return a completion condition function object that indicates that a read or -/// write operation should continue until all of the data has been transferred, -/// or until an error occurs. -#if defined(GENERATING_DOCUMENTATION) -unspecified transfer_all(); -#else -inline detail::transfer_all_t transfer_all() -{ - return detail::transfer_all_t(); -} -#endif - -/// Return a completion condition function object that indicates that a read or -/// write operation should continue until a minimum number of bytes has been -/// transferred, or until an error occurs. -#if defined(GENERATING_DOCUMENTATION) -unspecified transfer_at_least(std::size_t minimum); -#else -inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum) -{ - return detail::transfer_at_least_t(minimum); -} -#endif - -/*@}*/ - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_COMPLETION_CONDITION_HPP diff --git a/libtorrent/include/libtorrent/asio/datagram_socket_service.hpp b/libtorrent/include/libtorrent/asio/datagram_socket_service.hpp deleted file mode 100644 index 1f858de61..000000000 --- a/libtorrent/include/libtorrent/asio/datagram_socket_service.hpp +++ /dev/null @@ -1,320 +0,0 @@ -// -// datagram_socket_service.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_DATAGRAM_SOCKET_SERVICE_HPP -#define ASIO_DATAGRAM_SOCKET_SERVICE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/reactive_socket_service.hpp" -#include "asio/detail/win_iocp_socket_service.hpp" - -namespace asio { - -/// Default service implementation for a datagram socket. -template -class datagram_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::reactive_socket_service< - Protocol, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_socket_service< - Protocol, detail::kqueue_reactor > service_impl_type; -#else - typedef detail::reactive_socket_service< - Protocol, detail::select_reactor > service_impl_type; -#endif - -public: - /// The type of a datagram socket. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef typename service_impl_type::native_type native_type; -#endif - - /// Construct a new datagram socket service for the specified io_service. - explicit datagram_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - datagram_socket_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new datagram socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a datagram socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - // Open a new datagram socket implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (protocol.type() == SOCK_DGRAM) - service_impl_.open(impl, protocol, ec); - else - ec = asio::error::invalid_argument; - return ec; - } - - /// Assign an existing native socket to a datagram socket. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - return service_impl_.assign(impl, protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a datagram socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native socket implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - // Bind the datagram socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.bind(impl, endpoint, ec); - } - - /// Connect the datagram socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - return service_impl_.connect(impl, peer_endpoint, ec); - } - - /// Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, ConnectHandler handler) - { - service_impl_.async_connect(impl, peer_endpoint, handler); - } - - /// Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const SettableSocketOption& option, asio::error_code& ec) - { - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template - asio::error_code get_option(const implementation_type& impl, - GettableSocketOption& option, asio::error_code& ec) const - { - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IoControlCommand& command, asio::error_code& ec) - { - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - return service_impl_.shutdown(impl, what, ec); - } - - /// Send the given data to the peer. - template - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template - void async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - service_impl_.async_send(impl, buffers, flags, handler); - } - - /// Send a datagram to the specified endpoint. - template - std::size_t send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.send_to(impl, buffers, destination, flags, ec); - } - - /// Start an asynchronous send. - template - void async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, WriteHandler handler) - { - service_impl_.async_send_to(impl, buffers, destination, flags, handler); - } - - /// Receive some data from the peer. - template - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Start an asynchronous receive. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - service_impl_.async_receive(impl, buffers, flags, handler); - } - - /// Receive a datagram with the endpoint of the sender. - template - std::size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.receive_from(impl, buffers, sender_endpoint, flags, - ec); - } - - /// Start an asynchronous receive that will get the endpoint of the sender. - template - void async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, ReadHandler handler) - { - service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags, - handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DATAGRAM_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/deadline_timer.hpp b/libtorrent/include/libtorrent/asio/deadline_timer.hpp deleted file mode 100644 index 2079c5d61..000000000 --- a/libtorrent/include/libtorrent/asio/deadline_timer.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// deadline_timer.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_DEADLINE_TIMER_HPP -#define ASIO_DEADLINE_TIMER_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/socket_types.hpp" // Must come before posix_time. - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_deadline_timer.hpp" - -namespace asio { - -/// Typedef for the typical usage of timer. -typedef basic_deadline_timer deadline_timer; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DEADLINE_TIMER_HPP diff --git a/libtorrent/include/libtorrent/asio/deadline_timer_service.hpp b/libtorrent/include/libtorrent/asio/deadline_timer_service.hpp deleted file mode 100644 index 17b97350b..000000000 --- a/libtorrent/include/libtorrent/asio/deadline_timer_service.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// deadline_timer_service.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_DEADLINE_TIMER_SERVICE_HPP -#define ASIO_DEADLINE_TIMER_SERVICE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/time_traits.hpp" -#include "asio/detail/deadline_timer_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" - -namespace asio { - -/// Default service implementation for a timer. -template > -class deadline_timer_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base< - deadline_timer_service > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The time traits type. - typedef TimeTraits traits_type; - - /// The time type. - typedef typename traits_type::time_type time_type; - - /// The duration type. - typedef typename traits_type::duration_type duration_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::deadline_timer_service< - traits_type, detail::select_reactor > service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::deadline_timer_service< - traits_type, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::deadline_timer_service< - traits_type, detail::kqueue_reactor > service_impl_type; -#else - typedef detail::deadline_timer_service< - traits_type, detail::select_reactor > service_impl_type; -#endif - -public: - /// The implementation type of the deadline timer. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new timer service for the specified io_service. - explicit deadline_timer_service(asio::io_service& io_service) - : asio::detail::service_base< - deadline_timer_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new timer implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a timer implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Cancel any asynchronous wait operations associated with the timer. - std::size_t cancel(implementation_type& impl, asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Get the expiry time for the timer as an absolute time. - time_type expires_at(const implementation_type& impl) const - { - return service_impl_.expires_at(impl); - } - - /// Set the expiry time for the timer as an absolute time. - std::size_t expires_at(implementation_type& impl, - const time_type& expiry_time, asio::error_code& ec) - { - return service_impl_.expires_at(impl, expiry_time, ec); - } - - /// Get the expiry time for the timer relative to now. - duration_type expires_from_now(const implementation_type& impl) const - { - return service_impl_.expires_from_now(impl); - } - - /// Set the expiry time for the timer relative to now. - std::size_t expires_from_now(implementation_type& impl, - const duration_type& expiry_time, asio::error_code& ec) - { - return service_impl_.expires_from_now(impl, expiry_time, ec); - } - - // Perform a blocking wait on the timer. - void wait(implementation_type& impl, asio::error_code& ec) - { - service_impl_.wait(impl, ec); - } - - // Start an asynchronous wait on the timer. - template - void async_wait(implementation_type& impl, WaitHandler handler) - { - service_impl_.async_wait(impl, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DEADLINE_TIMER_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/bind_handler.hpp b/libtorrent/include/libtorrent/asio/detail/bind_handler.hpp deleted file mode 100644 index 497bcfcc2..000000000 --- a/libtorrent/include/libtorrent/asio/detail/bind_handler.hpp +++ /dev/null @@ -1,349 +0,0 @@ -// -// bind_handler.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_BIND_HANDLER_HPP -#define ASIO_DETAIL_BIND_HANDLER_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" - -namespace asio { -namespace detail { - -template -class binder1 -{ -public: - binder1(const Handler& handler, const Arg1& arg1) - : handler_(handler), - arg1_(arg1) - { - } - - void operator()() - { - handler_(arg1_); - } - - void operator()() const - { - handler_(arg1_); - } - -//private: - Handler handler_; - Arg1 arg1_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder1* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder1* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder1* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder1 bind_handler(const Handler& handler, - const Arg1& arg1) -{ - return binder1(handler, arg1); -} - -template -class binder2 -{ -public: - binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2) - : handler_(handler), - arg1_(arg1), - arg2_(arg2) - { - } - - void operator()() - { - handler_(arg1_, arg2_); - } - - void operator()() const - { - handler_(arg1_, arg2_); - } - -//private: - Handler handler_; - Arg1 arg1_; - Arg2 arg2_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder2* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder2* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder2* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder2 bind_handler(const Handler& handler, - const Arg1& arg1, const Arg2& arg2) -{ - return binder2(handler, arg1, arg2); -} - -template -class binder3 -{ -public: - binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3) - : handler_(handler), - arg1_(arg1), - arg2_(arg2), - arg3_(arg3) - { - } - - void operator()() - { - handler_(arg1_, arg2_, arg3_); - } - - void operator()() const - { - handler_(arg1_, arg2_, arg3_); - } - -//private: - Handler handler_; - Arg1 arg1_; - Arg2 arg2_; - Arg3 arg3_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder3* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder3* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder3* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder3 bind_handler(const Handler& handler, - const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) -{ - return binder3(handler, arg1, arg2, arg3); -} - -template -class binder4 -{ -public: - binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4) - : handler_(handler), - arg1_(arg1), - arg2_(arg2), - arg3_(arg3), - arg4_(arg4) - { - } - - void operator()() - { - handler_(arg1_, arg2_, arg3_, arg4_); - } - - void operator()() const - { - handler_(arg1_, arg2_, arg3_, arg4_); - } - -//private: - Handler handler_; - Arg1 arg1_; - Arg2 arg2_; - Arg3 arg3_; - Arg4 arg4_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder4* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder4* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder4* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder4 bind_handler( - const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4) -{ - return binder4(handler, arg1, arg2, arg3, - arg4); -} - -template -class binder5 -{ -public: - binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) - : handler_(handler), - arg1_(arg1), - arg2_(arg2), - arg3_(arg3), - arg4_(arg4), - arg5_(arg5) - { - } - - void operator()() - { - handler_(arg1_, arg2_, arg3_, arg4_, arg5_); - } - - void operator()() const - { - handler_(arg1_, arg2_, arg3_, arg4_, arg5_); - } - -//private: - Handler handler_; - Arg1 arg1_; - Arg2 arg2_; - Arg3 arg3_; - Arg4 arg4_; - Arg5 arg5_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - binder5* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - binder5* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -inline void asio_handler_invoke(const Function& function, - binder5* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); -} - -template -inline binder5 bind_handler( - const Handler& handler, const Arg1& arg1, const Arg2& arg2, - const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) -{ - return binder5(handler, arg1, arg2, - arg3, arg4, arg5); -} - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_BIND_HANDLER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/buffer_resize_guard.hpp b/libtorrent/include/libtorrent/asio/detail/buffer_resize_guard.hpp deleted file mode 100644 index 0dcbe6956..000000000 --- a/libtorrent/include/libtorrent/asio/detail/buffer_resize_guard.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// buffer_resize_guard.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_BUFFER_RESIZE_GUARD_HPP -#define ASIO_DETAIL_BUFFER_RESIZE_GUARD_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -// Helper class to manage buffer resizing in an exception safe way. -template -class buffer_resize_guard -{ -public: - // Constructor. - buffer_resize_guard(Buffer& buffer) - : buffer_(buffer), - old_size_(buffer.size()) - { - } - - // Destructor rolls back the buffer resize unless commit was called. - ~buffer_resize_guard() - { - if (old_size_ - != std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()) - { - buffer_.resize(old_size_); - } - } - - // Commit the resize transaction. - void commit() - { - old_size_ - = std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION(); - } - -private: - // The buffer being managed. - Buffer& buffer_; - - // The size of the buffer at the time the guard was constructed. - size_t old_size_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/buffered_stream_storage.hpp b/libtorrent/include/libtorrent/asio/detail/buffered_stream_storage.hpp deleted file mode 100644 index 2a84d876d..000000000 --- a/libtorrent/include/libtorrent/asio/detail/buffered_stream_storage.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// buffered_stream_storage.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_BUFFERED_STREAM_STORAGE_HPP -#define ASIO_DETAIL_BUFFERED_STREAM_STORAGE_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/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -class buffered_stream_storage -{ -public: - // The type of the bytes stored in the buffer. - typedef unsigned char byte_type; - - // The type used for offsets into the buffer. - typedef std::size_t size_type; - - // Constructor. - explicit buffered_stream_storage(std::size_t capacity) - : begin_offset_(0), - end_offset_(0), - buffer_(capacity) - { - } - - /// Clear the buffer. - void clear() - { - begin_offset_ = 0; - end_offset_ = 0; - } - - // Return a pointer to the beginning of the unread data. - byte_type* data() - { - return &buffer_[0] + begin_offset_; - } - - // Return a pointer to the beginning of the unread data. - const byte_type* data() const - { - return &buffer_[0] + begin_offset_; - } - - // Is there no unread data in the buffer. - bool empty() const - { - return begin_offset_ == end_offset_; - } - - // Return the amount of unread data the is in the buffer. - size_type size() const - { - return end_offset_ - begin_offset_; - } - - // Resize the buffer to the specified length. - void resize(size_type length) - { - assert(length <= capacity()); - if (begin_offset_ + length <= capacity()) - { - end_offset_ = begin_offset_ + length; - } - else - { - using namespace std; // For memmove. - memmove(&buffer_[0], &buffer_[0] + begin_offset_, size()); - end_offset_ = length; - begin_offset_ = 0; - } - } - - // Return the maximum size for data in the buffer. - size_type capacity() const - { - return buffer_.size(); - } - - // Consume multiple bytes from the beginning of the buffer. - void consume(size_type count) - { - assert(begin_offset_ + count <= end_offset_); - begin_offset_ += count; - if (empty()) - clear(); - } - -private: - // The offset to the beginning of the unread data. - size_type begin_offset_; - - // The offset to the end of the unread data. - size_type end_offset_; - - // The data in the buffer. - std::vector buffer_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/call_stack.hpp b/libtorrent/include/libtorrent/asio/detail/call_stack.hpp deleted file mode 100644 index 1373f46c7..000000000 --- a/libtorrent/include/libtorrent/asio/detail/call_stack.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// call_stack.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_CALL_STACK_HPP -#define ASIO_DETAIL_CALL_STACK_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/noncopyable.hpp" -#include "asio/detail/tss_ptr.hpp" - -namespace asio { -namespace detail { - -// Helper class to determine whether or not the current thread is inside an -// invocation of io_service::run() for a specified io_service object. -template -class call_stack -{ -public: - // Context class automatically pushes an owner on to the stack. - class context - : private noncopyable - { - public: - // Push the owner on to the stack. - explicit context(Owner* d) - : owner_(d), - next_(call_stack::top_) - { - call_stack::top_ = this; - } - - // Pop the owner from the stack. - ~context() - { - call_stack::top_ = next_; - } - - private: - friend class call_stack; - - // The owner associated with the context. - Owner* owner_; - - // The next element in the stack. - context* next_; - }; - - friend class context; - - // Determine whether the specified owner is on the stack. - static bool contains(Owner* d) - { - context* elem = top_; - while (elem) - { - if (elem->owner_ == d) - return true; - elem = elem->next_; - } - return false; - } - -private: - // The top of the stack of calls for the current thread. - static tss_ptr top_; -}; - -template -tss_ptr::context> -call_stack::top_; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_CALL_STACK_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/const_buffers_iterator.hpp b/libtorrent/include/libtorrent/asio/detail/const_buffers_iterator.hpp deleted file mode 100644 index 964294865..000000000 --- a/libtorrent/include/libtorrent/asio/detail/const_buffers_iterator.hpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// const_buffers_iterator.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_CONST_BUFFERS_ITERATOR_HPP -#define ASIO_DETAIL_CONST_BUFFERS_ITERATOR_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" - -namespace asio { -namespace detail { - -// A proxy iterator for a sub-range in a list of buffers. -template -class const_buffers_iterator - : public boost::iterator_facade, - const char, boost::bidirectional_traversal_tag> -{ -public: - // Default constructor creates an iterator in an undefined state. - const_buffers_iterator() - { - } - - // Create an iterator for the specified position. - const_buffers_iterator(const ConstBufferSequence& buffers, - std::size_t position) - : begin_(buffers.begin()), - current_(buffers.begin()), - end_(buffers.end()), - position_(0) - { - while (current_ != end_) - { - current_buffer_ = *current_; - std::size_t buffer_size = asio::buffer_size(current_buffer_); - if (position - position_ < buffer_size) - { - current_buffer_position_ = position - position_; - position_ = position; - return; - } - position_ += buffer_size; - ++current_; - } - current_buffer_ = asio::const_buffer(); - current_buffer_position_ = 0; - } - - std::size_t position() const - { - return position_; - } - -private: - friend class boost::iterator_core_access; - - void increment() - { - if (current_ == end_) - return; - - ++position_; - - ++current_buffer_position_; - if (current_buffer_position_ != asio::buffer_size(current_buffer_)) - return; - - ++current_; - current_buffer_position_ = 0; - while (current_ != end_) - { - current_buffer_ = *current_; - if (asio::buffer_size(current_buffer_) > 0) - return; - ++current_; - } - } - - void decrement() - { - if (position_ == 0) - return; - - --position_; - - if (current_buffer_position_ != 0) - { - --current_buffer_position_; - return; - } - - typename ConstBufferSequence::const_iterator iter = current_; - while (iter != begin_) - { - --iter; - asio::const_buffer buffer = *iter; - std::size_t buffer_size = asio::buffer_size(buffer); - if (buffer_size > 0) - { - current_ = iter; - current_buffer_ = buffer; - current_buffer_position_ = buffer_size - 1; - return; - } - } - } - - bool equal(const const_buffers_iterator& other) const - { - return position_ == other.position_; - } - - const char& dereference() const - { - return asio::buffer_cast( - current_buffer_)[current_buffer_position_]; - } - - asio::const_buffer current_buffer_; - std::size_t current_buffer_position_; - typename ConstBufferSequence::const_iterator begin_; - typename ConstBufferSequence::const_iterator current_; - typename ConstBufferSequence::const_iterator end_; - std::size_t position_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/consuming_buffers.hpp b/libtorrent/include/libtorrent/asio/detail/consuming_buffers.hpp deleted file mode 100644 index cbe38a926..000000000 --- a/libtorrent/include/libtorrent/asio/detail/consuming_buffers.hpp +++ /dev/null @@ -1,205 +0,0 @@ -// -// consuming_buffers.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_CONSUMING_BUFFERS_HPP -#define ASIO_DETAIL_CONSUMING_BUFFERS_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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -// A proxy iterator for a sub-range in a list of buffers. -template -class consuming_buffers_iterator - : public boost::iterator_facade< - consuming_buffers_iterator, - const Buffer, boost::forward_traversal_tag> -{ -public: - // Default constructor creates an end iterator. - consuming_buffers_iterator() - : at_end_(true) - { - } - - // Construct with a buffer for the first entry and an iterator - // range for the remaining entries. - consuming_buffers_iterator(bool at_end, const Buffer& first, - Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder) - : at_end_(at_end), - first_(buffer(first, max_size)), - begin_remainder_(begin_remainder), - end_remainder_(end_remainder), - offset_(0) - { - } - -private: - friend class boost::iterator_core_access; - - enum { max_size = 65536 }; - - void increment() - { - if (!at_end_) - { - if (begin_remainder_ == end_remainder_ - || offset_ + buffer_size(first_) >= max_size) - { - at_end_ = true; - } - else - { - offset_ += buffer_size(first_); - first_ = buffer(*begin_remainder_++, max_size - offset_); - } - } - } - - bool equal(const consuming_buffers_iterator& other) const - { - if (at_end_ && other.at_end_) - return true; - return !at_end_ && !other.at_end_ - && buffer_cast(first_) - == buffer_cast(other.first_) - && buffer_size(first_) == buffer_size(other.first_) - && begin_remainder_ == other.begin_remainder_ - && end_remainder_ == other.end_remainder_; - } - - const Buffer& dereference() const - { - return first_; - } - - bool at_end_; - Buffer first_; - Buffer_Iterator begin_remainder_; - Buffer_Iterator end_remainder_; - std::size_t offset_; -}; - -// A proxy for a sub-range in a list of buffers. -template -class consuming_buffers -{ -public: - // The type for each element in the list of buffers. - typedef Buffer value_type; - - // A forward-only iterator type that may be used to read elements. - typedef consuming_buffers_iterator - const_iterator; - - // Construct to represent the entire list of buffers. - consuming_buffers(const Buffers& buffers) - : buffers_(buffers), - at_end_(buffers_.begin() == buffers_.end()), - first_(*buffers_.begin()), - begin_remainder_(buffers_.begin()) - { - if (!at_end_) - ++begin_remainder_; - } - - // Copy constructor. - consuming_buffers(const consuming_buffers& other) - : buffers_(other.buffers_), - at_end_(other.at_end_), - first_(other.first_), - begin_remainder_(buffers_.begin()) - { - typename Buffers::const_iterator first = other.buffers_.begin(); - typename Buffers::const_iterator second = other.begin_remainder_; - std::advance(begin_remainder_, std::distance(first, second)); - } - - // Assignment operator. - consuming_buffers& operator=(const consuming_buffers& other) - { - buffers_ = other.buffers_; - at_end_ = other.at_end_; - first_ = other.first_; - begin_remainder_ = buffers_.begin(); - typename Buffers::const_iterator first = other.buffers_.begin(); - typename Buffers::const_iterator second = other.begin_remainder_; - std::advance(begin_remainder_, std::distance(first, second)); - return *this; - } - - // Get a forward-only iterator to the first element. - const_iterator begin() const - { - return const_iterator(at_end_, first_, begin_remainder_, buffers_.end()); - } - - // Get a forward-only iterator for one past the last element. - const_iterator end() const - { - return const_iterator(); - } - - // Consume the specified number of bytes from the buffers. - void consume(std::size_t size) - { - // Remove buffers from the start until the specified size is reached. - while (size > 0 && !at_end_) - { - if (buffer_size(first_) <= size) - { - size -= buffer_size(first_); - if (begin_remainder_ == buffers_.end()) - at_end_ = true; - else - first_ = *begin_remainder_++; - } - else - { - first_ = first_ + size; - size = 0; - } - } - - // Remove any more empty buffers at the start. - while (!at_end_ && buffer_size(first_) == 0) - { - if (begin_remainder_ == buffers_.end()) - at_end_ = true; - else - first_ = *begin_remainder_++; - } - } - -private: - Buffers buffers_; - bool at_end_; - Buffer first_; - typename Buffers::const_iterator begin_remainder_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp b/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp deleted file mode 100644 index c22c5a7b7..000000000 --- a/libtorrent/include/libtorrent/asio/detail/deadline_timer_service.hpp +++ /dev/null @@ -1,199 +0,0 @@ -// -// deadline_timer_service.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_DEADLINE_TIMER_SERVICE_HPP -#define ASIO_DETAIL_DEADLINE_TIMER_SERVICE_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/timer_queue.hpp" - -namespace asio { -namespace detail { - -template -class deadline_timer_service - : public asio::detail::service_base< - deadline_timer_service > -{ -public: - // The time type. - typedef typename Time_Traits::time_type time_type; - - // The duration type. - typedef typename Time_Traits::duration_type duration_type; - - // The implementation type of the timer. This type is dependent on the - // underlying implementation of the timer service. - struct implementation_type - : private asio::detail::noncopyable - { - time_type expiry; - bool might_have_pending_waits; - }; - - // Constructor. - deadline_timer_service(asio::io_service& io_service) - : asio::detail::service_base< - deadline_timer_service >(io_service), - scheduler_(asio::use_service(io_service)) - { - scheduler_.add_timer_queue(timer_queue_); - } - - // Destructor. - ~deadline_timer_service() - { - scheduler_.remove_timer_queue(timer_queue_); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Construct a new timer implementation. - void construct(implementation_type& impl) - { - impl.expiry = time_type(); - impl.might_have_pending_waits = false; - } - - // Destroy a timer implementation. - void destroy(implementation_type& impl) - { - asio::error_code ec; - cancel(impl, ec); - } - - // Cancel any asynchronous wait operations associated with the timer. - std::size_t cancel(implementation_type& impl, asio::error_code& ec) - { - if (!impl.might_have_pending_waits) - { - ec = asio::error_code(); - return 0; - } - std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl); - impl.might_have_pending_waits = false; - ec = asio::error_code(); - return count; - } - - // Get the expiry time for the timer as an absolute time. - time_type expires_at(const implementation_type& impl) const - { - return impl.expiry; - } - - // Set the expiry time for the timer as an absolute time. - std::size_t expires_at(implementation_type& impl, - const time_type& expiry_time, asio::error_code& ec) - { - std::size_t count = cancel(impl, ec); - impl.expiry = expiry_time; - ec = asio::error_code(); - return count; - } - - // Get the expiry time for the timer relative to now. - duration_type expires_from_now(const implementation_type& impl) const - { - return Time_Traits::subtract(expires_at(impl), Time_Traits::now()); - } - - // Set the expiry time for the timer relative to now. - std::size_t expires_from_now(implementation_type& impl, - const duration_type& expiry_time, asio::error_code& ec) - { - return expires_at(impl, - Time_Traits::add(Time_Traits::now(), expiry_time), ec); - } - - // Perform a blocking wait on the timer. - void wait(implementation_type& impl, asio::error_code& ec) - { - time_type now = Time_Traits::now(); - while (Time_Traits::less_than(now, impl.expiry)) - { - boost::posix_time::time_duration timeout = - Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now)); - ::timeval tv; - tv.tv_sec = timeout.total_seconds(); - tv.tv_usec = timeout.total_microseconds() % 1000000; - asio::error_code ec; - socket_ops::select(0, 0, 0, 0, &tv, ec); - now = Time_Traits::now(); - } - ec = asio::error_code(); - } - - template - class wait_handler - { - public: - wait_handler(asio::io_service& io_service, Handler handler) - : io_service_(io_service), - work_(io_service), - handler_(handler) - { - } - - void operator()(const asio::error_code& result) - { - io_service_.post(detail::bind_handler(handler_, result)); - } - - private: - asio::io_service& io_service_; - asio::io_service::work work_; - Handler handler_; - }; - - // Start an asynchronous wait on the timer. - template - void async_wait(implementation_type& impl, Handler handler) - { - impl.might_have_pending_waits = true; - scheduler_.schedule_timer(timer_queue_, impl.expiry, - wait_handler(this->io_service(), handler), &impl); - } - -private: - // The queue of timers. - timer_queue timer_queue_; - - // The object that schedules and executes timers. Usually a reactor. - Timer_Scheduler& scheduler_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/epoll_reactor.hpp b/libtorrent/include/libtorrent/asio/detail/epoll_reactor.hpp deleted file mode 100644 index d55e86454..000000000 --- a/libtorrent/include/libtorrent/asio/detail/epoll_reactor.hpp +++ /dev/null @@ -1,613 +0,0 @@ -// -// epoll_reactor.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_EPOLL_REACTOR_HPP -#define ASIO_DETAIL_EPOLL_REACTOR_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/epoll_reactor_fwd.hpp" - -#if defined(ASIO_HAS_EPOLL) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/hash_map.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/thread.hpp" -#include "asio/detail/reactor_op_queue.hpp" -#include "asio/detail/select_interrupter.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/signal_blocker.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/timer_queue.hpp" - -namespace asio { -namespace detail { - -template -class epoll_reactor - : public asio::detail::service_base > -{ -public: - // Constructor. - epoll_reactor(asio::io_service& io_service) - : asio::detail::service_base >(io_service), - mutex_(), - epoll_fd_(do_epoll_create()), - wait_in_progress_(false), - interrupter_(), - read_op_queue_(), - write_op_queue_(), - except_op_queue_(), - pending_cancellations_(), - stop_thread_(false), - thread_(0), - shutdown_(false) - { - // Start the reactor's internal thread only if needed. - if (Own_Thread) - { - asio::detail::signal_blocker sb; - thread_ = new asio::detail::thread( - bind_handler(&epoll_reactor::call_run_thread, this)); - } - - // Add the interrupter's descriptor to epoll. - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLIN | EPOLLERR; - ev.data.fd = interrupter_.read_descriptor(); - epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev); - } - - // Destructor. - ~epoll_reactor() - { - shutdown_service(); - close(epoll_fd_); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - stop_thread_ = true; - lock.unlock(); - - if (thread_) - { - interrupter_.interrupt(); - thread_->join(); - delete thread_; - thread_ = 0; - } - - read_op_queue_.destroy_operations(); - write_op_queue_.destroy_operations(); - except_op_queue_.destroy_operations(); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->destroy_timers(); - timer_queues_.clear(); - } - - // Register a socket with the reactor. Returns 0 on success, system error - // code on failure. - int register_descriptor(socket_type descriptor) - { - // No need to lock according to epoll documentation. - - epoll_event ev = { 0, { 0 } }; - ev.events = 0; - ev.data.fd = descriptor; - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev); - if (result != 0) - return errno; - return 0; - } - - // Start a new read operation. The handler object will be invoked when the - // given descriptor is ready to be read, or an error has occurred. - template - void start_read_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (!read_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) - return; - - if (read_op_queue_.enqueue_operation(descriptor, handler)) - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLIN | EPOLLERR | EPOLLHUP; - if (write_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLOUT; - if (except_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLPRI; - ev.data.fd = descriptor; - - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0) - { - asio::error_code ec(errno, asio::native_ecat); - read_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready to be written, or an error has occurred. - template - void start_write_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (!write_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) - return; - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLIN; - if (except_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLPRI; - ev.data.fd = descriptor; - - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0) - { - asio::error_code ec(errno, asio::native_ecat); - write_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - - // Start a new exception operation. The handler object will be invoked when - // the given descriptor has exception information, or an error has occurred. - template - void start_except_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (except_op_queue_.enqueue_operation(descriptor, handler)) - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLPRI | EPOLLERR | EPOLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLIN; - if (write_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLOUT; - ev.data.fd = descriptor; - - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0) - { - asio::error_code ec(errno, asio::native_ecat); - except_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. - template - void start_write_and_except_ops(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - bool need_mod = write_op_queue_.enqueue_operation(descriptor, handler); - need_mod = except_op_queue_.enqueue_operation(descriptor, handler) - && need_mod; - if (need_mod) - { - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLOUT | EPOLLPRI | EPOLLERR | EPOLLHUP; - if (read_op_queue_.has_operation(descriptor)) - ev.events |= EPOLLIN; - ev.data.fd = descriptor; - - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0) - { - asio::error_code ec(errno, asio::native_ecat); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - - // Cancel all operations associated with the given descriptor. The - // handlers associated with the descriptor will be invoked with the - // operation_aborted error. - void cancel_ops(socket_type descriptor) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // epoll_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. - void close_descriptor(socket_type descriptor) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Remove the descriptor from epoll. - epoll_event ev = { 0, { 0 } }; - epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev); - - // Cancel any outstanding operations associated with the descriptor. - cancel_ops_unlocked(descriptor); - } - - // Add a new timer queue to the reactor. - template - void add_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - timer_queues_.push_back(&timer_queue); - } - - // Remove a timer queue from the reactor. - template - void remove_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - if (timer_queues_[i] == &timer_queue) - { - timer_queues_.erase(timer_queues_.begin() + i); - return; - } - } - } - - // Schedule a timer in the given timer queue to expire at the specified - // absolute time. The handler object will be invoked when the timer expires. - template - void schedule_timer(timer_queue& timer_queue, - const typename Time_Traits::time_type& time, Handler handler, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (timer_queue.enqueue_timer(time, handler, token)) - interrupter_.interrupt(); - } - - // Cancel the timer associated with the given token. Returns the number of - // handlers that have been posted or dispatched. - template - std::size_t cancel_timer(timer_queue& timer_queue, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - return timer_queue.cancel_timer(token); - } - -private: - friend class task_io_service >; - - // Run epoll once until interrupted or events are ready to be dispatched. - void run(bool block) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Dispatch any operation cancellations that were made while the select - // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); - - // Check if the thread is supposed to stop. - if (stop_thread_) - { - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - return; - } - - // We can return immediately if there's no work to do and the reactor is - // not supposed to block. - if (!block && read_op_queue_.empty() && write_op_queue_.empty() - && except_op_queue_.empty() && all_timer_queues_are_empty()) - { - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - return; - } - - int timeout = block ? get_timeout() : 0; - wait_in_progress_ = true; - lock.unlock(); - - // Block on the epoll descriptor. - epoll_event events[128]; - int num_events = epoll_wait(epoll_fd_, events, 128, timeout); - - lock.lock(); - wait_in_progress_ = false; - - // Block signals while dispatching operations. - asio::detail::signal_blocker sb; - - // Dispatch the waiting events. - for (int i = 0; i < num_events; ++i) - { - int descriptor = events[i].data.fd; - if (descriptor == interrupter_.read_descriptor()) - { - interrupter_.reset(); - } - else - { - if (events[i].events & (EPOLLERR | EPOLLHUP)) - { - asio::error_code ec; - except_op_queue_.dispatch_all_operations(descriptor, ec); - read_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - - epoll_event ev = { 0, { 0 } }; - ev.events = 0; - ev.data.fd = descriptor; - epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - } - else - { - bool more_reads = false; - bool more_writes = false; - bool more_except = false; - asio::error_code ec; - - // Exception operations must be processed first to ensure that any - // out-of-band data is read before normal data. - if (events[i].events & EPOLLPRI) - more_except = except_op_queue_.dispatch_operation(descriptor, ec); - else - more_except = except_op_queue_.has_operation(descriptor); - - if (events[i].events & EPOLLIN) - more_reads = read_op_queue_.dispatch_operation(descriptor, ec); - else - more_reads = read_op_queue_.has_operation(descriptor); - - if (events[i].events & EPOLLOUT) - more_writes = write_op_queue_.dispatch_operation(descriptor, ec); - else - more_writes = write_op_queue_.has_operation(descriptor); - - epoll_event ev = { 0, { 0 } }; - ev.events = EPOLLERR | EPOLLHUP; - if (more_reads) - ev.events |= EPOLLIN; - if (more_writes) - ev.events |= EPOLLOUT; - if (more_except) - ev.events |= EPOLLPRI; - ev.data.fd = descriptor; - int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev); - if (result != 0) - { - ec = asio::error_code(errno, asio::native_ecat); - read_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - except_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - } - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->dispatch_timers(); - - // Issue any pending cancellations. - for (size_t i = 0; i < pending_cancellations_.size(); ++i) - cancel_ops_unlocked(pending_cancellations_[i]); - pending_cancellations_.clear(); - - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - } - - // Run the select loop in the thread. - void run_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - while (!stop_thread_) - { - lock.unlock(); - run(true); - lock.lock(); - } - } - - // Entry point for the select loop thread. - static void call_run_thread(epoll_reactor* reactor) - { - reactor->run_thread(); - } - - // Interrupt the select loop. - void interrupt() - { - interrupter_.interrupt(); - } - - // The hint to pass to epoll_create to size its data structures. - enum { epoll_size = 20000 }; - - // Create the epoll file descriptor. Throws an exception if the descriptor - // cannot be created. - static int do_epoll_create() - { - int fd = epoll_create(epoll_size); - if (fd == -1) - { - boost::throw_exception(asio::system_error( - asio::error_code(errno, asio::native_ecat), - "epoll")); - } - return fd; - } - - // Check if all timer queues are empty. - bool all_timer_queues_are_empty() const - { - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - if (!timer_queues_[i]->empty()) - return false; - return true; - } - - // Get the timeout value for the epoll_wait call. The timeout value is - // returned as a number of milliseconds. A return value of -1 indicates - // that epoll_wait should block indefinitely. - int get_timeout() - { - if (all_timer_queues_are_empty()) - return -1; - - // By default we will wait no longer than 5 minutes. This will ensure that - // any changes to the system clock are detected after no longer than this. - boost::posix_time::time_duration minimum_wait_duration - = boost::posix_time::minutes(5); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - boost::posix_time::time_duration wait_duration - = timer_queues_[i]->wait_duration(); - if (wait_duration < minimum_wait_duration) - minimum_wait_duration = wait_duration; - } - - if (minimum_wait_duration > boost::posix_time::time_duration()) - { - return minimum_wait_duration.total_milliseconds(); - } - else - { - return 0; - } - } - - // Cancel all operations associated with the given descriptor. The do_cancel - // function of the handler objects will be invoked. This function does not - // acquire the epoll_reactor's mutex. - void cancel_ops_unlocked(socket_type descriptor) - { - bool interrupt = read_op_queue_.cancel_operations(descriptor); - interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; - interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The epoll file descriptor. - int epoll_fd_; - - // Whether the epoll_wait call is currently in progress - bool wait_in_progress_; - - // The interrupter is used to break a blocking epoll_wait call. - select_interrupter interrupter_; - - // The queue of read operations. - reactor_op_queue read_op_queue_; - - // The queue of write operations. - reactor_op_queue write_op_queue_; - - // The queue of except operations. - reactor_op_queue except_op_queue_; - - // The timer queues. - std::vector timer_queues_; - - // The descriptors that are pending cancellation. - std::vector pending_cancellations_; - - // Does the reactor loop thread need to stop. - bool stop_thread_; - - // The thread that is running the reactor loop. - asio::detail::thread* thread_; - - // Whether the service has been shut down. - bool shutdown_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_EPOLL) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_EPOLL_REACTOR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/epoll_reactor_fwd.hpp b/libtorrent/include/libtorrent/asio/detail/epoll_reactor_fwd.hpp deleted file mode 100644 index 87fad6325..000000000 --- a/libtorrent/include/libtorrent/asio/detail/epoll_reactor_fwd.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// epoll_reactor_fwd.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_EPOLL_REACTOR_FWD_HPP -#define ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#if !defined(ASIO_DISABLE_EPOLL) -#if defined(__linux__) // This service is only supported on Linux. - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) // Only kernels >= 2.5.45. - -// Define this to indicate that epoll is supported on the target platform. -#define ASIO_HAS_EPOLL 1 - -namespace asio { -namespace detail { - -template -class epoll_reactor; - -} // namespace detail -} // namespace asio - -#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) -#endif // defined(__linux__) -#endif // !defined(ASIO_DISABLE_EPOLL) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/event.hpp b/libtorrent/include/libtorrent/asio/detail/event.hpp deleted file mode 100644 index 766f51716..000000000 --- a/libtorrent/include/libtorrent/asio/detail/event.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// event.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_EVENT_HPP -#define ASIO_DETAIL_EVENT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_event.hpp" -#elif defined(BOOST_WINDOWS) -# include "asio/detail/win_event.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_event.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -#if !defined(BOOST_HAS_THREADS) -typedef null_event event; -#elif defined(BOOST_WINDOWS) -typedef win_event event; -#elif defined(BOOST_HAS_PTHREADS) -typedef posix_event event; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_EVENT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/fd_set_adapter.hpp b/libtorrent/include/libtorrent/asio/detail/fd_set_adapter.hpp deleted file mode 100644 index 1d01dc5fb..000000000 --- a/libtorrent/include/libtorrent/asio/detail/fd_set_adapter.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// fd_set_adapter.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_FD_SET_ADAPTER_HPP -#define ASIO_DETAIL_FD_SET_ADAPTER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/posix_fd_set_adapter.hpp" -#include "asio/detail/win_fd_set_adapter.hpp" - -namespace asio { -namespace detail { - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef win_fd_set_adapter fd_set_adapter; -#else -typedef posix_fd_set_adapter fd_set_adapter; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/handler_alloc_helpers.hpp b/libtorrent/include/libtorrent/asio/detail/handler_alloc_helpers.hpp deleted file mode 100644 index 68e7cb15d..000000000 --- a/libtorrent/include/libtorrent/asio/detail/handler_alloc_helpers.hpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// handler_alloc_helpers.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_ALLOC_HELPERS_HPP -#define ASIO_DETAIL_HANDLER_ALLOC_HELPERS_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/handler_alloc_hook.hpp" -#include "asio/detail/noncopyable.hpp" - -// Calls to asio_handler_allocate and asio_handler_deallocate must be made from -// a namespace that does not contain any overloads of these functions. The -// asio_handler_alloc_helpers namespace is defined here for that purpose. -namespace asio_handler_alloc_helpers { - -template -inline void* allocate(std::size_t s, Handler* h) -{ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - return ::operator new(s); -#else - using namespace asio; - return asio_handler_allocate(s, h); -#endif -} - -template -inline void deallocate(void* p, std::size_t s, Handler* h) -{ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - ::operator delete(p); -#else - using namespace asio; - asio_handler_deallocate(p, s, h); -#endif -} - -} // namespace asio_handler_alloc_helpers - -namespace asio { -namespace detail { - -// Traits for handler allocation. -template -struct handler_alloc_traits -{ - typedef Handler handler_type; - typedef Object value_type; - typedef Object* pointer_type; - BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object)); -}; - -template -class handler_ptr; - -// Helper class to provide RAII on uninitialised handler memory. -template -class raw_handler_ptr - : private noncopyable -{ -public: - typedef typename Alloc_Traits::handler_type handler_type; - typedef typename Alloc_Traits::value_type value_type; - typedef typename Alloc_Traits::pointer_type pointer_type; - BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size); - - // Constructor allocates the memory. - raw_handler_ptr(handler_type& handler) - : handler_(handler), - pointer_(static_cast( - asio_handler_alloc_helpers::allocate(value_size, &handler_))) - { - } - - // Destructor automatically deallocates memory, unless it has been stolen by - // a handler_ptr object. - ~raw_handler_ptr() - { - if (pointer_) - asio_handler_alloc_helpers::deallocate( - pointer_, value_size, &handler_); - } - -private: - friend class handler_ptr; - handler_type& handler_; - pointer_type pointer_; -}; - -// Helper class to provide RAII on uninitialised handler memory. -template -class handler_ptr - : private noncopyable -{ -public: - typedef typename Alloc_Traits::handler_type handler_type; - typedef typename Alloc_Traits::value_type value_type; - typedef typename Alloc_Traits::pointer_type pointer_type; - BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size); - typedef raw_handler_ptr raw_ptr_type; - - // Take ownership of existing memory. - handler_ptr(handler_type& handler, pointer_type pointer) - : handler_(handler), - pointer_(pointer) - { - } - - // Construct object in raw memory and take ownership if construction succeeds. - handler_ptr(raw_ptr_type& raw_ptr) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, - Arg5& a5) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, - Arg5& a5, Arg6& a6) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, - Arg5& a5, Arg6& a6, Arg7& a7) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6, a7)) - { - raw_ptr.pointer_ = 0; - } - - // Construct object in raw memory and take ownership if construction succeeds. - template - handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4, - Arg5& a5, Arg6& a6, Arg7& a7, Arg8& a8) - : handler_(raw_ptr.handler_), - pointer_(new (raw_ptr.pointer_) value_type( - a1, a2, a3, a4, a5, a6, a7, a8)) - { - raw_ptr.pointer_ = 0; - } - - // Destructor automatically deallocates memory, unless it has been released. - ~handler_ptr() - { - reset(); - } - - // Get the memory. - pointer_type get() const - { - return pointer_; - } - - // Release ownership of the memory. - pointer_type release() - { - pointer_type tmp = pointer_; - pointer_ = 0; - return tmp; - } - - // Explicitly destroy and deallocate the memory. - void reset() - { - if (pointer_) - { - pointer_->value_type::~value_type(); - asio_handler_alloc_helpers::deallocate( - pointer_, value_size, &handler_); - pointer_ = 0; - } - } - -private: - handler_type& handler_; - pointer_type pointer_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/handler_invoke_helpers.hpp b/libtorrent/include/libtorrent/asio/detail/handler_invoke_helpers.hpp deleted file mode 100644 index b260c426c..000000000 --- a/libtorrent/include/libtorrent/asio/detail/handler_invoke_helpers.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// -// handler_invoke_helpers.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_INVOKE_HELPERS_HPP -#define ASIO_DETAIL_HANDLER_INVOKE_HELPERS_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/handler_invoke_hook.hpp" - -// Calls to asio_handler_invoke must be made from a namespace that does not -// contain overloads of this function. The asio_handler_invoke_helpers -// namespace is defined here for that purpose. -namespace asio_handler_invoke_helpers { - -template -inline void invoke(const Function& function, Context* context) -{ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - Function tmp(function); - tmp(); -#else - using namespace asio; - asio_handler_invoke(function, context); -#endif -} - -} // namespace asio_handler_invoke_helpers - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/hash_map.hpp b/libtorrent/include/libtorrent/asio/detail/hash_map.hpp deleted file mode 100644 index 05cebdf58..000000000 --- a/libtorrent/include/libtorrent/asio/detail/hash_map.hpp +++ /dev/null @@ -1,209 +0,0 @@ -// -// hash_map.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_HASH_MAP_HPP -#define ASIO_DETAIL_HASH_MAP_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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -template -inline std::size_t calculate_hash_value(const T& t) -{ - return boost::hash_value(t); -} - -#if defined(_WIN64) -inline std::size_t calculate_hash_value(SOCKET s) -{ - return static_cast(s); -} -#endif // defined(_WIN64) - -template -class hash_map - : private noncopyable -{ -public: - // The type of a value in the map. - typedef std::pair value_type; - - // The type of a non-const iterator over the hash map. - typedef typename std::list::iterator iterator; - - // The type of a const iterator over the hash map. - typedef typename std::list::const_iterator const_iterator; - - // Constructor. - hash_map() - { - // Initialise all buckets to empty. - for (size_t i = 0; i < num_buckets; ++i) - buckets_[i].first = buckets_[i].last = values_.end(); - } - - // Get an iterator for the beginning of the map. - iterator begin() - { - return values_.begin(); - } - - // Get an iterator for the beginning of the map. - const_iterator begin() const - { - return values_.begin(); - } - - // Get an iterator for the end of the map. - iterator end() - { - return values_.end(); - } - - // Get an iterator for the end of the map. - const_iterator end() const - { - return values_.end(); - } - - // Check whether the map is empty. - bool empty() const - { - return values_.empty(); - } - - // Find an entry in the map. - iterator find(const K& k) - { - size_t bucket = calculate_hash_value(k) % num_buckets; - iterator it = buckets_[bucket].first; - if (it == values_.end()) - return values_.end(); - iterator end = buckets_[bucket].last; - ++end; - while (it != end) - { - if (it->first == k) - return it; - ++it; - } - return values_.end(); - } - - // Find an entry in the map. - const_iterator find(const K& k) const - { - size_t bucket = calculate_hash_value(k) % num_buckets; - const_iterator it = buckets_[bucket].first; - if (it == values_.end()) - return it; - const_iterator end = buckets_[bucket].last; - ++end; - while (it != end) - { - if (it->first == k) - return it; - ++it; - } - return values_.end(); - } - - // Insert a new entry into the map. - std::pair insert(const value_type& v) - { - size_t bucket = calculate_hash_value(v.first) % num_buckets; - iterator it = buckets_[bucket].first; - if (it == values_.end()) - { - buckets_[bucket].first = buckets_[bucket].last = - values_.insert(values_.end(), v); - return std::pair(buckets_[bucket].last, true); - } - iterator end = buckets_[bucket].last; - ++end; - while (it != end) - { - if (it->first == v.first) - return std::pair(it, false); - ++it; - } - buckets_[bucket].last = values_.insert(end, v); - return std::pair(buckets_[bucket].last, true); - } - - // Erase an entry from the map. - void erase(iterator it) - { - assert(it != values_.end()); - - size_t bucket = calculate_hash_value(it->first) % num_buckets; - bool is_first = (it == buckets_[bucket].first); - bool is_last = (it == buckets_[bucket].last); - if (is_first && is_last) - buckets_[bucket].first = buckets_[bucket].last = values_.end(); - else if (is_first) - ++buckets_[bucket].first; - else if (is_last) - --buckets_[bucket].last; - - values_.erase(it); - } - - // Remove all entries from the map. - void clear() - { - // Clear the values. - values_.clear(); - - // Initialise all buckets to empty. - for (size_t i = 0; i < num_buckets; ++i) - buckets_[i].first = buckets_[i].last = values_.end(); - } - -private: - // The list of all values in the hash map. - std::list values_; - - // The type for a bucket in the hash table. - struct bucket_type - { - iterator first; - iterator last; - }; - - // The number of buckets in the hash. - enum { num_buckets = 1021 }; - - // The buckets in the hash. - bucket_type buckets_[num_buckets]; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HASH_MAP_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/io_control.hpp b/libtorrent/include/libtorrent/asio/detail/io_control.hpp deleted file mode 100644 index feb02d9d5..000000000 --- a/libtorrent/include/libtorrent/asio/detail/io_control.hpp +++ /dev/null @@ -1,137 +0,0 @@ -// -// io_control.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_IO_CONTROL_HPP -#define ASIO_DETAIL_IO_CONTROL_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { -namespace io_control { - -// IO control command for non-blocking I/O. -class non_blocking_io -{ -public: - // Default constructor. - non_blocking_io() - : value_(0) - { - } - - // Construct with a specific command value. - non_blocking_io(bool value) - : value_(value ? 1 : 0) - { - } - - // Get the name of the IO control command. - int name() const - { - return FIONBIO; - } - - // Set the value of the I/O control command. - void set(bool value) - { - value_ = value ? 1 : 0; - } - - // Get the current value of the I/O control command. - bool get() const - { - return value_ != 0; - } - - // Get the address of the command data. - detail::ioctl_arg_type* data() - { - return &value_; - } - - // Get the address of the command data. - const detail::ioctl_arg_type* data() const - { - return &value_; - } - -private: - detail::ioctl_arg_type value_; -}; - -// I/O control command for getting number of bytes available. -class bytes_readable -{ -public: - // Default constructor. - bytes_readable() - : value_(0) - { - } - - // Construct with a specific command value. - bytes_readable(std::size_t value) - : value_(static_cast(value)) - { - } - - // Get the name of the IO control command. - int name() const - { - return FIONREAD; - } - - // Set the value of the I/O control command. - void set(std::size_t value) - { - value_ = static_cast(value); - } - - // Get the current value of the I/O control command. - std::size_t get() const - { - return static_cast(value_); - } - - // Get the address of the command data. - detail::ioctl_arg_type* data() - { - return &value_; - } - - // Get the address of the command data. - const detail::ioctl_arg_type* data() const - { - return &value_; - } - -private: - detail::ioctl_arg_type value_; -}; - -} // namespace io_control -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_IO_CONTROL_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/kqueue_reactor.hpp b/libtorrent/include/libtorrent/asio/detail/kqueue_reactor.hpp deleted file mode 100644 index 6628803af..000000000 --- a/libtorrent/include/libtorrent/asio/detail/kqueue_reactor.hpp +++ /dev/null @@ -1,620 +0,0 @@ -// -// kqueue_reactor.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2005 Stefan Arentz (stefan at soze 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_KQUEUE_REACTOR_HPP -#define ASIO_DETAIL_KQUEUE_REACTOR_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/kqueue_reactor_fwd.hpp" - -#if defined(ASIO_HAS_KQUEUE) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/thread.hpp" -#include "asio/detail/reactor_op_queue.hpp" -#include "asio/detail/select_interrupter.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/signal_blocker.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/timer_queue.hpp" - -// Older versions of Mac OS X may not define EV_OOBAND. -#if !defined(EV_OOBAND) -# define EV_OOBAND EV_FLAG1 -#endif // !defined(EV_OOBAND) - -namespace asio { -namespace detail { - -template -class kqueue_reactor - : public asio::detail::service_base > -{ -public: - // Constructor. - kqueue_reactor(asio::io_service& io_service) - : asio::detail::service_base< - kqueue_reactor >(io_service), - mutex_(), - kqueue_fd_(do_kqueue_create()), - wait_in_progress_(false), - interrupter_(), - read_op_queue_(), - write_op_queue_(), - except_op_queue_(), - pending_cancellations_(), - stop_thread_(false), - thread_(0), - shutdown_(false) - { - // Start the reactor's internal thread only if needed. - if (Own_Thread) - { - asio::detail::signal_blocker sb; - thread_ = new asio::detail::thread( - bind_handler(&kqueue_reactor::call_run_thread, this)); - } - - // Add the interrupter's descriptor to the kqueue. - struct kevent event; - EV_SET(&event, interrupter_.read_descriptor(), - EVFILT_READ, EV_ADD, 0, 0, 0); - ::kevent(kqueue_fd_, &event, 1, 0, 0, 0); - } - - // Destructor. - ~kqueue_reactor() - { - shutdown_service(); - close(kqueue_fd_); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - stop_thread_ = true; - lock.unlock(); - - if (thread_) - { - interrupter_.interrupt(); - thread_->join(); - delete thread_; - thread_ = 0; - } - - read_op_queue_.destroy_operations(); - write_op_queue_.destroy_operations(); - except_op_queue_.destroy_operations(); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->destroy_timers(); - timer_queues_.clear(); - } - - // Register a socket with the reactor. Returns 0 on success, system error - // code on failure. - int register_descriptor(socket_type) - { - return 0; - } - - // Start a new read operation. The handler object will be invoked when the - // given descriptor is ready to be read, or an error has occurred. - template - void start_read_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (!read_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) - return; - - if (read_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, asio::native_ecat); - read_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready to be written, or an error has occurred. - template - void start_write_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (!write_op_queue_.has_operation(descriptor)) - if (handler(asio::error_code())) - return; - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, asio::native_ecat); - write_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - - // Start a new exception operation. The handler object will be invoked when - // the given descriptor has exception information, or an error has occurred. - template - void start_except_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (except_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - if (read_op_queue_.has_operation(descriptor)) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, asio::native_ecat); - except_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. - template - void start_write_and_except_ops(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - if (shutdown_) - return; - - if (write_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, asio::native_ecat); - write_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - - if (except_op_queue_.enqueue_operation(descriptor, handler)) - { - struct kevent event; - if (read_op_queue_.has_operation(descriptor)) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code ec(errno, asio::native_ecat); - except_op_queue_.dispatch_all_operations(descriptor, ec); - write_op_queue_.dispatch_all_operations(descriptor, ec); - } - } - } - - // Cancel all operations associated with the given descriptor. The - // handlers associated with the descriptor will be invoked with the - // operation_aborted error. - void cancel_ops(socket_type descriptor) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // kqueue_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. - void close_descriptor(socket_type descriptor) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Remove the descriptor from kqueue. - struct kevent event[2]; - EV_SET(&event[0], descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); - EV_SET(&event[1], descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - ::kevent(kqueue_fd_, event, 2, 0, 0, 0); - - // Cancel any outstanding operations associated with the descriptor. - cancel_ops_unlocked(descriptor); - } - - // Add a new timer queue to the reactor. - template - void add_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - timer_queues_.push_back(&timer_queue); - } - - // Remove a timer queue from the reactor. - template - void remove_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - if (timer_queues_[i] == &timer_queue) - { - timer_queues_.erase(timer_queues_.begin() + i); - return; - } - } - } - - // Schedule a timer in the given timer queue to expire at the specified - // absolute time. The handler object will be invoked when the timer expires. - template - void schedule_timer(timer_queue& timer_queue, - const typename Time_Traits::time_type& time, Handler handler, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (timer_queue.enqueue_timer(time, handler, token)) - interrupter_.interrupt(); - } - - // Cancel the timer associated with the given token. Returns the number of - // handlers that have been posted or dispatched. - template - std::size_t cancel_timer(timer_queue& timer_queue, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - return timer_queue.cancel_timer(token); - } - -private: - friend class task_io_service >; - - // Run the kqueue loop. - void run(bool block) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Dispatch any operation cancellations that were made while the select - // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); - - // Check if the thread is supposed to stop. - if (stop_thread_) - { - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - return; - } - - // We can return immediately if there's no work to do and the reactor is - // not supposed to block. - if (!block && read_op_queue_.empty() && write_op_queue_.empty() - && except_op_queue_.empty() && all_timer_queues_are_empty()) - { - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - return; - } - - // Determine how long to block while waiting for events. - timespec timeout_buf = { 0, 0 }; - timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf; - - wait_in_progress_ = true; - lock.unlock(); - - // Block on the kqueue descriptor. - struct kevent events[128]; - int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout); - - lock.lock(); - wait_in_progress_ = false; - - // Block signals while dispatching operations. - asio::detail::signal_blocker sb; - - // Dispatch the waiting events. - for (int i = 0; i < num_events; ++i) - { - int descriptor = events[i].ident; - if (descriptor == interrupter_.read_descriptor()) - { - interrupter_.reset(); - } - else if (events[i].filter == EVFILT_READ) - { - // Dispatch operations associated with the descriptor. - bool more_reads = false; - bool more_except = false; - if (events[i].flags & EV_ERROR) - { - asio::error_code error( - events[i].data, asio::native_ecat); - except_op_queue_.dispatch_all_operations(descriptor, error); - read_op_queue_.dispatch_all_operations(descriptor, error); - } - else if (events[i].flags & EV_OOBAND) - { - asio::error_code error; - more_except = except_op_queue_.dispatch_operation(descriptor, error); - if (events[i].data > 0) - more_reads = read_op_queue_.dispatch_operation(descriptor, error); - else - more_reads = read_op_queue_.has_operation(descriptor); - } - else - { - asio::error_code error; - more_reads = read_op_queue_.dispatch_operation(descriptor, error); - more_except = except_op_queue_.has_operation(descriptor); - } - - // Update the descriptor in the kqueue. - struct kevent event; - if (more_reads) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0); - else if (more_except) - EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code error(errno, asio::native_ecat); - except_op_queue_.dispatch_all_operations(descriptor, error); - read_op_queue_.dispatch_all_operations(descriptor, error); - } - } - else if (events[i].filter == EVFILT_WRITE) - { - // Dispatch operations associated with the descriptor. - bool more_writes = false; - if (events[i].flags & EV_ERROR) - { - asio::error_code error( - events[i].data, asio::native_ecat); - write_op_queue_.dispatch_all_operations(descriptor, error); - } - else - { - asio::error_code error; - more_writes = write_op_queue_.dispatch_operation(descriptor, error); - } - - // Update the descriptor in the kqueue. - struct kevent event; - if (more_writes) - EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0); - else - EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0); - if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1) - { - asio::error_code error(errno, asio::native_ecat); - write_op_queue_.dispatch_all_operations(descriptor, error); - } - } - } - - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->dispatch_timers(); - - // Issue any pending cancellations. - for (std::size_t i = 0; i < pending_cancellations_.size(); ++i) - cancel_ops_unlocked(pending_cancellations_[i]); - pending_cancellations_.clear(); - - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - } - - // Run the select loop in the thread. - void run_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - while (!stop_thread_) - { - lock.unlock(); - run(true); - lock.lock(); - } - } - - // Entry point for the select loop thread. - static void call_run_thread(kqueue_reactor* reactor) - { - reactor->run_thread(); - } - - // Interrupt the select loop. - void interrupt() - { - interrupter_.interrupt(); - } - - // Create the kqueue file descriptor. Throws an exception if the descriptor - // cannot be created. - static int do_kqueue_create() - { - int fd = kqueue(); - if (fd == -1) - { - boost::throw_exception(asio::system_error( - asio::error_code(errno, asio::native_ecat), - "kqueue")); - } - return fd; - } - - // Check if all timer queues are empty. - bool all_timer_queues_are_empty() const - { - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - if (!timer_queues_[i]->empty()) - return false; - return true; - } - - // Get the timeout value for the kevent call. - timespec* get_timeout(timespec& ts) - { - if (all_timer_queues_are_empty()) - return 0; - - // By default we will wait no longer than 5 minutes. This will ensure that - // any changes to the system clock are detected after no longer than this. - boost::posix_time::time_duration minimum_wait_duration - = boost::posix_time::minutes(5); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - boost::posix_time::time_duration wait_duration - = timer_queues_[i]->wait_duration(); - if (wait_duration < minimum_wait_duration) - minimum_wait_duration = wait_duration; - } - - if (minimum_wait_duration > boost::posix_time::time_duration()) - { - ts.tv_sec = minimum_wait_duration.total_seconds(); - ts.tv_nsec = minimum_wait_duration.total_nanoseconds() % 1000000000; - } - else - { - ts.tv_sec = 0; - ts.tv_nsec = 0; - } - - return &ts; - } - - // Cancel all operations associated with the given descriptor. The do_cancel - // function of the handler objects will be invoked. This function does not - // acquire the kqueue_reactor's mutex. - void cancel_ops_unlocked(socket_type descriptor) - { - bool interrupt = read_op_queue_.cancel_operations(descriptor); - interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; - interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The kqueue file descriptor. - int kqueue_fd_; - - // Whether the kqueue wait call is currently in progress - bool wait_in_progress_; - - // The interrupter is used to break a blocking kevent call. - select_interrupter interrupter_; - - // The queue of read operations. - reactor_op_queue read_op_queue_; - - // The queue of write operations. - reactor_op_queue write_op_queue_; - - // The queue of except operations. - reactor_op_queue except_op_queue_; - - // The timer queues. - std::vector timer_queues_; - - // The descriptors that are pending cancellation. - std::vector pending_cancellations_; - - // Does the reactor loop thread need to stop. - bool stop_thread_; - - // The thread that is running the reactor loop. - asio::detail::thread* thread_; - - // Whether the service has been shut down. - bool shutdown_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_KQUEUE) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_KQUEUE_REACTOR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/kqueue_reactor_fwd.hpp b/libtorrent/include/libtorrent/asio/detail/kqueue_reactor_fwd.hpp deleted file mode 100644 index 5171f4215..000000000 --- a/libtorrent/include/libtorrent/asio/detail/kqueue_reactor_fwd.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// kqueue_reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2007 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// Copyright (c) 2005 Stefan Arentz (stefan at soze 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_KQUEUE_REACTOR_FWD_HPP -#define ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#if !defined(ASIO_DISABLE_KQUEUE) -#if defined(__MACH__) && defined(__APPLE__) - -// Define this to indicate that epoll is supported on the target platform. -#define ASIO_HAS_KQUEUE 1 - -namespace asio { -namespace detail { - -template -class kqueue_reactor; - -} // namespace detail -} // namespace asio - -#endif // defined(__MACH__) && defined(__APPLE__) -#endif // !defined(ASIO_DISABLE_KQUEUE) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/local_free_on_block_exit.hpp b/libtorrent/include/libtorrent/asio/detail/local_free_on_block_exit.hpp deleted file mode 100644 index 8e1f6088d..000000000 --- a/libtorrent/include/libtorrent/asio/detail/local_free_on_block_exit.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// local_free_on_block_exit.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_LOCAL_FREE_ON_BLOCK_EXIT_HPP -#define ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -class local_free_on_block_exit - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - explicit local_free_on_block_exit(void* p) - : p_(p) - { - } - - // Destructor restores the previous signal mask. - ~local_free_on_block_exit() - { - ::LocalFree(p_); - } - -private: - void* p_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/mutex.hpp b/libtorrent/include/libtorrent/asio/detail/mutex.hpp deleted file mode 100644 index 87d32ba3c..000000000 --- a/libtorrent/include/libtorrent/asio/detail/mutex.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// mutex.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_MUTEX_HPP -#define ASIO_DETAIL_MUTEX_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_mutex.hpp" -#elif defined(BOOST_WINDOWS) -# include "asio/detail/win_mutex.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_mutex.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -#if !defined(BOOST_HAS_THREADS) -typedef null_mutex mutex; -#elif defined(BOOST_WINDOWS) -typedef win_mutex mutex; -#elif defined(BOOST_HAS_PTHREADS) -typedef posix_mutex mutex; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_MUTEX_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/noncopyable.hpp b/libtorrent/include/libtorrent/asio/detail/noncopyable.hpp deleted file mode 100644 index 8e9d54683..000000000 --- a/libtorrent/include/libtorrent/asio/detail/noncopyable.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// -// noncopyable.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_NONCOPYABLE_HPP -#define ASIO_DETAIL_NONCOPYABLE_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -// Redefine the noncopyable class for Borland C++ since that compiler does not -// apply the empty base optimisation unless the base class contains a dummy -// char data member. -class noncopyable -{ -protected: - noncopyable() {} - ~noncopyable() {} -private: - noncopyable(const noncopyable&); - const noncopyable& operator=(const noncopyable&); - char dummy_; -}; -#else -using boost::noncopyable; -#endif - -} // namespace detail - -using asio::detail::noncopyable; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NONCOPYABLE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/null_event.hpp b/libtorrent/include/libtorrent/asio/detail/null_event.hpp deleted file mode 100644 index df522ce0f..000000000 --- a/libtorrent/include/libtorrent/asio/detail/null_event.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// null_event.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_NULL_EVENT_HPP -#define ASIO_DETAIL_NULL_EVENT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class null_event - : private noncopyable -{ -public: - // Constructor. - null_event() - { - } - - // Destructor. - ~null_event() - { - } - - // Signal the event. - void signal() - { - } - - // Reset the event. - void clear() - { - } - - // Wait for the event to become signalled. - void wait() - { - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_EVENT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/null_mutex.hpp b/libtorrent/include/libtorrent/asio/detail/null_mutex.hpp deleted file mode 100644 index 2f6a72084..000000000 --- a/libtorrent/include/libtorrent/asio/detail/null_mutex.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// -// null_mutex.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_NULL_MUTEX_HPP -#define ASIO_DETAIL_NULL_MUTEX_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/scoped_lock.hpp" - -namespace asio { -namespace detail { - -class null_mutex - : private noncopyable -{ -public: - typedef asio::detail::scoped_lock scoped_lock; - - // Constructor. - null_mutex() - { - } - - // Destructor. - ~null_mutex() - { - } - - // Lock the mutex. - void lock() - { - } - - // Unlock the mutex. - void unlock() - { - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_MUTEX_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/null_signal_blocker.hpp b/libtorrent/include/libtorrent/asio/detail/null_signal_blocker.hpp deleted file mode 100644 index c10017d98..000000000 --- a/libtorrent/include/libtorrent/asio/detail/null_signal_blocker.hpp +++ /dev/null @@ -1,63 +0,0 @@ -// -// null_signal_blocker.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_NULL_SIGNAL_BLOCKER_HPP -#define ASIO_DETAIL_NULL_SIGNAL_BLOCKER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class null_signal_blocker - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - null_signal_blocker() - { - } - - // Destructor restores the previous signal mask. - ~null_signal_blocker() - { - } - - // Block all signals for the calling thread. - void block() - { - } - - // Restore the previous signal mask. - void unblock() - { - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/null_thread.hpp b/libtorrent/include/libtorrent/asio/detail/null_thread.hpp deleted file mode 100644 index c013a7701..000000000 --- a/libtorrent/include/libtorrent/asio/detail/null_thread.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// null_thread.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_NULL_THREAD_HPP -#define ASIO_DETAIL_NULL_THREAD_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class null_thread - : private noncopyable -{ -public: - // Constructor. - template - null_thread(Function f) - { - asio::system_error e( - asio::error::operation_not_supported, "thread"); - boost::throw_exception(e); - } - - // Destructor. - ~null_thread() - { - } - - // Wait for the thread to exit. - void join() - { - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_THREAD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/null_tss_ptr.hpp b/libtorrent/include/libtorrent/asio/detail/null_tss_ptr.hpp deleted file mode 100644 index 9f3b0ad0c..000000000 --- a/libtorrent/include/libtorrent/asio/detail/null_tss_ptr.hpp +++ /dev/null @@ -1,70 +0,0 @@ -// -// null_tss_ptr.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_NULL_TSS_PTR_HPP -#define ASIO_DETAIL_NULL_TSS_PTR_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -template -class null_tss_ptr - : private noncopyable -{ -public: - // Constructor. - null_tss_ptr() - : value_(0) - { - } - - // Destructor. - ~null_tss_ptr() - { - } - - // Get the value. - operator T*() const - { - return value_; - } - - // Set the value. - void operator=(T* value) - { - value_ = value; - } - -private: - T* value_; -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_HAS_THREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_NULL_TSS_PTR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/old_win_sdk_compat.hpp b/libtorrent/include/libtorrent/asio/detail/old_win_sdk_compat.hpp deleted file mode 100644 index da78f956d..000000000 --- a/libtorrent/include/libtorrent/asio/detail/old_win_sdk_compat.hpp +++ /dev/null @@ -1,317 +0,0 @@ -// -// old_win_sdk_compat.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_OLD_WIN_SDK_COMPAT_HPP -#define ASIO_DETAIL_OLD_WIN_SDK_COMPAT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -// Guess whether we are building against on old Platform SDK. -#if !defined(IN6ADDR_ANY_INIT) -#define ASIO_HAS_OLD_WIN_SDK 1 -#endif // !defined(IN6ADDR_ANY_INIT) - -#if defined(ASIO_HAS_OLD_WIN_SDK) - -// Emulation of types that are missing from old Platform SDKs. - -namespace asio { -namespace detail { - -enum -{ - sockaddr_storage_maxsize = 128, // Maximum size. - sockaddr_storage_alignsize = (sizeof(__int64)), // Desired alignment. - sockaddr_storage_pad1size = (sockaddr_storage_alignsize - sizeof(short)), - sockaddr_storage_pad2size = (sockaddr_storage_maxsize - - (sizeof(short) + sockaddr_storage_pad1size + sockaddr_storage_alignsize)) -}; - -struct sockaddr_storage_emulation -{ - short ss_family; - char __ss_pad1[sockaddr_storage_pad1size]; - __int64 __ss_align; - char __ss_pad2[sockaddr_storage_pad2size]; -}; - -struct in6_addr_emulation -{ - u_char s6_addr[16]; -}; - -struct sockaddr_in6_emulation -{ - short sin6_family; - u_short sin6_port; - u_long sin6_flowinfo; - in6_addr_emulation sin6_addr; - u_long sin6_scope_id; -}; - -struct ipv6_mreq_emulation -{ - in6_addr_emulation ipv6mr_multiaddr; - unsigned int ipv6mr_interface; -}; - -#if !defined(IN6ADDR_ANY_INIT) -# define IN6ADDR_ANY_INIT { 0 } -#endif - -#if !defined(IN6ADDR_LOOPBACK_INIT) -# define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } -#endif - -struct addrinfo_emulation -{ - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - size_t ai_addrlen; - char* ai_canonname; - sockaddr* ai_addr; - addrinfo_emulation* ai_next; -}; - -#if !defined(AI_PASSIVE) -# define AI_PASSIVE 0x1 -#endif - -#if !defined(AI_CANONNAME) -# define AI_CANONNAME 0x2 -#endif - -#if !defined(AI_NUMERICHOST) -# define AI_NUMERICHOST 0x4 -#endif - -#if !defined(EAI_AGAIN) -# define EAI_AGAIN WSATRY_AGAIN -#endif - -#if !defined(EAI_BADFLAGS) -# define EAI_BADFLAGS WSAEINVAL -#endif - -#if !defined(EAI_FAIL) -# define EAI_FAIL WSANO_RECOVERY -#endif - -#if !defined(EAI_FAMILY) -# define EAI_FAMILY WSAEAFNOSUPPORT -#endif - -#if !defined(EAI_MEMORY) -# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY -#endif - -#if !defined(EAI_NODATA) -# define EAI_NODATA WSANO_DATA -#endif - -#if !defined(EAI_NONAME) -# define EAI_NONAME WSAHOST_NOT_FOUND -#endif - -#if !defined(EAI_SERVICE) -# define EAI_SERVICE WSATYPE_NOT_FOUND -#endif - -#if !defined(EAI_SOCKTYPE) -# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT -#endif - -#if !defined(NI_NOFQDN) -# define NI_NOFQDN 0x01 -#endif - -#if !defined(NI_NUMERICHOST) -# define NI_NUMERICHOST 0x02 -#endif - -#if !defined(NI_NAMEREQD) -# define NI_NAMEREQD 0x04 -#endif - -#if !defined(NI_NUMERICSERV) -# define NI_NUMERICSERV 0x08 -#endif - -#if !defined(NI_DGRAM) -# define NI_DGRAM 0x10 -#endif - -#if !defined(IPPROTO_IPV6) -# define IPPROTO_IPV6 41 -#endif - -#if !defined(IPV6_MULTICAST_IF) -# define IPV6_MULTICAST_IF 9 -#endif - -#if !defined(IPV6_MULTICAST_HOPS) -# define IPV6_MULTICAST_HOPS 10 -#endif - -#if !defined(IPV6_MULTICAST_LOOP) -# define IPV6_MULTICAST_LOOP 11 -#endif - -#if !defined(IPV6_JOIN_GROUP) -# define IPV6_JOIN_GROUP 12 -#endif - -#if !defined(IPV6_LEAVE_GROUP) -# define IPV6_LEAVE_GROUP 13 -#endif - -inline int IN6_IS_ADDR_UNSPECIFIED(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0) - && (a->s6_addr[1] == 0) - && (a->s6_addr[2] == 0) - && (a->s6_addr[3] == 0) - && (a->s6_addr[4] == 0) - && (a->s6_addr[5] == 0) - && (a->s6_addr[6] == 0) - && (a->s6_addr[7] == 0) - && (a->s6_addr[8] == 0) - && (a->s6_addr[9] == 0) - && (a->s6_addr[10] == 0) - && (a->s6_addr[11] == 0) - && (a->s6_addr[12] == 0) - && (a->s6_addr[13] == 0) - && (a->s6_addr[14] == 0) - && (a->s6_addr[15] == 0)); -} - -inline int IN6_IS_ADDR_LOOPBACK(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0) - && (a->s6_addr[1] == 0) - && (a->s6_addr[2] == 0) - && (a->s6_addr[3] == 0) - && (a->s6_addr[4] == 0) - && (a->s6_addr[5] == 0) - && (a->s6_addr[6] == 0) - && (a->s6_addr[7] == 0) - && (a->s6_addr[8] == 0) - && (a->s6_addr[9] == 0) - && (a->s6_addr[10] == 0) - && (a->s6_addr[11] == 0) - && (a->s6_addr[12] == 0) - && (a->s6_addr[13] == 0) - && (a->s6_addr[14] == 0) - && (a->s6_addr[15] == 1)); -} - -inline int IN6_IS_ADDR_MULTICAST(const in6_addr_emulation* a) -{ - return (a->s6_addr[0] == 0xff); -} - -inline int IN6_IS_ADDR_LINKLOCAL(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0x80)); -} - -inline int IN6_IS_ADDR_SITELOCAL(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0xc0)); -} - -inline int IN6_IS_ADDR_V4MAPPED(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0) - && (a->s6_addr[1] == 0) - && (a->s6_addr[2] == 0) - && (a->s6_addr[3] == 0) - && (a->s6_addr[4] == 0) - && (a->s6_addr[5] == 0) - && (a->s6_addr[6] == 0) - && (a->s6_addr[7] == 0) - && (a->s6_addr[8] == 0) - && (a->s6_addr[9] == 0) - && (a->s6_addr[10] == 0xff) - && (a->s6_addr[11] == 0xff)); -} - -inline int IN6_IS_ADDR_V4COMPAT(const in6_addr_emulation* a) -{ - return ((a->s6_addr[0] == 0) - && (a->s6_addr[1] == 0) - && (a->s6_addr[2] == 0) - && (a->s6_addr[3] == 0) - && (a->s6_addr[4] == 0) - && (a->s6_addr[5] == 0) - && (a->s6_addr[6] == 0) - && (a->s6_addr[7] == 0) - && (a->s6_addr[8] == 0) - && (a->s6_addr[9] == 0) - && (a->s6_addr[10] == 0xff) - && (a->s6_addr[11] == 0xff) - && !((a->s6_addr[12] == 0) - && (a->s6_addr[13] == 0) - && (a->s6_addr[14] == 0) - && ((a->s6_addr[15] == 0) || (a->s6_addr[15] == 1)))); -} - -inline int IN6_IS_ADDR_MC_NODELOCAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 1); -} - -inline int IN6_IS_ADDR_MC_LINKLOCAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 2); -} - -inline int IN6_IS_ADDR_MC_SITELOCAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 5); -} - -inline int IN6_IS_ADDR_MC_ORGLOCAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 8); -} - -inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a) -{ - return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 0xe); -} - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_OLD_WIN_SDK) - -// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY. -#if !defined(IPV6_V6ONLY) -# define IPV6_V6ONLY 27 -#endif - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp b/libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp deleted file mode 100644 index e203669cb..000000000 --- a/libtorrent/include/libtorrent/asio/detail/pipe_select_interrupter.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// -// pipe_select_interrupter.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_PIPE_SELECT_INTERRUPTER_HPP -#define ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -class pipe_select_interrupter -{ -public: - // Constructor. - pipe_select_interrupter() - { - int pipe_fds[2]; - if (pipe(pipe_fds) == 0) - { - read_descriptor_ = pipe_fds[0]; - ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); - write_descriptor_ = pipe_fds[1]; - ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK); - } - } - - // Destructor. - ~pipe_select_interrupter() - { - if (read_descriptor_ != -1) - ::close(read_descriptor_); - if (write_descriptor_ != -1) - ::close(write_descriptor_); - } - - // Interrupt the select call. - void interrupt() - { - char byte = 0; - ::write(write_descriptor_, &byte, 1); - } - - // Reset the select interrupt. Returns true if the call was interrupted. - bool reset() - { - char data[1024]; - int bytes_read = ::read(read_descriptor_, data, sizeof(data)); - bool was_interrupted = (bytes_read > 0); - while (bytes_read == sizeof(data)) - bytes_read = ::read(read_descriptor_, data, sizeof(data)); - return was_interrupted; - } - - // Get the read descriptor to be passed to select. - int read_descriptor() const - { - return read_descriptor_; - } - -private: - // The read end of a connection used to interrupt the select call. This file - // descriptor is passed to select such that when it is time to stop, a single - // byte will be written on the other end of the connection and this - // descriptor will become readable. - int read_descriptor_; - - // The write end of a connection used to interrupt the select call. A single - // byte may be written to this to wake up the select which is waiting for the - // other end to become readable. - int write_descriptor_; -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/pop_options.hpp b/libtorrent/include/libtorrent/asio/detail/pop_options.hpp deleted file mode 100644 index c8b0ed93b..000000000 --- a/libtorrent/include/libtorrent/asio/detail/pop_options.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// pop_options.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) -// - -// No header guard - -#if defined(__COMO__) - -// Comeau C++ - -#elif defined(__DMC__) - -// Digital Mars C++ - -#elif defined(__INTEL_COMPILER) || defined(__ICL) \ - || defined(__ICC) || defined(__ECC) - -// Intel C++ - -#elif defined(__GNUC__) - -// GNU C++ - -# if defined(__MINGW32__) || defined(__CYGWIN__) -# pragma pack (pop) -# endif - -#elif defined(__KCC) - -// Kai C++ - -#elif defined(__sgi) - -// SGI MIPSpro C++ - -#elif defined(__DECCXX) - -// Compaq Tru64 Unix cxx - -#elif defined(__ghs) - -// Greenhills C++ - -#elif defined(__BORLANDC__) - -// Borland C++ - -# pragma option pop -# pragma nopushoptwarn -# pragma nopackwarning - -#elif defined(__MWERKS__) - -// Metrowerks CodeWarrior - -#elif defined(__SUNPRO_CC) - -// Sun Workshop Compiler C++ - -#elif defined(__HP_aCC) - -// HP aCC - -#elif defined(__MRC__) || defined(__SC__) - -// MPW MrCpp or SCpp - -#elif defined(__IBMCPP__) - -// IBM Visual Age - -#elif defined(_MSC_VER) - -// Microsoft Visual C++ -// -// Must remain the last #elif since some other vendors (Metrowerks, for example) -// also #define _MSC_VER - -# pragma warning (pop) -# pragma pack (pop) - -#endif diff --git a/libtorrent/include/libtorrent/asio/detail/posix_event.hpp b/libtorrent/include/libtorrent/asio/detail/posix_event.hpp deleted file mode 100644 index 408c23bb9..000000000 --- a/libtorrent/include/libtorrent/asio/detail/posix_event.hpp +++ /dev/null @@ -1,111 +0,0 @@ -// -// posix_event.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_POSIX_EVENT_HPP -#define ASIO_DETAIL_POSIX_EVENT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class posix_event - : private noncopyable -{ -public: - // Constructor. - posix_event() - : signalled_(false) - { - int error = ::pthread_mutex_init(&mutex_, 0); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "event"); - boost::throw_exception(e); - } - - error = ::pthread_cond_init(&cond_, 0); - if (error != 0) - { - ::pthread_mutex_destroy(&mutex_); - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "event"); - boost::throw_exception(e); - } - } - - // Destructor. - ~posix_event() - { - ::pthread_cond_destroy(&cond_); - ::pthread_mutex_destroy(&mutex_); - } - - // Signal the event. - void signal() - { - ::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK. - signalled_ = true; - ::pthread_cond_signal(&cond_); // Ignore EINVAL. - ::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM. - } - - // Reset the event. - void clear() - { - ::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK. - signalled_ = false; - ::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM. - } - - // Wait for the event to become signalled. - void wait() - { - ::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK. - while (!signalled_) - ::pthread_cond_wait(&cond_, &mutex_); // Ignore EINVAL. - ::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM. - } - -private: - ::pthread_mutex_t mutex_; - ::pthread_cond_t cond_; - bool signalled_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_EVENT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp b/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp deleted file mode 100644 index ae5bf6642..000000000 --- a/libtorrent/include/libtorrent/asio/detail/posix_fd_set_adapter.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// posix_fd_set_adapter.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_POSIX_FD_SET_ADAPTER_HPP -#define ASIO_DETAIL_POSIX_FD_SET_ADAPTER_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/socket_types.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -namespace asio { -namespace detail { - -// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements. -class posix_fd_set_adapter -{ -public: - posix_fd_set_adapter() - : max_descriptor_(invalid_socket) - { - using namespace std; // Needed for memset on Solaris. - FD_ZERO(&fd_set_); - } - - void set(socket_type descriptor) - { - if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_) - max_descriptor_ = descriptor; - FD_SET(descriptor, &fd_set_); - } - - bool is_set(socket_type descriptor) const - { - return FD_ISSET(descriptor, &fd_set_) != 0; - } - - operator fd_set*() - { - return &fd_set_; - } - - socket_type max_descriptor() const - { - return max_descriptor_; - } - -private: - fd_set fd_set_; - socket_type max_descriptor_; -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/posix_mutex.hpp b/libtorrent/include/libtorrent/asio/detail/posix_mutex.hpp deleted file mode 100644 index 154089f3c..000000000 --- a/libtorrent/include/libtorrent/asio/detail/posix_mutex.hpp +++ /dev/null @@ -1,100 +0,0 @@ -// -// posix_mutex.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_POSIX_MUTEX_HPP -#define ASIO_DETAIL_POSIX_MUTEX_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/scoped_lock.hpp" - -namespace asio { -namespace detail { - -class posix_mutex - : private noncopyable -{ -public: - typedef asio::detail::scoped_lock scoped_lock; - - // Constructor. - posix_mutex() - { - int error = ::pthread_mutex_init(&mutex_, 0); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "mutex"); - boost::throw_exception(e); - } - } - - // Destructor. - ~posix_mutex() - { - ::pthread_mutex_destroy(&mutex_); - } - - // Lock the mutex. - void lock() - { - int error = ::pthread_mutex_lock(&mutex_); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "mutex"); - boost::throw_exception(e); - } - } - - // Unlock the mutex. - void unlock() - { - int error = ::pthread_mutex_unlock(&mutex_); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "mutex"); - boost::throw_exception(e); - } - } - -private: - ::pthread_mutex_t mutex_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_MUTEX_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/posix_signal_blocker.hpp b/libtorrent/include/libtorrent/asio/detail/posix_signal_blocker.hpp deleted file mode 100644 index 73d0581e1..000000000 --- a/libtorrent/include/libtorrent/asio/detail/posix_signal_blocker.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// posix_signal_blocker.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_POSIX_SIGNAL_BLOCKER_HPP -#define ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class posix_signal_blocker - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - posix_signal_blocker() - : blocked_(false) - { - sigset_t new_mask; - sigfillset(&new_mask); - blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); - } - - // Destructor restores the previous signal mask. - ~posix_signal_blocker() - { - if (blocked_) - pthread_sigmask(SIG_SETMASK, &old_mask_, 0); - } - - // Block all signals for the calling thread. - void block() - { - if (!blocked_) - { - sigset_t new_mask; - sigfillset(&new_mask); - blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0); - } - } - - // Restore the previous signal mask. - void unblock() - { - if (blocked_) - blocked_ = (pthread_sigmask(SIG_SETMASK, &old_mask_, 0) != 0); - } - -private: - // Have signals been blocked. - bool blocked_; - - // The previous signal mask. - sigset_t old_mask_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/posix_thread.hpp b/libtorrent/include/libtorrent/asio/detail/posix_thread.hpp deleted file mode 100644 index f01b40428..000000000 --- a/libtorrent/include/libtorrent/asio/detail/posix_thread.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// posix_thread.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_POSIX_THREAD_HPP -#define ASIO_DETAIL_POSIX_THREAD_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -extern "C" void* asio_detail_posix_thread_function(void* arg); - -class posix_thread - : private noncopyable -{ -public: - // Constructor. - template - posix_thread(Function f) - : joined_(false) - { - std::auto_ptr arg(new func(f)); - int error = ::pthread_create(&thread_, 0, - asio_detail_posix_thread_function, arg.get()); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "thread"); - boost::throw_exception(e); - } - arg.release(); - } - - // Destructor. - ~posix_thread() - { - if (!joined_) - ::pthread_detach(thread_); - } - - // Wait for the thread to exit. - void join() - { - if (!joined_) - { - ::pthread_join(thread_, 0); - joined_ = true; - } - } - -private: - friend void* asio_detail_posix_thread_function(void* arg); - - class func_base - { - public: - virtual ~func_base() {} - virtual void run() = 0; - }; - - template - class func - : public func_base - { - public: - func(Function f) - : f_(f) - { - } - - virtual void run() - { - f_(); - } - - private: - Function f_; - }; - - ::pthread_t thread_; - bool joined_; -}; - -inline void* asio_detail_posix_thread_function(void* arg) -{ - std::auto_ptr f( - static_cast(arg)); - f->run(); - return 0; -} - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_THREAD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/posix_tss_ptr.hpp b/libtorrent/include/libtorrent/asio/detail/posix_tss_ptr.hpp deleted file mode 100644 index 93fce3479..000000000 --- a/libtorrent/include/libtorrent/asio/detail/posix_tss_ptr.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// -// posix_tss_ptr.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_POSIX_TSS_PTR_HPP -#define ASIO_DETAIL_POSIX_TSS_PTR_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -template -class posix_tss_ptr - : private noncopyable -{ -public: - // Constructor. - posix_tss_ptr() - { - int error = ::pthread_key_create(&tss_key_, 0); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "tss"); - boost::throw_exception(e); - } - } - - // Destructor. - ~posix_tss_ptr() - { - ::pthread_key_delete(tss_key_); - } - - // Get the value. - operator T*() const - { - return static_cast(::pthread_getspecific(tss_key_)); - } - - // Set the value. - void operator=(T* value) - { - ::pthread_setspecific(tss_key_, value); - } - -private: - // Thread-specific storage to allow unlocked access to determine whether a - // thread is a member of the pool. - pthread_key_t tss_key_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_HAS_PTHREADS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_POSIX_TSS_PTR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/push_options.hpp b/libtorrent/include/libtorrent/asio/detail/push_options.hpp deleted file mode 100644 index 0b68d2933..000000000 --- a/libtorrent/include/libtorrent/asio/detail/push_options.hpp +++ /dev/null @@ -1,106 +0,0 @@ -// -// push_options.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) -// - -// No header guard - -#if defined(__COMO__) - -// Comeau C++ - -#elif defined(__DMC__) - -// Digital Mars C++ - -#elif defined(__INTEL_COMPILER) || defined(__ICL) \ - || defined(__ICC) || defined(__ECC) - -// Intel C++ - -#elif defined(__GNUC__) - -// GNU C++ - -# if defined(__MINGW32__) || defined(__CYGWIN__) -# pragma pack (push, 8) -# endif - -#elif defined(__KCC) - -// Kai C++ - -#elif defined(__sgi) - -// SGI MIPSpro C++ - -#elif defined(__DECCXX) - -// Compaq Tru64 Unix cxx - -#elif defined(__ghs) - -// Greenhills C++ - -#elif defined(__BORLANDC__) - -// Borland C++ - -# pragma option push -a8 -b -Ve- -Vx- -w-inl -vi- -# pragma nopushoptwarn -# pragma nopackwarning -# if !defined(__MT__) -# error Multithreaded RTL must be selected. -# endif // !defined(__MT__) - -#elif defined(__MWERKS__) - -// Metrowerks CodeWarrior - -#elif defined(__SUNPRO_CC) - -// Sun Workshop Compiler C++ - -#elif defined(__HP_aCC) - -// HP aCC - -#elif defined(__MRC__) || defined(__SC__) - -// MPW MrCpp or SCpp - -#elif defined(__IBMCPP__) - -// IBM Visual Age - -#elif defined(_MSC_VER) - -// Microsoft Visual C++ -// -// Must remain the last #elif since some other vendors (Metrowerks, for example) -// also #define _MSC_VER - -# pragma warning (disable:4103) -# pragma warning (push) -# pragma warning (disable:4244) -# pragma warning (disable:4355) -# pragma warning (disable:4675) -# pragma pack (push, 8) -// Note that if the /Og optimisation flag is enabled with MSVC6, the compiler -// has a tendency to incorrectly optimise away some calls to member template -// functions, even though those functions contain code that should not be -// optimised away! Therefore we will always disable this optimisation option -// for the MSVC6 compiler. -# if (_MSC_VER < 1300) -# pragma optimize ("g", off) -# endif -# if !defined(_MT) -# error Multithreaded RTL must be selected. -# endif // !defined(_MT) - -#endif diff --git a/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp b/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp deleted file mode 100644 index b58f62781..000000000 --- a/libtorrent/include/libtorrent/asio/detail/reactive_socket_service.hpp +++ /dev/null @@ -1,1486 +0,0 @@ -// -// reactive_socket_service.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_REACTIVE_SOCKET_SERVICE_HPP -#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/socket_base.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/socket_holder.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -template -class reactive_socket_service - : public asio::detail::service_base< - reactive_socket_service > -{ -public: - // The protocol type. - typedef Protocol protocol_type; - - // The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - // The native type of a socket. - typedef socket_type native_type; - - // The implementation type of the socket. - class implementation_type - : private asio::detail::noncopyable - { - public: - // Default constructor. - implementation_type() - : socket_(invalid_socket), - flags_(0), - protocol_(endpoint_type().protocol()) - { - } - - private: - // Only this service will have access to the internal values. - friend class reactive_socket_service; - - // The native socket representation. - socket_type socket_; - - enum - { - user_set_non_blocking = 1, // The user wants a non-blocking socket. - internal_non_blocking = 2, // The socket has been set non-blocking. - enable_connection_aborted = 4, // User wants connection_aborted errors. - user_set_linger = 8 // The user set the linger option. - }; - - // Flags indicating the current state of the socket. - unsigned char flags_; - - // The protocol associated with the socket. - protocol_type protocol_; - }; - - // The maximum number of buffers to support in a single operation. - enum { max_buffers = 16 }; - - // Constructor. - reactive_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - reactive_socket_service >(io_service), - reactor_(asio::use_service(io_service)) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Construct a new socket implementation. - void construct(implementation_type& impl) - { - impl.socket_ = invalid_socket; - impl.flags_ = 0; - } - - // Destroy a socket implementation. - void destroy(implementation_type& impl) - { - if (impl.socket_ != invalid_socket) - { - reactor_.close_descriptor(impl.socket_); - - if (impl.flags_ & implementation_type::internal_non_blocking) - { - ioctl_arg_type non_blocking = 0; - asio::error_code ignored_ec; - socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); - impl.flags_ &= ~implementation_type::internal_non_blocking; - } - - if (impl.flags_ & implementation_type::user_set_linger) - { - ::linger opt; - opt.l_onoff = 0; - opt.l_linger = 0; - asio::error_code ignored_ec; - socket_ops::setsockopt(impl.socket_, - SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec); - } - - asio::error_code ignored_ec; - socket_ops::close(impl.socket_, ignored_ec); - - impl.socket_ = invalid_socket; - } - } - - // Open a new socket implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - socket_holder sock(socket_ops::socket(protocol.family(), - protocol.type(), protocol.protocol(), ec)); - if (sock.get() == invalid_socket) - return ec; - - if (int err = reactor_.register_descriptor(sock.get())) - { - ec = asio::error_code(err, asio::native_ecat); - return ec; - } - - impl.socket_ = sock.release(); - impl.flags_ = 0; - impl.protocol_ = protocol; - ec = asio::error_code(); - return ec; - } - - // Assign a native socket to a socket implementation. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - if (int err = reactor_.register_descriptor(native_socket)) - { - ec = asio::error_code(err, asio::native_ecat); - return ec; - } - - impl.socket_ = native_socket; - impl.flags_ = 0; - impl.protocol_ = protocol; - ec = asio::error_code(); - return ec; - } - - // Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return impl.socket_ != invalid_socket; - } - - // Destroy a socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - if (is_open(impl)) - { - reactor_.close_descriptor(impl.socket_); - - if (impl.flags_ & implementation_type::internal_non_blocking) - { - ioctl_arg_type non_blocking = 0; - asio::error_code ignored_ec; - socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec); - impl.flags_ &= ~implementation_type::internal_non_blocking; - } - - if (socket_ops::close(impl.socket_, ec) == socket_error_retval) - return ec; - - impl.socket_ = invalid_socket; - } - - ec = asio::error_code(); - return ec; - } - - // Get the native socket representation. - native_type native(implementation_type& impl) - { - return impl.socket_; - } - - // Cancel all operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - reactor_.cancel_ops(impl.socket_); - ec = asio::error_code(); - return ec; - } - - // Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return false; - } - - asio::detail::ioctl_arg_type value = 0; - socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec); -#if defined(ENOTTY) - if (ec.value() == ENOTTY) - ec = asio::error::not_socket; -#endif // defined(ENOTTY) - return ec ? false : value != 0; - } - - // Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - asio::detail::ioctl_arg_type value = 0; - socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec); -#if defined(ENOTTY) - if (ec.value() == ENOTTY) - ec = asio::error::not_socket; -#endif // defined(ENOTTY) - return ec ? static_cast(0) : static_cast(value); - } - - // Bind the socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); - return ec; - } - - // Place the socket into the state where it will listen for new connections. - asio::error_code listen(implementation_type& impl, int backlog, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::listen(impl.socket_, backlog, ec); - return ec; - } - - // Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const Option& option, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (option.level(impl.protocol_) == custom_socket_option_level - && option.name(impl.protocol_) == enable_connection_aborted_option) - { - if (option.size(impl.protocol_) != sizeof(int)) - { - ec = asio::error::invalid_argument; - } - else - { - if (*reinterpret_cast(option.data(impl.protocol_))) - impl.flags_ |= implementation_type::enable_connection_aborted; - else - impl.flags_ &= ~implementation_type::enable_connection_aborted; - ec = asio::error_code(); - } - return ec; - } - else - { - if (option.level(impl.protocol_) == SOL_SOCKET - && option.name(impl.protocol_) == SO_LINGER) - { - impl.flags_ |= implementation_type::user_set_linger; - } - - socket_ops::setsockopt(impl.socket_, - option.level(impl.protocol_), option.name(impl.protocol_), - option.data(impl.protocol_), option.size(impl.protocol_), ec); - return ec; - } - } - - // Set a socket option. - template - asio::error_code get_option(const implementation_type& impl, - Option& option, asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (option.level(impl.protocol_) == custom_socket_option_level - && option.name(impl.protocol_) == enable_connection_aborted_option) - { - if (option.size(impl.protocol_) != sizeof(int)) - { - ec = asio::error::invalid_argument; - } - else - { - int* target = reinterpret_cast(option.data(impl.protocol_)); - if (impl.flags_ & implementation_type::enable_connection_aborted) - *target = 1; - else - *target = 0; - option.resize(impl.protocol_, sizeof(int)); - ec = asio::error_code(); - } - return ec; - } - else - { - size_t size = option.size(impl.protocol_); - socket_ops::getsockopt(impl.socket_, - option.level(impl.protocol_), option.name(impl.protocol_), - option.data(impl.protocol_), &size, ec); - if (!ec) - option.resize(impl.protocol_, size); - return ec; - } - } - - // Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IO_Control_Command& command, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (command.name() == static_cast(FIONBIO)) - { - if (command.get()) - impl.flags_ |= implementation_type::user_set_non_blocking; - else - impl.flags_ &= ~implementation_type::user_set_non_blocking; - ec = asio::error_code(); - } - else - { - socket_ops::ioctl(impl.socket_, command.name(), - static_cast(command.data()), ec); - } - return ec; - } - - // Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return endpoint_type(); - } - - endpoint_type endpoint; - socket_addr_len_type addr_len = endpoint.capacity(); - if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) - return endpoint_type(); - endpoint.resize(addr_len); - return endpoint; - } - - // Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return endpoint_type(); - } - - endpoint_type endpoint; - socket_addr_len_type addr_len = endpoint.capacity(); - if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec)) - return endpoint_type(); - endpoint.resize(addr_len); - return endpoint; - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::shutdown(impl.socket_, what, ec); - return ec; - } - - // Send the given data to the peer. - template - size_t send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Send the data. - for (;;) - { - // Try to complete the operation without blocking. - int bytes_sent = socket_ops::send(impl.socket_, bufs, i, flags, ec); - - // Check if operation succeeded. - if (bytes_sent >= 0) - return bytes_sent; - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for socket to become ready. - if (socket_ops::poll_write(impl.socket_, ec) < 0) - return 0; - } - } - - template - class send_handler - { - public: - send_handler(socket_type socket, asio::io_service& io_service, - const ConstBufferSequence& buffers, socket_base::message_flags flags, - Handler handler) - : socket_(socket), - io_service_(io_service), - work_(io_service), - buffers_(buffers), - flags_(flags), - handler_(handler) - { - } - - bool operator()(const asio::error_code& result) - { - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result, 0)); - return true; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers_.begin(); - typename ConstBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Send the data. - asio::error_code ec; - int bytes = socket_ops::send(socket_, bufs, i, flags_, ec); - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); - return true; - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - ConstBufferSequence buffers_; - socket_base::message_flags flags_; - Handler handler_; - }; - - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - if (impl.protocol_.type() == SOCK_STREAM) - { - // Determine total size of buffers. - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (total_buffer_size == 0) - { - this->io_service().post(bind_handler(handler, - asio::error_code(), 0)); - return; - } - } - - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_write_op(impl.socket_, - send_handler( - impl.socket_, this->io_service(), buffers, flags, handler)); - } - } - - // Send a datagram to the specified endpoint. Returns the number of bytes - // sent. - template - size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Send the data. - for (;;) - { - // Try to complete the operation without blocking. - int bytes_sent = socket_ops::sendto(impl.socket_, bufs, i, flags, - destination.data(), destination.size(), ec); - - // Check if operation succeeded. - if (bytes_sent >= 0) - return bytes_sent; - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for socket to become ready. - if (socket_ops::poll_write(impl.socket_, ec) < 0) - return 0; - } - } - - template - class send_to_handler - { - public: - send_to_handler(socket_type socket, asio::io_service& io_service, - const ConstBufferSequence& buffers, const endpoint_type& endpoint, - socket_base::message_flags flags, Handler handler) - : socket_(socket), - io_service_(io_service), - work_(io_service), - buffers_(buffers), - destination_(endpoint), - flags_(flags), - handler_(handler) - { - } - - bool operator()(const asio::error_code& result) - { - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result, 0)); - return true; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers_.begin(); - typename ConstBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Send the data. - asio::error_code ec; - int bytes = socket_ops::sendto(socket_, bufs, i, flags_, - destination_.data(), destination_.size(), ec); - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); - return true; - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - ConstBufferSequence buffers_; - endpoint_type destination_; - socket_base::message_flags flags_; - Handler handler_; - }; - - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_write_op(impl.socket_, - send_to_handler( - impl.socket_, this->io_service(), buffers, - destination, flags, handler)); - } - } - - // Receive some data from the peer. Returns the number of bytes received. - template - size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Receive some data. - for (;;) - { - // Try to complete the operation without blocking. - int bytes_recvd = socket_ops::recv(impl.socket_, bufs, i, flags, ec); - - // Check if operation succeeded. - if (bytes_recvd > 0) - return bytes_recvd; - - // Check for EOF. - if (bytes_recvd == 0) - { - ec = asio::error::eof; - return 0; - } - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for socket to become ready. - if (socket_ops::poll_read(impl.socket_, ec) < 0) - return 0; - } - } - - template - class receive_handler - { - public: - receive_handler(socket_type socket, asio::io_service& io_service, - const MutableBufferSequence& buffers, socket_base::message_flags flags, - Handler handler) - : socket_(socket), - io_service_(io_service), - work_(io_service), - buffers_(buffers), - flags_(flags), - handler_(handler) - { - } - - bool operator()(const asio::error_code& result) - { - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result, 0)); - return true; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers_.begin(); - typename MutableBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Receive some data. - asio::error_code ec; - int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec); - if (bytes == 0) - ec = asio::error::eof; - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); - return true; - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - MutableBufferSequence buffers_; - socket_base::message_flags flags_; - Handler handler_; - }; - - // Start an asynchronous receive. The buffer for the data being received - // must be valid for the lifetime of the asynchronous operation. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - if (impl.protocol_.type() == SOCK_STREAM) - { - // Determine total size of buffers. - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (total_buffer_size == 0) - { - this->io_service().post(bind_handler(handler, - asio::error_code(), 0)); - return; - } - } - - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - if (flags & socket_base::message_out_of_band) - { - reactor_.start_except_op(impl.socket_, - receive_handler( - impl.socket_, this->io_service(), buffers, flags, handler)); - } - else - { - reactor_.start_read_op(impl.socket_, - receive_handler( - impl.socket_, this->io_service(), buffers, flags, handler)); - } - } - } - - // Receive a datagram with the endpoint of the sender. Returns the number of - // bytes received. - template - size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Receive some data. - for (;;) - { - // Try to complete the operation without blocking. - socket_addr_len_type addr_len = sender_endpoint.capacity(); - int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags, - sender_endpoint.data(), &addr_len, ec); - - // Check if operation succeeded. - if (bytes_recvd > 0) - { - sender_endpoint.resize(addr_len); - return bytes_recvd; - } - - // Check for EOF. - if (bytes_recvd == 0) - { - ec = asio::error::eof; - return 0; - } - - // Operation failed. - if ((impl.flags_ & implementation_type::user_set_non_blocking) - || (ec != asio::error::would_block - && ec != asio::error::try_again)) - return 0; - - // Wait for socket to become ready. - if (socket_ops::poll_read(impl.socket_, ec) < 0) - return 0; - } - } - - template - class receive_from_handler - { - public: - receive_from_handler(socket_type socket, - asio::io_service& io_service, - const MutableBufferSequence& buffers, endpoint_type& endpoint, - socket_base::message_flags flags, Handler handler) - : socket_(socket), - io_service_(io_service), - work_(io_service), - buffers_(buffers), - sender_endpoint_(endpoint), - flags_(flags), - handler_(handler) - { - } - - bool operator()(const asio::error_code& result) - { - // Check whether the operation was successful. - if (result != 0) - { - io_service_.post(bind_handler(handler_, result, 0)); - return true; - } - - // Copy buffers into array. - socket_ops::buf bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers_.begin(); - typename MutableBufferSequence::const_iterator end = buffers_.end(); - size_t i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - socket_ops::init_buf(bufs[i], - asio::buffer_cast(buffer), - asio::buffer_size(buffer)); - } - - // Receive some data. - socket_addr_len_type addr_len = sender_endpoint_.capacity(); - asio::error_code ec; - int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_, - sender_endpoint_.data(), &addr_len, ec); - if (bytes == 0) - ec = asio::error::eof; - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - - sender_endpoint_.resize(addr_len); - io_service_.post(bind_handler(handler_, ec, bytes < 0 ? 0 : bytes)); - return true; - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - MutableBufferSequence buffers_; - endpoint_type& sender_endpoint_; - socket_base::message_flags flags_; - Handler handler_; - }; - - // Start an asynchronous receive. The buffer for the data being received and - // the sender_endpoint object must both be valid for the lifetime of the - // asynchronous operation. - template - void async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - } - else - { - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->io_service().post(bind_handler(handler, ec, 0)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_read_op(impl.socket_, - receive_from_handler( - impl.socket_, this->io_service(), buffers, - sender_endpoint, flags, handler)); - } - } - - // Accept a new connection. - template - asio::error_code accept(implementation_type& impl, - Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - // We cannot accept a socket that is already open. - if (peer.is_open()) - { - ec = asio::error::already_open; - return ec; - } - - // Accept a socket. - for (;;) - { - // Try to complete the operation without blocking. - asio::error_code ec; - socket_holder new_socket; - socket_addr_len_type addr_len = 0; - if (peer_endpoint) - { - addr_len = peer_endpoint->capacity(); - new_socket.reset(socket_ops::accept(impl.socket_, - peer_endpoint->data(), &addr_len, ec)); - } - else - { - new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec)); - } - - // Check if operation succeeded. - if (new_socket.get() >= 0) - { - if (peer_endpoint) - peer_endpoint->resize(addr_len); - peer.assign(impl.protocol_, new_socket.get(), ec); - if (!ec) - new_socket.release(); - return ec; - } - - // Operation failed. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - { - if (impl.flags_ & implementation_type::user_set_non_blocking) - return ec; - // Fall through to retry operation. - } - else if (ec == asio::error::connection_aborted) - { - if (impl.flags_ & implementation_type::enable_connection_aborted) - return ec; - // Fall through to retry operation. - } - else - return ec; - - // Wait for socket to become ready. - if (socket_ops::poll_read(impl.socket_, ec) < 0) - return ec; - } - } - - template - class accept_handler - { - public: - accept_handler(socket_type socket, asio::io_service& io_service, - Socket& peer, const protocol_type& protocol, - endpoint_type* peer_endpoint, bool enable_connection_aborted, - Handler handler) - : socket_(socket), - io_service_(io_service), - work_(io_service), - peer_(peer), - protocol_(protocol), - peer_endpoint_(peer_endpoint), - enable_connection_aborted_(enable_connection_aborted), - handler_(handler) - { - } - - bool operator()(const asio::error_code& result) - { - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); - return true; - } - - // Accept the waiting connection. - asio::error_code ec; - socket_holder new_socket; - socket_addr_len_type addr_len = 0; - if (peer_endpoint_) - { - addr_len = peer_endpoint_->capacity(); - new_socket.reset(socket_ops::accept(socket_, - peer_endpoint_->data(), &addr_len, ec)); - } - else - { - new_socket.reset(socket_ops::accept(socket_, 0, 0, ec)); - } - - // Check if we need to run the operation again. - if (ec == asio::error::would_block - || ec == asio::error::try_again) - return false; - if (ec == asio::error::connection_aborted - && !enable_connection_aborted_) - return false; - - // Transfer ownership of the new socket to the peer object. - if (!ec) - { - if (peer_endpoint_) - peer_endpoint_->resize(addr_len); - peer_.assign(protocol_, new_socket.get(), ec); - if (!ec) - new_socket.release(); - } - - io_service_.post(bind_handler(handler_, ec)); - return true; - } - - private: - socket_type socket_; - asio::io_service& io_service_; - asio::io_service::work work_; - Socket& peer_; - protocol_type protocol_; - endpoint_type* peer_endpoint_; - bool enable_connection_aborted_; - Handler handler_; - }; - - // Start an asynchronous accept. The peer and peer_endpoint objects - // must be valid until the accept's handler is invoked. - template - void async_accept(implementation_type& impl, Socket& peer, - endpoint_type* peer_endpoint, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor)); - } - else if (peer.is_open()) - { - this->io_service().post(bind_handler(handler, - asio::error::already_open)); - } - else - { - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->io_service().post(bind_handler(handler, ec)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - reactor_.start_read_op(impl.socket_, - accept_handler( - impl.socket_, this->io_service(), - peer, impl.protocol_, peer_endpoint, - (impl.flags_ & implementation_type::enable_connection_aborted) != 0, - handler)); - } - } - - // Connect the socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (impl.flags_ & implementation_type::internal_non_blocking) - { - // Mark the socket as blocking while we perform the connect. - ioctl_arg_type non_blocking = 0; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - return ec; - impl.flags_ &= ~implementation_type::internal_non_blocking; - } - - // Perform the connect operation. - socket_ops::connect(impl.socket_, - peer_endpoint.data(), peer_endpoint.size(), ec); - return ec; - } - - template - class connect_handler - { - public: - connect_handler(socket_type socket, boost::shared_ptr completed, - asio::io_service& io_service, Reactor& reactor, Handler handler) - : socket_(socket), - completed_(completed), - io_service_(io_service), - work_(io_service), - reactor_(reactor), - handler_(handler) - { - } - - bool operator()(const asio::error_code& result) - { - // Check whether a handler has already been called for the connection. - // If it has, then we don't want to do anything in this handler. - if (*completed_) - return true; - - // Cancel the other reactor operation for the connection. - *completed_ = true; - reactor_.enqueue_cancel_ops_unlocked(socket_); - - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); - return true; - } - - // Get the error code from the connect operation. - int connect_error = 0; - size_t connect_error_len = sizeof(connect_error); - asio::error_code ec; - if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, - &connect_error, &connect_error_len, ec) == socket_error_retval) - { - io_service_.post(bind_handler(handler_, ec)); - return true; - } - - // If connection failed then post the handler with the error code. - if (connect_error) - { - ec = asio::error_code(connect_error, - asio::native_ecat); - io_service_.post(bind_handler(handler_, ec)); - return true; - } - - // Post the result of the successful connection operation. - io_service_.post(bind_handler(handler_, ec)); - return true; - } - - private: - socket_type socket_; - boost::shared_ptr completed_; - asio::io_service& io_service_; - asio::io_service::work work_; - Reactor& reactor_; - Handler handler_; - }; - - // Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor)); - return; - } - - // Make socket non-blocking. - if (!(impl.flags_ & implementation_type::internal_non_blocking)) - { - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->io_service().post(bind_handler(handler, ec)); - return; - } - impl.flags_ |= implementation_type::internal_non_blocking; - } - - // Start the connect operation. The socket is already marked as non-blocking - // so the connection will take place asynchronously. - asio::error_code ec; - if (socket_ops::connect(impl.socket_, peer_endpoint.data(), - peer_endpoint.size(), ec) == 0) - { - // The connect operation has finished successfully so we need to post the - // handler immediately. - this->io_service().post(bind_handler(handler, - asio::error_code())); - } - else if (ec == asio::error::in_progress - || ec == asio::error::would_block) - { - // The connection is happening in the background, and we need to wait - // until the socket becomes writeable. - boost::shared_ptr completed(new bool(false)); - reactor_.start_write_and_except_ops(impl.socket_, - connect_handler( - impl.socket_, completed, this->io_service(), reactor_, handler)); - } - else - { - // The connect operation has failed, so post the handler immediately. - this->io_service().post(bind_handler(handler, ec)); - } - } - -private: - // The selector that performs event demultiplexing for the service. - Reactor& reactor_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp b/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp deleted file mode 100644 index b2d1054c6..000000000 --- a/libtorrent/include/libtorrent/asio/detail/reactor_op_queue.hpp +++ /dev/null @@ -1,384 +0,0 @@ -// -// reactor_op_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_REACTOR_OP_QUEUE_HPP -#define ASIO_DETAIL_REACTOR_OP_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/hash_map.hpp" -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -template -class reactor_op_queue - : private noncopyable -{ -public: - // Constructor. - reactor_op_queue() - : operations_(), - cancelled_operations_(0), - cleanup_operations_(0) - { - } - - // Add a new operation to the queue. Returns true if this is the only - // operation for the given descriptor, in which case the reactor's event - // demultiplexing function call may need to be interrupted and restarted. - template - bool enqueue_operation(Descriptor descriptor, Handler handler) - { - op_base* new_op = new op(descriptor, handler); - - typedef typename operation_map::iterator iterator; - typedef typename operation_map::value_type value_type; - std::pair entry = - operations_.insert(value_type(descriptor, new_op)); - if (entry.second) - return true; - - op_base* current_op = entry.first->second; - while (current_op->next_) - current_op = current_op->next_; - current_op->next_ = new_op; - - return false; - } - - // Cancel all operations associated with the descriptor. Any operations - // pending for the descriptor will be notified that they have been cancelled - // next time dispatch_cancellations is called. Returns true if any operations - // were cancelled, in which case the reactor's event demultiplexing function - // may need to be interrupted and restarted. - bool cancel_operations(Descriptor descriptor) - { - typename operation_map::iterator i = operations_.find(descriptor); - if (i != operations_.end()) - { - op_base* last_op = i->second; - while (last_op->next_) - last_op = last_op->next_; - last_op->next_ = cancelled_operations_; - cancelled_operations_ = i->second; - operations_.erase(i); - return true; - } - - return false; - } - - // Whether there are no operations in the queue. - bool empty() const - { - return operations_.empty(); - } - - // Determine whether there are any operations associated with the descriptor. - bool has_operation(Descriptor descriptor) const - { - return operations_.find(descriptor) != operations_.end(); - } - - // Dispatch the first operation corresponding to the descriptor. Returns true - // if there are more operations queued for the descriptor. - bool dispatch_operation(Descriptor descriptor, - const asio::error_code& result) - { - typename operation_map::iterator i = operations_.find(descriptor); - if (i != operations_.end()) - { - op_base* this_op = i->second; - i->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); - if (done) - { - // Operation has finished. - if (i->second) - { - return true; - } - else - { - operations_.erase(i); - return false; - } - } - else - { - // Operation wants to be called again. Leave it at the front of the - // queue for this descriptor, and remove from the cleanup list. - cleanup_operations_ = this_op->next_; - this_op->next_ = i->second; - i->second = this_op; - return true; - } - } - return false; - } - - // Dispatch all operations corresponding to the descriptor. - void dispatch_all_operations(Descriptor descriptor, - const asio::error_code& result) - { - typename operation_map::iterator i = operations_.find(descriptor); - if (i != operations_.end()) - { - while (i->second) - { - op_base* this_op = i->second; - i->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); - if (!done) - { - // Operation has not finished yet, so leave at front of queue, and - // remove from the cleanup list. - cleanup_operations_ = this_op->next_; - this_op->next_ = i->second; - i->second = this_op; - return; - } - } - operations_.erase(i); - } - } - - // Fill a descriptor set with the descriptors corresponding to each active - // operation. - template - void get_descriptors(Descriptor_Set& descriptors) - { - typename operation_map::iterator i = operations_.begin(); - while (i != operations_.end()) - { - descriptors.set(i->first); - ++i; - } - } - - // Dispatch the operations corresponding to the ready file descriptors - // contained in the given descriptor set. - template - void dispatch_descriptors(const Descriptor_Set& descriptors, - const asio::error_code& result) - { - typename operation_map::iterator i = operations_.begin(); - while (i != operations_.end()) - { - typename operation_map::iterator op_iter = i++; - if (descriptors.is_set(op_iter->first)) - { - op_base* this_op = op_iter->second; - op_iter->second = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - bool done = this_op->invoke(result); - if (done) - { - if (!op_iter->second) - operations_.erase(op_iter); - } - else - { - // Operation has not finished yet, so leave at front of queue, and - // remove from the cleanup list. - cleanup_operations_ = this_op->next_; - this_op->next_ = op_iter->second; - op_iter->second = this_op; - } - } - } - } - - // Dispatch any pending cancels for operations. - void dispatch_cancellations() - { - while (cancelled_operations_) - { - op_base* this_op = cancelled_operations_; - cancelled_operations_ = this_op->next_; - this_op->next_ = cleanup_operations_; - cleanup_operations_ = this_op; - this_op->invoke(asio::error::operation_aborted); - } - } - - // Destroy operations that are waiting to be cleaned up. - void cleanup_operations() - { - while (cleanup_operations_) - { - op_base* next_op = cleanup_operations_->next_; - cleanup_operations_->next_ = 0; - cleanup_operations_->destroy(); - cleanup_operations_ = next_op; - } - } - - // Destroy all operations owned by the queue. - void destroy_operations() - { - while (cancelled_operations_) - { - op_base* next_op = cancelled_operations_->next_; - cancelled_operations_->next_ = 0; - cancelled_operations_->destroy(); - cancelled_operations_ = next_op; - } - - while (cleanup_operations_) - { - op_base* next_op = cleanup_operations_->next_; - cleanup_operations_->next_ = 0; - cleanup_operations_->destroy(); - cleanup_operations_ = next_op; - } - - typename operation_map::iterator i = operations_.begin(); - while (i != operations_.end()) - { - typename operation_map::iterator op_iter = i++; - op_base* curr_op = op_iter->second; - operations_.erase(op_iter); - while (curr_op) - { - op_base* next_op = curr_op->next_; - curr_op->next_ = 0; - curr_op->destroy(); - curr_op = next_op; - } - } - } - -private: - // Base class for reactor operations. A function pointer is used instead of - // virtual functions to avoid the associated overhead. - class op_base - { - public: - // Get the descriptor associated with the operation. - Descriptor descriptor() const - { - return descriptor_; - } - - // Perform the operation. - bool invoke(const asio::error_code& result) - { - return invoke_func_(this, result); - } - - // Destroy the operation. - void destroy() - { - return destroy_func_(this); - } - - protected: - typedef bool (*invoke_func_type)(op_base*, - const asio::error_code&); - typedef void (*destroy_func_type)(op_base*); - - // Construct an operation for the given descriptor. - op_base(invoke_func_type invoke_func, - destroy_func_type destroy_func, Descriptor descriptor) - : invoke_func_(invoke_func), - destroy_func_(destroy_func), - descriptor_(descriptor), - next_(0) - { - } - - // Prevent deletion through this type. - ~op_base() - { - } - - private: - friend class reactor_op_queue; - - // The function to be called to dispatch the handler. - invoke_func_type invoke_func_; - - // The function to be called to delete the handler. - destroy_func_type destroy_func_; - - // The descriptor associated with the operation. - Descriptor descriptor_; - - // The next operation for the same file descriptor. - op_base* next_; - }; - - // Adaptor class template for using handlers in operations. - template - class op - : public op_base - { - public: - // Constructor. - op(Descriptor descriptor, Handler handler) - : op_base(&op::invoke_handler, - &op::destroy_handler, descriptor), - handler_(handler) - { - } - - // Invoke the handler. - static bool invoke_handler(op_base* base, - const asio::error_code& result) - { - return static_cast*>(base)->handler_(result); - } - - // Delete the handler. - static void destroy_handler(op_base* base) - { - delete static_cast*>(base); - } - - private: - Handler handler_; - }; - - // The type for a map of operations. - typedef hash_map operation_map; - - // The operations that are currently executing asynchronously. - operation_map operations_; - - // The list of operations that have been cancelled. - op_base* cancelled_operations_; - - // The list of operations to be destroyed. - op_base* cleanup_operations_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_REACTOR_OP_QUEUE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/resolver_service.hpp b/libtorrent/include/libtorrent/asio/detail/resolver_service.hpp deleted file mode 100644 index c820b75f3..000000000 --- a/libtorrent/include/libtorrent/asio/detail/resolver_service.hpp +++ /dev/null @@ -1,357 +0,0 @@ -// -// resolver_service.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_RESOLVER_SERVICE_HPP -#define ASIO_DETAIL_RESOLVER_SERVICE_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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/thread.hpp" - -namespace asio { -namespace detail { - -template -class resolver_service - : public asio::detail::service_base > -{ -private: - // Helper class to perform exception-safe cleanup of addrinfo objects. - class auto_addrinfo - : private asio::detail::noncopyable - { - public: - explicit auto_addrinfo(asio::detail::addrinfo_type* ai) - : ai_(ai) - { - } - - ~auto_addrinfo() - { - if (ai_) - socket_ops::freeaddrinfo(ai_); - } - - operator asio::detail::addrinfo_type*() - { - return ai_; - } - - private: - asio::detail::addrinfo_type* ai_; - }; - -public: - // The implementation type of the resolver. The shared pointer is used as a - // cancellation token to indicate to the background thread that the operation - // has been cancelled. - typedef boost::shared_ptr implementation_type; - struct noop_deleter { void operator()(void*) {} }; - - // The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - // The query type. - typedef typename Protocol::resolver_query query_type; - - // The iterator type. - typedef typename Protocol::resolver_iterator iterator_type; - - // Constructor. - resolver_service(asio::io_service& io_service) - : asio::detail::service_base< - resolver_service >(io_service), - mutex_(), - work_io_service_(new asio::io_service), - work_(new asio::io_service::work(*work_io_service_)), - work_thread_(0) - { - } - - // Destructor. - ~resolver_service() - { - shutdown_service(); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - work_.reset(); - if (work_io_service_) - { - work_io_service_->stop(); - if (work_thread_) - { - work_thread_->join(); - work_thread_.reset(); - } - work_io_service_.reset(); - } - } - - // Construct a new resolver implementation. - void construct(implementation_type& impl) - { - impl.reset(static_cast(0), noop_deleter()); - } - - // Destroy a resolver implementation. - void destroy(implementation_type&) - { - } - - // Cancel pending asynchronous operations. - void cancel(implementation_type& impl) - { - impl.reset(static_cast(0), noop_deleter()); - } - - // Resolve a query to a list of entries. - iterator_type resolve(implementation_type&, const query_type& query, - asio::error_code& ec) - { - asio::detail::addrinfo_type* address_info = 0; - std::string host_name = query.host_name(); - std::string service_name = query.service_name(); - asio::detail::addrinfo_type hints = query.hints(); - - socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0, - service_name.c_str(), &hints, &address_info, ec); - auto_addrinfo auto_address_info(address_info); - - if (ec) - return iterator_type(); - - return iterator_type::create(address_info, host_name, service_name); - } - - template - class resolve_query_handler - { - public: - resolve_query_handler(implementation_type impl, const query_type& query, - asio::io_service& io_service, Handler handler) - : impl_(impl), - query_(query), - io_service_(io_service), - work_(io_service), - handler_(handler) - { - } - - void operator()() - { - // Check if the operation has been cancelled. - if (impl_.expired()) - { - iterator_type iterator; - io_service_.post(asio::detail::bind_handler(handler_, - asio::error::operation_aborted, iterator)); - return; - } - - // Perform the blocking host resolution operation. - asio::detail::addrinfo_type* address_info = 0; - std::string host_name = query_.host_name(); - std::string service_name = query_.service_name(); - asio::detail::addrinfo_type hints = query_.hints(); - asio::error_code ec; - socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0, - service_name.c_str(), &hints, &address_info, ec); - auto_addrinfo auto_address_info(address_info); - - // Invoke the handler and pass the result. - iterator_type iterator; - if (!ec) - iterator = iterator_type::create(address_info, host_name, service_name); - io_service_.post(asio::detail::bind_handler( - handler_, ec, iterator)); - } - - private: - boost::weak_ptr impl_; - query_type query_; - asio::io_service& io_service_; - asio::io_service::work work_; - Handler handler_; - }; - - // Asynchronously resolve a query to a list of entries. - template - void async_resolve(implementation_type& impl, const query_type& query, - Handler handler) - { - if (work_io_service_) - { - start_work_thread(); - work_io_service_->post( - resolve_query_handler( - impl, query, this->io_service(), handler)); - } - } - - // Resolve an endpoint to a list of entries. - iterator_type resolve(implementation_type&, - const endpoint_type& endpoint, asio::error_code& ec) - { - // First try resolving with the service name. If that fails try resolving - // but allow the service to be returned as a number. - char host_name[NI_MAXHOST]; - char service_name[NI_MAXSERV]; - int flags = endpoint.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0; - socket_ops::getnameinfo(endpoint.data(), endpoint.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - if (ec) - { - flags |= NI_NUMERICSERV; - socket_ops::getnameinfo(endpoint.data(), endpoint.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - } - - if (ec) - return iterator_type(); - - return iterator_type::create(endpoint, host_name, service_name); - } - - template - class resolve_endpoint_handler - { - public: - resolve_endpoint_handler(implementation_type impl, - const endpoint_type& endpoint, asio::io_service& io_service, - Handler handler) - : impl_(impl), - endpoint_(endpoint), - io_service_(io_service), - work_(io_service), - handler_(handler) - { - } - - void operator()() - { - // Check if the operation has been cancelled. - if (impl_.expired()) - { - iterator_type iterator; - io_service_.post(asio::detail::bind_handler(handler_, - asio::error::operation_aborted, iterator)); - return; - } - - - // First try resolving with the service name. If that fails try resolving - // but allow the service to be returned as a number. - char host_name[NI_MAXHOST]; - char service_name[NI_MAXSERV]; - int flags = endpoint_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0; - asio::error_code ec; - socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - if (ec) - { - flags |= NI_NUMERICSERV; - socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(), - host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec); - } - - // Invoke the handler and pass the result. - iterator_type iterator; - if (!ec) - iterator = iterator_type::create(endpoint_, host_name, service_name); - io_service_.post(asio::detail::bind_handler( - handler_, ec, iterator)); - } - - private: - boost::weak_ptr impl_; - endpoint_type endpoint_; - asio::io_service& io_service_; - asio::io_service::work work_; - Handler handler_; - }; - - // Asynchronously resolve an endpoint to a list of entries. - template - void async_resolve(implementation_type& impl, const endpoint_type& endpoint, - Handler handler) - { - if (work_io_service_) - { - start_work_thread(); - work_io_service_->post( - resolve_endpoint_handler( - impl, endpoint, this->io_service(), handler)); - } - } - -private: - // Helper class to run the work io_service in a thread. - class work_io_service_runner - { - public: - work_io_service_runner(asio::io_service& io_service) - : io_service_(io_service) {} - void operator()() { io_service_.run(); } - private: - asio::io_service& io_service_; - }; - - // Start the work thread if it's not already running. - void start_work_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (work_thread_ == 0) - { - work_thread_.reset(new asio::detail::thread( - work_io_service_runner(*work_io_service_))); - } - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // Private io_service used for performing asynchronous host resolution. - boost::scoped_ptr work_io_service_; - - // Work for the private io_service to perform. - boost::scoped_ptr work_; - - // Thread used for running the work io_service's run loop. - boost::scoped_ptr work_thread_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_RESOLVER_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/scoped_lock.hpp b/libtorrent/include/libtorrent/asio/detail/scoped_lock.hpp deleted file mode 100644 index 64c77cbab..000000000 --- a/libtorrent/include/libtorrent/asio/detail/scoped_lock.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// scoped_lock.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_SCOPED_LOCK_HPP -#define ASIO_DETAIL_SCOPED_LOCK_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/noncopyable.hpp" - -namespace asio { -namespace detail { - -// Helper class to lock and unlock a mutex automatically. -template -class scoped_lock - : private noncopyable -{ -public: - // Constructor acquires the lock. - scoped_lock(Mutex& m) - : mutex_(m) - { - mutex_.lock(); - locked_ = true; - } - - // Destructor releases the lock. - ~scoped_lock() - { - if (locked_) - mutex_.unlock(); - } - - // Explicitly acquire the lock. - void lock() - { - if (!locked_) - { - mutex_.lock(); - locked_ = true; - } - } - - // Explicitly release the lock. - void unlock() - { - if (locked_) - { - mutex_.unlock(); - locked_ = false; - } - } - -private: - // The underlying mutex. - Mutex& mutex_; - - // Whether the mutex is currently locked or unlocked. - bool locked_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SCOPED_LOCK_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/select_interrupter.hpp b/libtorrent/include/libtorrent/asio/detail/select_interrupter.hpp deleted file mode 100644 index de7fc9611..000000000 --- a/libtorrent/include/libtorrent/asio/detail/select_interrupter.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// -// select_interrupter.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_SELECT_INTERRUPTER_HPP -#define ASIO_DETAIL_SELECT_INTERRUPTER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/pipe_select_interrupter.hpp" -#include "asio/detail/socket_select_interrupter.hpp" - -namespace asio { -namespace detail { - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef socket_select_interrupter select_interrupter; -#else -typedef pipe_select_interrupter select_interrupter; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SELECT_INTERRUPTER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/select_reactor.hpp b/libtorrent/include/libtorrent/asio/detail/select_reactor.hpp deleted file mode 100644 index 83f093ae6..000000000 --- a/libtorrent/include/libtorrent/asio/detail/select_reactor.hpp +++ /dev/null @@ -1,456 +0,0 @@ -// -// select_reactor.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_SELECT_REACTOR_HPP -#define ASIO_DETAIL_SELECT_REACTOR_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/socket_types.hpp" // Must come before posix_time. - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/fd_set_adapter.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/reactor_op_queue.hpp" -#include "asio/detail/select_interrupter.hpp" -#include "asio/detail/select_reactor_fwd.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/signal_blocker.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/thread.hpp" -#include "asio/detail/timer_queue.hpp" - -namespace asio { -namespace detail { - -template -class select_reactor - : public asio::detail::service_base > -{ -public: - // Constructor. - select_reactor(asio::io_service& io_service) - : asio::detail::service_base< - select_reactor >(io_service), - mutex_(), - select_in_progress_(false), - interrupter_(), - read_op_queue_(), - write_op_queue_(), - except_op_queue_(), - pending_cancellations_(), - stop_thread_(false), - thread_(0), - shutdown_(false) - { - if (Own_Thread) - { - asio::detail::signal_blocker sb; - thread_ = new asio::detail::thread( - bind_handler(&select_reactor::call_run_thread, this)); - } - } - - // Destructor. - ~select_reactor() - { - shutdown_service(); - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - stop_thread_ = true; - lock.unlock(); - - if (thread_) - { - interrupter_.interrupt(); - thread_->join(); - delete thread_; - thread_ = 0; - } - - read_op_queue_.destroy_operations(); - write_op_queue_.destroy_operations(); - except_op_queue_.destroy_operations(); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->destroy_timers(); - timer_queues_.clear(); - } - - // Register a socket with the reactor. Returns 0 on success, system error - // code on failure. - int register_descriptor(socket_type descriptor) - { - return 0; - } - - // Start a new read operation. The handler object will be invoked when the - // given descriptor is ready to be read, or an error has occurred. - template - void start_read_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (read_op_queue_.enqueue_operation(descriptor, handler)) - interrupter_.interrupt(); - } - - // Start a new write operation. The handler object will be invoked when the - // given descriptor is ready to be written, or an error has occurred. - template - void start_write_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (write_op_queue_.enqueue_operation(descriptor, handler)) - interrupter_.interrupt(); - } - - // Start a new exception operation. The handler object will be invoked when - // the given descriptor has exception information, or an error has occurred. - template - void start_except_op(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (except_op_queue_.enqueue_operation(descriptor, handler)) - interrupter_.interrupt(); - } - - // Start new write and exception operations. The handler object will be - // invoked when the given descriptor is ready for writing or has exception - // information available, or an error has occurred. - template - void start_write_and_except_ops(socket_type descriptor, Handler handler) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - { - bool interrupt = write_op_queue_.enqueue_operation(descriptor, handler); - interrupt = except_op_queue_.enqueue_operation(descriptor, handler) - || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - } - - // Cancel all operations associated with the given descriptor. The - // handlers associated with the descriptor will be invoked with the - // operation_aborted error. - void cancel_ops(socket_type descriptor) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Enqueue cancellation of all operations associated with the given - // descriptor. The handlers associated with the descriptor will be invoked - // with the operation_aborted error. This function does not acquire the - // select_reactor's mutex, and so should only be used from within a reactor - // handler. - void enqueue_cancel_ops_unlocked(socket_type descriptor) - { - pending_cancellations_.push_back(descriptor); - } - - // Cancel any operations that are running against the descriptor and remove - // its registration from the reactor. - void close_descriptor(socket_type descriptor) - { - asio::detail::mutex::scoped_lock lock(mutex_); - cancel_ops_unlocked(descriptor); - } - - // Add a new timer queue to the reactor. - template - void add_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - timer_queues_.push_back(&timer_queue); - } - - // Remove a timer queue from the reactor. - template - void remove_timer_queue(timer_queue& timer_queue) - { - asio::detail::mutex::scoped_lock lock(mutex_); - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - if (timer_queues_[i] == &timer_queue) - { - timer_queues_.erase(timer_queues_.begin() + i); - return; - } - } - } - - // Schedule a timer in the given timer queue to expire at the specified - // absolute time. The handler object will be invoked when the timer expires. - template - void schedule_timer(timer_queue& timer_queue, - const typename Time_Traits::time_type& time, Handler handler, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (!shutdown_) - if (timer_queue.enqueue_timer(time, handler, token)) - interrupter_.interrupt(); - } - - // Cancel the timer associated with the given token. Returns the number of - // handlers that have been posted or dispatched. - template - std::size_t cancel_timer(timer_queue& timer_queue, void* token) - { - asio::detail::mutex::scoped_lock lock(mutex_); - return timer_queue.cancel_timer(token); - } - -private: - friend class task_io_service >; - - // Run select once until interrupted or events are ready to be dispatched. - void run(bool block) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Dispatch any operation cancellations that were made while the select - // loop was not running. - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - except_op_queue_.dispatch_cancellations(); - - // Check if the thread is supposed to stop. - if (stop_thread_) - { - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - return; - } - - // We can return immediately if there's no work to do and the reactor is - // not supposed to block. - if (!block && read_op_queue_.empty() && write_op_queue_.empty() - && except_op_queue_.empty() && all_timer_queues_are_empty()) - { - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - return; - } - - // Set up the descriptor sets. - fd_set_adapter read_fds; - read_fds.set(interrupter_.read_descriptor()); - read_op_queue_.get_descriptors(read_fds); - fd_set_adapter write_fds; - write_op_queue_.get_descriptors(write_fds); - fd_set_adapter except_fds; - except_op_queue_.get_descriptors(except_fds); - socket_type max_fd = read_fds.max_descriptor(); - if (write_fds.max_descriptor() > max_fd) - max_fd = write_fds.max_descriptor(); - if (except_fds.max_descriptor() > max_fd) - max_fd = except_fds.max_descriptor(); - - // Block on the select call without holding the lock so that new - // operations can be started while the call is executing. - timeval tv_buf = { 0, 0 }; - timeval* tv = block ? get_timeout(tv_buf) : &tv_buf; - select_in_progress_ = true; - lock.unlock(); - asio::error_code ec; - int retval = socket_ops::select(static_cast(max_fd + 1), - read_fds, write_fds, except_fds, tv, ec); - lock.lock(); - select_in_progress_ = false; - - // Block signals while dispatching operations. - asio::detail::signal_blocker sb; - - // Reset the interrupter. - if (retval > 0 && read_fds.is_set(interrupter_.read_descriptor())) - interrupter_.reset(); - - // Dispatch all ready operations. - if (retval > 0) - { - // Exception operations must be processed first to ensure that any - // out-of-band data is read before normal data. - except_op_queue_.dispatch_descriptors(except_fds, - asio::error_code()); - read_op_queue_.dispatch_descriptors(read_fds, - asio::error_code()); - write_op_queue_.dispatch_descriptors(write_fds, - asio::error_code()); - except_op_queue_.dispatch_cancellations(); - read_op_queue_.dispatch_cancellations(); - write_op_queue_.dispatch_cancellations(); - } - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - timer_queues_[i]->dispatch_timers(); - - // Issue any pending cancellations. - for (size_t i = 0; i < pending_cancellations_.size(); ++i) - cancel_ops_unlocked(pending_cancellations_[i]); - pending_cancellations_.clear(); - - // Clean up operations. We must not hold the lock since the operations may - // make calls back into this reactor. - lock.unlock(); - read_op_queue_.cleanup_operations(); - write_op_queue_.cleanup_operations(); - except_op_queue_.cleanup_operations(); - } - - // Run the select loop in the thread. - void run_thread() - { - asio::detail::mutex::scoped_lock lock(mutex_); - while (!stop_thread_) - { - lock.unlock(); - run(true); - lock.lock(); - } - } - - // Entry point for the select loop thread. - static void call_run_thread(select_reactor* reactor) - { - reactor->run_thread(); - } - - // Interrupt the select loop. - void interrupt() - { - interrupter_.interrupt(); - } - - // Check if all timer queues are empty. - bool all_timer_queues_are_empty() const - { - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - if (!timer_queues_[i]->empty()) - return false; - return true; - } - - // Get the timeout value for the select call. - timeval* get_timeout(timeval& tv) - { - if (all_timer_queues_are_empty()) - return 0; - - // By default we will wait no longer than 5 minutes. This will ensure that - // any changes to the system clock are detected after no longer than this. - boost::posix_time::time_duration minimum_wait_duration - = boost::posix_time::minutes(5); - - for (std::size_t i = 0; i < timer_queues_.size(); ++i) - { - boost::posix_time::time_duration wait_duration - = timer_queues_[i]->wait_duration(); - if (wait_duration < minimum_wait_duration) - minimum_wait_duration = wait_duration; - } - - if (minimum_wait_duration > boost::posix_time::time_duration()) - { - tv.tv_sec = minimum_wait_duration.total_seconds(); - tv.tv_usec = minimum_wait_duration.total_microseconds() % 1000000; - } - else - { - tv.tv_sec = 0; - tv.tv_usec = 0; - } - - return &tv; - } - - // Cancel all operations associated with the given descriptor. The do_cancel - // function of the handler objects will be invoked. This function does not - // acquire the select_reactor's mutex. - void cancel_ops_unlocked(socket_type descriptor) - { - bool interrupt = read_op_queue_.cancel_operations(descriptor); - interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt; - interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt; - if (interrupt) - interrupter_.interrupt(); - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // Whether the select loop is currently running or not. - bool select_in_progress_; - - // The interrupter is used to break a blocking select call. - select_interrupter interrupter_; - - // The queue of read operations. - reactor_op_queue read_op_queue_; - - // The queue of write operations. - reactor_op_queue write_op_queue_; - - // The queue of exception operations. - reactor_op_queue except_op_queue_; - - // The timer queues. - std::vector timer_queues_; - - // The descriptors that are pending cancellation. - std::vector pending_cancellations_; - - // Does the reactor loop thread need to stop. - bool stop_thread_; - - // The thread that is running the reactor loop. - asio::detail::thread* thread_; - - // Whether the service has been shut down. - bool shutdown_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SELECT_REACTOR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/select_reactor_fwd.hpp b/libtorrent/include/libtorrent/asio/detail/select_reactor_fwd.hpp deleted file mode 100644 index 3e1687eae..000000000 --- a/libtorrent/include/libtorrent/asio/detail/select_reactor_fwd.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// select_reactor_fwd.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_SELECT_REACTOR_FWD_HPP -#define ASIO_DETAIL_SELECT_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -template -class select_reactor; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SELECT_REACTOR_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/service_base.hpp b/libtorrent/include/libtorrent/asio/detail/service_base.hpp deleted file mode 100644 index 4f375c921..000000000 --- a/libtorrent/include/libtorrent/asio/detail/service_base.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// -// service_base.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_SERVICE_BASE_HPP -#define ASIO_DETAIL_SERVICE_BASE_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/io_service.hpp" -#include "asio/detail/service_id.hpp" - -namespace asio { -namespace detail { - -// Special service base class to keep classes header-file only. -template -class service_base - : public asio::io_service::service -{ -public: - static asio::detail::service_id id; - - // Constructor. - service_base(asio::io_service& io_service) - : asio::io_service::service(io_service) - { - } -}; - -template -asio::detail::service_id service_base::id; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SERVICE_BASE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/service_id.hpp b/libtorrent/include/libtorrent/asio/detail/service_id.hpp deleted file mode 100644 index 8ff19097b..000000000 --- a/libtorrent/include/libtorrent/asio/detail/service_id.hpp +++ /dev/null @@ -1,37 +0,0 @@ -// -// service_id.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_SERVICE_ID_HPP -#define ASIO_DETAIL_SERVICE_ID_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/io_service.hpp" - -namespace asio { -namespace detail { - -// Special derived service id type to keep classes header-file only. -template -class service_id - : public asio::io_service::id -{ -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SERVICE_ID_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/service_registry.hpp b/libtorrent/include/libtorrent/asio/detail/service_registry.hpp deleted file mode 100644 index bd1c3ea5b..000000000 --- a/libtorrent/include/libtorrent/asio/detail/service_registry.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// service_registry.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_SERVICE_REGISTRY_HPP -#define ASIO_DETAIL_SERVICE_REGISTRY_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_id.hpp" - -namespace asio { -namespace detail { - -class service_registry - : private noncopyable -{ -public: - // Constructor. - service_registry(asio::io_service& o) - : owner_(o), - first_service_(0) - { - } - - // Destructor. - ~service_registry() - { - // Shutdown all services. This must be done in a separate loop before the - // services are destroyed since the destructors of user-defined handler - // objects may try to access other service objects. - asio::io_service::service* service = first_service_; - while (service) - { - service->shutdown_service(); - service = service->next_; - } - - // Destroy all services. - while (first_service_) - { - asio::io_service::service* next_service = first_service_->next_; - delete first_service_; - first_service_ = next_service; - } - } - - // Get the service object corresponding to the specified service type. Will - // create a new service object automatically if no such object already - // exists. Ownership of the service object is not transferred to the caller. - template - Service& use_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // First see if there is an existing service object for the given type. - asio::io_service::service* service = first_service_; - while (service) - { - if (service_id_matches(*service, Service::id)) - return *static_cast(service); - service = service->next_; - } - - // Create a new service object. The service registry's mutex is not locked - // at this time to allow for nested calls into this function from the new - // service's constructor. - lock.unlock(); - std::auto_ptr new_service(new Service(owner_)); - init_service_id(*new_service, Service::id); - Service& new_service_ref = *new_service; - lock.lock(); - - // Check that nobody else created another service object of the same type - // while the lock was released. - service = first_service_; - while (service) - { - if (service_id_matches(*service, Service::id)) - return *static_cast(service); - service = service->next_; - } - - // Service was successfully initialised, pass ownership to registry. - new_service->next_ = first_service_; - first_service_ = new_service.release(); - - return new_service_ref; - } - - // Add a service object. Returns false on error, in which case ownership of - // the object is retained by the caller. - template - bool add_service(Service* new_service) - { - asio::detail::mutex::scoped_lock lock(mutex_); - - // Check if there is an existing service object for the given type. - asio::io_service::service* service = first_service_; - while (service) - { - if (service_id_matches(*service, Service::id)) - return false; - service = service->next_; - } - - // Take ownership of the service object. - init_service_id(*new_service, Service::id); - new_service->next_ = first_service_; - first_service_ = new_service; - - return true; - } - - // Check whether a service object of the specified type already exists. - template - bool has_service() const - { - asio::detail::mutex::scoped_lock lock(mutex_); - - asio::io_service::service* service = first_service_; - while (service) - { - if (service_id_matches(*service, Service::id)) - return true; - service = service->next_; - } - - return false; - } - -private: - // Set a service's id. - void init_service_id(asio::io_service::service& service, - const asio::io_service::id& id) - { - service.type_info_ = 0; - service.id_ = &id; - } - - // Set a service's id. - template - void init_service_id(asio::io_service::service& service, - const asio::detail::service_id& /*id*/) - { - service.type_info_ = &typeid(Service); - service.id_ = 0; - } - - // Check if a service matches the given id. - bool service_id_matches(const asio::io_service::service& service, - const asio::io_service::id& id) - { - return service.id_ == &id; - } - - // Check if a service matches the given id. - template - bool service_id_matches(const asio::io_service::service& service, - const asio::detail::service_id& /*id*/) - { - return service.type_info_ != 0 && *service.type_info_ == typeid(Service); - } - - // Mutex to protect access to internal data. - mutable asio::detail::mutex mutex_; - - // The owner of this service registry and the services it contains. - asio::io_service& owner_; - - // The first service in the list of contained services. - asio::io_service::service* first_service_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/service_registry_fwd.hpp b/libtorrent/include/libtorrent/asio/detail/service_registry_fwd.hpp deleted file mode 100644 index 596c24be3..000000000 --- a/libtorrent/include/libtorrent/asio/detail/service_registry_fwd.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// -// service_registry_fwd.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_SERVICE_REGISTRY_FWD_HPP -#define ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class service_registry; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/signal_blocker.hpp b/libtorrent/include/libtorrent/asio/detail/signal_blocker.hpp deleted file mode 100644 index 3eb3ba495..000000000 --- a/libtorrent/include/libtorrent/asio/detail/signal_blocker.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// signal_blocker.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_SIGNAL_BLOCKER_HPP -#define ASIO_DETAIL_SIGNAL_BLOCKER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_signal_blocker.hpp" -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# include "asio/detail/win_signal_blocker.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_signal_blocker.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -#if !defined(BOOST_HAS_THREADS) -typedef null_signal_blocker signal_blocker; -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef win_signal_blocker signal_blocker; -#elif defined(BOOST_HAS_PTHREADS) -typedef posix_signal_blocker signal_blocker; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SIGNAL_BLOCKER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/signal_init.hpp b/libtorrent/include/libtorrent/asio/detail/signal_init.hpp deleted file mode 100644 index 3df395dc3..000000000 --- a/libtorrent/include/libtorrent/asio/detail/signal_init.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// -// signal_init.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_SIGNAL_INIT_HPP -#define ASIO_DETAIL_SIGNAL_INIT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -template -class signal_init -{ -public: - // Constructor. - signal_init() - { - std::signal(Signal, SIG_IGN); - } -}; - -} // namespace detail -} // namespace asio - -#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SIGNAL_INIT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/socket_holder.hpp b/libtorrent/include/libtorrent/asio/detail/socket_holder.hpp deleted file mode 100644 index e45f4fd61..000000000 --- a/libtorrent/include/libtorrent/asio/detail/socket_holder.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// socket_holder.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_SOCKET_HOLDER_HPP -#define ASIO_DETAIL_SOCKET_HOLDER_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/noncopyable.hpp" -#include "asio/detail/socket_ops.hpp" - -namespace asio { -namespace detail { - -// Implement the resource acquisition is initialisation idiom for sockets. -class socket_holder - : private noncopyable -{ -public: - // Construct as an uninitialised socket. - socket_holder() - : socket_(invalid_socket) - { - } - - // Construct to take ownership of the specified socket. - explicit socket_holder(socket_type s) - : socket_(s) - { - } - - // Destructor. - ~socket_holder() - { - if (socket_ != invalid_socket) - { - asio::error_code ec; - socket_ops::close(socket_, ec); - } - } - - // Get the underlying socket. - socket_type get() const - { - return socket_; - } - - // Reset to an uninitialised socket. - void reset() - { - if (socket_ != invalid_socket) - { - asio::error_code ec; - socket_ops::close(socket_, ec); - socket_ = invalid_socket; - } - } - - // Reset to take ownership of the specified socket. - void reset(socket_type s) - { - reset(); - socket_ = s; - } - - // Release ownership of the socket. - socket_type release() - { - socket_type tmp = socket_; - socket_ = invalid_socket; - return tmp; - } - -private: - // The underlying socket. - socket_type socket_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_HOLDER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp b/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp deleted file mode 100644 index 166319bb1..000000000 --- a/libtorrent/include/libtorrent/asio/detail/socket_ops.hpp +++ /dev/null @@ -1,1592 +0,0 @@ -// -// socket_ops.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_SOCKET_OPS_HPP -#define ASIO_DETAIL_SOCKET_OPS_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/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(__MACH__) && defined(__APPLE__) -# include -#endif // defined(__MACH__) && defined(__APPLE__) -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { -namespace socket_ops { - -inline void clear_error(asio::error_code& ec) -{ - errno = 0; -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - WSASetLastError(0); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - ec = asio::error_code(); -} - -template -inline ReturnType error_wrapper(ReturnType return_value, - asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - ec = asio::error_code(WSAGetLastError(), asio::native_ecat); -#else - ec = asio::error_code(errno, asio::native_ecat); -#endif - return return_value; -} - -inline socket_type accept(socket_type s, socket_addr_type* addr, - socket_addr_len_type* addrlen, asio::error_code& ec) -{ - clear_error(ec); -#if defined(__MACH__) && defined(__APPLE__) - socket_type new_s = error_wrapper(::accept(s, addr, addrlen), ec); - if (new_s == invalid_socket) - return new_s; - - int optval = 1; - int result = error_wrapper(::setsockopt(new_s, - SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); - if (result != 0) - { - ::close(new_s); - return invalid_socket; - } - - return new_s; -#else - return error_wrapper(::accept(s, addr, addrlen), ec); -#endif -} - -inline int bind(socket_type s, const socket_addr_type* addr, - socket_addr_len_type addrlen, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::bind(s, addr, addrlen), ec); -} - -inline int close(socket_type s, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::closesocket(s), ec); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::close(s), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int shutdown(socket_type s, int what, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::shutdown(s, what), ec); -} - -inline int connect(socket_type s, const socket_addr_type* addr, - socket_addr_len_type addrlen, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::connect(s, addr, addrlen), ec); -} - -inline int listen(socket_type s, int backlog, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::listen(s, backlog), ec); -} - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef WSABUF buf; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef iovec buf; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -inline void init_buf(buf& b, void* data, size_t size) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - b.buf = static_cast(data); - b.len = static_cast(size); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - b.iov_base = data; - b.iov_len = size; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline void init_buf(buf& b, const void* data, size_t size) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - b.buf = static_cast(const_cast(data)); - b.len = static_cast(size); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - b.iov_base = const_cast(data); - b.iov_len = size; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int recv(socket_type s, buf* bufs, size_t count, int flags, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // Receive some data. - DWORD recv_buf_count = static_cast(count); - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = error_wrapper(::WSARecv(s, bufs, - recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec); - if (result != 0) - return -1; - return bytes_transferred; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - msghdr msg; - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = bufs; - msg.msg_iovlen = count; - msg.msg_control = 0; - msg.msg_controllen = 0; - msg.msg_flags = 0; - return error_wrapper(::recvmsg(s, &msg, flags), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags, - socket_addr_type* addr, socket_addr_len_type* addrlen, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // Receive some data. - DWORD recv_buf_count = static_cast(count); - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count, - &bytes_transferred, &recv_flags, addr, addrlen, 0, 0), ec); - if (result != 0) - return -1; - return bytes_transferred; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - msghdr msg; -#if defined(__MACH__) && defined(__APPLE__) \ - && (MAC_OS_X_VERSION_MAX_ALLOWED < 1040) - msg.msg_name = reinterpret_cast(addr); -#else - msg.msg_name = addr; -#endif - msg.msg_namelen = *addrlen; - msg.msg_iov = bufs; - msg.msg_iovlen = count; - msg.msg_control = 0; - msg.msg_controllen = 0; - msg.msg_flags = 0; - int result = error_wrapper(::recvmsg(s, &msg, flags), ec); - *addrlen = msg.msg_namelen; - return result; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int send(socket_type s, const buf* bufs, size_t count, int flags, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // Send the data. - DWORD send_buf_count = static_cast(count); - DWORD bytes_transferred = 0; - DWORD send_flags = flags; - int result = error_wrapper(::WSASend(s, const_cast(bufs), - send_buf_count, &bytes_transferred, send_flags, 0, 0), ec); - if (result != 0) - return -1; - return bytes_transferred; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - msghdr msg; - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = const_cast(bufs); - msg.msg_iovlen = count; - msg.msg_control = 0; - msg.msg_controllen = 0; - msg.msg_flags = 0; -#if defined(__linux__) - flags |= MSG_NOSIGNAL; -#endif // defined(__linux__) - return error_wrapper(::sendmsg(s, &msg, flags), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int sendto(socket_type s, const buf* bufs, size_t count, int flags, - const socket_addr_type* addr, socket_addr_len_type addrlen, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // Send the data. - DWORD send_buf_count = static_cast(count); - DWORD bytes_transferred = 0; - int result = error_wrapper(::WSASendTo(s, const_cast(bufs), - send_buf_count, &bytes_transferred, flags, addr, addrlen, 0, 0), ec); - if (result != 0) - return -1; - return bytes_transferred; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - msghdr msg; -#if defined(__MACH__) && defined(__APPLE__) \ - && (MAC_OS_X_VERSION_MAX_ALLOWED < 1040) - msg.msg_name = reinterpret_cast(const_cast(addr)); -#else - msg.msg_name = const_cast(addr); -#endif - msg.msg_namelen = addrlen; - msg.msg_iov = const_cast(bufs); - msg.msg_iovlen = count; - msg.msg_control = 0; - msg.msg_controllen = 0; - msg.msg_flags = 0; -#if defined(__linux__) - flags |= MSG_NOSIGNAL; -#endif // defined(__linux__) - return error_wrapper(::sendmsg(s, &msg, flags), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline socket_type socket(int af, int type, int protocol, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0, - WSA_FLAG_OVERLAPPED), ec); - if (s == invalid_socket) - return s; - - if (af == AF_INET6) - { - // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to - // false. This will only succeed on Windows Vista and later versions of - // Windows, where a dual-stack IPv4/v6 implementation is available. - DWORD optval = 0; - ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, - reinterpret_cast(&optval), sizeof(optval)); - } - - return s; -#elif defined(__MACH__) && defined(__APPLE__) - socket_type s = error_wrapper(::socket(af, type, protocol), ec); - if (s == invalid_socket) - return s; - - int optval = 1; - int result = error_wrapper(::setsockopt(s, - SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec); - if (result != 0) - { - ::close(s); - return invalid_socket; - } - - return s; -#else - return error_wrapper(::socket(af, type, protocol), ec); -#endif -} - -inline int setsockopt(socket_type s, int level, int optname, - const void* optval, size_t optlen, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::setsockopt(s, level, optname, - reinterpret_cast(optval), static_cast(optlen)), ec); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::setsockopt(s, level, optname, optval, - static_cast(optlen)), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int getsockopt(socket_type s, int level, int optname, void* optval, - size_t* optlen, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - int tmp_optlen = static_cast(*optlen); - int result = error_wrapper(::getsockopt(s, level, optname, - reinterpret_cast(optval), &tmp_optlen), ec); - *optlen = static_cast(tmp_optlen); - if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY - && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD)) - { - // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only - // supported on Windows Vista and later. To simplify program logic we will - // fake success of getting this option and specify that the value is - // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets - // on Windows platforms pre-Vista. - *static_cast(optval) = 1; - clear_error(ec); - } - return result; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - socklen_t tmp_optlen = static_cast(*optlen); - int result = error_wrapper(::getsockopt(s, level, optname, - optval, &tmp_optlen), ec); - *optlen = static_cast(tmp_optlen); -#if defined(__linux__) - if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int) - && (optname == SO_SNDBUF || optname == SO_RCVBUF)) - { - // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel - // to set the buffer size to N*2. Linux puts additional stuff into the - // buffers so that only about half is actually available to the application. - // The retrieved value is divided by 2 here to make it appear as though the - // correct value has been set. - *static_cast(optval) /= 2; - } -#endif // defined(__linux__) - return result; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int getpeername(socket_type s, socket_addr_type* addr, - socket_addr_len_type* addrlen, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::getpeername(s, addr, addrlen), ec); -} - -inline int getsockname(socket_type s, socket_addr_type* addr, - socket_addr_len_type* addrlen, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::getsockname(s, addr, addrlen), ec); -} - -inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::ioctlsocket(s, cmd, arg), ec); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::ioctl(s, cmd, arg), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int select(int nfds, fd_set* readfds, fd_set* writefds, - fd_set* exceptfds, timeval* timeout, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - if (!readfds && !writefds && !exceptfds && timeout) - { - DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; - if (milliseconds == 0) - milliseconds = 1; // Force context switch. - ::Sleep(milliseconds); - ec = asio::error_code(); - return 0; - } - - // The select() call allows timeout values measured in microseconds, but the - // system clock (as wrapped by boost::posix_time::microsec_clock) typically - // has a resolution of 10 milliseconds. This can lead to a spinning select - // reactor, meaning increased CPU usage, when waiting for the earliest - // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight - // spin we'll use a minimum timeout of 1 millisecond. - if (timeout && timeout->tv_sec == 0 - && timeout->tv_usec > 0 && timeout->tv_usec < 1000) - timeout->tv_usec = 1000; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return error_wrapper(::select(nfds, readfds, - writefds, exceptfds, timeout), ec); -} - -inline int poll_read(socket_type s, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - FD_SET fds; - FD_ZERO(&fds); - FD_SET(s, &fds); - clear_error(ec); - return error_wrapper(::select(s, &fds, 0, 0, 0), ec); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - pollfd fds; - fds.fd = s; - fds.events = POLLIN; - fds.revents = 0; - clear_error(ec); - return error_wrapper(::poll(&fds, 1, -1), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int poll_write(socket_type s, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - FD_SET fds; - FD_ZERO(&fds); - FD_SET(s, &fds); - clear_error(ec); - return error_wrapper(::select(s, 0, &fds, 0, 0), ec); -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - pollfd fds; - fds.fd = s; - fds.events = POLLOUT; - fds.revents = 0; - clear_error(ec); - return error_wrapper(::poll(&fds, 1, -1), ec); -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline const char* inet_ntop(int af, const void* src, char* dest, size_t length, - unsigned long scope_id, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - using namespace std; // For memcpy. - - if (af != AF_INET && af != AF_INET6) - { - ec = asio::error::address_family_not_supported; - return 0; - } - - sockaddr_storage_type address; - DWORD address_length; - if (af == AF_INET) - { - address_length = sizeof(sockaddr_in4_type); - sockaddr_in4_type* ipv4_address = - reinterpret_cast(&address); - ipv4_address->sin_family = AF_INET; - ipv4_address->sin_port = 0; - memcpy(&ipv4_address->sin_addr, src, sizeof(in4_addr_type)); - } - else // AF_INET6 - { - address_length = sizeof(sockaddr_in6_type); - sockaddr_in6_type* ipv6_address = - reinterpret_cast(&address); - ipv6_address->sin6_family = AF_INET6; - ipv6_address->sin6_port = 0; - ipv6_address->sin6_flowinfo = 0; - ipv6_address->sin6_scope_id = scope_id; - memcpy(&ipv6_address->sin6_addr, src, sizeof(in6_addr_type)); - } - - DWORD string_length = static_cast(length); - int result = error_wrapper(::WSAAddressToStringA( - reinterpret_cast(&address), - address_length, 0, dest, &string_length), ec); - - // Windows may set error code on success. - if (result != socket_error_retval) - clear_error(ec); - - // Windows may not set an error code on failure. - else if (result == socket_error_retval && !ec) - ec = asio::error::invalid_argument; - - return result == socket_error_retval ? 0 : dest; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec); - if (result == 0 && !ec) - ec = asio::error::invalid_argument; - if (result != 0 && af == AF_INET6 && scope_id != 0) - { - using namespace std; // For strcat and sprintf. - char if_name[IF_NAMESIZE + 1] = "%"; - const in6_addr_type* ipv6_address = static_cast(src); - bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address); - if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0) - sprintf(if_name + 1, "%lu", scope_id); - strcat(dest, if_name); - } - return result; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int inet_pton(int af, const char* src, void* dest, - unsigned long* scope_id, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - using namespace std; // For memcpy and strcmp. - - if (af != AF_INET && af != AF_INET6) - { - ec = asio::error::address_family_not_supported; - return -1; - } - - sockaddr_storage_type address; - int address_length = sizeof(sockaddr_storage_type); - int result = error_wrapper(::WSAStringToAddressA( - const_cast(src), af, 0, - reinterpret_cast(&address), - &address_length), ec); - - if (af == AF_INET) - { - if (result != socket_error_retval) - { - sockaddr_in4_type* ipv4_address = - reinterpret_cast(&address); - memcpy(dest, &ipv4_address->sin_addr, sizeof(in4_addr_type)); - clear_error(ec); - } - else if (strcmp(src, "255.255.255.255") == 0) - { - static_cast(dest)->s_addr = INADDR_NONE; - clear_error(ec); - } - } - else // AF_INET6 - { - if (result != socket_error_retval) - { - sockaddr_in6_type* ipv6_address = - reinterpret_cast(&address); - memcpy(dest, &ipv6_address->sin6_addr, sizeof(in6_addr_type)); - if (scope_id) - *scope_id = ipv6_address->sin6_scope_id; - clear_error(ec); - } - } - - // Windows may not set an error code on failure. - if (result == socket_error_retval && !ec) - ec = asio::error::invalid_argument; - - return result == socket_error_retval ? -1 : 1; -#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - int result = error_wrapper(::inet_pton(af, src, dest), ec); - if (result <= 0 && !ec) - ec = asio::error::invalid_argument; - if (result > 0 && af == AF_INET6 && scope_id) - { - using namespace std; // For strchr and atoi. - *scope_id = 0; - if (const char* if_name = strchr(src, '%')) - { - in6_addr_type* ipv6_address = static_cast(dest); - bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address); - if (is_link_local) - *scope_id = if_nametoindex(if_name + 1); - if (*scope_id == 0) - *scope_id = atoi(if_name + 1); - } - } - return result; -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -} - -inline int gethostname(char* name, int namelen, asio::error_code& ec) -{ - clear_error(ec); - return error_wrapper(::gethostname(name, namelen), ec); -} - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \ - || defined(__MACH__) && defined(__APPLE__) - -// The following functions are only needed for emulation of getaddrinfo and -// getnameinfo. - -inline asio::error_code translate_netdb_error(int error) -{ - switch (error) - { - case 0: - return asio::error_code(); - case HOST_NOT_FOUND: - return asio::error::host_not_found; - case TRY_AGAIN: - return asio::error::host_not_found_try_again; - case NO_RECOVERY: - return asio::error::no_recovery; - case NO_DATA: - return asio::error::no_data; - default: - BOOST_ASSERT(false); - return asio::error::invalid_argument; - } -} - -inline hostent* gethostbyaddr(const char* addr, int length, int af, - hostent* result, char* buffer, int buflength, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - (void)(buffer); - (void)(buflength); - hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec); - if (!retval) - return 0; - *result = *retval; - return retval; -#elif defined(__sun) || defined(__QNX__) - int error = 0; - hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result, - buffer, buflength, &error), ec); - if (error) - ec = translate_netdb_error(error); - return retval; -#elif defined(__MACH__) && defined(__APPLE__) - (void)(buffer); - (void)(buflength); - int error = 0; - hostent* retval = error_wrapper(::getipnodebyaddr( - addr, length, af, &error), ec); - if (error) - ec = translate_netdb_error(error); - if (!retval) - return 0; - *result = *retval; - return retval; -#else - hostent* retval = 0; - int error = 0; - error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer, - buflength, &retval, &error), ec); - if (error) - ec = translate_netdb_error(error); - return retval; -#endif -} - -inline hostent* gethostbyname(const char* name, int af, struct hostent* result, - char* buffer, int buflength, int ai_flags, asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - (void)(buffer); - (void)(buflength); - (void)(ai_flags); - if (af != AF_INET) - { - ec = asio::error::address_family_not_supported; - return 0; - } - hostent* retval = error_wrapper(::gethostbyname(name), ec); - if (!retval) - return 0; - *result = *retval; - return result; -#elif defined(__sun) || defined(__QNX__) - (void)(ai_flags); - if (af != AF_INET) - { - ec = asio::error::address_family_not_supported; - return 0; - } - int error = 0; - hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer, - buflength, &error), ec); - if (error) - ec = translate_netdb_error(error); - return retval; -#elif defined(__MACH__) && defined(__APPLE__) - (void)(buffer); - (void)(buflength); - int error = 0; - hostent* retval = error_wrapper(::getipnodebyname( - name, af, ai_flags, &error), ec); - if (error) - ec = translate_netdb_error(error); - if (!retval) - return 0; - *result = *retval; - return retval; -#else - (void)(ai_flags); - if (af != AF_INET) - { - ec = asio::error::address_family_not_supported; - return 0; - } - hostent* retval = 0; - int error = 0; - error_wrapper(::gethostbyname_r(name, result, - buffer, buflength, &retval, &error), ec); - if (error) - ec = translate_netdb_error(error); - return retval; -#endif -} - -inline void freehostent(hostent* h) -{ -#if defined(__MACH__) && defined(__APPLE__) - if (h) - ::freehostent(h); -#else - (void)(h); -#endif -} - -// Emulation of getaddrinfo based on implementation in: -// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998. - -struct gai_search -{ - const char* host; - int family; -}; - -inline int gai_nsearch(const char* host, - const addrinfo_type* hints, gai_search (&search)[2]) -{ - int search_count = 0; - if (host == 0 || host[0] == '\0') - { - if (hints->ai_flags & AI_PASSIVE) - { - // No host and AI_PASSIVE implies wildcard bind. - switch (hints->ai_family) - { - case AF_INET: - search[search_count].host = "0.0.0.0"; - search[search_count].family = AF_INET; - ++search_count; - break; - case AF_INET6: - search[search_count].host = "0::0"; - search[search_count].family = AF_INET6; - ++search_count; - break; - case AF_UNSPEC: - search[search_count].host = "0::0"; - search[search_count].family = AF_INET6; - ++search_count; - search[search_count].host = "0.0.0.0"; - search[search_count].family = AF_INET; - ++search_count; - break; - default: - break; - } - } - else - { - // No host and not AI_PASSIVE means connect to local host. - switch (hints->ai_family) - { - case AF_INET: - search[search_count].host = "localhost"; - search[search_count].family = AF_INET; - ++search_count; - break; - case AF_INET6: - search[search_count].host = "localhost"; - search[search_count].family = AF_INET6; - ++search_count; - break; - case AF_UNSPEC: - search[search_count].host = "localhost"; - search[search_count].family = AF_INET6; - ++search_count; - search[search_count].host = "localhost"; - search[search_count].family = AF_INET; - ++search_count; - break; - default: - break; - } - } - } - else - { - // Host is specified. - switch (hints->ai_family) - { - case AF_INET: - search[search_count].host = host; - search[search_count].family = AF_INET; - ++search_count; - break; - case AF_INET6: - search[search_count].host = host; - search[search_count].family = AF_INET6; - ++search_count; - break; - case AF_UNSPEC: - search[search_count].host = host; - search[search_count].family = AF_INET6; - ++search_count; - search[search_count].host = host; - search[search_count].family = AF_INET; - ++search_count; - break; - default: - break; - } - } - return search_count; -} - -template -inline T* gai_alloc(std::size_t size = sizeof(T)) -{ - using namespace std; - T* p = static_cast(::operator new(size, std::nothrow)); - if (p) - memset(p, 0, size); - return p; -} - -inline void gai_free(void* p) -{ - ::operator delete(p); -} - -enum { gai_clone_flag = 1 << 30 }; - -inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints, - const void* addr, int family) -{ - using namespace std; - - addrinfo_type* ai = gai_alloc(); - if (ai == 0) - return EAI_MEMORY; - - ai->ai_next = 0; - **next = ai; - *next = &ai->ai_next; - - ai->ai_canonname = 0; - ai->ai_socktype = hints->ai_socktype; - if (ai->ai_socktype == 0) - ai->ai_flags |= gai_clone_flag; - ai->ai_protocol = hints->ai_protocol; - ai->ai_family = family; - - switch (ai->ai_family) - { - case AF_INET: - { - sockaddr_in4_type* sinptr = gai_alloc(); - if (sinptr == 0) - return EAI_MEMORY; - sinptr->sin_family = AF_INET; - memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type)); - ai->ai_addr = reinterpret_cast(sinptr); - ai->ai_addrlen = sizeof(sockaddr_in4_type); - break; - } - case AF_INET6: - { - sockaddr_in6_type* sin6ptr = gai_alloc(); - if (sin6ptr == 0) - return EAI_MEMORY; - sin6ptr->sin6_family = AF_INET6; - memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type)); - ai->ai_addr = reinterpret_cast(sin6ptr); - ai->ai_addrlen = sizeof(sockaddr_in6_type); - break; - } - default: - break; - } - - return 0; -} - -inline addrinfo_type* gai_clone(addrinfo_type* ai) -{ - using namespace std; - - addrinfo_type* new_ai = gai_alloc(); - if (new_ai == 0) - return new_ai; - - new_ai->ai_next = ai->ai_next; - ai->ai_next = new_ai; - - new_ai->ai_flags = 0; - new_ai->ai_family = ai->ai_family; - new_ai->ai_socktype = ai->ai_socktype; - new_ai->ai_protocol = ai->ai_protocol; - new_ai->ai_canonname = 0; - new_ai->ai_addrlen = ai->ai_addrlen; - new_ai->ai_addr = gai_alloc(ai->ai_addrlen); - memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen); - - return new_ai; -} - -inline int gai_port(addrinfo_type* aihead, int port, int socktype) -{ - int num_found = 0; - - for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next) - { - if (ai->ai_flags & gai_clone_flag) - { - if (ai->ai_socktype != 0) - { - ai = gai_clone(ai); - if (ai == 0) - return -1; - // ai now points to newly cloned entry. - } - } - else if (ai->ai_socktype != socktype) - { - // Ignore if mismatch on socket type. - continue; - } - - ai->ai_socktype = socktype; - - switch (ai->ai_family) - { - case AF_INET: - { - sockaddr_in4_type* sinptr = - reinterpret_cast(ai->ai_addr); - sinptr->sin_port = port; - ++num_found; - break; - } - case AF_INET6: - { - sockaddr_in6_type* sin6ptr = - reinterpret_cast(ai->ai_addr); - sin6ptr->sin6_port = port; - ++num_found; - break; - } - default: - break; - } - } - - return num_found; -} - -inline int gai_serv(addrinfo_type* aihead, - const addrinfo_type* hints, const char* serv) -{ - using namespace std; - - int num_found = 0; - - if ( -#if defined(AI_NUMERICSERV) - (hints->ai_flags & AI_NUMERICSERV) || -#endif - isdigit(serv[0])) - { - int port = htons(atoi(serv)); - if (hints->ai_socktype) - { - // Caller specifies socket type. - int rc = gai_port(aihead, port, hints->ai_socktype); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - } - else - { - // Caller does not specify socket type. - int rc = gai_port(aihead, port, SOCK_STREAM); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - rc = gai_port(aihead, port, SOCK_DGRAM); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - } - } - else - { - // Try service name with TCP first, then UDP. - if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM) - { - servent* sptr = getservbyname(serv, "tcp"); - if (sptr != 0) - { - int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - } - } - if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM) - { - servent* sptr = getservbyname(serv, "udp"); - if (sptr != 0) - { - int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM); - if (rc < 0) - return EAI_MEMORY; - num_found += rc; - } - } - } - - if (num_found == 0) - { - if (hints->ai_socktype == 0) - { - // All calls to getservbyname() failed. - return EAI_NONAME; - } - else - { - // Service not supported for socket type. - return EAI_SERVICE; - } - } - - return 0; -} - -inline int gai_echeck(const char* host, const char* service, - int flags, int family, int socktype, int protocol) -{ - (void)(flags); - (void)(protocol); - - // Host or service must be specified. - if (host == 0 || host[0] == '\0') - if (service == 0 || service[0] == '\0') - return EAI_NONAME; - - // Check combination of family and socket type. - switch (family) - { - case AF_UNSPEC: - break; - case AF_INET: - case AF_INET6: - if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM) - return EAI_SOCKTYPE; - break; - default: - return EAI_FAMILY; - } - - return 0; -} - -inline void freeaddrinfo_emulation(addrinfo_type* aihead) -{ - addrinfo_type* ai = aihead; - while (ai) - { - gai_free(ai->ai_addr); - gai_free(ai->ai_canonname); - addrinfo_type* ainext = ai->ai_next; - gai_free(ai); - ai = ainext; - } -} - -inline int getaddrinfo_emulation(const char* host, const char* service, - const addrinfo_type* hintsp, addrinfo_type** result) -{ - // Set up linked list of addrinfo structures. - addrinfo_type* aihead = 0; - addrinfo_type** ainext = &aihead; - char* canon = 0; - - // Supply default hints if not specified by caller. - addrinfo_type hints = addrinfo_type(); - hints.ai_family = AF_UNSPEC; - if (hintsp) - hints = *hintsp; - - // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED - // and AI_ALL flags. -#if defined(AI_V4MAPPED) - if (hints.ai_family != AF_INET6) - hints.ai_flags &= ~AI_V4MAPPED; -#endif -#if defined(AI_ALL) - if (hints.ai_family != AF_INET6) - hints.ai_flags &= ~AI_ALL; -#endif - - // Basic error checking. - int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family, - hints.ai_socktype, hints.ai_protocol); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - return rc; - } - - gai_search search[2]; - int search_count = gai_nsearch(host, &hints, search); - for (gai_search* sptr = search; sptr < search + search_count; ++sptr) - { - // Check for IPv4 dotted decimal string. - in4_addr_type inaddr; - asio::error_code ec; - if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1) - { - if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - return EAI_FAMILY; - } - if (sptr->family == AF_INET) - { - rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - return rc; - } - } - continue; - } - - // Check for IPv6 hex string. - in6_addr_type in6addr; - if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1) - { - if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - return EAI_FAMILY; - } - if (sptr->family == AF_INET6) - { - rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - return rc; - } - } - continue; - } - - // Look up hostname. - hostent hent; - char hbuf[8192] = ""; - hostent* hptr = socket_ops::gethostbyname(sptr->host, - sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec); - if (hptr == 0) - { - if (search_count == 2) - { - // Failure is OK if there are multiple searches. - continue; - } - freeaddrinfo_emulation(aihead); - gai_free(canon); - if (ec == asio::error::host_not_found) - return EAI_NONAME; - if (ec == asio::error::host_not_found_try_again) - return EAI_AGAIN; - if (ec == asio::error::no_recovery) - return EAI_FAIL; - if (ec == asio::error::no_data) - return EAI_NONAME; - return EAI_NONAME; - } - - // Check for address family mismatch if one was specified. - if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - socket_ops::freehostent(hptr); - return EAI_FAMILY; - } - - // Save canonical name first time. - if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0] - && (hints.ai_flags & AI_CANONNAME) && canon == 0) - { - canon = gai_alloc(strlen(hptr->h_name) + 1); - if (canon == 0) - { - freeaddrinfo_emulation(aihead); - socket_ops::freehostent(hptr); - return EAI_MEMORY; - } - strcpy(canon, hptr->h_name); - } - - // Create an addrinfo structure for each returned address. - for (char** ap = hptr->h_addr_list; *ap; ++ap) - { - rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - gai_free(canon); - socket_ops::freehostent(hptr); - return EAI_FAMILY; - } - } - - socket_ops::freehostent(hptr); - } - - // Check if we found anything. - if (aihead == 0) - { - gai_free(canon); - return EAI_NONAME; - } - - // Return canonical name in first entry. - if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME)) - { - if (canon) - { - aihead->ai_canonname = canon; - canon = 0; - } - else - { - aihead->ai_canonname = gai_alloc(strlen(search[0].host) + 1); - if (aihead->ai_canonname == 0) - { - freeaddrinfo_emulation(aihead); - return EAI_MEMORY; - } - strcpy(aihead->ai_canonname, search[0].host); - } - } - gai_free(canon); - - // Process the service name. - if (service != 0 && service[0] != '\0') - { - rc = gai_serv(aihead, &hints, service); - if (rc != 0) - { - freeaddrinfo_emulation(aihead); - return rc; - } - } - - // Return result to caller. - *result = aihead; - return 0; -} - -inline asio::error_code getnameinfo_emulation( - const socket_addr_type* sa, socket_addr_len_type salen, char* host, - std::size_t hostlen, char* serv, std::size_t servlen, int flags, - asio::error_code& ec) -{ - using namespace std; - - const char* addr; - size_t addr_len; - unsigned short port; - switch (sa->sa_family) - { - case AF_INET: - if (salen != sizeof(sockaddr_in4_type)) - { - return ec = asio::error::invalid_argument; - } - addr = reinterpret_cast( - &reinterpret_cast(sa)->sin_addr); - addr_len = sizeof(in4_addr_type); - port = reinterpret_cast(sa)->sin_port; - break; - case AF_INET6: - if (salen != sizeof(sockaddr_in6_type)) - { - return ec = asio::error::invalid_argument; - } - addr = reinterpret_cast( - &reinterpret_cast(sa)->sin6_addr); - addr_len = sizeof(in6_addr_type); - port = reinterpret_cast(sa)->sin6_port; - break; - default: - return ec = asio::error::address_family_not_supported; - } - - if (host && hostlen > 0) - { - if (flags & NI_NUMERICHOST) - { - if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0) - { - return ec; - } - } - else - { - hostent hent; - char hbuf[8192] = ""; - hostent* hptr = socket_ops::gethostbyaddr(addr, - static_cast(addr_len), sa->sa_family, - &hent, hbuf, sizeof(hbuf), ec); - if (hptr && hptr->h_name && hptr->h_name[0] != '\0') - { - if (flags & NI_NOFQDN) - { - char* dot = strchr(hptr->h_name, '.'); - if (dot) - { - *dot = 0; - } - } - *host = '\0'; - strncat(host, hptr->h_name, hostlen); - socket_ops::freehostent(hptr); - } - else - { - socket_ops::freehostent(hptr); - if (flags & NI_NAMEREQD) - { - return ec = asio::error::host_not_found; - } - if (socket_ops::inet_ntop(sa->sa_family, - addr, host, hostlen, 0, ec) == 0) - { - return ec; - } - } - } - } - - if (serv && servlen > 0) - { - if (flags & NI_NUMERICSERV) - { - if (servlen < 6) - { - return ec = asio::error::no_buffer_space; - } - sprintf(serv, "%u", ntohs(port)); - } - else - { -#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) - static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - ::pthread_mutex_lock(&mutex); -#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) - servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0); - if (sptr && sptr->s_name && sptr->s_name[0] != '\0') - { - *serv = '\0'; - strncat(serv, sptr->s_name, servlen); - } - else - { - if (servlen < 6) - { - return ec = asio::error::no_buffer_space; - } - sprintf(serv, "%u", ntohs(port)); - } -#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) - ::pthread_mutex_unlock(&mutex); -#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) - } - } - - clear_error(ec); - return ec; -} - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - // || defined(__MACH__) && defined(__APPLE__) - -inline asio::error_code translate_addrinfo_error(int error) -{ - switch (error) - { - case 0: - return asio::error_code(); - case EAI_AGAIN: - return asio::error::host_not_found_try_again; - case EAI_BADFLAGS: - return asio::error::invalid_argument; - case EAI_FAIL: - return asio::error::no_recovery; - case EAI_FAMILY: - return asio::error::address_family_not_supported; - case EAI_MEMORY: - return asio::error::no_memory; - case EAI_NONAME: - return asio::error::host_not_found; - case EAI_SERVICE: - return asio::error::service_not_found; - case EAI_SOCKTYPE: - return asio::error::socket_type_not_supported; - default: // Possibly the non-portable EAI_SYSTEM. -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - return asio::error_code( - WSAGetLastError(), asio::native_ecat); -#else - return asio::error_code( - errno, asio::native_ecat); -#endif - } -} - -inline asio::error_code getaddrinfo(const char* host, - const char* service, const addrinfo_type* hints, addrinfo_type** result, - asio::error_code& ec) -{ - clear_error(ec); -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) - // Building for Windows XP, Windows Server 2003, or later. - int error = ::getaddrinfo(host, service, hints, result); - return ec = translate_addrinfo_error(error); -# else - // Building for Windows 2000 or earlier. - typedef int (WSAAPI *gai_t)(const char*, - const char*, const addrinfo_type*, addrinfo_type**); - if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) - { - if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo")) - { - int error = gai(host, service, hints, result); - return ec = translate_addrinfo_error(error); - } - } - int error = getaddrinfo_emulation(host, service, hints, result); - return ec = translate_addrinfo_error(error); -# endif -#elif defined(__MACH__) && defined(__APPLE__) - int error = getaddrinfo_emulation(host, service, hints, result); - return ec = translate_addrinfo_error(error); -#else - int error = ::getaddrinfo(host, service, hints, result); - return ec = translate_addrinfo_error(error); -#endif -} - -inline void freeaddrinfo(addrinfo_type* ai) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) - // Building for Windows XP, Windows Server 2003, or later. - ::freeaddrinfo(ai); -# else - // Building for Windows 2000 or earlier. - typedef int (WSAAPI *fai_t)(addrinfo_type*); - if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) - { - if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo")) - { - fai(ai); - return; - } - } - freeaddrinfo_emulation(ai); -# endif -#elif defined(__MACH__) && defined(__APPLE__) - freeaddrinfo_emulation(ai); -#else - ::freeaddrinfo(ai); -#endif -} - -inline asio::error_code getnameinfo(const socket_addr_type* addr, - socket_addr_len_type addrlen, char* host, std::size_t hostlen, - char* serv, std::size_t servlen, int flags, asio::error_code& ec) -{ -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) - // Building for Windows XP, Windows Server 2003, or later. - clear_error(ec); - int error = ::getnameinfo(addr, addrlen, host, static_cast(hostlen), - serv, static_cast(servlen), flags); - return ec = translate_addrinfo_error(error); -# else - // Building for Windows 2000 or earlier. - typedef int (WSAAPI *gni_t)(const socket_addr_type*, - socket_addr_len_type, char*, std::size_t, char*, std::size_t, int); - if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32")) - { - if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo")) - { - clear_error(ec); - int error = gni(addr, addrlen, host, hostlen, serv, servlen, flags); - return ec = translate_addrinfo_error(error); - } - } - clear_error(ec); - return getnameinfo_emulation(addr, addrlen, - host, hostlen, serv, servlen, flags, ec); -# endif -#elif defined(__MACH__) && defined(__APPLE__) - using namespace std; // For memcpy. - sockaddr_storage_type tmp_addr; - memcpy(&tmp_addr, addr, addrlen); - tmp_addr.ss_len = addrlen; - addr = reinterpret_cast(&tmp_addr); - clear_error(ec); - return getnameinfo_emulation(addr, addrlen, - host, hostlen, serv, servlen, flags, ec); -#else - clear_error(ec); - int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags); - return ec = translate_addrinfo_error(error); -#endif -} - -inline u_long_type network_to_host_long(u_long_type value) -{ - return ntohl(value); -} - -inline u_long_type host_to_network_long(u_long_type value) -{ - return htonl(value); -} - -inline u_short_type network_to_host_short(u_short_type value) -{ - return ntohs(value); -} - -inline u_short_type host_to_network_short(u_short_type value) -{ - return htons(value); -} - -} // namespace socket_ops -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_OPS_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/socket_option.hpp b/libtorrent/include/libtorrent/asio/detail/socket_option.hpp deleted file mode 100644 index ee867e6b2..000000000 --- a/libtorrent/include/libtorrent/asio/detail/socket_option.hpp +++ /dev/null @@ -1,298 +0,0 @@ -// -// socket_option.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_SOCKET_OPTION_HPP -#define ASIO_DETAIL_SOCKET_OPTION_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { -namespace socket_option { - -// Helper template for implementing boolean-based options. -template -class boolean -{ -public: - // Default constructor. - boolean() - : value_(0) - { - } - - // Construct with a specific option value. - explicit boolean(bool v) - : value_(v ? 1 : 0) - { - } - - // Set the current value of the boolean. - boolean& operator=(bool v) - { - value_ = v ? 1 : 0; - return *this; - } - - // Get the current value of the boolean. - bool value() const - { - return !!value_; - } - - // Convert to bool. - operator bool() const - { - return !!value_; - } - - // Test for false. - bool operator!() const - { - return !value_; - } - - // Get the level of the socket option. - template - int level(const Protocol&) const - { - return Level; - } - - // Get the name of the socket option. - template - int name(const Protocol&) const - { - return Name; - } - - // Get the address of the boolean data. - template - int* data(const Protocol&) - { - return &value_; - } - - // Get the address of the boolean data. - template - const int* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the boolean data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the boolean data. - template - void resize(const Protocol&, std::size_t s) - { - if (s != sizeof(value_)) - throw std::length_error("boolean socket option resize"); - } - -private: - int value_; -}; - -// Helper template for implementing integer options. -template -class integer -{ -public: - // Default constructor. - integer() - : value_(0) - { - } - - // Construct with a specific option value. - explicit integer(int v) - : value_(v) - { - } - - // Set the value of the int option. - integer& operator=(int v) - { - value_ = v; - return *this; - } - - // Get the current value of the int option. - int value() const - { - return value_; - } - - // Get the level of the socket option. - template - int level(const Protocol&) const - { - return Level; - } - - // Get the name of the socket option. - template - int name(const Protocol&) const - { - return Name; - } - - // Get the address of the int data. - template - int* data(const Protocol&) - { - return &value_; - } - - // Get the address of the int data. - template - const int* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the int data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the int data. - template - void resize(const Protocol&, std::size_t s) - { - if (s != sizeof(value_)) - throw std::length_error("integer socket option resize"); - } - -private: - int value_; -}; - -// Helper template for implementing linger options. -template -class linger -{ -public: - // Default constructor. - linger() - { - value_.l_onoff = 0; - value_.l_linger = 0; - } - - // Construct with specific option values. - linger(bool e, int t) - { - enabled(e); - timeout(t); - } - - // Set the value for whether linger is enabled. - void enabled(bool value) - { - value_.l_onoff = value ? 1 : 0; - } - - // Get the value for whether linger is enabled. - bool enabled() const - { - return value_.l_onoff != 0; - } - - // Set the value for the linger timeout. - void timeout(int value) - { -#if defined(WIN32) - value_.l_linger = static_cast(value); -#else - value_.l_linger = value; -#endif - } - - // Get the value for the linger timeout. - int timeout() const - { - return static_cast(value_.l_linger); - } - - // Get the level of the socket option. - template - int level(const Protocol&) const - { - return Level; - } - - // Get the name of the socket option. - template - int name(const Protocol&) const - { - return Name; - } - - // Get the address of the linger data. - template - ::linger* data(const Protocol&) - { - return &value_; - } - - // Get the address of the linger data. - template - const ::linger* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the linger data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the int data. - template - void resize(const Protocol&, std::size_t s) - { - if (s != sizeof(value_)) - throw std::length_error("linger socket option resize"); - } - -private: - ::linger value_; -}; - -} // namespace socket_option -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_OPTION_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/socket_select_interrupter.hpp b/libtorrent/include/libtorrent/asio/detail/socket_select_interrupter.hpp deleted file mode 100644 index 6117d309d..000000000 --- a/libtorrent/include/libtorrent/asio/detail/socket_select_interrupter.hpp +++ /dev/null @@ -1,184 +0,0 @@ -// -// socket_select_interrupter.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_SOCKET_SELECT_INTERRUPTER_HPP -#define ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/socket_holder.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -class socket_select_interrupter -{ -public: - // Constructor. - socket_select_interrupter() - { - asio::error_code ec; - socket_holder acceptor(socket_ops::socket( - AF_INET, SOCK_STREAM, IPPROTO_TCP, ec)); - if (acceptor.get() == invalid_socket) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - int opt = 1; - socket_ops::setsockopt(acceptor.get(), - SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec); - - sockaddr_in4_type addr; - socket_addr_len_type addr_len = sizeof(addr); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - addr.sin_port = 0; - if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr, - addr_len, ec) == socket_error_retval) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr, - &addr_len, ec) == socket_error_retval) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - if (socket_ops::listen(acceptor.get(), - SOMAXCONN, ec) == socket_error_retval) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - socket_holder client(socket_ops::socket( - AF_INET, SOCK_STREAM, IPPROTO_TCP, ec)); - if (client.get() == invalid_socket) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr, - addr_len, ec) == socket_error_retval) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec)); - if (server.get() == invalid_socket) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - ioctl_arg_type non_blocking = 1; - if (socket_ops::ioctl(client.get(), FIONBIO, &non_blocking, ec)) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - opt = 1; - socket_ops::setsockopt(client.get(), - IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec); - - non_blocking = 1; - if (socket_ops::ioctl(server.get(), FIONBIO, &non_blocking, ec)) - { - asio::system_error e(ec, "socket_select_interrupter"); - boost::throw_exception(e); - } - - opt = 1; - socket_ops::setsockopt(server.get(), - IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec); - - read_descriptor_ = server.release(); - write_descriptor_ = client.release(); - } - - // Destructor. - ~socket_select_interrupter() - { - asio::error_code ec; - if (read_descriptor_ != invalid_socket) - socket_ops::close(read_descriptor_, ec); - if (write_descriptor_ != invalid_socket) - socket_ops::close(write_descriptor_, ec); - } - - // Interrupt the select call. - void interrupt() - { - char byte = 0; - socket_ops::buf b; - socket_ops::init_buf(b, &byte, 1); - asio::error_code ec; - socket_ops::send(write_descriptor_, &b, 1, 0, ec); - } - - // Reset the select interrupt. Returns true if the call was interrupted. - bool reset() - { - char data[1024]; - socket_ops::buf b; - socket_ops::init_buf(b, data, sizeof(data)); - asio::error_code ec; - int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec); - bool was_interrupted = (bytes_read > 0); - while (bytes_read == sizeof(data)) - bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec); - return was_interrupted; - } - - // Get the read descriptor to be passed to select. - socket_type read_descriptor() const - { - return read_descriptor_; - } - -private: - // The read end of a connection used to interrupt the select call. This file - // descriptor is passed to select such that when it is time to stop, a single - // byte will be written on the other end of the connection and this - // descriptor will become readable. - socket_type read_descriptor_; - - // The write end of a connection used to interrupt the select call. A single - // byte may be written to this to wake up the select which is waiting for the - // other end to become readable. - socket_type write_descriptor_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/socket_types.hpp b/libtorrent/include/libtorrent/asio/detail/socket_types.hpp deleted file mode 100644 index b2a03f2f1..000000000 --- a/libtorrent/include/libtorrent/asio/detail/socket_types.hpp +++ /dev/null @@ -1,178 +0,0 @@ -// -// socket_types.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_SOCKET_TYPES_HPP -#define ASIO_DETAIL_SOCKET_TYPES_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/push_options.hpp" -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) -# error WinSock.h has already been included -# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_) -# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) -# if defined(_MSC_VER) || defined(__BORLANDC__) -# pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately") -# pragma message("Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target)") -# else // defined(_MSC_VER) || defined(__BORLANDC__) -# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately -# warning Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target) -# endif // defined(_MSC_VER) || defined(__BORLANDC__) -# define _WIN32_WINNT 0x0500 -# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS) -# if defined(_MSC_VER) -# if defined(_WIN32) && !defined(WIN32) -# if !defined(_WINSOCK2API_) -# define WIN32 // Needed for correct types in winsock2.h -# else // !defined(_WINSOCK2API_) -# error Please define the macro WIN32 in your compiler options -# endif // !defined(_WINSOCK2API_) -# endif // defined(_WIN32) && !defined(WIN32) -# endif // defined(_MSC_VER) -# if defined(__BORLANDC__) -# include // Needed for __errno -# if defined(__WIN32__) && !defined(WIN32) -# if !defined(_WINSOCK2API_) -# define WIN32 // Needed for correct types in winsock2.h -# else // !defined(_WINSOCK2API_) -# error Please define the macro WIN32 in your compiler options -# endif // !defined(_WINSOCK2API_) -# endif // defined(__WIN32__) && !defined(WIN32) -# if !defined(_WSPIAPI_H_) -# define _WSPIAPI_H_ -# define ASIO_WSPIAPI_H_DEFINED -# endif // !defined(_WSPIAPI_H_) -# endif // defined(__BORLANDC__) -# if !defined(ASIO_NO_WIN32_LEAN_AND_MEAN) -# if !defined(WIN32_LEAN_AND_MEAN) -# define WIN32_LEAN_AND_MEAN -# endif // !defined(WIN32_LEAN_AND_MEAN) -# endif // !defined(ASIO_NO_WIN32_LEAN_AND_MEAN) -# if defined(__CYGWIN__) -# if !defined(__USE_W32_SOCKETS) -# error You must add -D__USE_W32_SOCKETS to your compiler options. -# endif // !defined(__USE_W32_SOCKETS) -# if !defined(NOMINMAX) -# define NOMINMAX 1 -# endif // !defined(NOMINMAX) -# endif // defined(__CYGWIN__) -# include -# include -# include -# if defined(ASIO_WSPIAPI_H_DEFINED) -# undef _WSPIAPI_H_ -# undef ASIO_WSPIAPI_H_DEFINED -# endif // defined(ASIO_WSPIAPI_H_DEFINED) -# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS) -# if defined(_MSC_VER) || defined(__BORLANDC__) -# pragma comment(lib, "ws2_32.lib") -# pragma comment(lib, "mswsock.lib") -# endif // defined(_MSC_VER) || defined(__BORLANDC__) -# endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS) -# include "asio/detail/old_win_sdk_compat.hpp" -#else -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# if defined(__sun) -# include -# include -# endif -#endif -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -typedef SOCKET socket_type; -const SOCKET invalid_socket = INVALID_SOCKET; -const int socket_error_retval = SOCKET_ERROR; -const int max_addr_v4_str_len = 256; -const int max_addr_v6_str_len = 256; -typedef sockaddr socket_addr_type; -typedef int socket_addr_len_type; -typedef in_addr in4_addr_type; -typedef ip_mreq in4_mreq_type; -typedef sockaddr_in sockaddr_in4_type; -# if defined(ASIO_HAS_OLD_WIN_SDK) -typedef in6_addr_emulation in6_addr_type; -typedef ipv6_mreq_emulation in6_mreq_type; -typedef sockaddr_in6_emulation sockaddr_in6_type; -typedef sockaddr_storage_emulation sockaddr_storage_type; -typedef addrinfo_emulation addrinfo_type; -# else -typedef in6_addr in6_addr_type; -typedef ipv6_mreq in6_mreq_type; -typedef sockaddr_in6 sockaddr_in6_type; -typedef sockaddr_storage sockaddr_storage_type; -typedef addrinfo addrinfo_type; -# endif -typedef unsigned long ioctl_arg_type; -typedef u_long u_long_type; -typedef u_short u_short_type; -const int shutdown_receive = SD_RECEIVE; -const int shutdown_send = SD_SEND; -const int shutdown_both = SD_BOTH; -const int message_peek = MSG_PEEK; -const int message_out_of_band = MSG_OOB; -const int message_do_not_route = MSG_DONTROUTE; -#else -typedef int socket_type; -const int invalid_socket = -1; -const int socket_error_retval = -1; -const int max_addr_v4_str_len = INET_ADDRSTRLEN; -const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE; -typedef sockaddr socket_addr_type; -typedef socklen_t socket_addr_len_type; -typedef in_addr in4_addr_type; -typedef ip_mreq in4_mreq_type; -typedef sockaddr_in sockaddr_in4_type; -typedef in6_addr in6_addr_type; -typedef ipv6_mreq in6_mreq_type; -typedef sockaddr_in6 sockaddr_in6_type; -typedef sockaddr_storage sockaddr_storage_type; -typedef addrinfo addrinfo_type; -typedef int ioctl_arg_type; -typedef uint32_t u_long_type; -typedef uint16_t u_short_type; -const int shutdown_receive = SHUT_RD; -const int shutdown_send = SHUT_WR; -const int shutdown_both = SHUT_RDWR; -const int message_peek = MSG_PEEK; -const int message_out_of_band = MSG_OOB; -const int message_do_not_route = MSG_DONTROUTE; -#endif -const int custom_socket_option_level = 0xA5100000; -const int enable_connection_aborted_option = 1; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_SOCKET_TYPES_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/strand_service.hpp b/libtorrent/include/libtorrent/asio/detail/strand_service.hpp deleted file mode 100644 index f10289090..000000000 --- a/libtorrent/include/libtorrent/asio/detail/strand_service.hpp +++ /dev/null @@ -1,526 +0,0 @@ -// -// strand_service.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_STRAND_SERVICE_HPP -#define ASIO_DETAIL_STRAND_SERVICE_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/call_stack.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/service_base.hpp" - -namespace asio { -namespace detail { - -// Default service implementation for a strand. -class strand_service - : public asio::detail::service_base -{ -public: - class handler_base; - class invoke_current_handler; - class post_next_waiter_on_exit; - - // The underlying implementation of a strand. - class strand_impl - { -#if defined (__BORLANDC__) - public: -#else - private: -#endif - void add_ref() - { - asio::detail::mutex::scoped_lock lock(mutex_); - ++ref_count_; - } - - void release() - { - asio::detail::mutex::scoped_lock lock(mutex_); - --ref_count_; - if (ref_count_ == 0) - { - lock.unlock(); - delete this; - } - } - - private: - // Only this service will have access to the internal values. - friend class strand_service; - friend class post_next_waiter_on_exit; - friend class invoke_current_handler; - - strand_impl(strand_service& owner) - : owner_(owner), - current_handler_(0), - first_waiter_(0), - last_waiter_(0), - ref_count_(0) - { - // Insert implementation into linked list of all implementations. - asio::detail::mutex::scoped_lock lock(owner_.mutex_); - next_ = owner_.impl_list_; - prev_ = 0; - if (owner_.impl_list_) - owner_.impl_list_->prev_ = this; - owner_.impl_list_ = this; - } - - ~strand_impl() - { - // Remove implementation from linked list of all implementations. - asio::detail::mutex::scoped_lock lock(owner_.mutex_); - if (owner_.impl_list_ == this) - owner_.impl_list_ = next_; - if (prev_) - prev_->next_ = next_; - if (next_) - next_->prev_= prev_; - next_ = 0; - prev_ = 0; - lock.unlock(); - - if (current_handler_) - { - current_handler_->destroy(); - } - - while (first_waiter_) - { - handler_base* next = first_waiter_->next_; - first_waiter_->destroy(); - first_waiter_ = next; - } - } - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The service that owns this implementation. - strand_service& owner_; - - // The handler that is ready to execute. If this pointer is non-null then it - // indicates that a handler holds the lock. - handler_base* current_handler_; - - // The start of the list of waiting handlers for the strand. - handler_base* first_waiter_; - - // The end of the list of waiting handlers for the strand. - handler_base* last_waiter_; - - // Storage for posted handlers. - typedef boost::aligned_storage<64> handler_storage_type; -#if defined(__BORLANDC__) - boost::aligned_storage<64> handler_storage_; -#else - handler_storage_type handler_storage_; -#endif - - // Pointers to adjacent socket implementations in linked list. - strand_impl* next_; - strand_impl* prev_; - - // The reference count on the strand implementation. - size_t ref_count_; - -#if !defined(__BORLANDC__) - friend void intrusive_ptr_add_ref(strand_impl* p) - { - p->add_ref(); - } - - friend void intrusive_ptr_release(strand_impl* p) - { - p->release(); - } -#endif - }; - - friend class strand_impl; - - typedef boost::intrusive_ptr implementation_type; - - // Base class for all handler types. - class handler_base - { - public: - typedef void (*invoke_func_type)(handler_base*, - strand_service&, implementation_type&); - typedef void (*destroy_func_type)(handler_base*); - - handler_base(invoke_func_type invoke_func, destroy_func_type destroy_func) - : next_(0), - invoke_func_(invoke_func), - destroy_func_(destroy_func) - { - } - - void invoke(strand_service& service_impl, implementation_type& impl) - { - invoke_func_(this, service_impl, impl); - } - - void destroy() - { - destroy_func_(this); - } - - protected: - ~handler_base() - { - } - - private: - friend class strand_service; - friend class strand_impl; - friend class post_next_waiter_on_exit; - handler_base* next_; - invoke_func_type invoke_func_; - destroy_func_type destroy_func_; - }; - - // Helper class to allow handlers to be dispatched. - class invoke_current_handler - { - public: - invoke_current_handler(strand_service& service_impl, - const implementation_type& impl) - : service_impl_(service_impl), - impl_(impl) - { - } - - void operator()() - { - impl_->current_handler_->invoke(service_impl_, impl_); - } - - friend void* asio_handler_allocate(std::size_t size, - invoke_current_handler* this_handler) - { - return this_handler->do_handler_allocate(size); - } - - friend void asio_handler_deallocate(void*, std::size_t, - invoke_current_handler*) - { - } - - void* do_handler_allocate(std::size_t size) - { -#if defined(__BORLANDC__) - BOOST_ASSERT(size <= boost::aligned_storage<64>::size); -#else - BOOST_ASSERT(size <= strand_impl::handler_storage_type::size); -#endif - return impl_->handler_storage_.address(); - } - - // The asio_handler_invoke hook is not defined here since the default one - // provides the correct behaviour, and including it here breaks MSVC 7.1 - // in some situations. - - private: - strand_service& service_impl_; - implementation_type impl_; - }; - - // Helper class to automatically enqueue next waiter on block exit. - class post_next_waiter_on_exit - { - public: - post_next_waiter_on_exit(strand_service& service_impl, - implementation_type& impl) - : service_impl_(service_impl), - impl_(impl), - cancelled_(false) - { - } - - ~post_next_waiter_on_exit() - { - if (!cancelled_) - { - asio::detail::mutex::scoped_lock lock(impl_->mutex_); - impl_->current_handler_ = impl_->first_waiter_; - if (impl_->current_handler_) - { - impl_->first_waiter_ = impl_->first_waiter_->next_; - if (impl_->first_waiter_ == 0) - impl_->last_waiter_ = 0; - lock.unlock(); - service_impl_.io_service().post( - invoke_current_handler(service_impl_, impl_)); - } - } - } - - void cancel() - { - cancelled_ = true; - } - - private: - strand_service& service_impl_; - implementation_type& impl_; - bool cancelled_; - }; - - // Class template for a waiter. - template - class handler_wrapper - : public handler_base - { - public: - handler_wrapper(Handler handler) - : handler_base(&handler_wrapper::do_invoke, - &handler_wrapper::do_destroy), - handler_(handler) - { - } - - static void do_invoke(handler_base* base, - strand_service& service_impl, implementation_type& impl) - { - // Take ownership of the handler object. - typedef handler_wrapper this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - - post_next_waiter_on_exit p1(service_impl, impl); - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(h->handler_); - - // A handler object must still be valid when the next waiter is posted - // since destroying the last handler might cause the strand object to be - // destroyed. Therefore we create a second post_next_waiter_on_exit object - // that will be destroyed before the handler object. - p1.cancel(); - post_next_waiter_on_exit p2(service_impl, impl); - - // Free the memory associated with the handler. - ptr.reset(); - - // Indicate that this strand is executing on the current thread. - call_stack::context ctx(impl.get()); - - // 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 this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - } - - private: - Handler handler_; - }; - - // Construct a new strand service for the specified io_service. - explicit strand_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - mutex_(), - impl_list_(0) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - // Construct a list of all handlers to be destroyed. - asio::detail::mutex::scoped_lock lock(mutex_); - strand_impl* impl = impl_list_; - handler_base* first_handler = 0; - while (impl) - { - if (impl->current_handler_) - { - impl->current_handler_->next_ = first_handler; - first_handler = impl->current_handler_; - impl->current_handler_ = 0; - } - if (impl->first_waiter_) - { - impl->last_waiter_->next_ = first_handler; - first_handler = impl->first_waiter_; - impl->first_waiter_ = 0; - impl->last_waiter_ = 0; - } - impl = impl->next_; - } - - // Destroy all handlers without holding the lock. - lock.unlock(); - while (first_handler) - { - handler_base* next = first_handler->next_; - first_handler->destroy(); - first_handler = next; - } - } - - // Construct a new strand implementation. - void construct(implementation_type& impl) - { - impl = implementation_type(new strand_impl(*this)); - } - - // Destroy a strand implementation. - void destroy(implementation_type& impl) - { - implementation_type().swap(impl); - } - - // Request the io_service to invoke the given handler. - template - void dispatch(implementation_type& impl, Handler handler) - { - if (call_stack::contains(impl.get())) - { - asio_handler_invoke_helpers::invoke(handler, &handler); - } - else - { - asio::detail::mutex::scoped_lock lock(impl->mutex_); - - // Allocate and construct an object to wrap the handler. - typedef handler_wrapper value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, handler); - - if (impl->current_handler_ == 0) - { - // This handler now has the lock, so can be dispatched immediately. - impl->current_handler_ = ptr.get(); - lock.unlock(); - this->io_service().dispatch(invoke_current_handler(*this, impl)); - ptr.release(); - } - else - { - // Another handler already holds the lock, so this handler must join - // the list of waiters. The handler will be posted automatically when - // its turn comes. - if (impl->last_waiter_) - { - impl->last_waiter_->next_ = ptr.get(); - impl->last_waiter_ = impl->last_waiter_->next_; - } - else - { - impl->first_waiter_ = ptr.get(); - impl->last_waiter_ = ptr.get(); - } - ptr.release(); - } - } - } - - // Request the io_service to invoke the given handler and return immediately. - template - void post(implementation_type& impl, Handler handler) - { - asio::detail::mutex::scoped_lock lock(impl->mutex_); - - // Allocate and construct an object to wrap the handler. - typedef handler_wrapper value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, handler); - - if (impl->current_handler_ == 0) - { - // This handler now has the lock, so can be dispatched immediately. - impl->current_handler_ = ptr.get(); - lock.unlock(); - this->io_service().post(invoke_current_handler(*this, impl)); - ptr.release(); - } - else - { - // Another handler already holds the lock, so this handler must join the - // list of waiters. The handler will be posted automatically when its turn - // comes. - if (impl->last_waiter_) - { - impl->last_waiter_->next_ = ptr.get(); - impl->last_waiter_ = impl->last_waiter_->next_; - } - else - { - impl->first_waiter_ = ptr.get(); - impl->last_waiter_ = ptr.get(); - } - ptr.release(); - } - } - -private: - // Mutex to protect access to the linked list of implementations. - asio::detail::mutex mutex_; - - // The head of a linked list of all implementations. - strand_impl* impl_list_; -}; - -} // namespace detail -} // namespace asio - -#if defined(__BORLANDC__) - -namespace boost { - -inline void intrusive_ptr_add_ref( - asio::detail::strand_service::strand_impl* p) -{ - p->add_ref(); -} - -inline void intrusive_ptr_release( - asio::detail::strand_service::strand_impl* p) -{ - p->release(); -} - -} // namespace boost - -#endif // defined(__BORLANDC__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_STRAND_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp b/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp deleted file mode 100644 index 07df1c18a..000000000 --- a/libtorrent/include/libtorrent/asio/detail/task_io_service.hpp +++ /dev/null @@ -1,538 +0,0 @@ -// -// task_io_service.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_TASK_IO_SERVICE_HPP -#define ASIO_DETAIL_TASK_IO_SERVICE_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/error_code.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/call_stack.hpp" -#include "asio/detail/event.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/task_io_service_fwd.hpp" - -namespace asio { -namespace detail { - -template -class task_io_service - : public asio::detail::service_base > -{ -public: - // Constructor. - task_io_service(asio::io_service& io_service) - : asio::detail::service_base >(io_service), - mutex_(), - task_(use_service(io_service)), - outstanding_work_(0), - handler_queue_(&task_handler_), - handler_queue_end_(&task_handler_), - stopped_(false), - shutdown_(false), - first_idle_thread_(0) - { - } - - void init(size_t /*concurrency_hint*/) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - asio::detail::mutex::scoped_lock lock(mutex_); - shutdown_ = true; - lock.unlock(); - - // Destroy handler objects. - while (handler_queue_) - { - handler_base* h = handler_queue_; - handler_queue_ = h->next_; - if (h != &task_handler_) - h->destroy(); - } - - // Reset handler queue to initial state. - handler_queue_ = &task_handler_; - handler_queue_end_ = &task_handler_; - } - - // Run the event loop until interrupted or no more work. - size_t run(asio::error_code& ec) - { - typename call_stack::context ctx(this); - - idle_thread_info this_idle_thread; - this_idle_thread.prev = &this_idle_thread; - this_idle_thread.next = &this_idle_thread; - - asio::detail::mutex::scoped_lock lock(mutex_); - - size_t n = 0; - while (do_one(lock, &this_idle_thread, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Run until interrupted or one operation is performed. - size_t run_one(asio::error_code& ec) - { - typename call_stack::context ctx(this); - - idle_thread_info this_idle_thread; - this_idle_thread.prev = &this_idle_thread; - this_idle_thread.next = &this_idle_thread; - - asio::detail::mutex::scoped_lock lock(mutex_); - - return do_one(lock, &this_idle_thread, ec); - } - - // Poll for operations without blocking. - size_t poll(asio::error_code& ec) - { - typename call_stack::context ctx(this); - - asio::detail::mutex::scoped_lock lock(mutex_); - - size_t n = 0; - while (do_one(lock, 0, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Poll for one operation without blocking. - size_t poll_one(asio::error_code& ec) - { - typename call_stack::context ctx(this); - - asio::detail::mutex::scoped_lock lock(mutex_); - - return do_one(lock, 0, ec); - } - - // Interrupt the event processing loop. - void stop() - { - asio::detail::mutex::scoped_lock lock(mutex_); - stop_all_threads(); - } - - // Reset in preparation for a subsequent run invocation. - void reset() - { - asio::detail::mutex::scoped_lock lock(mutex_); - stopped_ = false; - } - - // Notify that some work has started. - void work_started() - { - asio::detail::mutex::scoped_lock lock(mutex_); - ++outstanding_work_; - } - - // Notify that some work has finished. - void work_finished() - { - asio::detail::mutex::scoped_lock lock(mutex_); - if (--outstanding_work_ == 0) - stop_all_threads(); - } - - // Request invocation of the given handler. - template - void dispatch(Handler handler) - { - if (call_stack::contains(this)) - asio_handler_invoke_helpers::invoke(handler, &handler); - else - post(handler); - } - - // Request invocation of the given handler and return immediately. - template - void post(Handler handler) - { - // Allocate and construct an operation to wrap the handler. - typedef handler_wrapper value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, handler); - - asio::detail::mutex::scoped_lock lock(mutex_); - - // If the service has been shut down we silently discard the handler. - if (shutdown_) - return; - - // Add the handler to the end of the queue. - if (handler_queue_end_) - { - handler_queue_end_->next_ = ptr.get(); - handler_queue_end_ = ptr.get(); - } - else - { - handler_queue_ = handler_queue_end_ = ptr.get(); - } - ptr.release(); - - // An undelivered handler is treated as unfinished work. - ++outstanding_work_; - - // Wake up a thread to execute the handler. - if (!interrupt_one_idle_thread()) - if (task_handler_.next_ == 0 && handler_queue_end_ != &task_handler_) - task_.interrupt(); - } - -private: - struct idle_thread_info; - - size_t do_one(asio::detail::mutex::scoped_lock& lock, - idle_thread_info* this_idle_thread, asio::error_code& ec) - { - if (outstanding_work_ == 0 && !stopped_) - { - stop_all_threads(); - ec = asio::error_code(); - return 0; - } - - bool polling = !this_idle_thread; - bool task_has_run = false; - while (!stopped_) - { - if (handler_queue_) - { - // Prepare to execute first handler from queue. - handler_base* h = handler_queue_; - handler_queue_ = h->next_; - if (handler_queue_ == 0) - handler_queue_end_ = 0; - bool more_handlers = (handler_queue_ != 0); - lock.unlock(); - - if (h == &task_handler_) - { - // If the task has already run and we're polling then we're done. - if (task_has_run && polling) - { - ec = asio::error_code(); - return 0; - } - task_has_run = true; - - task_cleanup c(lock, *this); - - // Run the task. May throw an exception. Only block if the handler - // queue is empty and we have an idle_thread_info object, otherwise - // we want to return as soon as possible. - task_.run(!more_handlers && !polling); - } - else - { - handler_cleanup c(lock, *this); - - // Invoke the handler. May throw an exception. - h->call(); // call() deletes the handler object - - ec = asio::error_code(); - return 1; - } - } - else if (this_idle_thread) - { - // Nothing to run right now, so just wait for work to do. - if (first_idle_thread_) - { - this_idle_thread->next = first_idle_thread_; - this_idle_thread->prev = first_idle_thread_->prev; - first_idle_thread_->prev->next = this_idle_thread; - first_idle_thread_->prev = this_idle_thread; - } - first_idle_thread_ = this_idle_thread; - this_idle_thread->wakeup_event.clear(); - lock.unlock(); - this_idle_thread->wakeup_event.wait(); - lock.lock(); - if (this_idle_thread->next == this_idle_thread) - { - first_idle_thread_ = 0; - } - else - { - if (first_idle_thread_ == this_idle_thread) - first_idle_thread_ = this_idle_thread->next; - this_idle_thread->next->prev = this_idle_thread->prev; - this_idle_thread->prev->next = this_idle_thread->next; - this_idle_thread->next = this_idle_thread; - this_idle_thread->prev = this_idle_thread; - } - } - else - { - ec = asio::error_code(); - return 0; - } - } - - ec = asio::error_code(); - return 0; - } - - // Stop the task and all idle threads. - void stop_all_threads() - { - stopped_ = true; - interrupt_all_idle_threads(); - if (task_handler_.next_ == 0 && handler_queue_end_ != &task_handler_) - task_.interrupt(); - } - - // Interrupt a single idle thread. Returns true if a thread was interrupted, - // false if no running thread could be found to interrupt. - bool interrupt_one_idle_thread() - { - if (first_idle_thread_) - { - first_idle_thread_->wakeup_event.signal(); - first_idle_thread_ = first_idle_thread_->next; - return true; - } - return false; - } - - // Interrupt all idle threads. - void interrupt_all_idle_threads() - { - if (first_idle_thread_) - { - first_idle_thread_->wakeup_event.signal(); - idle_thread_info* current_idle_thread = first_idle_thread_->next; - while (current_idle_thread != first_idle_thread_) - { - current_idle_thread->wakeup_event.signal(); - current_idle_thread = current_idle_thread->next; - } - } - } - - 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; - friend class task_cleanup; - handler_base* next_; - call_func_type call_func_; - destroy_func_type destroy_func_; - }; - - // Template wrapper for handlers. - template - class handler_wrapper - : public handler_base - { - public: - handler_wrapper(Handler handler) - : handler_base(&handler_wrapper::do_call, - &handler_wrapper::do_destroy), - handler_(handler) - { - } - - static void do_call(handler_base* base) - { - // Take ownership of the handler object. - typedef handler_wrapper this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr 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 this_type; - this_type* h(static_cast(base)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(h->handler_, h); - } - - private: - Handler handler_; - }; - - // Helper class to perform task-related operations on block exit. - class task_cleanup - { - public: - task_cleanup(asio::detail::mutex::scoped_lock& lock, - task_io_service& task_io_svc) - : lock_(lock), - task_io_service_(task_io_svc) - { - } - - ~task_cleanup() - { - // Reinsert the task at the end of the handler queue. - lock_.lock(); - task_io_service_.task_handler_.next_ = 0; - if (task_io_service_.handler_queue_end_) - { - task_io_service_.handler_queue_end_->next_ - = &task_io_service_.task_handler_; - task_io_service_.handler_queue_end_ - = &task_io_service_.task_handler_; - } - else - { - task_io_service_.handler_queue_ - = task_io_service_.handler_queue_end_ - = &task_io_service_.task_handler_; - } - } - - private: - asio::detail::mutex::scoped_lock& lock_; - task_io_service& task_io_service_; - }; - - // Helper class to perform handler-related operations on block exit. - class handler_cleanup; - friend class handler_cleanup; - class handler_cleanup - { - public: - handler_cleanup(asio::detail::mutex::scoped_lock& lock, - task_io_service& task_io_svc) - : lock_(lock), - task_io_service_(task_io_svc) - { - } - - ~handler_cleanup() - { - lock_.lock(); - if (--task_io_service_.outstanding_work_ == 0) - task_io_service_.stop_all_threads(); - } - - private: - asio::detail::mutex::scoped_lock& lock_; - task_io_service& task_io_service_; - }; - - // Mutex to protect access to internal data. - asio::detail::mutex mutex_; - - // The task to be run by this service. - Task& task_; - - // Handler object to represent the position of the task in the queue. - class task_handler - : public handler_base - { - public: - task_handler() - : handler_base(0, 0) - { - } - } task_handler_; - - // The count of unfinished work. - int outstanding_work_; - - // The start of a linked list of handlers that are ready to be delivered. - handler_base* handler_queue_; - - // The end of a linked list of handlers that are ready to be delivered. - handler_base* handler_queue_end_; - - // Flag to indicate that the dispatcher has been stopped. - bool stopped_; - - // Flag to indicate that the dispatcher has been shut down. - bool shutdown_; - - // Structure containing information about an idle thread. - struct idle_thread_info - { - event wakeup_event; - idle_thread_info* prev; - idle_thread_info* next; - }; - - // The number of threads that are currently idle. - idle_thread_info* first_idle_thread_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TASK_IO_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/task_io_service_fwd.hpp b/libtorrent/include/libtorrent/asio/detail/task_io_service_fwd.hpp deleted file mode 100644 index 208a9d3ca..000000000 --- a/libtorrent/include/libtorrent/asio/detail/task_io_service_fwd.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// task_io_service_fwd.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_TASK_IO_SERVICE_FWD_HPP -#define ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -template -class task_io_service; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/thread.hpp b/libtorrent/include/libtorrent/asio/detail/thread.hpp deleted file mode 100644 index b334c38af..000000000 --- a/libtorrent/include/libtorrent/asio/detail/thread.hpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// thread.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_THREAD_HPP -#define ASIO_DETAIL_THREAD_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_thread.hpp" -#elif defined(BOOST_WINDOWS) -# include "asio/detail/win_thread.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_thread.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -#if !defined(BOOST_HAS_THREADS) -typedef null_thread thread; -#elif defined(BOOST_WINDOWS) -typedef win_thread thread; -#elif defined(BOOST_HAS_PTHREADS) -typedef posix_thread thread; -#endif - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_THREAD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/throw_error.hpp b/libtorrent/include/libtorrent/asio/detail/throw_error.hpp deleted file mode 100644 index d2ad09a2e..000000000 --- a/libtorrent/include/libtorrent/asio/detail/throw_error.hpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// throw_error.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_THROW_ERROR_HPP -#define ASIO_DETAIL_THROW_ERROR_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/system_error.hpp" - -namespace asio { -namespace detail { - -inline void throw_error(const asio::error_code& err) -{ - if (err) - { - asio::system_error e(err); - boost::throw_exception(e); - } -} - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_THROW_ERROR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/timer_queue.hpp b/libtorrent/include/libtorrent/asio/detail/timer_queue.hpp deleted file mode 100644 index ab6eac263..000000000 --- a/libtorrent/include/libtorrent/asio/detail/timer_queue.hpp +++ /dev/null @@ -1,347 +0,0 @@ -// -// timer_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_TIMER_QUEUE_HPP -#define ASIO_DETAIL_TIMER_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/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/hash_map.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/timer_queue_base.hpp" - -namespace asio { -namespace detail { - -template -class timer_queue - : public timer_queue_base -{ -public: - // The time type. - typedef typename Time_Traits::time_type time_type; - - // The duration type. - typedef typename Time_Traits::duration_type duration_type; - - // Constructor. - timer_queue() - : timers_(), - heap_() - { - } - - // Add a new timer to the queue. Returns true if this is the timer that is - // earliest in the queue, in which case the reactor's event demultiplexing - // function call may need to be interrupted and restarted. - template - bool enqueue_timer(const time_type& time, Handler handler, void* token) - { - // Ensure that there is space for the timer in the heap. We reserve here so - // that the push_back below will not throw due to a reallocation failure. - heap_.reserve(heap_.size() + 1); - - // Create a new timer object. - std::auto_ptr > new_timer( - new timer(time, handler, token)); - - // Insert the new timer into the hash. - typedef typename hash_map::iterator iterator; - typedef typename hash_map::value_type value_type; - std::pair result = - timers_.insert(value_type(token, new_timer.get())); - if (!result.second) - { - result.first->second->prev_ = new_timer.get(); - new_timer->next_ = result.first->second; - result.first->second = new_timer.get(); - } - - // Put the timer at the correct position in the heap. - new_timer->heap_index_ = heap_.size(); - heap_.push_back(new_timer.get()); - up_heap(heap_.size() - 1); - bool is_first = (heap_[0] == new_timer.get()); - - // Ownership of the timer is transferred to the timer queue. - new_timer.release(); - - return is_first; - } - - // Whether there are no timers in the queue. - virtual bool empty() const - { - return heap_.empty(); - } - - // Get the time for the timer that is earliest in the queue. - virtual boost::posix_time::time_duration wait_duration() const - { - return Time_Traits::to_posix_duration( - Time_Traits::subtract(heap_[0]->time_, Time_Traits::now())); - } - - // Dispatch the timers that are earlier than the specified time. - virtual void dispatch_timers() - { - const time_type now = Time_Traits::now(); - while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_)) - { - timer_base* t = heap_[0]; - remove_timer(t); - t->invoke(asio::error_code()); - } - } - - // Cancel the timer with the given token. The handler will be invoked - // immediately with the result operation_aborted. - std::size_t cancel_timer(void* timer_token) - { - std::size_t num_cancelled = 0; - typedef typename hash_map::iterator iterator; - iterator it = timers_.find(timer_token); - if (it != timers_.end()) - { - timer_base* t = it->second; - while (t) - { - timer_base* next = t->next_; - remove_timer(t); - t->invoke(asio::error::operation_aborted); - t = next; - ++num_cancelled; - } - } - return num_cancelled; - } - - // Destroy all timers. - virtual void destroy_timers() - { - typename hash_map::iterator i = timers_.begin(); - typename hash_map::iterator end = timers_.end(); - while (i != end) - { - timer_base* t = i->second; - typename hash_map::iterator old_i = i++; - timers_.erase(old_i); - t->destroy(); - } - heap_.clear(); - timers_.clear(); - } - -private: - // Base class for timer operations. Function pointers are used instead of - // virtual functions to avoid the associated overhead. - class timer_base - { - public: - // Perform the timer operation and then destroy. - void invoke(const asio::error_code& result) - { - invoke_func_(this, result); - } - - // Destroy the timer operation. - void destroy() - { - destroy_func_(this); - } - - protected: - typedef void (*invoke_func_type)(timer_base*, - const asio::error_code&); - typedef void (*destroy_func_type)(timer_base*); - - // Constructor. - timer_base(invoke_func_type invoke_func, destroy_func_type destroy_func, - const time_type& time, void* token) - : invoke_func_(invoke_func), - destroy_func_(destroy_func), - time_(time), - token_(token), - next_(0), - prev_(0), - heap_index_( - std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION()) - { - } - - // Prevent deletion through this type. - ~timer_base() - { - } - - private: - friend class timer_queue; - - // The function to be called to dispatch the handler. - invoke_func_type invoke_func_; - - // The function to be called to destroy the handler. - destroy_func_type destroy_func_; - - // The time when the operation should fire. - time_type time_; - - // The token associated with the timer. - void* token_; - - // The next timer known to the queue. - timer_base* next_; - - // The previous timer known to the queue. - timer_base* prev_; - - // The index of the timer in the heap. - size_t heap_index_; - }; - - // Adaptor class template for using handlers in timers. - template - class timer - : public timer_base - { - public: - // Constructor. - timer(const time_type& time, Handler handler, void* token) - : timer_base(&timer::invoke_handler, - &timer::destroy_handler, time, token), - handler_(handler) - { - } - - // Invoke the handler and then destroy it. - static void invoke_handler(timer_base* base, - const asio::error_code& result) - { - std::auto_ptr > t(static_cast*>(base)); - t->handler_(result); - } - - // Destroy the handler. - static void destroy_handler(timer_base* base) - { - delete static_cast*>(base); - } - - private: - Handler handler_; - }; - - // Move the item at the given index up the heap to its correct position. - void up_heap(size_t index) - { - size_t parent = (index - 1) / 2; - while (index > 0 - && Time_Traits::less_than(heap_[index]->time_, heap_[parent]->time_)) - { - swap_heap(index, parent); - index = parent; - parent = (index - 1) / 2; - } - } - - // Move the item at the given index down the heap to its correct position. - void down_heap(size_t index) - { - size_t child = index * 2 + 1; - while (child < heap_.size()) - { - size_t min_child = (child + 1 == heap_.size() - || Time_Traits::less_than( - heap_[child]->time_, heap_[child + 1]->time_)) - ? child : child + 1; - if (Time_Traits::less_than(heap_[index]->time_, heap_[min_child]->time_)) - break; - swap_heap(index, min_child); - index = min_child; - child = index * 2 + 1; - } - } - - // Swap two entries in the heap. - void swap_heap(size_t index1, size_t index2) - { - timer_base* tmp = heap_[index1]; - heap_[index1] = heap_[index2]; - heap_[index2] = tmp; - heap_[index1]->heap_index_ = index1; - heap_[index2]->heap_index_ = index2; - } - - // Remove a timer from the heap and list of timers. - void remove_timer(timer_base* t) - { - // Remove the timer from the heap. - size_t index = t->heap_index_; - if (!heap_.empty() && index < heap_.size()) - { - if (index == heap_.size() - 1) - { - heap_.pop_back(); - } - else - { - swap_heap(index, heap_.size() - 1); - heap_.pop_back(); - size_t parent = (index - 1) / 2; - if (index > 0 && Time_Traits::less_than(t->time_, heap_[parent]->time_)) - up_heap(index); - else - down_heap(index); - } - } - - // Remove the timer from the hash. - typedef typename hash_map::iterator iterator; - iterator it = timers_.find(t->token_); - if (it != timers_.end()) - { - if (it->second == t) - it->second = t->next_; - if (t->prev_) - t->prev_->next_ = t->next_; - if (t->next_) - t->next_->prev_ = t->prev_; - if (it->second == 0) - timers_.erase(it); - } - } - - // A hash of timer token to linked lists of timers. - hash_map timers_; - - // The heap of timers, with the earliest timer at the front. - std::vector heap_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TIMER_QUEUE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/timer_queue_base.hpp b/libtorrent/include/libtorrent/asio/detail/timer_queue_base.hpp deleted file mode 100644 index c8be49748..000000000 --- a/libtorrent/include/libtorrent/asio/detail/timer_queue_base.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// -// timer_queue_base.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_TIMER_QUEUE_BASE_HPP -#define ASIO_DETAIL_TIMER_QUEUE_BASE_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/socket_types.hpp" // Must come before posix_time. - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class timer_queue_base - : private noncopyable -{ -public: - // Destructor. - virtual ~timer_queue_base() {} - - // Whether there are no timers in the queue. - virtual bool empty() const = 0; - - // Get the time to wait until the next timer. - virtual boost::posix_time::time_duration wait_duration() const = 0; - - // Dispatch all ready timers. - virtual void dispatch_timers() = 0; - - // Destroy all timers. - virtual void destroy_timers() = 0; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TIMER_QUEUE_BASE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/tss_ptr.hpp b/libtorrent/include/libtorrent/asio/detail/tss_ptr.hpp deleted file mode 100644 index 8a860a68f..000000000 --- a/libtorrent/include/libtorrent/asio/detail/tss_ptr.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// tss_ptr.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_TSS_PTR_HPP -#define ASIO_DETAIL_TSS_PTR_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if !defined(BOOST_HAS_THREADS) -# include "asio/detail/null_tss_ptr.hpp" -#elif defined(BOOST_WINDOWS) -# include "asio/detail/win_tss_ptr.hpp" -#elif defined(BOOST_HAS_PTHREADS) -# include "asio/detail/posix_tss_ptr.hpp" -#else -# error Only Windows and POSIX are supported! -#endif - -namespace asio { -namespace detail { - -template -class tss_ptr -#if !defined(BOOST_HAS_THREADS) - : public null_tss_ptr -#elif defined(BOOST_WINDOWS) - : public win_tss_ptr -#elif defined(BOOST_HAS_PTHREADS) - : public posix_tss_ptr -#endif -{ -public: - void operator=(T* value) - { -#if !defined(BOOST_HAS_THREADS) - null_tss_ptr::operator=(value); -#elif defined(BOOST_WINDOWS) - win_tss_ptr::operator=(value); -#elif defined(BOOST_HAS_PTHREADS) - posix_tss_ptr::operator=(value); -#endif - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_TSS_PTR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_event.hpp b/libtorrent/include/libtorrent/asio/detail/win_event.hpp deleted file mode 100644 index 8de9383da..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_event.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// win_event.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_WIN_EVENT_HPP -#define ASIO_DETAIL_WIN_EVENT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -class win_event - : private noncopyable -{ -public: - // Constructor. - win_event() - : event_(::CreateEvent(0, true, false, 0)) - { - if (!event_) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, asio::native_ecat), - "event"); - boost::throw_exception(e); - } - } - - // Destructor. - ~win_event() - { - ::CloseHandle(event_); - } - - // Signal the event. - void signal() - { - ::SetEvent(event_); - } - - // Reset the event. - void clear() - { - ::ResetEvent(event_); - } - - // Wait for the event to become signalled. - void wait() - { - ::WaitForSingleObject(event_, INFINITE); - } - -private: - HANDLE event_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_EVENT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp b/libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp deleted file mode 100644 index f2632c4d0..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_fd_set_adapter.hpp +++ /dev/null @@ -1,84 +0,0 @@ -// -// win_fd_set_adapter.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_WIN_FD_SET_ADAPTER_HPP -#define ASIO_DETAIL_WIN_FD_SET_ADAPTER_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/socket_types.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -namespace asio { -namespace detail { - -// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements. -class win_fd_set_adapter -{ -public: - enum { win_fd_set_size = 1024 }; - - win_fd_set_adapter() - : max_descriptor_(invalid_socket) - { - fd_set_.fd_count = 0; - } - - void set(socket_type descriptor) - { - for (u_int i = 0; i < fd_set_.fd_count; ++i) - if (fd_set_.fd_array[i] == descriptor) - return; - if (fd_set_.fd_count < win_fd_set_size) - fd_set_.fd_array[fd_set_.fd_count++] = descriptor; - } - - bool is_set(socket_type descriptor) const - { - return !!__WSAFDIsSet(descriptor, - const_cast(reinterpret_cast(&fd_set_))); - } - - operator fd_set*() - { - return reinterpret_cast(&fd_set_); - } - - socket_type max_descriptor() const - { - return max_descriptor_; - } - -private: - // This structure is defined to be compatible with the Windows API fd_set - // structure, but without being dependent on the value of FD_SETSIZE. - struct win_fd_set - { - u_int fd_count; - SOCKET fd_array[win_fd_set_size]; - }; - - win_fd_set fd_set_; - socket_type max_descriptor_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service.hpp b/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service.hpp deleted file mode 100644 index 4957fb01a..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service.hpp +++ /dev/null @@ -1,424 +0,0 @@ -// -// win_iocp_io_service.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_WIN_IOCP_IO_SERVICE_HPP -#define ASIO_DETAIL_WIN_IOCP_IO_SERVICE_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/win_iocp_io_service_fwd.hpp" - -#if defined(ASIO_HAS_IOCP) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/system_error.hpp" -#include "asio/detail/call_stack.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/win_iocp_operation.hpp" - -namespace asio { -namespace detail { - -class win_iocp_io_service - : public asio::detail::service_base -{ -public: - // Base class for all operations. - typedef win_iocp_operation operation; - - // Constructor. - win_iocp_io_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - iocp_(), - outstanding_work_(0), - stopped_(0), - shutdown_(0) - { - } - - void init(size_t concurrency_hint) - { - iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, - static_cast((std::min)(concurrency_hint, DWORD(~0)))); - if (!iocp_.handle) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, asio::native_ecat), - "iocp"); - boost::throw_exception(e); - } - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - ::InterlockedExchange(&shutdown_, 1); - - for (;;) - { - DWORD bytes_transferred = 0; -#if (WINVER < 0x0500) - DWORD completion_key = 0; -#else - DWORD_PTR completion_key = 0; -#endif - LPOVERLAPPED overlapped = 0; - ::SetLastError(0); - BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, - &bytes_transferred, &completion_key, &overlapped, 0); - DWORD last_error = ::GetLastError(); - if (!ok && overlapped == 0 && last_error == WAIT_TIMEOUT) - break; - if (overlapped) - static_cast(overlapped)->destroy(); - } - } - - // Register a handle with the IO completion port. - void register_handle(HANDLE handle) - { - ::CreateIoCompletionPort(handle, iocp_.handle, 0, 0); - } - - // Run the event loop until stopped or no more work. - size_t run(asio::error_code& ec) - { - if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) - { - ec = asio::error_code(); - return 0; - } - - call_stack::context ctx(this); - - size_t n = 0; - while (do_one(true, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Run until stopped or one operation is performed. - size_t run_one(asio::error_code& ec) - { - if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) - { - ec = asio::error_code(); - return 0; - } - - call_stack::context ctx(this); - - return do_one(true, ec); - } - - // Poll for operations without blocking. - size_t poll(asio::error_code& ec) - { - if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) - { - ec = asio::error_code(); - return 0; - } - - call_stack::context ctx(this); - - size_t n = 0; - while (do_one(false, ec)) - if (n != (std::numeric_limits::max)()) - ++n; - return n; - } - - // Poll for one operation without blocking. - size_t poll_one(asio::error_code& ec) - { - if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) - { - ec = asio::error_code(); - return 0; - } - - call_stack::context ctx(this); - - return do_one(false, ec); - } - - // Stop the event processing loop. - void stop() - { - if (::InterlockedExchange(&stopped_, 1) == 0) - { - if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, asio::native_ecat), - "pqcs"); - boost::throw_exception(e); - } - } - } - - // Reset in preparation for a subsequent run invocation. - void reset() - { - ::InterlockedExchange(&stopped_, 0); - } - - // Notify that some work has started. - void work_started() - { - ::InterlockedIncrement(&outstanding_work_); - } - - // Notify that some work has finished. - void work_finished() - { - if (::InterlockedDecrement(&outstanding_work_) == 0) - stop(); - } - - // Request invocation of the given handler. - template - void dispatch(Handler handler) - { - if (call_stack::contains(this)) - asio_handler_invoke_helpers::invoke(handler, &handler); - else - post(handler); - } - - // Request invocation of the given handler and return immediately. - template - void post(Handler handler) - { - // If the service has been shut down we silently discard the handler. - if (::InterlockedExchangeAdd(&shutdown_, 0) != 0) - return; - - // Allocate and construct an operation to wrap the handler. - typedef handler_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, *this, handler); - - // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, ptr.get())) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, asio::native_ecat), - "pqcs"); - boost::throw_exception(e); - } - - // Operation has been successfully posted. - ptr.release(); - } - - // Request invocation of the given OVERLAPPED-derived operation. - void post_completion(win_iocp_operation* op, DWORD op_last_error, - DWORD bytes_transferred) - { - // Enqueue the operation on the I/O completion port. - if (!::PostQueuedCompletionStatus(iocp_.handle, - bytes_transferred, op_last_error, op)) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, asio::native_ecat), - "pqcs"); - boost::throw_exception(e); - } - } - -private: - // Dequeues at most one operation from the I/O completion port, and then - // executes it. Returns the number of operations that were dequeued (i.e. - // either 0 or 1). - size_t do_one(bool block, asio::error_code& ec) - { - for (;;) - { - // Get the next operation from the queue. - DWORD bytes_transferred = 0; -#if (WINVER < 0x0500) - DWORD completion_key = 0; -#else - DWORD_PTR completion_key = 0; -#endif - LPOVERLAPPED overlapped = 0; - ::SetLastError(0); - BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred, - &completion_key, &overlapped, block ? 1000 : 0); - DWORD last_error = ::GetLastError(); - - if (!ok && overlapped == 0) - { - if (block && last_error == WAIT_TIMEOUT) - continue; - ec = asio::error_code(); - return 0; - } - - if (overlapped) - { - // We may have been passed a last_error value in the completion_key. - if (last_error == 0) - { - last_error = completion_key; - } - - // Ensure that the io_service does not exit due to running out of work - // while we make the upcall. - auto_work work(*this); - - // Dispatch the operation. - operation* op = static_cast(overlapped); - op->do_completion(last_error, bytes_transferred); - - ec = asio::error_code(); - return 1; - } - else - { - // The stopped_ flag is always checked to ensure that any leftover - // interrupts from a previous run invocation are ignored. - if (::InterlockedExchangeAdd(&stopped_, 0) != 0) - { - // Wake up next thread that is blocked on GetQueuedCompletionStatus. - if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, - asio::native_ecat); - return 0; - } - - ec = asio::error_code(); - return 0; - } - } - } - } - - struct auto_work - { - auto_work(win_iocp_io_service& io_service) - : io_service_(io_service) - { - io_service_.work_started(); - } - - ~auto_work() - { - io_service_.work_finished(); - } - - private: - win_iocp_io_service& io_service_; - }; - - template - struct handler_operation - : public operation - { - handler_operation(win_iocp_io_service& io_service, - Handler handler) - : operation(&handler_operation::do_completion_impl, - &handler_operation::destroy_impl), - io_service_(io_service), - handler_(handler) - { - io_service_.work_started(); - } - - ~handler_operation() - { - io_service_.work_finished(); - } - - private: - // Prevent copying and assignment. - handler_operation(const handler_operation&); - void operator=(const handler_operation&); - - static void do_completion_impl(operation* op, DWORD, size_t) - { - // Take ownership of the operation object. - typedef handler_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Make the upcall. - asio_handler_invoke_helpers::invoke(handler, &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef handler_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - } - - win_iocp_io_service& io_service_; - Handler handler_; - }; - - // The IO completion port used for queueing operations. - struct iocp_holder - { - HANDLE handle; - iocp_holder() : handle(0) {} - ~iocp_holder() { if (handle) ::CloseHandle(handle); } - } iocp_; - - // The count of unfinished work. - long outstanding_work_; - - // Flag to indicate whether the event loop has been stopped. - long stopped_; - - // Flag to indicate whether the service has been shut down. - long shutdown_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service_fwd.hpp b/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service_fwd.hpp deleted file mode 100644 index 184fdfa18..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_iocp_io_service_fwd.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// -// win_iocp_io_service_fwd.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_WIN_IOCP_IO_SERVICE_FWD_HPP -#define ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -// This service is only supported on Win32 (NT4 and later). -#if !defined(ASIO_DISABLE_IOCP) -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) -#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) - -// Define this to indicate that IOCP is supported on the target platform. -#define ASIO_HAS_IOCP 1 - -namespace asio { -namespace detail { - -class win_iocp_io_service; - -} // namespace detail -} // namespace asio - -#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400) -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) -#endif // !defined(ASIO_DISABLE_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_operation.hpp b/libtorrent/include/libtorrent/asio/detail/win_iocp_operation.hpp deleted file mode 100644 index 34b0fad90..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_iocp_operation.hpp +++ /dev/null @@ -1,81 +0,0 @@ -// -// win_iocp_operation.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_WIN_IOCP_OPERATION_HPP -#define ASIO_DETAIL_WIN_IOCP_OPERATION_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/win_iocp_io_service_fwd.hpp" - -#if defined(ASIO_HAS_IOCP) - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -// Base class for all IOCP operations. A function pointer is used instead of -// virtual functions to avoid the associated overhead. -// -// This class inherits from OVERLAPPED so that we can downcast to get back to -// the win_iocp_operation pointer from the LPOVERLAPPED out parameter of -// GetQueuedCompletionStatus. -struct win_iocp_operation - : public OVERLAPPED -{ - typedef void (*invoke_func_type)(win_iocp_operation*, DWORD, size_t); - typedef void (*destroy_func_type)(win_iocp_operation*); - - win_iocp_operation(invoke_func_type invoke_func, - destroy_func_type destroy_func) - : invoke_func_(invoke_func), - destroy_func_(destroy_func) - { - Internal = 0; - InternalHigh = 0; - Offset = 0; - OffsetHigh = 0; - hEvent = 0; - } - - void do_completion(DWORD last_error, size_t bytes_transferred) - { - invoke_func_(this, last_error, bytes_transferred); - } - - void destroy() - { - destroy_func_(this); - } - -protected: - // Prevent deletion through this type. - ~win_iocp_operation() - { - } - -private: - invoke_func_type invoke_func_; - destroy_func_type destroy_func_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_OPERATION_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp b/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp deleted file mode 100644 index 667553960..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_iocp_socket_service.hpp +++ /dev/null @@ -1,1963 +0,0 @@ -// -// win_iocp_socket_service.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_WIN_IOCP_SOCKET_SERVICE_HPP -#define ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_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/win_iocp_io_service_fwd.hpp" - -#if defined(ASIO_HAS_IOCP) - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/socket_base.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/mutex.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/socket_holder.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/win_iocp_io_service.hpp" - -namespace asio { -namespace detail { - -template -class win_iocp_socket_service - : public asio::detail::service_base > -{ -public: - // The protocol type. - typedef Protocol protocol_type; - - // The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - // Base class for all operations. - typedef win_iocp_operation operation; - - struct noop_deleter { void operator()(void*) {} }; - typedef boost::shared_ptr shared_cancel_token_type; - typedef boost::weak_ptr weak_cancel_token_type; - - // The native type of a socket. - class native_type - { - public: - native_type(socket_type s) - : socket_(s), - have_remote_endpoint_(false) - { - } - - native_type(socket_type s, const endpoint_type& ep) - : socket_(s), - have_remote_endpoint_(true), - remote_endpoint_(ep) - { - } - - void operator=(socket_type s) - { - socket_ = s; - have_remote_endpoint_ = false; - remote_endpoint_ = endpoint_type(); - } - - operator socket_type() const - { - return socket_; - } - - HANDLE as_handle() const - { - return reinterpret_cast(socket_); - } - - bool have_remote_endpoint() const - { - return have_remote_endpoint_; - } - - endpoint_type remote_endpoint() const - { - return remote_endpoint_; - } - - private: - socket_type socket_; - bool have_remote_endpoint_; - endpoint_type remote_endpoint_; - }; - - // The implementation type of the socket. - class implementation_type - { - public: - // Default constructor. - implementation_type() - : socket_(invalid_socket), - flags_(0), - cancel_token_(), - protocol_(endpoint_type().protocol()), - next_(0), - prev_(0) - { - } - - private: - // Only this service will have access to the internal values. - friend class win_iocp_socket_service; - - // The native socket representation. - native_type socket_; - - enum - { - enable_connection_aborted = 1, // User wants connection_aborted errors. - user_set_linger = 2 // The user set the linger option. - }; - - // Flags indicating the current state of the socket. - unsigned char flags_; - - // We use a shared pointer as a cancellation token here to work around the - // broken Windows support for cancellation. MSDN says that when you call - // closesocket any outstanding WSARecv or WSASend operations will complete - // with the error ERROR_OPERATION_ABORTED. In practice they complete with - // ERROR_NETNAME_DELETED, which means you can't tell the difference between - // a local cancellation and the socket being hard-closed by the peer. - shared_cancel_token_type cancel_token_; - - // The protocol associated with the socket. - protocol_type protocol_; - - // The ID of the thread from which it is safe to cancel asynchronous - // operations. 0 means no asynchronous operations have been started yet. - // ~0 means asynchronous operations have been started from more than one - // thread, and cancellation is not supported for the socket. - DWORD safe_cancellation_thread_id_; - - // Pointers to adjacent socket implementations in linked list. - implementation_type* next_; - implementation_type* prev_; - }; - - // The type of the reactor used for connect operations. - typedef detail::select_reactor reactor_type; - - // The maximum number of buffers to support in a single operation. - enum { max_buffers = 16 }; - - // Constructor. - win_iocp_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - win_iocp_socket_service >(io_service), - iocp_service_(asio::use_service(io_service)), - reactor_(0), - mutex_(), - impl_list_(0) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - // Close all implementations, causing all operations to complete. - asio::detail::mutex::scoped_lock lock(mutex_); - implementation_type* impl = impl_list_; - while (impl) - { - asio::error_code ignored_ec; - close(*impl, ignored_ec); - impl = impl->next_; - } - } - - // Construct a new socket implementation. - void construct(implementation_type& impl) - { - impl.socket_ = invalid_socket; - impl.cancel_token_.reset(); - impl.safe_cancellation_thread_id_ = 0; - - // Insert implementation into linked list of all implementations. - asio::detail::mutex::scoped_lock lock(mutex_); - impl.next_ = impl_list_; - impl.prev_ = 0; - if (impl_list_) - impl_list_->prev_ = &impl; - impl_list_ = &impl; - } - - // Destroy a socket implementation. - void destroy(implementation_type& impl) - { - if (impl.socket_ != invalid_socket) - { - // Check if the reactor was created, in which case we need to close the - // socket on the reactor as well to cancel any operations that might be - // running there. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (reactor) - reactor->close_descriptor(impl.socket_); - - if (impl.flags_ & implementation_type::user_set_linger) - { - ::linger opt; - opt.l_onoff = 0; - opt.l_linger = 0; - asio::error_code ignored_ec; - socket_ops::setsockopt(impl.socket_, - SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec); - } - - asio::error_code ignored_ec; - socket_ops::close(impl.socket_, ignored_ec); - impl.socket_ = invalid_socket; - impl.cancel_token_.reset(); - impl.safe_cancellation_thread_id_ = 0; - } - - // Remove implementation from linked list of all implementations. - asio::detail::mutex::scoped_lock lock(mutex_); - if (impl_list_ == &impl) - impl_list_ = impl.next_; - if (impl.prev_) - impl.prev_->next_ = impl.next_; - if (impl.next_) - impl.next_->prev_= impl.prev_; - impl.next_ = 0; - impl.prev_ = 0; - } - - // Open a new socket implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - socket_holder sock(socket_ops::socket(protocol.family(), protocol.type(), - protocol.protocol(), ec)); - if (sock.get() == invalid_socket) - return ec; - - HANDLE sock_as_handle = reinterpret_cast(sock.get()); - iocp_service_.register_handle(sock_as_handle); - - impl.socket_ = sock.release(); - impl.cancel_token_.reset(static_cast(0), noop_deleter()); - impl.protocol_ = protocol; - ec = asio::error_code(); - return ec; - } - - // Assign a native socket to a socket implementation. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - if (is_open(impl)) - { - ec = asio::error::already_open; - return ec; - } - - iocp_service_.register_handle(native_socket.as_handle()); - - impl.socket_ = native_socket; - impl.cancel_token_.reset(static_cast(0), noop_deleter()); - impl.protocol_ = protocol; - ec = asio::error_code(); - return ec; - } - - // Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return impl.socket_ != invalid_socket; - } - - // Destroy a socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - if (is_open(impl)) - { - // Check if the reactor was created, in which case we need to close the - // socket on the reactor as well to cancel any operations that might be - // running there. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (reactor) - reactor->close_descriptor(impl.socket_); - - if (socket_ops::close(impl.socket_, ec) == socket_error_retval) - return ec; - - impl.socket_ = invalid_socket; - impl.cancel_token_.reset(); - impl.safe_cancellation_thread_id_ = 0; - } - - ec = asio::error_code(); - return ec; - } - - // Get the native socket representation. - native_type native(implementation_type& impl) - { - return impl.socket_; - } - - // Cancel all operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - } - else if (impl.safe_cancellation_thread_id_ == 0) - { - // No operations have been started, so there's nothing to cancel. - ec = asio::error_code(); - } - else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId()) - { - // Asynchronous operations have been started from the current thread only, - // so it is safe to try to cancel them using CancelIo. - socket_type sock = impl.socket_; - HANDLE sock_as_handle = reinterpret_cast(sock); - if (!::CancelIo(sock_as_handle)) - { - DWORD last_error = ::GetLastError(); - ec = asio::error_code(last_error, asio::native_ecat); - } - else - { - ec = asio::error_code(); - } - } - else - { - // Asynchronous operations have been started from more than one thread, - // so cancellation is not safe. - ec = asio::error::operation_not_supported; - } - - return ec; - } - - // Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return false; - } - - asio::detail::ioctl_arg_type value = 0; - socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec); - return ec ? false : value != 0; - } - - // Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - asio::detail::ioctl_arg_type value = 0; - socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec); - return ec ? static_cast(0) : static_cast(value); - } - - // Bind the socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); - return ec; - } - - // Place the socket into the state where it will listen for new connections. - asio::error_code listen(implementation_type& impl, int backlog, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::listen(impl.socket_, backlog, ec); - return ec; - } - - // Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const Option& option, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (option.level(impl.protocol_) == custom_socket_option_level - && option.name(impl.protocol_) == enable_connection_aborted_option) - { - if (option.size(impl.protocol_) != sizeof(int)) - { - ec = asio::error::invalid_argument; - } - else - { - if (*reinterpret_cast(option.data(impl.protocol_))) - impl.flags_ |= implementation_type::enable_connection_aborted; - else - impl.flags_ &= ~implementation_type::enable_connection_aborted; - ec = asio::error_code(); - } - return ec; - } - else - { - if (option.level(impl.protocol_) == SOL_SOCKET - && option.name(impl.protocol_) == SO_LINGER) - { - impl.flags_ |= implementation_type::user_set_linger; - } - - socket_ops::setsockopt(impl.socket_, - option.level(impl.protocol_), option.name(impl.protocol_), - option.data(impl.protocol_), option.size(impl.protocol_), ec); - return ec; - } - } - - // Set a socket option. - template - asio::error_code get_option(const implementation_type& impl, - Option& option, asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - if (option.level(impl.protocol_) == custom_socket_option_level - && option.name(impl.protocol_) == enable_connection_aborted_option) - { - if (option.size(impl.protocol_) != sizeof(int)) - { - ec = asio::error::invalid_argument; - } - else - { - int* target = reinterpret_cast(option.data(impl.protocol_)); - if (impl.flags_ & implementation_type::enable_connection_aborted) - *target = 1; - else - *target = 0; - option.resize(impl.protocol_, sizeof(int)); - ec = asio::error_code(); - } - return ec; - } - else - { - size_t size = option.size(impl.protocol_); - socket_ops::getsockopt(impl.socket_, - option.level(impl.protocol_), option.name(impl.protocol_), - option.data(impl.protocol_), &size, ec); - if (!ec) - option.resize(impl.protocol_, size); - return ec; - } - } - - // Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IO_Control_Command& command, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::ioctl(impl.socket_, command.name(), - static_cast(command.data()), ec); - return ec; - } - - // Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return endpoint_type(); - } - - endpoint_type endpoint; - socket_addr_len_type addr_len = endpoint.capacity(); - if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) - return endpoint_type(); - endpoint.resize(addr_len); - return endpoint; - } - - // Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return endpoint_type(); - } - - if (impl.socket_.have_remote_endpoint()) - { - // Check if socket is still connected. - DWORD connect_time = 0; - size_t connect_time_len = sizeof(connect_time); - if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_CONNECT_TIME, - &connect_time, &connect_time_len, ec) == socket_error_retval) - { - return endpoint_type(); - } - if (connect_time == 0xFFFFFFFF) - { - ec = asio::error::not_connected; - return endpoint_type(); - } - - ec = asio::error_code(); - return impl.socket_.remote_endpoint(); - } - else - { - endpoint_type endpoint; - socket_addr_len_type addr_len = endpoint.capacity(); - if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec)) - return endpoint_type(); - endpoint.resize(addr_len); - return endpoint; - } - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - socket_ops::shutdown(impl.socket_, what, ec); - return ec; - } - - // Send the given data to the peer. Returns the number of bytes sent. - template - size_t send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = const_cast( - asio::buffer_cast(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Send the data. - DWORD bytes_transferred = 0; - int result = ::WSASend(impl.socket_, bufs, - i, &bytes_transferred, flags, 0, 0); - if (result != 0) - { - DWORD last_error = ::WSAGetLastError(); - if (last_error == ERROR_NETNAME_DELETED) - last_error = WSAECONNRESET; - else if (last_error == ERROR_PORT_UNREACHABLE) - last_error = WSAECONNREFUSED; - ec = asio::error_code(last_error, asio::native_ecat); - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - template - class send_operation - : public operation - { - public: - send_operation(asio::io_service& io_service, - weak_cancel_token_type cancel_token, - const ConstBufferSequence& buffers, Handler handler) - : operation( - &send_operation::do_completion_impl, - &send_operation::destroy_impl), - work_(io_service), - cancel_token_(cancel_token), - buffers_(buffers), - handler_(handler) - { - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef send_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename ConstBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename ConstBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::const_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Map non-portable errors to their portable counterparts. - asio::error_code ec(last_error, asio::native_ecat); - if (ec.value() == ERROR_NETNAME_DELETED) - { - if (handler_op->cancel_token_.expired()) - ec = asio::error::operation_aborted; - else - ec = asio::error::connection_reset; - } - else if (ec.value() == ERROR_PORT_UNREACHABLE) - { - ec = asio::error::connection_refused; - } - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef send_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - } - - asio::io_service::work work_; - weak_cancel_token_type cancel_token_; - ConstBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_send(implementation_type& impl, const ConstBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); - - // Allocate and construct an operation to wrap the handler. - typedef send_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, - this->io_service(), impl.cancel_token_, buffers, handler); - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = const_cast( - asio::buffer_cast(buffer)); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - asio::io_service::work work(this->io_service()); - ptr.reset(); - asio::error_code error; - iocp_service_.post(bind_handler(handler, error, 0)); - return; - } - - // Send the data. - DWORD bytes_transferred = 0; - int result = ::WSASend(impl.socket_, bufs, i, - &bytes_transferred, flags, ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - - // Check if the operation completed immediately. - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->io_service()); - ptr.reset(); - asio::error_code ec(last_error, asio::native_ecat); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - // Send a datagram to the specified endpoint. Returns the number of bytes - // sent. - template - size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, - const endpoint_type& destination, socket_base::message_flags flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = const_cast( - asio::buffer_cast(buffer)); - } - - // Send the data. - DWORD bytes_transferred = 0; - int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, - flags, destination.data(), destination.size(), 0, 0); - if (result != 0) - { - DWORD last_error = ::WSAGetLastError(); - if (last_error == ERROR_PORT_UNREACHABLE) - last_error = WSAECONNREFUSED; - ec = asio::error_code(last_error, asio::native_ecat); - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - template - class send_to_operation - : public operation - { - public: - send_to_operation(asio::io_service& io_service, - const ConstBufferSequence& buffers, Handler handler) - : operation( - &send_to_operation::do_completion_impl, - &send_to_operation::destroy_impl), - work_(io_service), - buffers_(buffers), - handler_(handler) - { - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef send_to_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename ConstBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename ConstBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::const_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Map non-portable errors to their portable counterparts. - asio::error_code ec(last_error, asio::native_ecat); - if (ec.value() == ERROR_PORT_UNREACHABLE) - { - ec = asio::error::connection_refused; - } - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef send_to_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - } - - asio::io_service::work work_; - ConstBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous send. The data being sent must be valid for the - // lifetime of the asynchronous operation. - template - void async_send_to(implementation_type& impl, - const ConstBufferSequence& buffers, const endpoint_type& destination, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); - - // Allocate and construct an operation to wrap the handler. - typedef send_to_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, - this->io_service(), buffers, handler); - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename ConstBufferSequence::const_iterator iter = buffers.begin(); - typename ConstBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::const_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = const_cast( - asio::buffer_cast(buffer)); - } - - // Send the data. - DWORD bytes_transferred = 0; - int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, - flags, destination.data(), destination.size(), ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - - // Check if the operation completed immediately. - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->io_service()); - ptr.reset(); - asio::error_code ec(last_error, asio::native_ecat); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - // Receive some data from the peer. Returns the number of bytes received. - template - size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = asio::buffer_cast(buffer); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - ec = asio::error_code(); - return 0; - } - - // Receive some data. - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = ::WSARecv(impl.socket_, bufs, i, - &bytes_transferred, &recv_flags, 0, 0); - if (result != 0) - { - DWORD last_error = ::WSAGetLastError(); - if (last_error == ERROR_NETNAME_DELETED) - last_error = WSAECONNRESET; - else if (last_error == ERROR_PORT_UNREACHABLE) - last_error = WSAECONNREFUSED; - ec = asio::error_code(last_error, asio::native_ecat); - return 0; - } - if (bytes_transferred == 0) - { - ec = asio::error::eof; - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - template - class receive_operation - : public operation - { - public: - receive_operation(asio::io_service& io_service, - weak_cancel_token_type cancel_token, - const MutableBufferSequence& buffers, Handler handler) - : operation( - &receive_operation< - MutableBufferSequence, Handler>::do_completion_impl, - &receive_operation< - MutableBufferSequence, Handler>::destroy_impl), - work_(io_service), - cancel_token_(cancel_token), - buffers_(buffers), - handler_(handler) - { - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef receive_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename MutableBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename MutableBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::mutable_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Map non-portable errors to their portable counterparts. - asio::error_code ec(last_error, asio::native_ecat); - if (ec.value() == ERROR_NETNAME_DELETED) - { - if (handler_op->cancel_token_.expired()) - ec = asio::error::operation_aborted; - else - ec = asio::error::connection_reset; - } - else if (ec.value() == ERROR_PORT_UNREACHABLE) - { - ec = asio::error::connection_refused; - } - - // Check for connection closed. - else if (!ec && bytes_transferred == 0) - { - ec = asio::error::eof; - } - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef receive_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - } - - asio::io_service::work work_; - weak_cancel_token_type cancel_token_; - MutableBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous receive. The buffer for the data being received - // must be valid for the lifetime of the asynchronous operation. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); - - // Allocate and construct an operation to wrap the handler. - typedef receive_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, - this->io_service(), impl.cancel_token_, buffers, handler); - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - size_t total_buffer_size = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = asio::buffer_cast(buffer); - total_buffer_size += asio::buffer_size(buffer); - } - - // A request to receive 0 bytes on a stream socket is a no-op. - if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0) - { - asio::io_service::work work(this->io_service()); - ptr.reset(); - asio::error_code error; - iocp_service_.post(bind_handler(handler, error, 0)); - return; - } - - // Receive some data. - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = ::WSARecv(impl.socket_, bufs, i, - &bytes_transferred, &recv_flags, ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->io_service()); - ptr.reset(); - asio::error_code ec(last_error, asio::native_ecat); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - // Receive a datagram with the endpoint of the sender. Returns the number of - // bytes received. - template - size_t receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, - endpoint_type& sender_endpoint, socket_base::message_flags flags, - asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return 0; - } - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = asio::buffer_cast(buffer); - } - - // Receive some data. - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int endpoint_size = sender_endpoint.capacity(); - int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred, - &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0); - if (result != 0) - { - DWORD last_error = ::WSAGetLastError(); - if (last_error == ERROR_PORT_UNREACHABLE) - last_error = WSAECONNREFUSED; - ec = asio::error_code(last_error, asio::native_ecat); - return 0; - } - if (bytes_transferred == 0) - { - ec = asio::error::eof; - return 0; - } - - sender_endpoint.resize(endpoint_size); - - ec = asio::error_code(); - return bytes_transferred; - } - - template - class receive_from_operation - : public operation - { - public: - receive_from_operation(asio::io_service& io_service, - endpoint_type& endpoint, const MutableBufferSequence& buffers, - Handler handler) - : operation( - &receive_from_operation< - MutableBufferSequence, Handler>::do_completion_impl, - &receive_from_operation< - MutableBufferSequence, Handler>::destroy_impl), - endpoint_(endpoint), - endpoint_size_(endpoint.capacity()), - work_(io_service), - buffers_(buffers), - handler_(handler) - { - } - - int& endpoint_size() - { - return endpoint_size_; - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef receive_from_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - -#if defined(ASIO_ENABLE_BUFFER_DEBUGGING) - // Check whether buffers are still valid. - typename MutableBufferSequence::const_iterator iter - = handler_op->buffers_.begin(); - typename MutableBufferSequence::const_iterator end - = handler_op->buffers_.end(); - while (iter != end) - { - asio::mutable_buffer buffer(*iter); - asio::buffer_cast(buffer); - ++iter; - } -#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) - - // Map non-portable errors to their portable counterparts. - asio::error_code ec(last_error, asio::native_ecat); - if (ec.value() == ERROR_PORT_UNREACHABLE) - { - ec = asio::error::connection_refused; - } - - // Check for connection closed. - if (!ec && bytes_transferred == 0) - { - ec = asio::error::eof; - } - - // Record the size of the endpoint returned by the operation. - handler_op->endpoint_.resize(handler_op->endpoint_size_); - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec, bytes_transferred), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef receive_from_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - } - - endpoint_type& endpoint_; - int endpoint_size_; - asio::io_service::work work_; - MutableBufferSequence buffers_; - Handler handler_; - }; - - // Start an asynchronous receive. The buffer for the data being received and - // the sender_endpoint object must both be valid for the lifetime of the - // asynchronous operation. - template - void async_receive_from(implementation_type& impl, - const MutableBufferSequence& buffers, endpoint_type& sender_endp, - socket_base::message_flags flags, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor, 0)); - return; - } - - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); - - // Allocate and construct an operation to wrap the handler. - typedef receive_from_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - handler_ptr ptr(raw_ptr, - this->io_service(), sender_endp, buffers, handler); - - // Copy buffers into WSABUF array. - ::WSABUF bufs[max_buffers]; - typename MutableBufferSequence::const_iterator iter = buffers.begin(); - typename MutableBufferSequence::const_iterator end = buffers.end(); - DWORD i = 0; - for (; iter != end && i < max_buffers; ++iter, ++i) - { - asio::mutable_buffer buffer(*iter); - bufs[i].len = static_cast(asio::buffer_size(buffer)); - bufs[i].buf = asio::buffer_cast(buffer); - } - - // Receive some data. - DWORD bytes_transferred = 0; - DWORD recv_flags = flags; - int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred, - &recv_flags, sender_endp.data(), &ptr.get()->endpoint_size(), - ptr.get(), 0); - DWORD last_error = ::WSAGetLastError(); - if (result != 0 && last_error != WSA_IO_PENDING) - { - asio::io_service::work work(this->io_service()); - ptr.reset(); - asio::error_code ec(last_error, asio::native_ecat); - iocp_service_.post(bind_handler(handler, ec, bytes_transferred)); - } - else - { - ptr.release(); - } - } - - // Accept a new connection. - template - asio::error_code accept(implementation_type& impl, Socket& peer, - endpoint_type* peer_endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - // We cannot accept a socket that is already open. - if (peer.is_open()) - { - ec = asio::error::already_open; - return ec; - } - - for (;;) - { - asio::error_code ec; - socket_holder new_socket; - socket_addr_len_type addr_len = 0; - if (peer_endpoint) - { - addr_len = peer_endpoint->capacity(); - new_socket.reset(socket_ops::accept(impl.socket_, - peer_endpoint->data(), &addr_len, ec)); - } - else - { - new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec)); - } - - if (ec) - { - if (ec == asio::error::connection_aborted - && !(impl.flags_ & implementation_type::enable_connection_aborted)) - { - // Retry accept operation. - continue; - } - else - { - return ec; - } - } - - if (peer_endpoint) - peer_endpoint->resize(addr_len); - - peer.assign(impl.protocol_, new_socket.get(), ec); - if (!ec) - new_socket.release(); - return ec; - } - } - - template - class accept_operation - : public operation - { - public: - accept_operation(win_iocp_io_service& io_service, - socket_type socket, socket_type new_socket, Socket& peer, - const protocol_type& protocol, endpoint_type* peer_endpoint, - bool enable_connection_aborted, Handler handler) - : operation( - &accept_operation::do_completion_impl, - &accept_operation::destroy_impl), - io_service_(io_service), - socket_(socket), - new_socket_(new_socket), - peer_(peer), - protocol_(protocol), - peer_endpoint_(peer_endpoint), - work_(io_service.io_service()), - enable_connection_aborted_(enable_connection_aborted), - handler_(handler) - { - } - - socket_type new_socket() - { - return new_socket_.get(); - } - - void* output_buffer() - { - return output_buffer_; - } - - DWORD address_length() - { - return sizeof(sockaddr_storage_type) + 16; - } - - private: - static void do_completion_impl(operation* op, - DWORD last_error, size_t bytes_transferred) - { - // Take ownership of the operation object. - typedef accept_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - - // Map Windows error ERROR_NETNAME_DELETED to connection_aborted. - if (last_error == ERROR_NETNAME_DELETED) - { - last_error = WSAECONNABORTED; - } - - // Restart the accept operation if we got the connection_aborted error - // and the enable_connection_aborted socket option is not set. - if (last_error == WSAECONNABORTED - && !ptr.get()->enable_connection_aborted_) - { - // Reset OVERLAPPED structure. - ptr.get()->Internal = 0; - ptr.get()->InternalHigh = 0; - ptr.get()->Offset = 0; - ptr.get()->OffsetHigh = 0; - ptr.get()->hEvent = 0; - - // Create a new socket for the next connection, since the AcceptEx call - // fails with WSAEINVAL if we try to reuse the same socket. - asio::error_code ec; - ptr.get()->new_socket_.reset(); - ptr.get()->new_socket_.reset(socket_ops::socket( - ptr.get()->protocol_.family(), ptr.get()->protocol_.type(), - ptr.get()->protocol_.protocol(), ec)); - if (ptr.get()->new_socket() != invalid_socket) - { - // Accept a connection. - DWORD bytes_read = 0; - BOOL result = ::AcceptEx(ptr.get()->socket_, ptr.get()->new_socket(), - ptr.get()->output_buffer(), 0, ptr.get()->address_length(), - ptr.get()->address_length(), &bytes_read, ptr.get()); - last_error = ::WSAGetLastError(); - - // Check if the operation completed immediately. - if (!result && last_error != WSA_IO_PENDING) - { - if (last_error == ERROR_NETNAME_DELETED - || last_error == WSAECONNABORTED) - { - // Post this handler so that operation will be restarted again. - ptr.get()->io_service_.post_completion(ptr.get(), last_error, 0); - ptr.release(); - return; - } - else - { - // Operation already complete. Continue with rest of this handler. - } - } - else - { - // Asynchronous operation has been successfully restarted. - ptr.release(); - return; - } - } - } - - // Get the address of the peer. - endpoint_type peer_endpoint; - if (last_error == 0) - { - LPSOCKADDR local_addr = 0; - int local_addr_length = 0; - LPSOCKADDR remote_addr = 0; - int remote_addr_length = 0; - GetAcceptExSockaddrs(handler_op->output_buffer(), 0, - handler_op->address_length(), handler_op->address_length(), - &local_addr, &local_addr_length, &remote_addr, &remote_addr_length); - if (remote_addr_length > peer_endpoint.capacity()) - { - last_error = WSAEINVAL; - } - else - { - using namespace std; // For memcpy. - memcpy(peer_endpoint.data(), remote_addr, remote_addr_length); - peer_endpoint.resize(remote_addr_length); - } - } - - // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname - // and getpeername will work on the accepted socket. - if (last_error == 0) - { - SOCKET update_ctx_param = handler_op->socket_; - asio::error_code ec; - if (socket_ops::setsockopt(handler_op->new_socket_.get(), - SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, - &update_ctx_param, sizeof(SOCKET), ec) != 0) - { - last_error = ec.value(); - } - } - - // If the socket was successfully accepted, transfer ownership of the - // socket to the peer object. - if (last_error == 0) - { - asio::error_code ec; - handler_op->peer_.assign(handler_op->protocol_, - native_type(handler_op->new_socket_.get(), peer_endpoint), ec); - if (ec) - last_error = ec.value(); - else - handler_op->new_socket_.release(); - } - - // Pass endpoint back to caller. - if (handler_op->peer_endpoint_) - *handler_op->peer_endpoint_ = peer_endpoint; - - // Make a copy of the handler so that the memory can be deallocated before - // the upcall is made. - Handler handler(handler_op->handler_); - - // Free the memory associated with the handler. - ptr.reset(); - - // Call the handler. - asio::error_code ec(last_error, asio::native_ecat); - asio_handler_invoke_helpers::invoke( - detail::bind_handler(handler, ec), &handler); - } - - static void destroy_impl(operation* op) - { - // Take ownership of the operation object. - typedef accept_operation op_type; - op_type* handler_op(static_cast(op)); - typedef handler_alloc_traits alloc_traits; - handler_ptr ptr(handler_op->handler_, handler_op); - } - - win_iocp_io_service& io_service_; - socket_type socket_; - socket_holder new_socket_; - Socket& peer_; - protocol_type protocol_; - endpoint_type* peer_endpoint_; - asio::io_service::work work_; - unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; - bool enable_connection_aborted_; - Handler handler_; - }; - - // Start an asynchronous accept. The peer and peer_endpoint objects - // must be valid until the accept's handler is invoked. - template - void async_accept(implementation_type& impl, Socket& peer, - endpoint_type* peer_endpoint, Handler handler) - { - // Check whether acceptor has been initialised. - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor)); - return; - } - - // Check that peer socket has not already been opened. - if (peer.is_open()) - { - this->io_service().post(bind_handler(handler, - asio::error::already_open)); - return; - } - - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); - - // Create a new socket for the connection. - asio::error_code ec; - socket_holder sock(socket_ops::socket(impl.protocol_.family(), - impl.protocol_.type(), impl.protocol_.protocol(), ec)); - if (sock.get() == invalid_socket) - { - this->io_service().post(bind_handler(handler, ec)); - return; - } - - // Allocate and construct an operation to wrap the handler. - typedef accept_operation value_type; - typedef handler_alloc_traits alloc_traits; - raw_handler_ptr raw_ptr(handler); - socket_type new_socket = sock.get(); - bool enable_connection_aborted = - (impl.flags_ & implementation_type::enable_connection_aborted); - handler_ptr ptr(raw_ptr, - iocp_service_, impl.socket_, new_socket, peer, impl.protocol_, - peer_endpoint, enable_connection_aborted, handler); - sock.release(); - - // Accept a connection. - DWORD bytes_read = 0; - BOOL result = ::AcceptEx(impl.socket_, ptr.get()->new_socket(), - ptr.get()->output_buffer(), 0, ptr.get()->address_length(), - ptr.get()->address_length(), &bytes_read, ptr.get()); - DWORD last_error = ::WSAGetLastError(); - - // Check if the operation completed immediately. - if (!result && last_error != WSA_IO_PENDING) - { - if (!enable_connection_aborted - && (last_error == ERROR_NETNAME_DELETED - || last_error == WSAECONNABORTED)) - { - // Post handler so that operation will be restarted again. We do not - // perform the AcceptEx again here to avoid the possibility of starving - // other handlers. - iocp_service_.post_completion(ptr.get(), last_error, 0); - ptr.release(); - } - else - { - asio::io_service::work work(this->io_service()); - ptr.reset(); - asio::error_code ec(last_error, asio::native_ecat); - iocp_service_.post(bind_handler(handler, ec)); - } - } - else - { - ptr.release(); - } - } - - // Connect the socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - if (!is_open(impl)) - { - ec = asio::error::bad_descriptor; - return ec; - } - - // Perform the connect operation. - socket_ops::connect(impl.socket_, - peer_endpoint.data(), peer_endpoint.size(), ec); - return ec; - } - - template - class connect_handler - { - public: - connect_handler(socket_type socket, - boost::shared_ptr completed, - asio::io_service& io_service, - reactor_type& reactor, Handler handler) - : socket_(socket), - completed_(completed), - io_service_(io_service), - reactor_(reactor), - work_(io_service), - handler_(handler) - { - } - - bool operator()(const asio::error_code& result) - { - // Check whether a handler has already been called for the connection. - // If it has, then we don't want to do anything in this handler. - if (*completed_) - return true; - - // Cancel the other reactor operation for the connection. - *completed_ = true; - reactor_.enqueue_cancel_ops_unlocked(socket_); - - // Check whether the operation was successful. - if (result) - { - io_service_.post(bind_handler(handler_, result)); - return true; - } - - // Get the error code from the connect operation. - int connect_error = 0; - size_t connect_error_len = sizeof(connect_error); - asio::error_code ec; - if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR, - &connect_error, &connect_error_len, ec) == socket_error_retval) - { - io_service_.post(bind_handler(handler_, ec)); - return true; - } - - // If connection failed then post the handler with the error code. - if (connect_error) - { - ec = asio::error_code( - connect_error, asio::native_ecat); - io_service_.post(bind_handler(handler_, ec)); - return true; - } - - // Make the socket blocking again (the default). - ioctl_arg_type non_blocking = 0; - if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec)) - { - io_service_.post(bind_handler(handler_, ec)); - return true; - } - - // Post the result of the successful connection operation. - ec = asio::error_code(); - io_service_.post(bind_handler(handler_, ec)); - return true; - } - - private: - socket_type socket_; - boost::shared_ptr completed_; - asio::io_service& io_service_; - reactor_type& reactor_; - asio::io_service::work work_; - Handler handler_; - }; - - // Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, Handler handler) - { - if (!is_open(impl)) - { - this->io_service().post(bind_handler(handler, - asio::error::bad_descriptor)); - return; - } - - // Update the ID of the thread from which cancellation is safe. - if (impl.safe_cancellation_thread_id_ == 0) - impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId(); - else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId()) - impl.safe_cancellation_thread_id_ = ~DWORD(0); - - // Check if the reactor was already obtained from the io_service. - reactor_type* reactor = static_cast( - interlocked_compare_exchange_pointer( - reinterpret_cast(&reactor_), 0, 0)); - if (!reactor) - { - reactor = &(asio::use_service(this->io_service())); - interlocked_exchange_pointer( - reinterpret_cast(&reactor_), reactor); - } - - // Mark the socket as non-blocking so that the connection will take place - // asynchronously. - ioctl_arg_type non_blocking = 1; - asio::error_code ec; - if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec)) - { - this->io_service().post(bind_handler(handler, ec)); - return; - } - - // Start the connect operation. - if (socket_ops::connect(impl.socket_, peer_endpoint.data(), - peer_endpoint.size(), ec) == 0) - { - // The connect operation has finished successfully so we need to post the - // handler immediately. - this->io_service().post(bind_handler(handler, ec)); - } - else if (ec == asio::error::in_progress - || ec == asio::error::would_block) - { - // The connection is happening in the background, and we need to wait - // until the socket becomes writeable. - boost::shared_ptr completed(new bool(false)); - reactor->start_write_and_except_ops(impl.socket_, - connect_handler( - impl.socket_, completed, this->io_service(), *reactor, handler)); - } - else - { - // The connect operation has failed, so post the handler immediately. - this->io_service().post(bind_handler(handler, ec)); - } - } - -private: - // Helper function to provide InterlockedCompareExchangePointer functionality - // on very old Platform SDKs. - void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp) - { -#if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x400) && (_M_IX86) - return reinterpret_cast(InterlockedCompareExchange( - reinterpret_cast(dest), reinterpret_cast(exch), - reinterpret_cast(cmp))); -#else - return InterlockedCompareExchangePointer(dest, exch, cmp); -#endif - } - - // Helper function to provide InterlockedExchangePointer functionality on very - // old Platform SDKs. - void* interlocked_exchange_pointer(void** dest, void* val) - { -#if defined(_WIN32_WINNT) && (_WIN32_WINNT <= 0x400) && (_M_IX86) - return reinterpret_cast(InterlockedExchange( - reinterpret_cast(dest), reinterpret_cast(val))); -#else - return InterlockedExchangePointer(dest, val); -#endif - } - - // The IOCP service used for running asynchronous operations and dispatching - // handlers. - win_iocp_io_service& iocp_service_; - - // The reactor used for performing connect operations. This object is created - // only if needed. - reactor_type* reactor_; - - // Mutex to protect access to the linked list of implementations. - asio::detail::mutex mutex_; - - // The head of a linked list of all implementations. - implementation_type* impl_list_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(ASIO_HAS_IOCP) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_local_free_on_block_exit.hpp b/libtorrent/include/libtorrent/asio/detail/win_local_free_on_block_exit.hpp deleted file mode 100644 index c909e1af3..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_local_free_on_block_exit.hpp +++ /dev/null @@ -1,59 +0,0 @@ -// -// win_local_free_on_block_exit.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2006 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_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP -#define ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -class win_local_free_on_block_exit - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - explicit win_local_free_on_block_exit(void* p) - : p_(p) - { - } - - // Destructor restores the previous signal mask. - ~win_local_free_on_block_exit() - { - ::LocalFree(p_); - } - -private: - void* p_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_mutex.hpp b/libtorrent/include/libtorrent/asio/detail/win_mutex.hpp deleted file mode 100644 index 82659831f..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_mutex.hpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// win_mutex.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_WIN_MUTEX_HPP -#define ASIO_DETAIL_WIN_MUTEX_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/scoped_lock.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -class win_mutex - : private noncopyable -{ -public: - typedef asio::detail::scoped_lock scoped_lock; - - // Constructor. - win_mutex() - { - int error = do_init(); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "mutex"); - boost::throw_exception(e); - } - } - - // Destructor. - ~win_mutex() - { - ::DeleteCriticalSection(&crit_section_); - } - - // Lock the mutex. - void lock() - { - int error = do_lock(); - if (error != 0) - { - asio::system_error e( - asio::error_code(error, asio::native_ecat), - "mutex"); - boost::throw_exception(e); - } - } - - // Unlock the mutex. - void unlock() - { - ::LeaveCriticalSection(&crit_section_); - } - -private: - // Initialisation must be performed in a separate function to the constructor - // since the compiler does not support the use of structured exceptions and - // C++ exceptions in the same function. - int do_init() - { -#if defined(__MINGW32__) - // Not sure if MinGW supports structured exception handling, so for now - // we'll just call the Windows API and hope. - ::InitializeCriticalSection(&crit_section_); - return 0; -#else - __try - { - ::InitializeCriticalSection(&crit_section_); - } - __except(GetExceptionCode() == STATUS_NO_MEMORY - ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) - { - return ERROR_OUTOFMEMORY; - } - - return 0; -#endif - } - - // Locking must be performed in a separate function to lock() since the - // compiler does not support the use of structured exceptions and C++ - // exceptions in the same function. - int do_lock() - { -#if defined(__MINGW32__) - // Not sure if MinGW supports structured exception handling, so for now - // we'll just call the Windows API and hope. - ::EnterCriticalSection(&crit_section_); - return 0; -#else - __try - { - ::EnterCriticalSection(&crit_section_); - } - __except(GetExceptionCode() == STATUS_INVALID_HANDLE - || GetExceptionCode() == STATUS_NO_MEMORY - ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) - { - if (GetExceptionCode() == STATUS_NO_MEMORY) - return ERROR_OUTOFMEMORY; - return ERROR_INVALID_HANDLE; - } - - return 0; -#endif - } - - ::CRITICAL_SECTION crit_section_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_MUTEX_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_signal_blocker.hpp b/libtorrent/include/libtorrent/asio/detail/win_signal_blocker.hpp deleted file mode 100644 index 892c40f89..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_signal_blocker.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// win_signal_blocker.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_WIN_SIGNAL_BLOCKER_HPP -#define ASIO_DETAIL_WIN_SIGNAL_BLOCKER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/noncopyable.hpp" - -namespace asio { -namespace detail { - -class win_signal_blocker - : private noncopyable -{ -public: - // Constructor blocks all signals for the calling thread. - win_signal_blocker() - { - // No-op. - } - - // Destructor restores the previous signal mask. - ~win_signal_blocker() - { - // No-op. - } - - // Block all signals for the calling thread. - void block() - { - // No-op. - } - - // Restore the previous signal mask. - void unblock() - { - // No-op. - } -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_thread.hpp b/libtorrent/include/libtorrent/asio/detail/win_thread.hpp deleted file mode 100644 index a6c9b15d2..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_thread.hpp +++ /dev/null @@ -1,123 +0,0 @@ -// -// win_thread.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_WIN_THREAD_HPP -#define ASIO_DETAIL_WIN_THREAD_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -unsigned int __stdcall win_thread_function(void* arg); - -class win_thread - : private noncopyable -{ -public: - // Constructor. - template - win_thread(Function f) - { - std::auto_ptr arg(new func(f)); - unsigned int thread_id = 0; - thread_ = reinterpret_cast(::_beginthreadex(0, 0, - win_thread_function, arg.get(), 0, &thread_id)); - if (!thread_) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, asio::native_ecat), - "thread"); - boost::throw_exception(e); - } - arg.release(); - } - - // Destructor. - ~win_thread() - { - ::CloseHandle(thread_); - } - - // Wait for the thread to exit. - void join() - { - ::WaitForSingleObject(thread_, INFINITE); - } - -private: - friend unsigned int __stdcall win_thread_function(void* arg); - - class func_base - { - public: - virtual ~func_base() {} - virtual void run() = 0; - }; - - template - class func - : public func_base - { - public: - func(Function f) - : f_(f) - { - } - - virtual void run() - { - f_(); - } - - private: - Function f_; - }; - - ::HANDLE thread_; -}; - -inline unsigned int __stdcall win_thread_function(void* arg) -{ - std::auto_ptr func( - static_cast(arg)); - func->run(); - return 0; -} - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_THREAD_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/win_tss_ptr.hpp b/libtorrent/include/libtorrent/asio/detail/win_tss_ptr.hpp deleted file mode 100644 index d3e2f8161..000000000 --- a/libtorrent/include/libtorrent/asio/detail/win_tss_ptr.hpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// win_tss_ptr.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_WIN_TSS_PTR_HPP -#define ASIO_DETAIL_WIN_TSS_PTR_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace detail { - -template -class win_tss_ptr - : private noncopyable -{ -public: - // Constructor. - win_tss_ptr() - { - tss_key_ = ::TlsAlloc(); - if (tss_key_ == TLS_OUT_OF_INDEXES) - { - DWORD last_error = ::GetLastError(); - asio::system_error e( - asio::error_code(last_error, asio::native_ecat), - "tss"); - boost::throw_exception(e); - } - } - - // Destructor. - ~win_tss_ptr() - { - ::TlsFree(tss_key_); - } - - // Get the value. - operator T*() const - { - return static_cast(::TlsGetValue(tss_key_)); - } - - // Set the value. - void operator=(T* value) - { - ::TlsSetValue(tss_key_, value); - } - -private: - // Thread-specific storage to allow unlocked access to determine whether a - // thread is a member of the pool. - DWORD tss_key_; -}; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WIN_TSS_PTR_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/winsock_init.hpp b/libtorrent/include/libtorrent/asio/detail/winsock_init.hpp deleted file mode 100644 index 67c69e8ce..000000000 --- a/libtorrent/include/libtorrent/asio/detail/winsock_init.hpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// winsock_init.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_WINSOCK_INIT_HPP -#define ASIO_DETAIL_WINSOCK_INIT_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/system_error.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace detail { - -template -class winsock_init - : private noncopyable -{ -private: - // Structure to perform the actual initialisation. - struct do_init - { - do_init() - { - WSADATA wsa_data; - result_ = ::WSAStartup(MAKEWORD(Major, Minor), &wsa_data); - } - - ~do_init() - { - ::WSACleanup(); - } - - int result() const - { - return result_; - } - - // Helper function to manage a do_init singleton. The static instance of the - // winsock_init object ensures that this function is always called before - // main, and therefore before any other threads can get started. The do_init - // instance must be static in this function to ensure that it gets - // initialised before any other global objects try to use it. - static boost::shared_ptr instance() - { - static boost::shared_ptr init(new do_init); - return init; - } - - private: - int result_; - }; - -public: - // Constructor. - winsock_init() - : ref_(do_init::instance()) - { - // Check whether winsock was successfully initialised. This check is not - // performed for the global instance since there will be nobody around to - // catch the exception. - if (this != &instance_ && ref_->result() != 0) - { - asio::system_error e( - asio::error_code(ref_->result(), asio::native_ecat), - "winsock"); - boost::throw_exception(e); - } - } - - // Destructor. - ~winsock_init() - { - } - -private: - // Instance to force initialisation of winsock at global scope. - static winsock_init instance_; - - // Reference to singleton do_init object to ensure that winsock does not get - // cleaned up until the last user has finished with it. - boost::shared_ptr ref_; -}; - -template -winsock_init winsock_init::instance_; - -} // namespace detail -} // namespace asio - -#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WINSOCK_INIT_HPP diff --git a/libtorrent/include/libtorrent/asio/detail/wrapped_handler.hpp b/libtorrent/include/libtorrent/asio/detail/wrapped_handler.hpp deleted file mode 100644 index f757fd3dc..000000000 --- a/libtorrent/include/libtorrent/asio/detail/wrapped_handler.hpp +++ /dev/null @@ -1,187 +0,0 @@ -// -// wrapped_handler.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_WRAPPED_HANDLER_HPP -#define ASIO_DETAIL_WRAPPED_HANDLER_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/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" - -namespace asio { -namespace detail { - -template -class wrapped_handler -{ -public: - typedef void result_type; - - wrapped_handler(Dispatcher& dispatcher, Handler handler) - : dispatcher_(dispatcher), - handler_(handler) - { - } - - void operator()() - { - dispatcher_.dispatch(handler_); - } - - void operator()() const - { - dispatcher_.dispatch(handler_); - } - - template - void operator()(const Arg1& arg1) - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); - } - - template - void operator()(const Arg1& arg1) const - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2) - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2) const - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) const - { - dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, - const Arg4& arg4) - { - dispatcher_.dispatch( - detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, - const Arg4& arg4) const - { - dispatcher_.dispatch( - detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, - const Arg4& arg4, const Arg5& arg5) - { - dispatcher_.dispatch( - detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); - } - - template - void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, - const Arg4& arg4, const Arg5& arg5) const - { - dispatcher_.dispatch( - detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); - } - -//private: - Dispatcher& dispatcher_; - Handler handler_; -}; - -template -inline void* asio_handler_allocate(std::size_t size, - wrapped_handler* this_handler) -{ - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); -} - -template -inline void asio_handler_deallocate(void* pointer, std::size_t size, - wrapped_handler* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); -} - -template -class rewrapped_handler -{ -public: - explicit rewrapped_handler(const Handler& handler, const Context& context) - : handler_(handler), - context_(context) - { - } - - void operator()() - { - handler_(); - } - - void operator()() const - { - handler_(); - } - -//private: - Handler handler_; - Context context_; -}; - -template -inline void asio_handler_invoke(const Function& function, - wrapped_handler* this_handler) -{ - this_handler->dispatcher_.dispatch( - rewrapped_handler( - function, this_handler->handler_)); -} - -template -inline void asio_handler_invoke(const Function& function, - rewrapped_handler* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, &this_handler->context_); -} - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_WRAPPED_HANDLER_HPP diff --git a/libtorrent/include/libtorrent/asio/error.hpp b/libtorrent/include/libtorrent/asio/error.hpp deleted file mode 100644 index 935cc6796..000000000 --- a/libtorrent/include/libtorrent/asio/error.hpp +++ /dev/null @@ -1,367 +0,0 @@ -// -// error.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_ERROR_HPP -#define ASIO_ERROR_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/detail/socket_types.hpp" - -#if defined(GENERATING_DOCUMENTATION) -/// INTERNAL ONLY. -# define ASIO_NATIVE_ERROR(e) implementation_defined -/// INTERNAL ONLY. -# define ASIO_SOCKET_ERROR(e) implementation_defined -/// INTERNAL ONLY. -# define ASIO_NETDB_ERROR(e) implementation_defined -/// INTERNAL ONLY. -# define ASIO_GETADDRINFO_ERROR(e) implementation_defined -/// INTERNAL ONLY. -# define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# define ASIO_NATIVE_ERROR(e) \ - asio::error_code(e, \ - asio::native_ecat) -# define ASIO_SOCKET_ERROR(e) \ - asio::error_code(WSA ## e, \ - asio::native_ecat) -# define ASIO_NETDB_ERROR(e) \ - asio::error_code(WSA ## e, \ - asio::native_ecat) -# define ASIO_GETADDRINFO_ERROR(e) \ - asio::error_code(WSA ## e, \ - asio::native_ecat) -# define ASIO_MISC_ERROR(e) \ - asio::error_code(e, \ - asio::misc_ecat) -# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_win -#else -# define ASIO_NATIVE_ERROR(e) \ - asio::error_code(e, \ - asio::native_ecat) -# define ASIO_SOCKET_ERROR(e) \ - asio::error_code(e, \ - asio::native_ecat) -# define ASIO_NETDB_ERROR(e) \ - asio::error_code(e, \ - asio::netdb_ecat) -# define ASIO_GETADDRINFO_ERROR(e) \ - asio::error_code(e, \ - asio::addrinfo_ecat) -# define ASIO_MISC_ERROR(e) \ - asio::error_code(e, \ - asio::misc_ecat) -# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix -#endif - -namespace asio { - -namespace detail { - -/// Hack to keep asio library header-file-only. -template -class error_base -{ -public: - // boostify: error category declarations go here. - - /// Permission denied. - static const asio::error_code access_denied; - - /// Address family not supported by protocol. - static const asio::error_code address_family_not_supported; - - /// Address already in use. - static const asio::error_code address_in_use; - - /// Transport endpoint is already connected. - static const asio::error_code already_connected; - - /// Already open. - static const asio::error_code already_open; - - /// Operation already in progress. - static const asio::error_code already_started; - - /// A connection has been aborted. - static const asio::error_code connection_aborted; - - /// Connection refused. - static const asio::error_code connection_refused; - - /// Connection reset by peer. - static const asio::error_code connection_reset; - - /// Bad file descriptor. - static const asio::error_code bad_descriptor; - - /// End of file or stream. - static const asio::error_code eof; - - /// Bad address. - static const asio::error_code fault; - - /// Host not found (authoritative). - static const asio::error_code host_not_found; - - /// Host not found (non-authoritative). - static const asio::error_code host_not_found_try_again; - - /// No route to host. - static const asio::error_code host_unreachable; - - /// Operation now in progress. - static const asio::error_code in_progress; - - /// Interrupted system call. - static const asio::error_code interrupted; - - /// Invalid argument. - static const asio::error_code invalid_argument; - - /// Message too long. - static const asio::error_code message_size; - - /// Network is down. - static const asio::error_code network_down; - - /// Network dropped connection on reset. - static const asio::error_code network_reset; - - /// Network is unreachable. - static const asio::error_code network_unreachable; - - /// Too many open files. - static const asio::error_code no_descriptors; - - /// No buffer space available. - static const asio::error_code no_buffer_space; - - /// The query is valid but does not have associated address data. - static const asio::error_code no_data; - - /// Cannot allocate memory. - static const asio::error_code no_memory; - - /// Operation not permitted. - static const asio::error_code no_permission; - - /// Protocol not available. - static const asio::error_code no_protocol_option; - - /// A non-recoverable error occurred. - static const asio::error_code no_recovery; - - /// Transport endpoint is not connected. - static const asio::error_code not_connected; - - /// Element not found. - static const asio::error_code not_found; - - /// Socket operation on non-socket. - static const asio::error_code not_socket; - - /// Operation cancelled. - static const asio::error_code operation_aborted; - - /// Operation not supported. - static const asio::error_code operation_not_supported; - - /// The service is not supported for the given socket type. - static const asio::error_code service_not_found; - - /// The socket type is not supported. - static const asio::error_code socket_type_not_supported; - - /// Cannot send after transport endpoint shutdown. - static const asio::error_code shut_down; - - /// Connection timed out. - static const asio::error_code timed_out; - - /// Resource temporarily unavailable. - static const asio::error_code try_again; - - /// The socket is marked non-blocking and the requested operation would block. - static const asio::error_code would_block; - -private: - error_base(); -}; - -// boostify: error category definitions go here. - -template const asio::error_code -error_base::access_denied = ASIO_SOCKET_ERROR(EACCES); - -template const asio::error_code -error_base::address_family_not_supported = ASIO_SOCKET_ERROR( - EAFNOSUPPORT); - -template const asio::error_code -error_base::address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE); - -template const asio::error_code -error_base::already_connected = ASIO_SOCKET_ERROR(EISCONN); - -template const asio::error_code -error_base::already_open = ASIO_MISC_ERROR(1); - -template const asio::error_code -error_base::already_started = ASIO_SOCKET_ERROR(EALREADY); - -template const asio::error_code -error_base::connection_aborted = ASIO_SOCKET_ERROR(ECONNABORTED); - -template const asio::error_code -error_base::connection_refused = ASIO_SOCKET_ERROR(ECONNREFUSED); - -template const asio::error_code -error_base::connection_reset = ASIO_SOCKET_ERROR(ECONNRESET); - -template const asio::error_code -error_base::bad_descriptor = ASIO_SOCKET_ERROR(EBADF); - -template const asio::error_code -error_base::eof = ASIO_MISC_ERROR(2); - -template const asio::error_code -error_base::fault = ASIO_SOCKET_ERROR(EFAULT); - -template const asio::error_code -error_base::host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND); - -template const asio::error_code -error_base::host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN); - -template const asio::error_code -error_base::host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH); - -template const asio::error_code -error_base::in_progress = ASIO_SOCKET_ERROR(EINPROGRESS); - -template const asio::error_code -error_base::interrupted = ASIO_SOCKET_ERROR(EINTR); - -template const asio::error_code -error_base::invalid_argument = ASIO_SOCKET_ERROR(EINVAL); - -template const asio::error_code -error_base::message_size = ASIO_SOCKET_ERROR(EMSGSIZE); - -template const asio::error_code -error_base::network_down = ASIO_SOCKET_ERROR(ENETDOWN); - -template const asio::error_code -error_base::network_reset = ASIO_SOCKET_ERROR(ENETRESET); - -template const asio::error_code -error_base::network_unreachable = ASIO_SOCKET_ERROR(ENETUNREACH); - -template const asio::error_code -error_base::no_descriptors = ASIO_SOCKET_ERROR(EMFILE); - -template const asio::error_code -error_base::no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS); - -template const asio::error_code -error_base::no_data = ASIO_NETDB_ERROR(NO_DATA); - -template const asio::error_code -error_base::no_memory = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_OUTOFMEMORY), - ASIO_NATIVE_ERROR(ENOMEM)); - -template const asio::error_code -error_base::no_permission = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_ACCESS_DENIED), - ASIO_NATIVE_ERROR(EPERM)); - -template const asio::error_code -error_base::no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT); - -template const asio::error_code -error_base::no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY); - -template const asio::error_code -error_base::not_connected = ASIO_SOCKET_ERROR(ENOTCONN); - -template const asio::error_code -error_base::not_found = ASIO_MISC_ERROR(3); - -template const asio::error_code -error_base::not_socket = ASIO_SOCKET_ERROR(ENOTSOCK); - -template const asio::error_code -error_base::operation_aborted = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_OPERATION_ABORTED), - ASIO_NATIVE_ERROR(ECANCELED)); - -template const asio::error_code -error_base::operation_not_supported = ASIO_SOCKET_ERROR(EOPNOTSUPP); - -template const asio::error_code -error_base::service_not_found = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(WSATYPE_NOT_FOUND), - ASIO_GETADDRINFO_ERROR(EAI_SERVICE)); - -template const asio::error_code -error_base::socket_type_not_supported = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(WSAESOCKTNOSUPPORT), - ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE)); - -template const asio::error_code -error_base::shut_down = ASIO_SOCKET_ERROR(ESHUTDOWN); - -template const asio::error_code -error_base::timed_out = ASIO_SOCKET_ERROR(ETIMEDOUT); - -template const asio::error_code -error_base::try_again = ASIO_WIN_OR_POSIX( - ASIO_NATIVE_ERROR(ERROR_RETRY), - ASIO_NATIVE_ERROR(EAGAIN)); - -template const asio::error_code -error_base::would_block = ASIO_SOCKET_ERROR(EWOULDBLOCK); - -} // namespace detail - -/// Contains error constants. -class error : public asio::detail::error_base -{ -private: - error(); -}; - -} // namespace asio - -#undef ASIO_NATIVE_ERROR -#undef ASIO_SOCKET_ERROR -#undef ASIO_NETDB_ERROR -#undef ASIO_GETADDRINFO_ERROR -#undef ASIO_MISC_ERROR -#undef ASIO_WIN_OR_POSIX - -#include "asio/impl/error_code.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_ERROR_HPP diff --git a/libtorrent/include/libtorrent/asio/error_code.hpp b/libtorrent/include/libtorrent/asio/error_code.hpp deleted file mode 100644 index 0614490e2..000000000 --- a/libtorrent/include/libtorrent/asio/error_code.hpp +++ /dev/null @@ -1,139 +0,0 @@ -// -// error_code.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_ERROR_CODE_HPP -#define ASIO_ERROR_CODE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) -# define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined -#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__) -# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_win -#else -# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix -#endif - -namespace asio { - -/// Available error code categories. -enum error_category -{ - /// Native error codes. - native_ecat = ASIO_WIN_OR_POSIX(0, 0), - - /// Error codes from NetDB functions. - netdb_ecat = ASIO_WIN_OR_POSIX(native_ecat, 1), - - /// Error codes from getaddrinfo. - addrinfo_ecat = ASIO_WIN_OR_POSIX(native_ecat, 2), - - /// Miscellaneous error codes. - misc_ecat = ASIO_WIN_OR_POSIX(3, 3), - - /// SSL error codes. - ssl_ecat = ASIO_WIN_OR_POSIX(4, 4) -}; - -/// Class to represent an error code value. -class error_code -{ -public: - /// The underlying representation of an error code. - typedef int value_type; - - /// Default constructor. - error_code() - : value_(0), - category_(native_ecat) - { - } - - /// Construct with specific error code and category. - error_code(value_type v, error_category c) - : value_(v), - category_(c) - { - } - - /// Get the error value. - value_type value() const - { - return value_; - } - - /// Get the error category. - error_category category() const - { - return category_; - } - - /// Get the message associated with the error. - std::string message() const; - - struct unspecified_bool_type_t - { - }; - - typedef unspecified_bool_type_t* unspecified_bool_type; - - /// Operator returns non-null if there is a non-success error code. - operator unspecified_bool_type() const - { - if (value_ == 0) - return 0; - else - return reinterpret_cast(1); - } - - /// Operator to test if the error represents success. - bool operator!() const - { - return value_ == 0; - } - - /// Equality operator to compare two error objects. - friend bool operator==(const error_code& e1, const error_code& e2) - { - return e1.value_ == e2.value_ && e1.category_ == e2.category_; - } - - /// Inequality operator to compare two error objects. - friend bool operator!=(const error_code& e1, const error_code& e2) - { - return e1.value_ != e2.value_ || e1.category_ != e2.category_; - } - -private: - // The value associated with the error code. - value_type value_; - - // The category associated with the error code. - error_category category_; -}; - -} // namespace asio - -#undef ASIO_WIN_OR_POSIX - -#include "asio/error.hpp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_ERROR_CODE_HPP diff --git a/libtorrent/include/libtorrent/asio/error_handler.hpp b/libtorrent/include/libtorrent/asio/error_handler.hpp deleted file mode 100644 index c315c8d5e..000000000 --- a/libtorrent/include/libtorrent/asio/error_handler.hpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// error_handler.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2006 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_ERROR_HANDLER_HPP -#define ASIO_ERROR_HANDLER_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { - -namespace detail { - -class ignore_error_t -{ -public: - typedef void result_type; - - template - void operator()(const Error&) const - { - } -}; - -class throw_error_t -{ -public: - typedef void result_type; - - template - void operator()(const Error& err) const - { - if (err) - boost::throw_exception(err); - } -}; - -template -class assign_error_t -{ -public: - typedef void result_type; - - assign_error_t(Target& target) - : target_(&target) - { - } - - template - void operator()(const Error& err) const - { - *target_ = err; - } - -private: - Target* target_; -}; - -} // namespace detail - -/** - * @defgroup error_handler Error Handler Function Objects - * - * Function objects for custom error handling. - */ -/*@{*/ - -/// Return a function object that always ignores the error. -#if defined(GENERATING_DOCUMENTATION) -unspecified ignore_error(); -#else -inline detail::ignore_error_t ignore_error() -{ - return detail::ignore_error_t(); -} -#endif - -/// Return a function object that always throws the error. -#if defined(GENERATING_DOCUMENTATION) -unspecified throw_error(); -#else -inline detail::throw_error_t throw_error() -{ - return detail::throw_error_t(); -} -#endif - -/// Return a function object that assigns the error to a variable. -#if defined(GENERATING_DOCUMENTATION) -template -unspecified assign_error(Target& target); -#else -template -inline detail::assign_error_t assign_error(Target& target) -{ - return detail::assign_error_t(target); -} -#endif - -/*@}*/ - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_ERROR_HANDLER_HPP diff --git a/libtorrent/include/libtorrent/asio/handler_alloc_hook.hpp b/libtorrent/include/libtorrent/asio/handler_alloc_hook.hpp deleted file mode 100644 index 042b1fecd..000000000 --- a/libtorrent/include/libtorrent/asio/handler_alloc_hook.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// handler_alloc_hook.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_HANDLER_ALLOC_HOOK_HPP -#define ASIO_HANDLER_ALLOC_HOOK_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { - -/// Default allocation function for handlers. -/** - * Asynchronous operations may need to allocate temporary objects. Since - * asynchronous operations have a handler function object, these temporary - * objects can be said to be associated with the handler. - * - * Implement asio_handler_allocate and asio_handler_deallocate for your own - * handlers to provide custom allocation for these temporary objects. - * - * This default implementation is simply: - * @code - * return ::operator new(bytes); - * @endcode - * - * @note All temporary objects associated with a handler will be deallocated - * before the upcall to the handler is performed. This allows the same memory to - * be reused for a subsequent asynchronous operation initiated by the handler. - * - * @par Example - * @code - * class my_handler; - * - * void* asio_handler_allocate(std::size_t size, my_handler* context) - * { - * return ::operator new(size); - * } - * - * void asio_handler_deallocate(void* pointer, std::size_t size, - * my_handler* context) - * { - * ::operator delete(pointer); - * } - * @endcode - */ -inline void* asio_handler_allocate(std::size_t size, ...) -{ - return ::operator new(size); -} - -/// Default deallocation function for handlers. -/** - * Implement asio_handler_allocate and asio_handler_deallocate for your own - * handlers to provide custom allocation for the associated temporary objects. - * - * This default implementation is simply: - * @code - * ::operator delete(pointer); - * @endcode - * - * @sa asio_handler_allocate. - */ -inline void asio_handler_deallocate(void* pointer, std::size_t size, ...) -{ - (void)(size); - ::operator delete(pointer); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_HANDLER_ALLOC_HOOK_HPP diff --git a/libtorrent/include/libtorrent/asio/handler_invoke_hook.hpp b/libtorrent/include/libtorrent/asio/handler_invoke_hook.hpp deleted file mode 100644 index 4ba5db329..000000000 --- a/libtorrent/include/libtorrent/asio/handler_invoke_hook.hpp +++ /dev/null @@ -1,69 +0,0 @@ -// -// handler_invoke_hook.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_HANDLER_INVOKE_HOOK_HPP -#define ASIO_HANDLER_INVOKE_HOOK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -/// Default invoke function for handlers. -/** - * Completion handlers for asynchronous operations are invoked by the - * io_service associated with the corresponding object (e.g. a socket or - * deadline_timer). Certain guarantees are made on when the handler may be - * invoked, in particular that a handler can only be invoked from a thread that - * is currently calling asio::io_service::run() on the corresponding - * io_service object. Handlers may subsequently be invoked through other - * objects (such as asio::strand objects) that provide additional - * guarantees. - * - * When asynchronous operations are composed from other asynchronous - * operations, all intermediate handlers should be invoked using the same - * method as the final handler. This is required to ensure that user-defined - * objects are not accessed in a way that may violate the guarantees. This - * hooking function ensures that the invoked method used for the final handler - * is accessible at each intermediate step. - * - * Implement asio_handler_invoke for your own handlers to specify a custom - * invocation strategy. - * - * This default implementation is simply: - * @code - * function(); - * @endcode - * - * @par Example - * @code - * class my_handler; - * - * template - * void asio_handler_invoke(Function function, my_handler* context) - * { - * context->strand_.dispatch(function); - * } - * @endcode - */ -template -inline void asio_handler_invoke(Function function, ...) -{ - function(); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_HANDLER_INVOKE_HOOK_HPP diff --git a/libtorrent/include/libtorrent/asio/impl/error_code.ipp b/libtorrent/include/libtorrent/asio/impl/error_code.ipp deleted file mode 100644 index da2f98833..000000000 --- a/libtorrent/include/libtorrent/asio/impl/error_code.ipp +++ /dev/null @@ -1,98 +0,0 @@ -// -// error_code.ipp -// ~~~~~~~~~~~~~~ -// -// 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_ERROR_CODE_IPP -#define ASIO_ERROR_CODE_IPP - -#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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/local_free_on_block_exit.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { - -inline std::string error_code::message() const -{ - if (*this == error::already_open) - return "Already open."; - if (*this == error::not_found) - return "Not found."; - if (category_ == ssl_ecat) - return "SSL error."; -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - value_type value = value_; - if (*this == error::eof) - value = ERROR_HANDLE_EOF; - char* msg = 0; - DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); - detail::local_free_on_block_exit local_free_obj(msg); - if (length && msg[length - 1] == '\n') - msg[--length] = '\0'; - if (length && msg[length - 1] == '\r') - msg[--length] = '\0'; - if (length) - return msg; - else - return "asio error"; -#else // defined(BOOST_WINDOWS) - if (*this == error::eof) - return "End of file."; - if (*this == error::host_not_found) - return "Host not found (authoritative)."; - if (*this == error::host_not_found_try_again) - return "Host not found (non-authoritative), try again later."; - if (*this == error::no_recovery) - return "A non-recoverable error occurred during database lookup."; - if (*this == error::no_data) - return "The query is valid, but it does not have associated data."; - if (*this == error::not_found) - return "Element not found."; -#if !defined(__sun) - if (*this == error::operation_aborted) - return "Operation aborted."; -#endif // !defined(__sun) - if (*this == error::service_not_found) - return "Service not found."; - if (*this == error::socket_type_not_supported) - return "Socket type not supported."; -#if defined(__sun) || defined(__QNX__) - return strerror(value_); -#elif defined(__MACH__) && defined(__APPLE__) \ -|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \ -|| defined(_AIX) - char buf[256] = ""; - strerror_r(value_, buf, sizeof(buf)); - return buf; -#else - char buf[256] = ""; - return strerror_r(value_, buf, sizeof(buf)); -#endif -#endif // defined(BOOST_WINDOWS) -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_ERROR_CODE_IPP diff --git a/libtorrent/include/libtorrent/asio/impl/io_service.ipp b/libtorrent/include/libtorrent/asio/impl/io_service.ipp deleted file mode 100644 index e973619d1..000000000 --- a/libtorrent/include/libtorrent/asio/impl/io_service.ipp +++ /dev/null @@ -1,213 +0,0 @@ -// -// io_service.ipp -// ~~~~~~~~~~~~~~ -// -// 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_IO_SERVICE_IPP -#define ASIO_IO_SERVICE_IPP - -#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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_registry.hpp" -#include "asio/detail/task_io_service.hpp" -#include "asio/detail/throw_error.hpp" -#include "asio/detail/win_iocp_io_service.hpp" - -namespace asio { - -inline io_service::io_service() - : service_registry_(new asio::detail::service_registry(*this)), - impl_(service_registry_->use_service()) -{ - impl_.init((std::numeric_limits::max)()); -} - -inline io_service::io_service(std::size_t concurrency_hint) - : service_registry_(new asio::detail::service_registry(*this)), - impl_(service_registry_->use_service()) -{ - impl_.init(concurrency_hint); -} - -inline io_service::~io_service() -{ - delete service_registry_; -} - -inline std::size_t io_service::run() -{ - asio::error_code ec; - std::size_t s = impl_.run(ec); - asio::detail::throw_error(ec); - return s; -} - -inline std::size_t io_service::run(asio::error_code& ec) -{ - return impl_.run(ec); -} - -inline std::size_t io_service::run_one() -{ - asio::error_code ec; - std::size_t s = impl_.run_one(ec); - asio::detail::throw_error(ec); - return s; -} - -inline std::size_t io_service::run_one(asio::error_code& ec) -{ - return impl_.run_one(ec); -} - -inline std::size_t io_service::poll() -{ - asio::error_code ec; - std::size_t s = impl_.poll(ec); - asio::detail::throw_error(ec); - return s; -} - -inline std::size_t io_service::poll(asio::error_code& ec) -{ - return impl_.poll(ec); -} - -inline std::size_t io_service::poll_one() -{ - asio::error_code ec; - std::size_t s = impl_.poll_one(ec); - asio::detail::throw_error(ec); - return s; -} - -inline std::size_t io_service::poll_one(asio::error_code& ec) -{ - return impl_.poll_one(ec); -} - -inline void io_service::stop() -{ - impl_.stop(); -} - -inline void io_service::reset() -{ - impl_.reset(); -} - -template -inline void io_service::dispatch(Handler handler) -{ - impl_.dispatch(handler); -} - -template -inline void io_service::post(Handler handler) -{ - impl_.post(handler); -} - -template -#if defined(GENERATING_DOCUMENTATION) -unspecified -#else -inline detail::wrapped_handler -#endif -io_service::wrap(Handler handler) -{ - return detail::wrapped_handler(*this, handler); -} - -inline io_service::work::work(asio::io_service& io_service) - : io_service_(io_service) -{ - io_service_.impl_.work_started(); -} - -inline io_service::work::work(const work& other) - : io_service_(other.io_service_) -{ - io_service_.impl_.work_started(); -} - -inline io_service::work::~work() -{ - io_service_.impl_.work_finished(); -} - -inline asio::io_service& io_service::work::io_service() -{ - return io_service_; -} - -inline io_service::service::service(asio::io_service& owner) - : owner_(owner), - type_info_(0), - next_(0) -{ -} - -inline io_service::service::~service() -{ -} - -inline asio::io_service& io_service::service::io_service() -{ - return owner_; -} - -template -inline Service& use_service(io_service& ios) -{ - // Check that Service meets the necessary type requirements. - (void)static_cast(static_cast(0)); - (void)static_cast(&Service::id); - - return ios.service_registry_->template use_service(); -} - -template -void add_service(io_service& ios, Service* svc) -{ - // Check that Service meets the necessary type requirements. - (void)static_cast(static_cast(0)); - (void)static_cast(&Service::id); - - if (&ios != &svc->io_service()) - boost::throw_exception(invalid_service_owner()); - if (!ios.service_registry_->template add_service(svc)) - boost::throw_exception(service_already_exists()); -} - -template -bool has_service(io_service& ios) -{ - // Check that Service meets the necessary type requirements. - (void)static_cast(static_cast(0)); - (void)static_cast(&Service::id); - - return ios.service_registry_->template has_service(); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IO_SERVICE_IPP diff --git a/libtorrent/include/libtorrent/asio/impl/read.ipp b/libtorrent/include/libtorrent/asio/impl/read.ipp deleted file mode 100644 index f30f50fb0..000000000 --- a/libtorrent/include/libtorrent/asio/impl/read.ipp +++ /dev/null @@ -1,314 +0,0 @@ -// -// read.ipp -// ~~~~~~~~ -// -// 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_READ_IPP -#define ASIO_READ_IPP - -#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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" -#include "asio/error.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/consuming_buffers.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -template -std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec) -{ - asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> tmp(buffers); - std::size_t total_transferred = 0; - while (tmp.begin() != tmp.end()) - { - std::size_t bytes_transferred = s.read_some(tmp, ec); - tmp.consume(bytes_transferred); - total_transferred += bytes_transferred; - if (completion_condition(ec, total_transferred)) - return total_transferred; - } - ec = asio::error_code(); - return total_transferred; -} - -template -inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers) -{ - asio::error_code ec; - std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = read(s, buffers, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t read(SyncReadStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec) -{ - std::size_t total_transferred = 0; - for (;;) - { - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec); - b.commit(bytes_transferred); - total_transferred += bytes_transferred; - if (b.size() == b.max_size() - || completion_condition(ec, total_transferred)) - return total_transferred; - } -} - -template -inline std::size_t read(SyncReadStream& s, - asio::basic_streambuf& b) -{ - asio::error_code ec; - std::size_t bytes_transferred = read(s, b, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t read(SyncReadStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = read(s, b, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - template - class read_handler - { - public: - typedef asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> buffers_type; - - read_handler(AsyncReadStream& stream, const buffers_type& buffers, - CompletionCondition completion_condition, ReadHandler handler) - : stream_(stream), - buffers_(buffers), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - buffers_.consume(bytes_transferred); - if (completion_condition_(ec, total_transferred_) - || buffers_.begin() == buffers_.end()) - { - handler_(ec, total_transferred_); - } - else - { - stream_.async_read_some(buffers_, *this); - } - } - - //private: - AsyncReadStream& stream_; - buffers_type buffers_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, ReadHandler handler) -{ - asio::detail::consuming_buffers< - mutable_buffer, MutableBufferSequence> tmp(buffers); - s.async_read_some(tmp, - detail::read_handler( - s, tmp, completion_condition, handler)); -} - -template -inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - ReadHandler handler) -{ - async_read(s, buffers, transfer_all(), handler); -} - -namespace detail -{ - template - class read_streambuf_handler - { - public: - read_streambuf_handler(AsyncReadStream& stream, - basic_streambuf& streambuf, - CompletionCondition completion_condition, ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - streambuf_.commit(bytes_transferred); - if (streambuf_.size() == streambuf_.max_size() - || completion_condition_(ec, total_transferred_)) - { - handler_(ec, total_transferred_); - } - else - { - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_streambuf_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_streambuf_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_streambuf_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_read(AsyncReadStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition, ReadHandler handler) -{ - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_streambuf_handler( - s, b, completion_condition, handler)); -} - -template -inline void async_read(AsyncReadStream& s, - asio::basic_streambuf& b, ReadHandler handler) -{ - async_read(s, b, transfer_all(), handler); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_IPP diff --git a/libtorrent/include/libtorrent/asio/impl/read_until.ipp b/libtorrent/include/libtorrent/asio/impl/read_until.ipp deleted file mode 100644 index 64c15ec7d..000000000 --- a/libtorrent/include/libtorrent/asio/impl/read_until.ipp +++ /dev/null @@ -1,750 +0,0 @@ -// -// read_until.ipp -// ~~~~~~~~~~~~~~ -// -// 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_READ_UNTIL_IPP -#define ASIO_READ_UNTIL_IPP - -#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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/const_buffers_iterator.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -template -inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_until(s, b, delim, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim, - asio::error_code& ec) -{ - std::size_t next_search_start = 0; - for (;;) - { - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - iterator iter = std::find(begin, end, delim); - if (iter != end) - { - // Found a match. We're done. - ec = asio::error_code(); - return iter.position() + 1; - } - else - { - // No match. Next search can start with the new data. - next_search_start = end.position(); - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - ec = error::not_found; - return 0; - } - - // Need more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - b.commit(s.read_some(b.prepare(bytes_available), ec)); - if (ec) - return 0; - } -} - -template -inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_until(s, b, delim, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - // Algorithm that finds a subsequence of equal values in a sequence. Returns - // (iterator,true) if a full match was found, in which case the iterator - // points to the beginning of the match. Returns (iterator,false) if a - // partial match was found at the end of the first sequence, in which case - // the iterator points to the beginning of the partial match. Returns - // (last1,false) if no full or partial match was found. - template - std::pair partial_search( - Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2) - { - for (Iterator1 iter1 = first1; iter1 != last1; ++iter1) - { - Iterator1 test_iter1 = iter1; - Iterator2 test_iter2 = first2; - for (;; ++test_iter1, ++test_iter2) - { - if (test_iter2 == last2) - return std::make_pair(iter1, true); - if (test_iter1 == last1) - { - if (test_iter2 != first2) - return std::make_pair(iter1, false); - else - break; - } - if (*test_iter1 != *test_iter2) - break; - } - } - return std::make_pair(last1, false); - } -} // namespace detail - -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - asio::error_code& ec) -{ - std::size_t next_search_start = 0; - for (;;) - { - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - std::pair result = asio::detail::partial_search( - begin, end, delim.begin(), delim.end()); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - ec = asio::error_code(); - return result.first.position() + delim.length(); - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first.position(); - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end.position(); - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - ec = error::not_found; - return 0; - } - - // Need more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - b.commit(s.read_some(b.prepare(bytes_available), ec)); - if (ec) - return 0; - } -} - -template -inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr) -{ - asio::error_code ec; - std::size_t bytes_transferred = read_until(s, b, expr, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - asio::error_code& ec) -{ - std::size_t next_search_start = 0; - for (;;) - { - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = b.data(); - iterator begin(buffers, next_search_start); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - boost::match_results match_results; - if (boost::regex_search(begin, end, match_results, expr, - boost::match_default | boost::match_partial)) - { - if (match_results[0].matched) - { - // Full match. We're done. - ec = asio::error_code(); - return match_results[0].second.position(); - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = match_results[0].first.position(); - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end.position(); - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - ec = error::not_found; - return 0; - } - - // Need more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - b.commit(s.read_some(b.prepare(bytes_available), ec)); - if (ec) - return 0; - } -} - -namespace detail -{ - template - class read_until_delim_handler - { - public: - read_until_delim_handler(AsyncReadStream& stream, - asio::basic_streambuf& streambuf, char delim, - std::size_t next_search_start, ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - delim_(delim), - next_search_start_(next_search_start), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - // Check for errors. - if (ec) - { - std::size_t bytes = 0; - handler_(ec, bytes); - return; - } - - // Commit received data to streambuf's get area. - streambuf_.commit(bytes_transferred); - - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - iterator iter = std::find(begin, end, delim_); - if (iter != end) - { - // Found a match. We're done. - std::size_t bytes = iter.position() + 1; - handler_(ec, bytes); - return; - } - - // No match. Check if buffer is full. - if (streambuf_.size() == streambuf_.max_size()) - { - std::size_t bytes = 0; - handler_(error::not_found, bytes); - return; - } - - // Next search can start with the new data. - next_search_start_ = end.position(); - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - char delim_; - std::size_t next_search_start_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_until_delim_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_until_delim_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, char delim, ReadHandler handler) -{ - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - iterator iter = std::find(begin, end, delim); - if (iter != end) - { - // Found a match. We're done. - asio::error_code ec; - std::size_t bytes = iter.position() + 1; - s.io_service().post(detail::bind_handler(handler, ec, bytes)); - return; - } - - // No match. Check if buffer is full. - if (b.size() == b.max_size()) - { - s.io_service().post(detail::bind_handler(handler, error::not_found, 0)); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_until_delim_handler( - s, b, delim, end.position(), handler)); -} - -namespace detail -{ - template - class read_until_delim_string_handler - { - public: - read_until_delim_string_handler(AsyncReadStream& stream, - asio::basic_streambuf& streambuf, - const std::string& delim, std::size_t next_search_start, - ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - delim_(delim), - next_search_start_(next_search_start), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - // Check for errors. - if (ec) - { - std::size_t bytes = 0; - handler_(ec, bytes); - return; - } - - // Commit received data to streambuf's get area. - streambuf_.commit(bytes_transferred); - - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - std::pair result = asio::detail::partial_search( - begin, end, delim_.begin(), delim_.end()); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - std::size_t bytes = result.first.position() + delim_.length(); - handler_(ec, bytes); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start_ = result.first.position(); - } - } - else - { - // No match. Next search can start with the new data. - next_search_start_ = end.position(); - } - - // Check if buffer is full. - if (streambuf_.size() == streambuf_.max_size()) - { - std::size_t bytes = 0; - handler_(error::not_found, bytes); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - std::string delim_; - std::size_t next_search_start_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_until_delim_string_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_string_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_until_delim_string_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - ReadHandler handler) -{ - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - std::size_t next_search_start; - std::pair result = asio::detail::partial_search( - begin, end, delim.begin(), delim.end()); - if (result.first != end) - { - if (result.second) - { - // Full match. We're done. - asio::error_code ec; - std::size_t bytes = result.first.position() + delim.length(); - s.io_service().post(detail::bind_handler(handler, ec, bytes)); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first.position(); - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end.position(); - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - s.io_service().post(detail::bind_handler(handler, error::not_found, 0)); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_until_delim_string_handler< - AsyncReadStream, Allocator, ReadHandler>( - s, b, delim, next_search_start, handler)); -} - -namespace detail -{ - template - class read_until_expr_handler - { - public: - read_until_expr_handler(AsyncReadStream& stream, - asio::basic_streambuf& streambuf, - const boost::regex& expr, std::size_t next_search_start, - ReadHandler handler) - : stream_(stream), - streambuf_(streambuf), - expr_(expr), - next_search_start_(next_search_start), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - // Check for errors. - if (ec) - { - std::size_t bytes = 0; - handler_(ec, bytes); - return; - } - - // Commit received data to streambuf's get area. - streambuf_.commit(bytes_transferred); - - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = streambuf_.data(); - iterator begin(buffers, next_search_start_); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - boost::match_results match_results; - if (boost::regex_search(begin, end, match_results, expr_, - boost::match_default | boost::match_partial)) - { - if (match_results[0].matched) - { - // Full match. We're done. - std::size_t bytes = match_results[0].second.position(); - handler_(ec, bytes); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start_ = match_results[0].first.position(); - } - } - else - { - // No match. Next search can start with the new data. - next_search_start_ = end.position(); - } - - // Check if buffer is full. - if (streambuf_.size() == streambuf_.max_size()) - { - std::size_t bytes = 0; - handler_(error::not_found, bytes); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, streambuf_.max_size() - streambuf_.size()); - stream_.async_read_some(streambuf_.prepare(bytes_available), *this); - } - - //private: - AsyncReadStream& stream_; - asio::basic_streambuf& streambuf_; - boost::regex expr_; - std::size_t next_search_start_; - ReadHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - read_until_expr_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - read_until_expr_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - read_until_expr_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - ReadHandler handler) -{ - // Determine the range of the data to be searched. - typedef typename asio::basic_streambuf< - Allocator>::const_buffers_type const_buffers_type; - typedef asio::detail::const_buffers_iterator< - const_buffers_type> iterator; - const_buffers_type buffers = b.data(); - iterator begin(buffers, 0); - iterator end(buffers, (std::numeric_limits::max)()); - - // Look for a match. - std::size_t next_search_start; - boost::match_results match_results; - if (boost::regex_search(begin, end, match_results, expr, - boost::match_default | boost::match_partial)) - { - if (match_results[0].matched) - { - // Full match. We're done. - asio::error_code ec; - std::size_t bytes = match_results[0].second.position(); - s.io_service().post(detail::bind_handler(handler, ec, bytes)); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = match_results[0].first.position(); - } - } - else - { - // No match. Next search can start with the new data. - next_search_start = end.position(); - } - - // Check if buffer is full. - if (b.size() == b.max_size()) - { - s.io_service().post(detail::bind_handler(handler, error::not_found, 0)); - return; - } - - // Start a new asynchronous read operation to obtain more data. - std::size_t bytes_available = - std::min(512, b.max_size() - b.size()); - s.async_read_some(b.prepare(bytes_available), - detail::read_until_expr_handler( - s, b, expr, next_search_start, handler)); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_UNTIL_IPP diff --git a/libtorrent/include/libtorrent/asio/impl/write.ipp b/libtorrent/include/libtorrent/asio/impl/write.ipp deleted file mode 100644 index 8c2d1d33f..000000000 --- a/libtorrent/include/libtorrent/asio/impl/write.ipp +++ /dev/null @@ -1,279 +0,0 @@ -// -// write.ipp -// ~~~~~~~~~ -// -// 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_WRITE_IPP -#define ASIO_WRITE_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/consuming_buffers.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { - -template -std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec) -{ - asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> tmp(buffers); - std::size_t total_transferred = 0; - while (tmp.begin() != tmp.end()) - { - std::size_t bytes_transferred = s.write_some(tmp, ec); - tmp.consume(bytes_transferred); - total_transferred += bytes_transferred; - if (completion_condition(ec, total_transferred)) - return total_transferred; - } - ec = asio::error_code(); - return total_transferred; -} - -template -inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers) -{ - asio::error_code ec; - std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = write(s, buffers, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -std::size_t write(SyncWriteStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec) -{ - std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec); - b.consume(bytes_transferred); - return bytes_transferred; -} - -template -inline std::size_t write(SyncWriteStream& s, - asio::basic_streambuf& b) -{ - asio::error_code ec; - std::size_t bytes_transferred = write(s, b, transfer_all(), ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -template -inline std::size_t write(SyncWriteStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition) -{ - asio::error_code ec; - std::size_t bytes_transferred = write(s, b, completion_condition, ec); - asio::detail::throw_error(ec); - return bytes_transferred; -} - -namespace detail -{ - template - class write_handler - { - public: - typedef asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> buffers_type; - - write_handler(AsyncWriteStream& stream, const buffers_type& buffers, - CompletionCondition completion_condition, WriteHandler handler) - : stream_(stream), - buffers_(buffers), - total_transferred_(0), - completion_condition_(completion_condition), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - total_transferred_ += bytes_transferred; - buffers_.consume(bytes_transferred); - if (completion_condition_(ec, total_transferred_) - || buffers_.begin() == buffers_.end()) - { - handler_(ec, total_transferred_); - } - else - { - stream_.async_write_some(buffers_, *this); - } - } - - //private: - AsyncWriteStream& stream_; - buffers_type buffers_; - std::size_t total_transferred_; - CompletionCondition completion_condition_; - WriteHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - write_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - write_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - write_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, WriteHandler handler) -{ - asio::detail::consuming_buffers< - const_buffer, ConstBufferSequence> tmp(buffers); - s.async_write_some(tmp, - detail::write_handler( - s, tmp, completion_condition, handler)); -} - -template -inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - WriteHandler handler) -{ - async_write(s, buffers, transfer_all(), handler); -} - -namespace detail -{ - template - class write_streambuf_handler - { - public: - write_streambuf_handler(asio::basic_streambuf& streambuf, - WriteHandler handler) - : streambuf_(streambuf), - handler_(handler) - { - } - - void operator()(const asio::error_code& ec, - std::size_t bytes_transferred) - { - streambuf_.consume(bytes_transferred); - handler_(ec, bytes_transferred); - } - - //private: - asio::basic_streambuf& streambuf_; - WriteHandler handler_; - }; - - template - inline void* asio_handler_allocate(std::size_t size, - write_streambuf_handler* this_handler) - { - return asio_handler_alloc_helpers::allocate( - size, &this_handler->handler_); - } - - template - inline void asio_handler_deallocate(void* pointer, std::size_t size, - write_streambuf_handler* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, &this_handler->handler_); - } - - template - inline void asio_handler_invoke(const Function& function, - write_streambuf_handler* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, &this_handler->handler_); - } -} // namespace detail - -template -inline void async_write(AsyncWriteStream& s, - asio::basic_streambuf& b, - CompletionCondition completion_condition, WriteHandler handler) -{ - async_write(s, b.data(), completion_condition, - detail::write_streambuf_handler< - AsyncWriteStream, Allocator, WriteHandler>(b, handler)); -} - -template -inline void async_write(AsyncWriteStream& s, - asio::basic_streambuf& b, WriteHandler handler) -{ - async_write(s, b, transfer_all(), handler); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WRITE_IPP diff --git a/libtorrent/include/libtorrent/asio/io_service.hpp b/libtorrent/include/libtorrent/asio/io_service.hpp deleted file mode 100644 index 731a7ac9a..000000000 --- a/libtorrent/include/libtorrent/asio/io_service.hpp +++ /dev/null @@ -1,501 +0,0 @@ -// -// io_service.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_IO_SERVICE_HPP -#define ASIO_IO_SERVICE_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/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" -#include "asio/detail/epoll_reactor_fwd.hpp" -#include "asio/detail/kqueue_reactor_fwd.hpp" -#include "asio/detail/noncopyable.hpp" -#include "asio/detail/select_reactor_fwd.hpp" -#include "asio/detail/service_registry_fwd.hpp" -#include "asio/detail/signal_init.hpp" -#include "asio/detail/task_io_service_fwd.hpp" -#include "asio/detail/win_iocp_io_service_fwd.hpp" -#include "asio/detail/winsock_init.hpp" -#include "asio/detail/wrapped_handler.hpp" - -namespace asio { - -/// Provides core I/O functionality. -/** - * The io_service class provides the core I/O functionality for users of the - * asynchronous I/O objects, including: - * - * @li asio::ip::tcp::socket - * @li asio::ip::tcp::acceptor - * @li asio::ip::udp::socket - * @li asio::deadline_timer. - * - * The io_service class also includes facilities intended for developers of - * custom asynchronous services. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe, with the exception that calling reset() - * while there are unfinished run() calls results in undefined behaviour. - * - * @par Concepts: - * Dispatcher. - * - * @sa @ref io_service_handler_exception - */ -class io_service - : private noncopyable -{ -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_io_service impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::task_io_service > impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::task_io_service > impl_type; -#else - typedef detail::task_io_service > impl_type; -#endif - -public: - class work; - friend class work; - - class id; - - class service; - - class strand; - - /// Constructor. - io_service(); - - /// Constructor. - /** - * Construct with a hint about the required level of concurrency. - * - * @param concurrency_hint A suggestion to the implementation on how many - * threads it should allow to run simultaneously. - */ - explicit io_service(std::size_t concurrency_hint); - - /// Destructor. - ~io_service(); - - /// Run the io_service's event processing loop. - /** - * The run() function blocks until all work has finished and there are no - * more handlers to be dispatched, or until the io_service has been stopped. - * - * Multiple threads may call the run() function to set up a pool of threads - * from which the io_service may execute handlers. - * - * The run() function may be safely called again once it has completed only - * after a call to reset(). - * - * @return The number of handlers that were executed. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t run(); - - /// Run the io_service's event processing loop. - /** - * The run() function blocks until all work has finished and there are no - * more handlers to be dispatched, or until the io_service has been stopped. - * - * Multiple threads may call the run() function to set up a pool of threads - * from which the io_service may execute handlers. - * - * The run() function may be safely called again once it has completed only - * after a call to reset(). - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of handlers that were executed. - */ - std::size_t run(asio::error_code& ec); - - /// Run the io_service's event processing loop to execute at most one handler. - /** - * The run_one() function blocks until one handler has been dispatched, or - * until the io_service has been stopped. - * - * @return The number of handlers that were executed. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t run_one(); - - /// Run the io_service's event processing loop to execute at most one handler. - /** - * The run_one() function blocks until one handler has been dispatched, or - * until the io_service has been stopped. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of handlers that were executed. - */ - std::size_t run_one(asio::error_code& ec); - - /// Run the io_service's event processing loop to execute ready handlers. - /** - * The poll() function runs handlers that are ready to run, without blocking, - * until the io_service has been stopped or there are no more ready handlers. - * - * @return The number of handlers that were executed. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t poll(); - - /// Run the io_service's event processing loop to execute ready handlers. - /** - * The poll() function runs handlers that are ready to run, without blocking, - * until the io_service has been stopped or there are no more ready handlers. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of handlers that were executed. - */ - std::size_t poll(asio::error_code& ec); - - /// Run the io_service's event processing loop to execute one ready handler. - /** - * The poll_one() function runs at most one handler that is ready to run, - * without blocking. - * - * @return The number of handlers that were executed. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t poll_one(); - - /// Run the io_service's event processing loop to execute one ready handler. - /** - * The poll_one() function runs at most one handler that is ready to run, - * without blocking. - * - * @param ec Set to indicate what error occurred, if any. - * - * @return The number of handlers that were executed. - */ - std::size_t poll_one(asio::error_code& ec); - - /// Stop the io_service's event processing loop. - /** - * This function does not block, but instead simply signals the io_service to - * stop. All invocations of its run() or run_one() member functions should - * return as soon as possible. Subsequent calls to run(), run_one(), poll() - * or poll_one() will return immediately until reset() is called. - */ - void stop(); - - /// Reset the io_service in preparation for a subsequent run() invocation. - /** - * This function must be called prior to any second or later set of - * invocations of the run(), run_one(), poll() or poll_one() functions when a - * previous invocation of these functions returned due to the io_service - * being stopped or running out of work. This function allows the io_service - * to reset any internal state, such as a "stopped" flag. - * - * This function must not be called while there are any unfinished calls to - * the run(), run_one(), poll() or poll_one() functions. - */ - void reset(); - - /// Request the io_service to invoke the given handler. - /** - * This function is used to ask the io_service to execute the given handler. - * - * The io_service guarantees that the handler will only be called in a thread - * in which the run(), run_one(), poll() or poll_one() member functions is - * currently being invoked. The handler may be executed inside this function - * if the guarantee can be met. - * - * @param handler The handler to be called. The io_service will make - * a copy of the handler object as required. The function signature of the - * handler must be: @code void handler(); @endcode - */ - template - void dispatch(CompletionHandler handler); - - /// Request the io_service to invoke the given handler and return immediately. - /** - * This function is used to ask the io_service to execute the given handler, - * but without allowing the io_service to call the handler from inside this - * function. - * - * The io_service guarantees that the handler will only be called in a thread - * in which the run(), run_one(), poll() or poll_one() member functions is - * currently being invoked. - * - * @param handler The handler to be called. The io_service will make - * a copy of the handler object as required. The function signature of the - * handler must be: @code void handler(); @endcode - */ - template - void post(CompletionHandler handler); - - /// Create a new handler that automatically dispatches the wrapped handler - /// on the io_service. - /** - * This function is used to create a new handler function object that, when - * invoked, will automatically pass the wrapped handler to the io_service's - * dispatch function. - * - * @param handler The handler to be wrapped. The io_service will make a copy - * of the handler object as required. The function signature of the handler - * must be: @code void handler(A1 a1, ... An an); @endcode - * - * @return A function object that, when invoked, passes the wrapped handler to - * the io_service's dispatch function. Given a function object with the - * signature: - * @code R f(A1 a1, ... An an); @endcode - * If this function object is passed to the wrap function like so: - * @code io_service.wrap(f); @endcode - * then the return value is a function object with the signature - * @code void g(A1 a1, ... An an); @endcode - * that, when invoked, executes code equivalent to: - * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode - */ - template -#if defined(GENERATING_DOCUMENTATION) - unspecified -#else - detail::wrapped_handler -#endif - wrap(Handler handler); - - /// Obtain the service object corresponding to the given type. - /** - * This function is used to locate a service object that corresponds to - * the given service type. If there is no existing implementation of the - * service, then the io_service will create a new instance of the service. - * - * @param ios The io_service object that owns the service. - * - * @return The service interface implementing the specified service type. - * Ownership of the service interface is not transferred to the caller. - */ - template - friend Service& use_service(io_service& ios); - - /// Add a service object to the io_service. - /** - * This function is used to add a service to the io_service. - * - * @param ios The io_service object that owns the service. - * - * @param svc The service object. On success, ownership of the service object - * is transferred to the io_service. When the io_service object is destroyed, - * it will destroy the service object by performing: - * @code delete static_cast(svc) @endcode - * - * @throws asio::service_already_exists Thrown if a service of the - * given type is already present in the io_service. - * - * @throws asio::invalid_service_owner Thrown if the service's owning - * io_service is not the io_service object specified by the ios parameter. - */ - template - friend void add_service(io_service& ios, Service* svc); - - /// Determine if an io_service contains a specified service type. - /** - * This function is used to determine whether the io_service contains a - * service object corresponding to the given service type. - * - * @param ios The io_service object that owns the service. - * - * @return A boolean indicating whether the io_service contains the service. - */ - template - friend bool has_service(io_service& ios); - -private: -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - detail::winsock_init<> init_; -#elif defined(__sun) || defined(__QNX__) - detail::signal_init<> init_; -#endif - - // The service registry. - asio::detail::service_registry* service_registry_; - - // The implementation. - impl_type& impl_; -}; - -/// Class to inform the io_service when it has work to do. -/** - * The work class is used to inform the io_service when work starts and - * finishes. This ensures that the io_service's run() function will not exit - * while work is underway, and that it does exit when there is no unfinished - * work remaining. - * - * The work class is copy-constructible so that it may be used as a data member - * in a handler class. It is not assignable. - */ -class io_service::work -{ -public: - /// Constructor notifies the io_service that work is starting. - /** - * The constructor is used to inform the io_service that some work has begun. - * This ensures that the io_service's run() function will not exit while the - * work is underway. - */ - explicit work(asio::io_service& io_service); - - /// Copy constructor notifies the io_service that work is starting. - /** - * The constructor is used to inform the io_service that some work has begun. - * This ensures that the io_service's run() function will not exit while the - * work is underway. - */ - work(const work& other); - - /// Destructor notifies the io_service that the work is complete. - /** - * The destructor is used to inform the io_service that some work has - * finished. Once the count of unfinished work reaches zero, the io_service's - * run() function is permitted to exit. - */ - ~work(); - - /// Get the io_service associated with the work. - asio::io_service& io_service(); - -private: - // Prevent assignment. - void operator=(const work& other); - - // The io_service. - asio::io_service& io_service_; -}; - -/// Class used to uniquely identify a service. -class io_service::id - : private noncopyable -{ -public: - /// Constructor. - id() {} -}; - -/// Base class for all io_service services. -class io_service::service - : private noncopyable -{ -public: - /// Get the io_service object that owns the service. - asio::io_service& io_service(); - -protected: - /// Constructor. - /** - * @param owner The io_service object that owns the service. - */ - service(asio::io_service& owner); - - /// Destructor. - virtual ~service(); - -private: - /// Destroy all user-defined handler objects owned by the service. - virtual void shutdown_service() = 0; - - friend class asio::detail::service_registry; - asio::io_service& owner_; - const std::type_info* type_info_; - const asio::io_service::id* id_; - service* next_; -}; - -/// Exception thrown when trying to add a duplicate service to an io_service. -class service_already_exists - : public std::logic_error -{ -public: - service_already_exists() - : std::logic_error("Service already exists.") - { - } -}; - -/// Exception thrown when trying to add a service object to an io_service where -/// the service has a different owner. -class invalid_service_owner - : public std::logic_error -{ -public: - invalid_service_owner() - : std::logic_error("Invalid service owner.") - { - } -}; - -/** - * @page io_service_handler_exception Effect of exceptions thrown from handlers - * - * If an exception is thrown from a handler, the exception is allowed to - * propagate through the throwing thread's invocation of - * asio::io_service::run(), asio::io_service::run_one(), - * asio::io_service::poll() or asio::io_service::poll_one(). - * No other threads that are calling any of these functions are affected. It is - * then the responsibility of the application to catch the exception. - * - * After the exception has been caught, the - * asio::io_service::run(), asio::io_service::run_one(), - * asio::io_service::poll() or asio::io_service::poll_one() - * call may be restarted @em without the need for an intervening call to - * asio::io_service::reset(). This allows the thread to rejoin the - * io_service's thread pool without impacting any other threads in the pool. - * - * @par Example - * @code - * asio::io_service io_service; - * ... - * for (;;) - * { - * try - * { - * io_service.run(); - * break; // run() exited normally - * } - * catch (my_exception& e) - * { - * // Deal with exception as appropriate. - * } - * } - * @endcode - */ - -} // namespace asio - -#include "asio/impl/io_service.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IO_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/address.hpp b/libtorrent/include/libtorrent/asio/ip/address.hpp deleted file mode 100644 index 1b2c548bf..000000000 --- a/libtorrent/include/libtorrent/asio/ip/address.hpp +++ /dev/null @@ -1,277 +0,0 @@ -// -// address.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_IP_ADDRESS_HPP -#define ASIO_IP_ADDRESS_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/ip/address_v4.hpp" -#include "asio/ip/address_v6.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ip { - -/// Implements version-independent IP addresses. -/** - * The asio::ip::address class provides the ability to use either IP - * version 4 or version 6 addresses. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class address -{ -public: - /// Default constructor. - address() - : type_(ipv4), - ipv4_address_(), - ipv6_address_() - { - } - - /// Construct an address from an IPv4 address. - address(const asio::ip::address_v4& ipv4_address) - : type_(ipv4), - ipv4_address_(ipv4_address), - ipv6_address_() - { - } - - /// Construct an address from an IPv6 address. - address(const asio::ip::address_v6& ipv6_address) - : type_(ipv6), - ipv4_address_(), - ipv6_address_(ipv6_address) - { - } - - /// Copy constructor. - address(const address& other) - : type_(other.type_), - ipv4_address_(other.ipv4_address_), - ipv6_address_(other.ipv6_address_) - { - } - - /// Assign from another address. - address& operator=(const address& other) - { - type_ = other.type_; - ipv4_address_ = other.ipv4_address_; - ipv6_address_ = other.ipv6_address_; - return *this; - } - - /// Assign from an IPv4 address. - address& operator=(const asio::ip::address_v4& ipv4_address) - { - type_ = ipv4; - ipv4_address_ = ipv4_address; - ipv6_address_ = asio::ip::address_v6(); - return *this; - } - - /// Assign from an IPv6 address. - address& operator=(const asio::ip::address_v6& ipv6_address) - { - type_ = ipv6; - ipv4_address_ = asio::ip::address_v4(); - ipv6_address_ = ipv6_address; - return *this; - } - - /// Get whether the address is an IP version 4 address. - bool is_v4() const - { - return type_ == ipv4; - } - - /// Get whether the address is an IP version 6 address. - bool is_v6() const - { - return type_ == ipv6; - } - - /// Get the address as an IP version 4 address. - asio::ip::address_v4 to_v4() const - { - if (type_ != ipv4) - { - asio::system_error e( - asio::error::address_family_not_supported); - boost::throw_exception(e); - } - return ipv4_address_; - } - - /// Get the address as an IP version 6 address. - asio::ip::address_v6 to_v6() const - { - if (type_ != ipv6) - { - asio::system_error e( - asio::error::address_family_not_supported); - boost::throw_exception(e); - } - return ipv6_address_; - } - - /// Get the address as a string in dotted decimal format. - std::string to_string() const - { - if (type_ == ipv6) - return ipv6_address_.to_string(); - return ipv4_address_.to_string(); - } - - /// Get the address as a string in dotted decimal format. - std::string to_string(asio::error_code& ec) const - { - if (type_ == ipv6) - return ipv6_address_.to_string(ec); - return ipv4_address_.to_string(ec); - } - - /// Create an address from an IPv4 address string in dotted decimal form, - /// or from an IPv6 address in hexadecimal notation. - static address from_string(const char* str) - { - asio::error_code ec; - address addr = from_string(str, ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Create an address from an IPv4 address string in dotted decimal form, - /// or from an IPv6 address in hexadecimal notation. - static address from_string(const char* str, asio::error_code& ec) - { - asio::ip::address_v6 ipv6_address = - asio::ip::address_v6::from_string(str, ec); - if (!ec) - { - address tmp; - tmp.type_ = ipv6; - tmp.ipv6_address_ = ipv6_address; - return tmp; - } - - asio::ip::address_v4 ipv4_address = - asio::ip::address_v4::from_string(str, ec); - if (!ec) - { - address tmp; - tmp.type_ = ipv4; - tmp.ipv4_address_ = ipv4_address; - return tmp; - } - - return address(); - } - - /// Create an address from an IPv4 address string in dotted decimal form, - /// or from an IPv6 address in hexadecimal notation. - static address from_string(const std::string& str) - { - return from_string(str.c_str()); - } - - /// Create an address from an IPv4 address string in dotted decimal form, - /// or from an IPv6 address in hexadecimal notation. - static address from_string(const std::string& str, - asio::error_code& ec) - { - return from_string(str.c_str(), ec); - } - - /// Compare two addresses for equality. - friend bool operator==(const address& a1, const address& a2) - { - if (a1.type_ != a2.type_) - return false; - if (a1.type_ == ipv6) - return a1.ipv6_address_ == a2.ipv6_address_; - return a1.ipv4_address_ == a2.ipv4_address_; - } - - /// Compare two addresses for inequality. - friend bool operator!=(const address& a1, const address& a2) - { - if (a1.type_ != a2.type_) - return true; - if (a1.type_ == ipv6) - return a1.ipv6_address_ != a2.ipv6_address_; - return a1.ipv4_address_ != a2.ipv4_address_; - } - - /// Compare addresses for ordering. - friend bool operator<(const address& a1, const address& a2) - { - if (a1.type_ < a2.type_) - return true; - if (a1.type_ > a2.type_) - return false; - if (a1.type_ == ipv6) - return a1.ipv6_address_ < a2.ipv6_address_; - return a1.ipv4_address_ < a2.ipv4_address_; - } - -private: - // The type of the address. - enum { ipv4, ipv6 } type_; - - // The underlying IPv4 address. - asio::ip::address_v4 ipv4_address_; - - // The underlying IPv6 address. - asio::ip::address_v6 ipv6_address_; -}; - -/// Output an address as a string. -/** - * Used to output a human-readable string for a specified address. - * - * @param os The output stream to which the string will be written. - * - * @param addr The address to be written. - * - * @return The output stream. - * - * @relates asio::ip::address - */ -template -std::basic_ostream& operator<<( - std::basic_ostream& os, const address& addr) -{ - os << addr.to_string(); - return os; -} - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_ADDRESS_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/address_v4.hpp b/libtorrent/include/libtorrent/asio/ip/address_v4.hpp deleted file mode 100644 index ae3891c95..000000000 --- a/libtorrent/include/libtorrent/asio/ip/address_v4.hpp +++ /dev/null @@ -1,283 +0,0 @@ -// -// address_v4.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_IP_ADDRESS_V4_HPP -#define ASIO_IP_ADDRESS_V4_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ip { - -/// Implements IP version 4 style addresses. -/** - * The asio::ip::address_v4 class provides the ability to use and - * manipulate IP version 4 addresses. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class address_v4 -{ -public: - /// The type used to represent an address as an array of bytes. - typedef boost::array bytes_type; - - /// Default constructor. - address_v4() - { - addr_.s_addr = 0; - } - - /// Construct an address from raw bytes. - explicit address_v4(const bytes_type& bytes) - { - using namespace std; // For memcpy. - memcpy(&addr_.s_addr, bytes.elems, 4); - } - - /// Construct an address from a unsigned long in host byte order. - explicit address_v4(unsigned long addr) - { - addr_.s_addr = asio::detail::socket_ops::host_to_network_long(addr); - } - - /// Copy constructor. - address_v4(const address_v4& other) - : addr_(other.addr_) - { - } - - /// Assign from another address. - address_v4& operator=(const address_v4& other) - { - addr_ = other.addr_; - return *this; - } - - /// Get the address in bytes. - bytes_type to_bytes() const - { - using namespace std; // For memcpy. - bytes_type bytes; - memcpy(bytes.elems, &addr_.s_addr, 4); - return bytes; - } - - /// Get the address as an unsigned long in host byte order - unsigned long to_ulong() const - { - return asio::detail::socket_ops::network_to_host_long(addr_.s_addr); - } - - /// Get the address as a string in dotted decimal format. - std::string to_string() const - { - asio::error_code ec; - std::string addr = to_string(ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Get the address as a string in dotted decimal format. - std::string to_string(asio::error_code& ec) const - { - char addr_str[asio::detail::max_addr_v4_str_len]; - const char* addr = - asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str, - asio::detail::max_addr_v4_str_len, 0, ec); - if (addr == 0) - return std::string(); - return addr; - } - - /// Create an address from an IP address string in dotted decimal form. - static address_v4 from_string(const char* str) - { - asio::error_code ec; - address_v4 addr = from_string(str, ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Create an address from an IP address string in dotted decimal form. - static address_v4 from_string(const char* str, asio::error_code& ec) - { - address_v4 tmp; - if (asio::detail::socket_ops::inet_pton( - AF_INET, str, &tmp.addr_, 0, ec) <= 0) - return address_v4(); - return tmp; - } - - /// Create an address from an IP address string in dotted decimal form. - static address_v4 from_string(const std::string& str) - { - return from_string(str.c_str()); - } - - /// Create an address from an IP address string in dotted decimal form. - static address_v4 from_string(const std::string& str, - asio::error_code& ec) - { - return from_string(str.c_str(), ec); - } - - /// Determine whether the address is a class A address. - bool is_class_a() const - { - return IN_CLASSA(to_ulong()); - } - - /// Determine whether the address is a class B address. - bool is_class_b() const - { - return IN_CLASSB(to_ulong()); - } - - /// Determine whether the address is a class C address. - bool is_class_c() const - { - return IN_CLASSC(to_ulong()); - } - - /// Determine whether the address is a multicast address. - bool is_multicast() const - { - return IN_MULTICAST(to_ulong()); - } - - /// Compare two addresses for equality. - friend bool operator==(const address_v4& a1, const address_v4& a2) - { - return a1.addr_.s_addr == a2.addr_.s_addr; - } - - /// Compare two addresses for inequality. - friend bool operator!=(const address_v4& a1, const address_v4& a2) - { - return a1.addr_.s_addr != a2.addr_.s_addr; - } - - /// Compare addresses for ordering. - friend bool operator<(const address_v4& a1, const address_v4& a2) - { - return a1.to_ulong() < a2.to_ulong(); - } - - /// Compare addresses for ordering. - friend bool operator>(const address_v4& a1, const address_v4& a2) - { - return a1.to_ulong() > a2.to_ulong(); - } - - /// Compare addresses for ordering. - friend bool operator<=(const address_v4& a1, const address_v4& a2) - { - return a1.to_ulong() <= a2.to_ulong(); - } - - /// Compare addresses for ordering. - friend bool operator>=(const address_v4& a1, const address_v4& a2) - { - return a1.to_ulong() >= a2.to_ulong(); - } - - /// Obtain an address object that represents any address. - static address_v4 any() - { - return address_v4(static_cast(INADDR_ANY)); - } - - /// Obtain an address object that represents the loopback address. - static address_v4 loopback() - { - return address_v4(static_cast(INADDR_LOOPBACK)); - } - - /// Obtain an address object that represents the broadcast address. - static address_v4 broadcast() - { - return address_v4(static_cast(INADDR_BROADCAST)); - } - - /// Obtain an address object that represents the broadcast address that - /// corresponds to the specified address and netmask. - static address_v4 broadcast(const address_v4& addr, const address_v4& mask) - { - return address_v4(addr.to_ulong() | ~mask.to_ulong()); - } - - /// Obtain the netmask that corresponds to the address, based on its address - /// class. - static address_v4 netmask(const address_v4& addr) - { - if (addr.is_class_a()) - return address_v4(0xFF000000); - if (addr.is_class_b()) - return address_v4(0xFFFF0000); - if (addr.is_class_c()) - return address_v4(0xFFFFFF00); - return address_v4(0xFFFFFFFF); - } - -private: - // The underlying IPv4 address. - asio::detail::in4_addr_type addr_; -}; - -/// Output an address as a string. -/** - * Used to output a human-readable string for a specified address. - * - * @param os The output stream to which the string will be written. - * - * @param addr The address to be written. - * - * @return The output stream. - * - * @relates asio::ip::address_v4 - */ -template -std::basic_ostream& operator<<( - std::basic_ostream& os, const address_v4& addr) -{ - asio::error_code ec; - std::string s = addr.to_string(ec); - if (ec) - os.setstate(std::ios_base::failbit); - else - for (std::string::iterator i = s.begin(); i != s.end(); ++i) - os << os.widen(*i); - return os; -} - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_ADDRESS_V4_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/address_v6.hpp b/libtorrent/include/libtorrent/asio/ip/address_v6.hpp deleted file mode 100644 index f732955fa..000000000 --- a/libtorrent/include/libtorrent/asio/ip/address_v6.hpp +++ /dev/null @@ -1,401 +0,0 @@ -// -// address_v6.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_IP_ADDRESS_V6_HPP -#define ASIO_IP_ADDRESS_V6_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/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/detail/throw_error.hpp" -#include "asio/ip/address_v4.hpp" - -namespace asio { -namespace ip { - -/// Implements IP version 6 style addresses. -/** - * The asio::ip::address_v6 class provides the ability to use and - * manipulate IP version 6 addresses. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -class address_v6 -{ -public: - /// The type used to represent an address as an array of bytes. - typedef boost::array bytes_type; - - /// Default constructor. - address_v6() - : scope_id_(0) - { - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - addr_ = tmp_addr; - } - - /// Construct an address from raw bytes and scope ID. - explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0) - : scope_id_(scope_id) - { - using namespace std; // For memcpy. - memcpy(addr_.s6_addr, bytes.elems, 16); - } - - /// Copy constructor. - address_v6(const address_v6& other) - : addr_(other.addr_), - scope_id_(other.scope_id_) - { - } - - /// Assign from another address. - address_v6& operator=(const address_v6& other) - { - addr_ = other.addr_; - scope_id_ = other.scope_id_; - return *this; - } - - /// The scope ID of the address. - /** - * Returns the scope ID associated with the IPv6 address. - */ - unsigned long scope_id() const - { - return scope_id_; - } - - /// The scope ID of the address. - /** - * Modifies the scope ID associated with the IPv6 address. - */ - void scope_id(unsigned long id) - { - scope_id_ = id; - } - - /// Get the address in bytes. - bytes_type to_bytes() const - { - using namespace std; // For memcpy. - bytes_type bytes; - memcpy(bytes.elems, addr_.s6_addr, 16); - return bytes; - } - - /// Get the address as a string. - std::string to_string() const - { - asio::error_code ec; - std::string addr = to_string(ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Get the address as a string. - std::string to_string(asio::error_code& ec) const - { - char addr_str[asio::detail::max_addr_v6_str_len]; - const char* addr = - asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str, - asio::detail::max_addr_v6_str_len, scope_id_, ec); - if (addr == 0) - return std::string(); - return addr; - } - - /// Create an address from an IP address string. - static address_v6 from_string(const char* str) - { - asio::error_code ec; - address_v6 addr = from_string(str, ec); - asio::detail::throw_error(ec); - return addr; - } - - /// Create an address from an IP address string. - static address_v6 from_string(const char* str, asio::error_code& ec) - { - address_v6 tmp; - if (asio::detail::socket_ops::inet_pton( - AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0) - return address_v6(); - return tmp; - } - - /// Create an address from an IP address string. - static address_v6 from_string(const std::string& str) - { - return from_string(str.c_str()); - } - - /// Create an address from an IP address string. - static address_v6 from_string(const std::string& str, - asio::error_code& ec) - { - return from_string(str.c_str(), ec); - } - - /// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address. - address_v4 to_v4() const - { - if (!is_v4_mapped() && !is_v4_compatible()) - throw std::bad_cast(); - address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12], - addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } }; - return address_v4(v4_bytes); - } - - /// Determine whether the address is a loopback address. - bool is_loopback() const - { -#if defined(__BORLANDC__) - return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) - && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) - && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) - && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) - && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) - && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) - && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) - && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1)); -#else - using namespace asio::detail; - return IN6_IS_ADDR_LOOPBACK(&addr_) != 0; -#endif - } - - /// Determine whether the address is unspecified. - bool is_unspecified() const - { -#if defined(__BORLANDC__) - return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) - && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) - && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0) - && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0) - && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0) - && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0) - && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0) - && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0)); -#else - using namespace asio::detail; - return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0; -#endif - } - - /// Determine whether the address is link local. - bool is_link_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0; - } - - /// Determine whether the address is site local. - bool is_site_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_SITELOCAL(&addr_) != 0; - } - - /// Determine whether the address is a mapped IPv4 address. - bool is_v4_mapped() const - { - using namespace asio::detail; - return IN6_IS_ADDR_V4MAPPED(&addr_) != 0; - } - - /// Determine whether the address is an IPv4-compatible address. - bool is_v4_compatible() const - { - using namespace asio::detail; - return IN6_IS_ADDR_V4COMPAT(&addr_) != 0; - } - - /// Determine whether the address is a multicast address. - bool is_multicast() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MULTICAST(&addr_) != 0; - } - - /// Determine whether the address is a global multicast address. - bool is_multicast_global() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0; - } - - /// Determine whether the address is a link-local multicast address. - bool is_multicast_link_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0; - } - - /// Determine whether the address is a node-local multicast address. - bool is_multicast_node_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0; - } - - /// Determine whether the address is a org-local multicast address. - bool is_multicast_org_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0; - } - - /// Determine whether the address is a site-local multicast address. - bool is_multicast_site_local() const - { - using namespace asio::detail; - return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0; - } - - /// Compare two addresses for equality. - friend bool operator==(const address_v6& a1, const address_v6& a2) - { - using namespace std; // For memcmp. - return memcmp(&a1.addr_, &a2.addr_, - sizeof(asio::detail::in6_addr_type)) == 0 - && a1.scope_id_ == a2.scope_id_; - } - - /// Compare two addresses for inequality. - friend bool operator!=(const address_v6& a1, const address_v6& a2) - { - using namespace std; // For memcmp. - return memcmp(&a1.addr_, &a2.addr_, - sizeof(asio::detail::in6_addr_type)) != 0 - || a1.scope_id_ != a2.scope_id_; - } - - /// Compare addresses for ordering. - friend bool operator<(const address_v6& a1, const address_v6& a2) - { - using namespace std; // For memcmp. - int memcmp_result = memcmp(&a1.addr_, &a2.addr_, - sizeof(asio::detail::in6_addr_type)) < 0; - if (memcmp_result < 0) - return true; - if (memcmp_result > 0) - return false; - return a1.scope_id_ < a2.scope_id_; - } - - /// Compare addresses for ordering. - friend bool operator>(const address_v6& a1, const address_v6& a2) - { - return a2 < a1; - } - - /// Compare addresses for ordering. - friend bool operator<=(const address_v6& a1, const address_v6& a2) - { - return !(a2 < a1); - } - - /// Compare addresses for ordering. - friend bool operator>=(const address_v6& a1, const address_v6& a2) - { - return !(a1 < a2); - } - - /// Obtain an address object that represents any address. - static address_v6 any() - { - return address_v6(); - } - - /// Obtain an address object that represents the loopback address. - static address_v6 loopback() - { - address_v6 tmp; - asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT; - tmp.addr_ = tmp_addr; - return tmp; - } - - /// Create an IPv4-mapped IPv6 address. - static address_v6 v4_mapped(const address_v4& addr) - { - address_v4::bytes_type v4_bytes = addr.to_bytes(); - bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, - v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; - return address_v6(v6_bytes); - } - - /// Create an IPv4-compatible IPv6 address. - static address_v6 v4_compatible(const address_v4& addr) - { - address_v4::bytes_type v4_bytes = addr.to_bytes(); - bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } }; - return address_v6(v6_bytes); - } - -private: - // The underlying IPv6 address. - asio::detail::in6_addr_type addr_; - - // The scope ID associated with the address. - unsigned long scope_id_; -}; - -/// Output an address as a string. -/** - * Used to output a human-readable string for a specified address. - * - * @param os The output stream to which the string will be written. - * - * @param addr The address to be written. - * - * @return The output stream. - * - * @relates asio::ip::address_v6 - */ -template -std::basic_ostream& operator<<( - std::basic_ostream& os, const address_v6& addr) -{ - asio::error_code ec; - std::string s = addr.to_string(ec); - if (ec) - os.setstate(std::ios_base::failbit); - else - for (std::string::iterator i = s.begin(); i != s.end(); ++i) - os << os.widen(*i); - return os; -} - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_ADDRESS_V6_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/basic_endpoint.hpp b/libtorrent/include/libtorrent/asio/ip/basic_endpoint.hpp deleted file mode 100644 index 3ca91dc03..000000000 --- a/libtorrent/include/libtorrent/asio/ip/basic_endpoint.hpp +++ /dev/null @@ -1,368 +0,0 @@ -// -// basic_endpoint.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_IP_BASIC_ENDPOINT_HPP -#define ASIO_IP_BASIC_ENDPOINT_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/push_options.hpp" -#include -#include -#include -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# include -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/ip/address.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// Describes an endpoint for a version-independent IP socket. -/** - * The asio::ip::basic_endpoint class template describes an endpoint that - * may be associated with a particular socket. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Concepts: - * Endpoint. - */ -template -class basic_endpoint -{ -public: - /// The protocol type associated with the endpoint. - typedef InternetProtocol protocol_type; - - /// The type of the endpoint structure. This type is dependent on the - /// underlying implementation of the socket layer. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined data_type; -#else - typedef asio::detail::socket_addr_type data_type; -#endif - - /// The type for the size of the endpoint structure. This type is dependent on - /// the underlying implementation of the socket layer. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined size_type; -#else - typedef asio::detail::socket_addr_len_type size_type; -#endif - - /// Default constructor. - basic_endpoint() - : data_() - { - asio::detail::sockaddr_in4_type& data - = reinterpret_cast(data_); - data.sin_family = AF_INET; - data.sin_port = 0; - data.sin_addr.s_addr = INADDR_ANY; - } - - /// Construct an endpoint using a port number, specified in the host's byte - /// order. The IP address will be the any address (i.e. INADDR_ANY or - /// in6addr_any). This constructor would typically be used for accepting new - /// connections. - /** - * @par Examples - * To initialise an IPv4 TCP endpoint for port 1234, use: - * @code - * asio::ip::tcp::endpoint ep(asio::ip::tcp::v4(), 1234); - * @endcode - * - * To specify an IPv6 UDP endpoint for port 9876, use: - * @code - * asio::ip::udp::endpoint ep(asio::ip::udp::v6(), 9876); - * @endcode - */ - basic_endpoint(const InternetProtocol& protocol, unsigned short port_num) - : data_() - { - using namespace std; // For memcpy. - if (protocol.family() == PF_INET) - { - asio::detail::sockaddr_in4_type& data - = reinterpret_cast(data_); - data.sin_family = AF_INET; - data.sin_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data.sin_addr.s_addr = INADDR_ANY; - } - else - { - asio::detail::sockaddr_in6_type& data - = reinterpret_cast(data_); - data.sin6_family = AF_INET6; - data.sin6_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data.sin6_flowinfo = 0; - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - data.sin6_addr = tmp_addr; - data.sin6_scope_id = 0; - } - } - - /// Construct an endpoint using a port number and an IP address. This - /// constructor may be used for accepting connections on a specific interface - /// or for making a connection to a remote endpoint. - basic_endpoint(const asio::ip::address& addr, unsigned short port_num) - : data_() - { - using namespace std; // For memcpy. - if (addr.is_v4()) - { - asio::detail::sockaddr_in4_type& data - = reinterpret_cast(data_); - data.sin_family = AF_INET; - data.sin_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data.sin_addr.s_addr = - asio::detail::socket_ops::host_to_network_long( - addr.to_v4().to_ulong()); - } - else - { - asio::detail::sockaddr_in6_type& data - = reinterpret_cast(data_); - data.sin6_family = AF_INET6; - data.sin6_port = - asio::detail::socket_ops::host_to_network_short(port_num); - data.sin6_flowinfo = 0; - asio::ip::address_v6 v6_addr = addr.to_v6(); - asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes(); - memcpy(data.sin6_addr.s6_addr, bytes.elems, 16); - data.sin6_scope_id = v6_addr.scope_id(); - } - } - - /// Copy constructor. - basic_endpoint(const basic_endpoint& other) - : data_(other.data_) - { - } - - /// Assign from another endpoint. - basic_endpoint& operator=(const basic_endpoint& other) - { - data_ = other.data_; - return *this; - } - - /// The protocol associated with the endpoint. - protocol_type protocol() const - { - if (is_v4()) - return InternetProtocol::v4(); - return InternetProtocol::v6(); - } - - /// Get the underlying endpoint in the native type. - data_type* data() - { - return reinterpret_cast(&data_); - } - - /// Get the underlying endpoint in the native type. - const data_type* data() const - { - return reinterpret_cast(&data_); - } - - /// Get the underlying size of the endpoint in the native type. - size_type size() const - { - if (is_v4()) - return sizeof(asio::detail::sockaddr_in4_type); - else - return sizeof(asio::detail::sockaddr_in6_type); - } - - /// Set the underlying size of the endpoint in the native type. - void resize(size_type size) - { - if (size > size_type(sizeof(data_))) - { - asio::system_error e(asio::error::invalid_argument); - boost::throw_exception(e); - } - } - - /// Get the capacity of the endpoint in the native type. - size_type capacity() const - { - return sizeof(data_); - } - - /// Get the port associated with the endpoint. The port number is always in - /// the host's byte order. - unsigned short port() const - { - if (is_v4()) - { - return asio::detail::socket_ops::network_to_host_short( - reinterpret_cast( - data_).sin_port); - } - else - { - return asio::detail::socket_ops::network_to_host_short( - reinterpret_cast( - data_).sin6_port); - } - } - - /// Set the port associated with the endpoint. The port number is always in - /// the host's byte order. - void port(unsigned short port_num) - { - if (is_v4()) - { - reinterpret_cast(data_).sin_port - = asio::detail::socket_ops::host_to_network_short(port_num); - } - else - { - reinterpret_cast(data_).sin6_port - = asio::detail::socket_ops::host_to_network_short(port_num); - } - } - - /// Get the IP address associated with the endpoint. - asio::ip::address address() const - { - using namespace std; // For memcpy. - if (is_v4()) - { - const asio::detail::sockaddr_in4_type& data - = reinterpret_cast( - data_); - return asio::ip::address_v4( - asio::detail::socket_ops::network_to_host_long( - data.sin_addr.s_addr)); - } - else - { - const asio::detail::sockaddr_in6_type& data - = reinterpret_cast( - data_); - asio::ip::address_v6::bytes_type bytes; - memcpy(bytes.elems, data.sin6_addr.s6_addr, 16); - return asio::ip::address_v6(bytes, data.sin6_scope_id); - } - } - - /// Set the IP address associated with the endpoint. - void address(const asio::ip::address& addr) - { - basic_endpoint tmp_endpoint(addr, port()); - data_ = tmp_endpoint.data_; - } - - /// Compare two endpoints for equality. - friend bool operator==(const basic_endpoint& e1, - const basic_endpoint& e2) - { - return e1.address() == e2.address() && e1.port() == e2.port(); - } - - /// Compare two endpoints for inequality. - friend bool operator!=(const basic_endpoint& e1, - const basic_endpoint& e2) - { - return e1.address() != e2.address() || e1.port() != e2.port(); - } - - /// Compare endpoints for ordering. - friend bool operator<(const basic_endpoint& e1, - const basic_endpoint& e2) - { - if (e1.address() < e2.address()) - return true; - if (e1.address() != e2.address()) - return false; - return e1.port() < e2.port(); - } - -private: - // Helper function to determine whether the endpoint is IPv4. - bool is_v4() const - { -#if defined(_AIX) - return data_.__ss_family == AF_INET; -#else - return data_.ss_family == AF_INET; -#endif - } - - // The underlying IP socket address. - asio::detail::sockaddr_storage_type data_; -}; - -/// Output an endpoint as a string. -/** - * Used to output a human-readable string for a specified endpoint. - * - * @param os The output stream to which the string will be written. - * - * @param endpoint The endpoint to be written. - * - * @return The output stream. - * - * @relates asio::ip::basic_endpoint - */ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -template -std::ostream& operator<<(std::ostream& os, - const basic_endpoint& endpoint) -{ - const address& addr = endpoint.address(); - if (addr.is_v4()) - os << addr.to_string(); - else - os << '[' << addr.to_string() << ']'; - os << ':' << endpoint.port(); - return os; -} -#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -template -std::basic_ostream& operator<<( - std::basic_ostream& os, - const basic_endpoint& endpoint) -{ - const address& addr = endpoint.address(); - if (addr.is_v4()) - os << addr.to_string(); - else - os << '[' << addr.to_string() << ']'; - os << ':' << endpoint.port(); - return os; -} -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_ENDPOINT_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/basic_resolver.hpp b/libtorrent/include/libtorrent/asio/ip/basic_resolver.hpp deleted file mode 100644 index 8c9d25486..000000000 --- a/libtorrent/include/libtorrent/asio/ip/basic_resolver.hpp +++ /dev/null @@ -1,245 +0,0 @@ -// -// basic_resolver.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_IP_BASIC_RESOLVER_HPP -#define ASIO_IP_BASIC_RESOLVER_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/basic_io_object.hpp" -#include "asio/error.hpp" -#include "asio/ip/resolver_service.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ip { - -/// Provides endpoint resolution functionality. -/** - * The basic_resolver class template provides the ability to resolve a query - * to a list of endpoints. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template > -class basic_resolver - : public basic_io_object -{ -public: - /// The protocol type. - typedef InternetProtocol protocol_type; - - /// The endpoint type. - typedef typename InternetProtocol::endpoint endpoint_type; - - /// The query type. - typedef typename InternetProtocol::resolver_query query; - - /// The iterator type. - typedef typename InternetProtocol::resolver_iterator iterator; - - /// Constructor. - /** - * This constructor creates a basic_resolver. - * - * @param io_service The io_service object that the resolver will use to - * dispatch handlers for any asynchronous operations performed on the timer. - */ - explicit basic_resolver(asio::io_service& io_service) - : basic_io_object(io_service) - { - } - - /// Cancel any asynchronous operations that are waiting on the resolver. - /** - * This function forces the completion of any pending asynchronous - * operations on the host resolver. The handler for each cancelled operation - * will be invoked with the asio::error::operation_aborted error code. - */ - void cancel() - { - return this->service.cancel(this->implementation); - } - - /// Resolve a query to a list of entries. - /** - * This function is used to resolve a query into a list of endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. - * - * @throws asio::system_error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. - */ - iterator resolve(const query& q) - { - asio::error_code ec; - iterator i = this->service.resolve(this->implementation, q, ec); - asio::detail::throw_error(ec); - return i; - } - - /// Resolve a query to a list of entries. - /** - * This function is used to resolve a query into a list of endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. - */ - iterator resolve(const query& q, asio::error_code& ec) - { - return this->service.resolve(this->implementation, q, ec); - } - - /// Asynchronously resolve a query to a list of entries. - /** - * This function is used to asynchronously resolve a query into a list of - * endpoint entries. - * - * @param q A query object that determines what endpoints will be returned. - * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can - * // be used to traverse the list - * // of endpoint entries. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note A default constructed iterator represents the end of the list. - * - * A successful resolve operation is guaranteed to pass at least one entry to - * the handler. - */ - template - void async_resolve(const query& q, ResolveHandler handler) - { - return this->service.async_resolve(this->implementation, q, handler); - } - - /// Resolve an endpoint to a list of entries. - /** - * This function is used to resolve an endpoint into a list of endpoint - * entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. - * - * @throws asio::system_error Thrown on failure. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. - */ - iterator resolve(const endpoint_type& e) - { - asio::error_code ec; - iterator i = this->service.resolve(this->implementation, e, ec); - asio::detail::throw_error(ec); - return i; - } - - /// Resolve an endpoint to a list of entries. - /** - * This function is used to resolve an endpoint into a list of endpoint - * entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns A forward-only iterator that can be used to traverse the list - * of endpoint entries. Returns a default constructed iterator if an error - * occurs. - * - * @note A default constructed iterator represents the end of the list. - * - * A successful call to this function is guaranteed to return at least one - * entry. - */ - iterator resolve(const endpoint_type& e, asio::error_code& ec) - { - return this->service.resolve(this->implementation, e, ec); - } - - /// Asynchronously resolve an endpoint to a list of entries. - /** - * This function is used to asynchronously resolve an endpoint into a list of - * endpoint entries. - * - * @param e An endpoint object that determines what endpoints will be - * returned. - * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * resolver::iterator iterator // Forward-only iterator that can - * // be used to traverse the list - * // of endpoint entries. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation - * of the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note A default constructed iterator represents the end of the list. - * - * A successful resolve operation is guaranteed to pass at least one entry to - * the handler. - */ - template - void async_resolve(const endpoint_type& e, ResolveHandler handler) - { - return this->service.async_resolve(this->implementation, e, handler); - } -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_RESOLVER_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/basic_resolver_entry.hpp b/libtorrent/include/libtorrent/asio/ip/basic_resolver_entry.hpp deleted file mode 100644 index 03184d8f5..000000000 --- a/libtorrent/include/libtorrent/asio/ip/basic_resolver_entry.hpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// basic_resolver_entry.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_IP_BASIC_RESOLVER_ENTRY_HPP -#define ASIO_IP_BASIC_RESOLVER_ENTRY_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace ip { - -/// An entry produced by a resolver. -/** - * The asio::ip::basic_resolver_entry class template describes an entry - * as returned by a resolver. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_resolver_entry -{ -public: - /// The protocol type associated with the endpoint entry. - typedef InternetProtocol protocol_type; - - /// The endpoint type associated with the endpoint entry. - typedef typename InternetProtocol::endpoint endpoint_type; - - /// Default constructor. - basic_resolver_entry() - { - } - - /// Construct with specified endpoint, host name and service name. - basic_resolver_entry(const endpoint_type& endpoint, - const std::string& host_name, const std::string& service_name) - : endpoint_(endpoint), - host_name_(host_name), - service_name_(service_name) - { - } - - /// Get the endpoint associated with the entry. - endpoint_type endpoint() const - { - return endpoint_; - } - - /// Convert to the endpoint associated with the entry. - operator endpoint_type() const - { - return endpoint_; - } - - /// Get the host name associated with the entry. - std::string host_name() const - { - return host_name_; - } - - /// Get the service name associated with the entry. - std::string service_name() const - { - return service_name_; - } - -private: - endpoint_type endpoint_; - std::string host_name_; - std::string service_name_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_RESOLVER_ENTRY_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/basic_resolver_iterator.hpp b/libtorrent/include/libtorrent/asio/ip/basic_resolver_iterator.hpp deleted file mode 100644 index 9edec2b0a..000000000 --- a/libtorrent/include/libtorrent/asio/ip/basic_resolver_iterator.hpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// basic_resolver_iterator.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_IP_BASIC_RESOLVER_ITERATOR_HPP -#define ASIO_IP_BASIC_RESOLVER_ITERATOR_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/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" -#include "asio/ip/basic_resolver_entry.hpp" - -namespace asio { -namespace ip { - -/// An iterator over the entries produced by a resolver. -/** - * The asio::ip::basic_resolver_iterator class template is used to define - * iterators over the results returned by a resolver. - * - * The iterator's value_type, obtained when the iterator is dereferenced, is: - * @code const basic_resolver_entry @endcode - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_resolver_iterator - : public boost::iterator_facade< - basic_resolver_iterator, - const basic_resolver_entry, - boost::forward_traversal_tag> -{ -public: - /// Default constructor creates an end iterator. - basic_resolver_iterator() - { - } - - /// Create an iterator from an addrinfo list returned by getaddrinfo. - static basic_resolver_iterator create( - asio::detail::addrinfo_type* address_info, - const std::string& host_name, const std::string& service_name) - { - basic_resolver_iterator iter; - if (!address_info) - return iter; - - std::string actual_host_name = host_name; - if (address_info->ai_canonname) - actual_host_name = address_info->ai_canonname; - - iter.values_.reset(new values_type); - - while (address_info) - { - if (address_info->ai_family == PF_INET - || address_info->ai_family == PF_INET6) - { - using namespace std; // For memcpy. - typename InternetProtocol::endpoint endpoint; - endpoint.resize( - static_cast( - address_info->ai_addrlen)); - memcpy(endpoint.data(), address_info->ai_addr, - address_info->ai_addrlen); - iter.values_->push_back( - basic_resolver_entry(endpoint, - actual_host_name, service_name)); - } - address_info = address_info->ai_next; - } - - if (iter.values_->size()) - iter.iter_ = iter.values_->begin(); - else - iter.values_.reset(); - - return iter; - } - - /// Create an iterator from an endpoint, host name and service name. - static basic_resolver_iterator create( - const typename InternetProtocol::endpoint& endpoint, - const std::string& host_name, const std::string& service_name) - { - basic_resolver_iterator iter; - iter.values_.reset(new values_type); - iter.values_->push_back( - basic_resolver_entry( - endpoint, host_name, service_name)); - iter.iter_ = iter.values_->begin(); - return iter; - } - -private: - friend class boost::iterator_core_access; - - void increment() - { - if (++iter_ == values_->end()) - { - // Reset state to match a default constructed end iterator. - values_.reset(); - typedef typename values_type::const_iterator values_iterator_type; - iter_ = values_iterator_type(); - } - } - - bool equal(const basic_resolver_iterator& other) const - { - if (!values_ && !other.values_) - return true; - if (values_ != other.values_) - return false; - return iter_ == other.iter_; - } - - const basic_resolver_entry& dereference() const - { - return *iter_; - } - - typedef std::vector > values_type; - boost::shared_ptr values_; - typename values_type::const_iterator iter_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/basic_resolver_query.hpp b/libtorrent/include/libtorrent/asio/ip/basic_resolver_query.hpp deleted file mode 100644 index 0fdd003fe..000000000 --- a/libtorrent/include/libtorrent/asio/ip/basic_resolver_query.hpp +++ /dev/null @@ -1,149 +0,0 @@ -// -// basic_resolver_query.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_IP_BASIC_RESOLVER_QUERY_HPP -#define ASIO_IP_BASIC_RESOLVER_QUERY_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_ops.hpp" -#include "asio/ip/resolver_query_base.hpp" - -namespace asio { -namespace ip { - -/// An query to be passed to a resolver. -/** - * The asio::ip::basic_resolver_query class template describes a query - * that can be passed to a resolver. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - */ -template -class basic_resolver_query - : public resolver_query_base -{ -public: - /// The protocol type associated with the endpoint query. - typedef InternetProtocol protocol_type; - - /// Construct with specified service name for any protocol. - basic_resolver_query(const std::string& service_name, - int flags = passive | address_configured) - : hints_(), - host_name_(), - service_name_(service_name) - { - typename InternetProtocol::endpoint endpoint; - hints_.ai_flags = flags; - hints_.ai_family = PF_UNSPEC; - hints_.ai_socktype = endpoint.protocol().type(); - hints_.ai_protocol = endpoint.protocol().protocol(); - hints_.ai_addrlen = 0; - hints_.ai_canonname = 0; - hints_.ai_addr = 0; - hints_.ai_next = 0; - } - - /// Construct with specified service name for a given protocol. - basic_resolver_query(const protocol_type& protocol, - const std::string& service_name, - int flags = passive | address_configured) - : hints_(), - host_name_(), - service_name_(service_name) - { - hints_.ai_flags = flags; - hints_.ai_family = protocol.family(); - hints_.ai_socktype = protocol.type(); - hints_.ai_protocol = protocol.protocol(); - hints_.ai_addrlen = 0; - hints_.ai_canonname = 0; - hints_.ai_addr = 0; - hints_.ai_next = 0; - } - - /// Construct with specified host name and service name for any protocol. - basic_resolver_query(const std::string& host_name, - const std::string& service_name, int flags = address_configured) - : hints_(), - host_name_(host_name), - service_name_(service_name) - { - typename InternetProtocol::endpoint endpoint; - hints_.ai_flags = flags; - hints_.ai_family = PF_UNSPEC; - hints_.ai_socktype = endpoint.protocol().type(); - hints_.ai_protocol = endpoint.protocol().protocol(); - hints_.ai_addrlen = 0; - hints_.ai_canonname = 0; - hints_.ai_addr = 0; - hints_.ai_next = 0; - } - - /// Construct with specified host name and service name for a given protocol. - basic_resolver_query(const protocol_type& protocol, - const std::string& host_name, const std::string& service_name, - int flags = address_configured) - : hints_(), - host_name_(host_name), - service_name_(service_name) - { - hints_.ai_flags = flags; - hints_.ai_family = protocol.family(); - hints_.ai_socktype = protocol.type(); - hints_.ai_protocol = protocol.protocol(); - hints_.ai_addrlen = 0; - hints_.ai_canonname = 0; - hints_.ai_addr = 0; - hints_.ai_next = 0; - } - - /// Get the hints associated with the query. - const asio::detail::addrinfo_type& hints() const - { - return hints_; - } - - /// Get the host name associated with the query. - std::string host_name() const - { - return host_name_; - } - - /// Get the service name associated with the query. - std::string service_name() const - { - return service_name_; - } - -private: - asio::detail::addrinfo_type hints_; - std::string host_name_; - std::string service_name_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_BASIC_RESOLVER_QUERY_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp b/libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp deleted file mode 100644 index db7f8edc4..000000000 --- a/libtorrent/include/libtorrent/asio/ip/detail/socket_option.hpp +++ /dev/null @@ -1,530 +0,0 @@ -// -// socket_option.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_IP_DETAIL_SOCKET_OPTION_HPP -#define ASIO_IP_DETAIL_SOCKET_OPTION_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/ip/address.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { -namespace detail { -namespace socket_option { - -// Helper template for implementing boolean-based options. -template -class boolean -{ -public: - // Default constructor. - boolean() - : value_(0) - { - } - - // Construct with a specific option value. - explicit boolean(bool v) - : value_(v ? 1 : 0) - { - } - - // Set the value of the boolean. - boolean& operator=(bool v) - { - value_ = v ? 1 : 0; - return *this; - } - - // Get the current value of the boolean. - bool value() const - { - return !!value_; - } - - // Convert to bool. - operator bool() const - { - return !!value_; - } - - // Test for false. - bool operator!() const - { - return !value_; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the boolean data. - template - int* data(const Protocol&) - { - return &value_; - } - - // Get the address of the boolean data. - template - const int* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the boolean data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the boolean data. - template - void resize(const Protocol&, std::size_t s) - { - if (s != sizeof(value_)) - throw std::length_error("boolean socket option resize"); - } - -private: - int value_; -}; - -// Helper template for implementing unicast hops options. -template -class unicast_hops -{ -public: - // Default constructor. - unicast_hops() - : value_(0) - { - } - - // Construct with a specific option value. - explicit unicast_hops(int v) - : value_(v) - { - } - - // Set the value of the option. - unicast_hops& operator=(int v) - { - value_ = v; - return *this; - } - - // Get the current value of the option. - int value() const - { - return value_; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the data. - template - int* data(const Protocol&) - { - return &value_; - } - - // Get the address of the data. - template - const int* data(const Protocol&) const - { - return &value_; - } - - // Get the size of the data. - template - std::size_t size(const Protocol&) const - { - return sizeof(value_); - } - - // Set the size of the data. - template - void resize(const Protocol&, std::size_t s) - { - if (s != sizeof(value_)) - throw std::length_error("unicast hops socket option resize"); - } - -private: - int value_; -}; - -// Helper template for implementing multicast hops options. -template -class multicast_hops -{ -public: - // Default constructor. - multicast_hops() - : ipv4_value_(0), - ipv6_value_(0) - { - } - - // Construct with a specific option value. - explicit multicast_hops(int v) - { - if (v < 0 || v > 255) - throw std::out_of_range("multicast hops value out of range"); - ipv4_value_ = static_cast(v); - ipv6_value_ = v; - } - - // Set the value of the option. - multicast_hops& operator=(int v) - { - if (v < 0 || v > 255) - throw std::out_of_range("multicast hops value out of range"); - ipv4_value_ = static_cast(v); - ipv6_value_ = v; - return *this; - } - - // Get the current value of the option. - int value() const - { - return ipv6_value_; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the data. - template - void* data(const Protocol& protocol) - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the address of the data. - template - const void* data(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the size of the data. - template - std::size_t size(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return sizeof(ipv6_value_); - return sizeof(ipv4_value_); - } - - // Set the size of the data. - template - void resize(const Protocol& protocol, std::size_t s) - { - if (protocol.family() == PF_INET6) - { - if (s != sizeof(ipv6_value_)) - throw std::length_error("multicast hops socket option resize"); - if (ipv6_value_ < 0) - ipv4_value_ = 0; - else if (ipv6_value_ > 255) - ipv4_value_ = 255; - else - ipv4_value_ = static_cast(ipv6_value_); - } - else - { - if (s != sizeof(ipv4_value_)) - throw std::length_error("multicast hops socket option resize"); - ipv6_value_ = ipv4_value_; - } - } - -private: - unsigned char ipv4_value_; - int ipv6_value_; -}; - -// Helper template for implementing ip_mreq-based options. -template -class multicast_request -{ -public: - // Default constructor. - multicast_request() - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - ipv6_value_.ipv6mr_multiaddr = tmp_addr; - ipv6_value_.ipv6mr_interface = 0; - } - - // Construct with multicast address only. - explicit multicast_request(const asio::ip::address& multicast_address) - { - if (multicast_address.is_v6()) - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - - using namespace std; // For memcpy. - asio::ip::address_v6 ipv6_address = multicast_address.to_v6(); - asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes(); - memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16); - ipv6_value_.ipv6mr_interface = 0; - } - else - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - multicast_address.to_v4().to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - ipv6_value_.ipv6mr_multiaddr = tmp_addr; - ipv6_value_.ipv6mr_interface = 0; - } - } - - // Construct with multicast address and IPv4 address specifying an interface. - explicit multicast_request( - const asio::ip::address_v4& multicast_address, - const asio::ip::address_v4& network_interface - = asio::ip::address_v4::any()) - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - multicast_address.to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - network_interface.to_ulong()); - - asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT; - ipv6_value_.ipv6mr_multiaddr = tmp_addr; - ipv6_value_.ipv6mr_interface = 0; - } - - // Construct with multicast address and IPv6 network interface index. - explicit multicast_request( - const asio::ip::address_v6& multicast_address, - unsigned long network_interface = 0) - { - ipv4_value_.imr_multiaddr.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv4_value_.imr_interface.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - - using namespace std; // For memcpy. - asio::ip::address_v6::bytes_type bytes = - multicast_address.to_bytes(); - memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16); - ipv6_value_.ipv6mr_interface = network_interface; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the option data. - template - const void* data(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the size of the option data. - template - std::size_t size(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return sizeof(ipv6_value_); - return sizeof(ipv4_value_); - } - -private: - asio::detail::in4_mreq_type ipv4_value_; - asio::detail::in6_mreq_type ipv6_value_; -}; - -// Helper template for implementing options that specify a network interface. -template -class network_interface -{ -public: - // Default constructor. - network_interface() - { - ipv4_value_.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv6_value_ = 0; - } - - // Construct with IPv4 interface. - explicit network_interface(const asio::ip::address_v4& ipv4_interface) - { - ipv4_value_.s_addr = - asio::detail::socket_ops::host_to_network_long( - ipv4_interface.to_ulong()); - ipv6_value_ = 0; - } - - // Construct with IPv6 interface. - explicit network_interface(unsigned long ipv6_interface) - { - ipv4_value_.s_addr = - asio::detail::socket_ops::host_to_network_long( - asio::ip::address_v4::any().to_ulong()); - ipv6_value_ = ipv6_interface; - } - - // Get the level of the socket option. - template - int level(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Level; - return IPv4_Level; - } - - // Get the name of the socket option. - template - int name(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return IPv6_Name; - return IPv4_Name; - } - - // Get the address of the option data. - template - const void* data(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return &ipv6_value_; - return &ipv4_value_; - } - - // Get the size of the option data. - template - std::size_t size(const Protocol& protocol) const - { - if (protocol.family() == PF_INET6) - return sizeof(ipv6_value_); - return sizeof(ipv4_value_); - } - -private: - asio::detail::in4_addr_type ipv4_value_; - unsigned long ipv6_value_; -}; - -} // namespace socket_option -} // namespace detail -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_DETAIL_SOCKET_OPTION_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/host_name.hpp b/libtorrent/include/libtorrent/asio/ip/host_name.hpp deleted file mode 100644 index 15adc08cc..000000000 --- a/libtorrent/include/libtorrent/asio/ip/host_name.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// host_name.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_IP_HOST_NAME_HPP -#define ASIO_IP_HOST_NAME_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ip { - -/// Get the current host name. -std::string host_name(); - -/// Get the current host name. -std::string host_name(asio::error_code& ec); - -inline std::string host_name() -{ - char name[1024]; - asio::error_code ec; - if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0) - { - asio::detail::throw_error(ec); - return std::string(); - } - return std::string(name); -} - -inline std::string host_name(asio::error_code& ec) -{ - char name[1024]; - if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0) - return std::string(); - return std::string(name); -} - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_HOST_NAME_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/multicast.hpp b/libtorrent/include/libtorrent/asio/ip/multicast.hpp deleted file mode 100644 index 0d90659ca..000000000 --- a/libtorrent/include/libtorrent/asio/ip/multicast.hpp +++ /dev/null @@ -1,181 +0,0 @@ -// -// multicast.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_IP_MULTICAST_HPP -#define ASIO_IP_MULTICAST_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/ip/detail/socket_option.hpp" - -namespace asio { -namespace ip { -namespace multicast { - -/// Socket option to join a multicast group on a specified interface. -/** - * Implements the IPPROTO_IP/IP_ADD_MEMBERSHIP socket option. - * - * @par Examples - * Setting the option to join a multicast group: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::address multicast_address = - * asio::ip::address::from_string("225.0.0.1"); - * asio::ip::multicast::join_group option(multicast_address); - * socket.set_option(option); - * @endcode - * - * @par Concepts: - * SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined join_group; -#else -typedef asio::ip::detail::socket_option::multicast_request< - IPPROTO_IP, IP_ADD_MEMBERSHIP, IPPROTO_IPV6, IPV6_JOIN_GROUP> join_group; -#endif - -/// Socket option to leave a multicast group on a specified interface. -/** - * Implements the IPPROTO_IP/IP_DROP_MEMBERSHIP socket option. - * - * @par Examples - * Setting the option to leave a multicast group: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::address multicast_address = - * asio::ip::address::from_string("225.0.0.1"); - * asio::ip::multicast::leave_group option(multicast_address); - * socket.set_option(option); - * @endcode - * - * @par Concepts: - * SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined leave_group; -#else -typedef asio::ip::detail::socket_option::multicast_request< - IPPROTO_IP, IP_DROP_MEMBERSHIP, IPPROTO_IPV6, IPV6_LEAVE_GROUP> leave_group; -#endif - -/// Socket option for local interface to use for outgoing multicast packets. -/** - * Implements the IPPROTO_IP/IP_MULTICAST_IF socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::address_v4 local_interface = - * asio::ip::address_v4::from_string("1.2.3.4"); - * asio::ip::multicast::outbound_interface option(local_interface); - * socket.set_option(option); - * @endcode - * - * @par Concepts: - * SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined outbound_interface; -#else -typedef asio::ip::detail::socket_option::network_interface< - IPPROTO_IP, IP_MULTICAST_IF, IPPROTO_IPV6, IPV6_MULTICAST_IF> - outbound_interface; -#endif - -/// Socket option for time-to-live associated with outgoing multicast packets. -/** - * Implements the IPPROTO_IP/IP_MULTICAST_TTL socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::multicast::hops option(4); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::multicast::hops option; - * socket.get_option(option); - * int ttl = option.value(); - * @endcode - * - * @par Concepts: - * GettableSocketOption, SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined hops; -#else -typedef asio::ip::detail::socket_option::multicast_hops< - IPPROTO_IP, IP_MULTICAST_TTL, IPPROTO_IPV6, IPV6_MULTICAST_HOPS> hops; -#endif - -/// Socket option determining whether outgoing multicast packets will be -/// received on the same socket if it is a member of the multicast group. -/** - * Implements the IPPROTO_IP/IP_MULTICAST_LOOP socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::multicast::enable_loopback option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::ip::multicast::enable_loopback option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * GettableSocketOption, SettableSocketOption. - */ -#if defined(GENERATING_DOCUMENTATION) -typedef implementation_defined enable_loopback; -#else -typedef asio::ip::detail::socket_option::boolean< - IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP> - enable_loopback; -#endif - -} // namespace multicast -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_MULTICAST_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/resolver_query_base.hpp b/libtorrent/include/libtorrent/asio/ip/resolver_query_base.hpp deleted file mode 100644 index 5b76fb3c2..000000000 --- a/libtorrent/include/libtorrent/asio/ip/resolver_query_base.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// resolver_query_base.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_IP_RESOLVER_QUERY_BASE_HPP -#define ASIO_IP_RESOLVER_QUERY_BASE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// The resolver_query_base class is used as a base for the -/// basic_resolver_query class templates to provide a common place to define -/// the flag constants. -class resolver_query_base -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// Determine the canonical name of the host specified in the query. - static const int canonical_name = implementation_defined; - - /// Indicate that returned endpoint is intended for use as a locally bound - /// socket endpoint. - static const int passive = implementation_defined; - - /// Host name should be treated as a numeric string defining an IPv4 or IPv6 - /// address and no name resolution should be attempted. - static const int numeric_host = implementation_defined; - - /// Service name should be treated as a numeric string defining a port number - /// and no name resolution should be attempted. - static const int numeric_service = implementation_defined; - - /// If the query protocol family is specified as IPv6, return IPv4-mapped - /// IPv6 addresses on finding no IPv6 addresses. - static const int v4_mapped = implementation_defined; - - /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses. - static const int all_matching = implementation_defined; - - /// Only return IPv4 addresses if a non-loopback IPv4 address is configured - /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address - /// is configured for the system. - static const int address_configured = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, canonical_name = AI_CANONNAME); - BOOST_STATIC_CONSTANT(int, passive = AI_PASSIVE); - BOOST_STATIC_CONSTANT(int, numeric_host = AI_NUMERICHOST); -# if defined(AI_NUMERICSERV) - BOOST_STATIC_CONSTANT(int, numeric_service = AI_NUMERICSERV); -# else - BOOST_STATIC_CONSTANT(int, numeric_service = 0); -# endif -# if defined(AI_V4MAPPED) - BOOST_STATIC_CONSTANT(int, v4_mapped = AI_V4MAPPED); -# else - BOOST_STATIC_CONSTANT(int, v4_mapped = 0); -# endif -# if defined(AI_ALL) - BOOST_STATIC_CONSTANT(int, all_matching = AI_ALL); -# else - BOOST_STATIC_CONSTANT(int, all_matching = 0); -# endif -# if defined(AI_ADDRCONFIG) - BOOST_STATIC_CONSTANT(int, address_configured = AI_ADDRCONFIG); -# else - BOOST_STATIC_CONSTANT(int, address_configured = 0); -# endif -#endif - -protected: - /// Protected destructor to prevent deletion through this type. - ~resolver_query_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_RESOLVER_QUERY_BASE_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/resolver_service.hpp b/libtorrent/include/libtorrent/asio/ip/resolver_service.hpp deleted file mode 100644 index 6d5193ea8..000000000 --- a/libtorrent/include/libtorrent/asio/ip/resolver_service.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// -// resolver_service.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_IP_RESOLVER_SERVICE_HPP -#define ASIO_IP_RESOLVER_SERVICE_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/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/resolver_service.hpp" -#include "asio/detail/service_base.hpp" - -namespace asio { -namespace ip { - -/// Default service implementation for a resolver. -template -class resolver_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base< - resolver_service > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef InternetProtocol protocol_type; - - /// The endpoint type. - typedef typename InternetProtocol::endpoint endpoint_type; - - /// The query type. - typedef typename InternetProtocol::resolver_query query_type; - - /// The iterator type. - typedef typename InternetProtocol::resolver_iterator iterator_type; - -private: - // The type of the platform-specific implementation. - typedef asio::detail::resolver_service - service_impl_type; - -public: - /// The type of a resolver implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new resolver service for the specified io_service. - explicit resolver_service(asio::io_service& io_service) - : asio::detail::service_base< - resolver_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new resolver implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a resolver implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Cancel pending asynchronous operations. - void cancel(implementation_type& impl) - { - service_impl_.cancel(impl); - } - - /// Resolve a query to a list of entries. - iterator_type resolve(implementation_type& impl, const query_type& query, - asio::error_code& ec) - { - return service_impl_.resolve(impl, query, ec); - } - - /// Asynchronously resolve a query to a list of entries. - template - void async_resolve(implementation_type& impl, const query_type& query, - Handler handler) - { - service_impl_.async_resolve(impl, query, handler); - } - - /// Resolve an endpoint to a list of entries. - iterator_type resolve(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.resolve(impl, endpoint, ec); - } - - /// Asynchronously resolve an endpoint to a list of entries. - template - void async_resolve(implementation_type& impl, const endpoint_type& endpoint, - ResolveHandler handler) - { - return service_impl_.async_resolve(impl, endpoint, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_RESOLVER_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/tcp.hpp b/libtorrent/include/libtorrent/asio/ip/tcp.hpp deleted file mode 100644 index 447210caf..000000000 --- a/libtorrent/include/libtorrent/asio/ip/tcp.hpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// tcp.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_IP_TCP_HPP -#define ASIO_IP_TCP_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/basic_socket_acceptor.hpp" -#include "asio/basic_socket_iostream.hpp" -#include "asio/basic_stream_socket.hpp" -#include "asio/ip/basic_endpoint.hpp" -#include "asio/ip/basic_resolver.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" -#include "asio/ip/basic_resolver_query.hpp" -#include "asio/detail/socket_option.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// Encapsulates the flags needed for TCP. -/** - * The asio::ip::tcp class contains flags necessary for TCP sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Protocol, InternetProtocol. - */ -class tcp -{ -public: - /// The type of a TCP endpoint. - typedef basic_endpoint endpoint; - - /// The type of a resolver query. - typedef basic_resolver_query resolver_query; - - /// The type of a resolver iterator. - typedef basic_resolver_iterator resolver_iterator; - - /// Construct to represent the IPv4 TCP protocol. - static tcp v4() - { - return tcp(PF_INET); - } - - /// Construct to represent the IPv4 TCP protocol. - static tcp v6() - { - return tcp(PF_INET6); - } - - /// Obtain an identifier for the type of the protocol. - int type() const - { - return SOCK_STREAM; - } - - /// Obtain an identifier for the protocol. - int protocol() const - { - return IPPROTO_TCP; - } - - /// Obtain an identifier for the protocol family. - int family() const - { - return family_; - } - - /// The TCP socket type. - typedef basic_stream_socket socket; - - /// The TCP acceptor type. - typedef basic_socket_acceptor acceptor; - - /// The TCP resolver type. - typedef basic_resolver resolver; - - /// The TCP iostream type. - typedef basic_socket_iostream iostream; - - /// Socket option for disabling the Nagle algorithm. - /** - * Implements the IPPROTO_TCP/TCP_NODELAY socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::no_delay option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::ip::tcp::no_delay option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined no_delay; -#else - typedef asio::detail::socket_option::boolean< - IPPROTO_TCP, TCP_NODELAY> no_delay; -#endif - - /// Compare two protocols for equality. - friend bool operator==(const tcp& p1, const tcp& p2) - { - return p1.family_ == p2.family_; - } - - /// Compare two protocols for inequality. - friend bool operator!=(const tcp& p1, const tcp& p2) - { - return p1.family_ != p2.family_; - } - -private: - // Construct with a specific family. - explicit tcp(int family) - : family_(family) - { - } - - int family_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_TCP_HPP diff --git a/libtorrent/include/libtorrent/asio/ip/udp.hpp b/libtorrent/include/libtorrent/asio/ip/udp.hpp deleted file mode 100644 index ed3bb8536..000000000 --- a/libtorrent/include/libtorrent/asio/ip/udp.hpp +++ /dev/null @@ -1,116 +0,0 @@ -// -// udp.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_IP_UDP_HPP -#define ASIO_IP_UDP_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/basic_datagram_socket.hpp" -#include "asio/ip/basic_endpoint.hpp" -#include "asio/ip/basic_resolver.hpp" -#include "asio/ip/basic_resolver_iterator.hpp" -#include "asio/ip/basic_resolver_query.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { -namespace ip { - -/// Encapsulates the flags needed for UDP. -/** - * The asio::ip::udp class contains flags necessary for UDP sockets. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Protocol, InternetProtocol. - */ -class udp -{ -public: - /// The type of a UDP endpoint. - typedef basic_endpoint endpoint; - - /// The type of a resolver query. - typedef basic_resolver_query resolver_query; - - /// The type of a resolver iterator. - typedef basic_resolver_iterator resolver_iterator; - - /// Construct to represent the IPv4 UDP protocol. - static udp v4() - { - return udp(PF_INET); - } - - /// Construct to represent the IPv4 UDP protocol. - static udp v6() - { - return udp(PF_INET6); - } - - /// Obtain an identifier for the type of the protocol. - int type() const - { - return SOCK_DGRAM; - } - - /// Obtain an identifier for the protocol. - int protocol() const - { - return IPPROTO_UDP; - } - - /// Obtain an identifier for the protocol family. - int family() const - { - return family_; - } - - /// The IPv4 UDP socket type. - typedef basic_datagram_socket socket; - - /// The UDP resolver type. - typedef basic_resolver resolver; - - /// Compare two protocols for equality. - friend bool operator==(const udp& p1, const udp& p2) - { - return p1.family_ == p2.family_; - } - - /// Compare two protocols for inequality. - friend bool operator!=(const udp& p1, const udp& p2) - { - return p1.family_ != p2.family_; - } - -private: - // Construct with a specific family. - explicit udp(int family) - : family_(family) - { - } - - int family_; -}; - -} // namespace ip -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IP_UDP_HPP diff --git a/libtorrent/include/libtorrent/asio/is_read_buffered.hpp b/libtorrent/include/libtorrent/asio/is_read_buffered.hpp deleted file mode 100644 index 091ba8c5f..000000000 --- a/libtorrent/include/libtorrent/asio/is_read_buffered.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// is_read_buffered.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_IS_READ_BUFFERED_HPP -#define ASIO_IS_READ_BUFFERED_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_read_stream_fwd.hpp" -#include "asio/buffered_stream_fwd.hpp" - -namespace asio { - -namespace detail { - -template -char is_read_buffered_helper(buffered_stream* s); - -template -char is_read_buffered_helper(buffered_read_stream* s); - -struct is_read_buffered_big_type { char data[10]; }; -is_read_buffered_big_type is_read_buffered_helper(...); - -} // namespace detail - -/// The is_read_buffered class is a traits class that may be used to determine -/// whether a stream type supports buffering of read data. -template -class is_read_buffered -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The value member is true only if the Stream type supports buffering of - /// read data. - static const bool value; -#else - BOOST_STATIC_CONSTANT(bool, - value = sizeof(detail::is_read_buffered_helper((Stream*)0)) == 1); -#endif -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IS_READ_BUFFERED_HPP diff --git a/libtorrent/include/libtorrent/asio/is_write_buffered.hpp b/libtorrent/include/libtorrent/asio/is_write_buffered.hpp deleted file mode 100644 index 946f7468c..000000000 --- a/libtorrent/include/libtorrent/asio/is_write_buffered.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// is_write_buffered.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_IS_WRITE_BUFFERED_HPP -#define ASIO_IS_WRITE_BUFFERED_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffered_stream_fwd.hpp" -#include "asio/buffered_write_stream_fwd.hpp" - -namespace asio { - -namespace detail { - -template -char is_write_buffered_helper(buffered_stream* s); - -template -char is_write_buffered_helper(buffered_write_stream* s); - -struct is_write_buffered_big_type { char data[10]; }; -is_write_buffered_big_type is_write_buffered_helper(...); - -} // namespace detail - -/// The is_write_buffered class is a traits class that may be used to determine -/// whether a stream type supports buffering of written data. -template -class is_write_buffered -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The value member is true only if the Stream type supports buffering of - /// written data. - static const bool value; -#else - BOOST_STATIC_CONSTANT(bool, - value = sizeof(detail::is_write_buffered_helper((Stream*)0)) == 1); -#endif -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IS_WRITE_BUFFERED_HPP diff --git a/libtorrent/include/libtorrent/asio/placeholders.hpp b/libtorrent/include/libtorrent/asio/placeholders.hpp deleted file mode 100644 index 0c1b6b4a6..000000000 --- a/libtorrent/include/libtorrent/asio/placeholders.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// -// placeholders.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_PLACEHOLDERS_HPP -#define ASIO_PLACEHOLDERS_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace placeholders { - -#if defined(GENERATING_DOCUMENTATION) - -/// An argument placeholder, for use with @ref boost_bind, that corresponds to -/// the error argument of a handler for any of the asynchronous functions. -unspecified error; - -/// An argument placeholder, for use with @ref boost_bind, that corresponds to -/// the bytes_transferred argument of a handler for asynchronous functions such -/// as asio::basic_stream_socket::async_write_some or -/// asio::async_write. -unspecified bytes_transferred; - -/// An argument placeholder, for use with @ref boost_bind, that corresponds to -/// the iterator argument of a handler for asynchronous functions such as -/// asio::basic_resolver::resolve. -unspecified iterator; - -#elif defined(__BORLANDC__) || defined(__GNUC__) - -inline boost::arg<1> error() -{ - return boost::arg<1>(); -} - -inline boost::arg<2> bytes_transferred() -{ - return boost::arg<2>(); -} - -inline boost::arg<2> iterator() -{ - return boost::arg<2>(); -} - -#else - -namespace detail -{ - template - struct placeholder - { - static boost::arg& get() - { - static boost::arg result; - return result; - } - }; -} - -#if BOOST_WORKAROUND(BOOST_MSVC, < 1400) - -static boost::arg<1>& error - = asio::placeholders::detail::placeholder<1>::get(); -static boost::arg<2>& bytes_transferred - = asio::placeholders::detail::placeholder<2>::get(); -static boost::arg<2>& iterator - = asio::placeholders::detail::placeholder<2>::get(); - -#else - -namespace -{ - boost::arg<1>& error - = asio::placeholders::detail::placeholder<1>::get(); - boost::arg<2>& bytes_transferred - = asio::placeholders::detail::placeholder<2>::get(); - boost::arg<2>& iterator - = asio::placeholders::detail::placeholder<2>::get(); -} // namespace - -#endif - -#endif - -} // namespace placeholders -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_PLACEHOLDERS_HPP diff --git a/libtorrent/include/libtorrent/asio/read.hpp b/libtorrent/include/libtorrent/asio/read.hpp deleted file mode 100644 index 6e9772dee..000000000 --- a/libtorrent/include/libtorrent/asio/read.hpp +++ /dev/null @@ -1,516 +0,0 @@ -// -// read.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_READ_HPP -#define ASIO_READ_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -/** - * @defgroup read asio::read - */ -/*@{*/ - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::read(s, asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::read( - * s, buffers, - * asio::transfer_all()); @endcode - */ -template -std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's read_some function are required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::read(s, asio::buffer(data, size), - * asio::transfer_at_least(32)); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's read_some function are required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @note This overload is equivalent to calling: - * @code asio::read( - * s, b, - * asio::transfer_all()); @endcode - */ -template -std::size_t read(SyncReadStream& s, basic_streambuf& b); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's read_some function are required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - */ -template -std::size_t read(SyncReadStream& s, basic_streambuf& b, - CompletionCondition completion_condition); - -/// Attempt to read a certain amount of data from a stream before returning. -/** - * This function is used to read a certain number of bytes of data from a - * stream. The call will block until one of the following conditions is true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b The basic_streambuf object into which the data will be read. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's read_some function are required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t read(SyncReadStream& s, basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec); - -/*@}*/ -/** - * @defgroup async_read asio::async_read - */ -/*@{*/ - -/// Start an asynchronous operation to read a certain amount of data from a -/// stream. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. Although the buffers object may be copied as necessary, ownership of - * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code - * asio::async_read(s, asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::async_read( - * s, buffers, - * asio::transfer_all(), - * handler); @endcode - */ -template -void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data from a -/// stream. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: - * - * @li The supplied buffers are full. That is, the bytes transferred is equal to - * the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param buffers One or more buffers into which the data will be read. The sum - * of the buffer sizes indicates the maximum number of bytes to read from the - * stream. Although the buffers object may be copied as necessary, ownership of - * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's async_read_some function are - * required. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To read into a single data buffer use the @ref buffer function as follows: - * @code asio::async_read(s, - * asio::buffer(data, size), - * asio::transfer_at_least(32), - * handler); @endcode - * See the @ref buffer documentation for information on reading into multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data from a -/// stream. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A basic_streambuf object into which the data will be read. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @note This overload is equivalent to calling: - * @code asio::async_read( - * s, b, - * asio::transfer_all(), - * handler); @endcode - */ -template -void async_read(AsyncReadStream& s, basic_streambuf& b, - ReadHandler handler); - -/// Start an asynchronous operation to read a certain amount of data from a -/// stream. -/** - * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_read_some function. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A basic_streambuf object into which the data will be read. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the read operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest read_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the read operation is complete. False - * indicates that further calls to the stream's async_read_some function are - * required. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_read(AsyncReadStream& s, basic_streambuf& b, - CompletionCondition completion_condition, ReadHandler handler); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/read.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_HPP diff --git a/libtorrent/include/libtorrent/asio/read_until.hpp b/libtorrent/include/libtorrent/asio/read_until.hpp deleted file mode 100644 index 6917ec6b8..000000000 --- a/libtorrent/include/libtorrent/asio/read_until.hpp +++ /dev/null @@ -1,452 +0,0 @@ -// -// read_until.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_READ_UNTIL_HPP -#define ASIO_READ_UNTIL_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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -/** - * @defgroup read_until asio::read_until - */ -/*@{*/ - -/// Read data into a streambuf until a delimiter is encountered. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter character. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, '\n'); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim); - -/// Read data into a streambuf until a delimiter is encountered. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter character. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. Returns 0 if an error occurred. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, char delim, - asio::error_code& ec); - -/// Read data into a streambuf until a delimiter is encountered. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter string. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, "\r\n"); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim); - -/// Read data into a streambuf until a delimiter is encountered. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains the specified delimiter. The call will block - * until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains the - * delimiter, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param delim The delimiter string. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the delimiter. Returns 0 if an error occurred. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - asio::error_code& ec); - -/// Read data into a streambuf until a regular expression is located. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains some data that matches a regular expression. - * The call will block until one of the following conditions is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains data that - * matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param expr The regular expression. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the substring that matches the regular expression. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To read data into a streambuf until a CR-LF sequence is encountered: - * @code asio::streambuf b; - * asio::read_until(s, b, boost::regex("\r\n")); - * std::istream is(&b); - * std::string line; - * std::getline(is, line); @endcode - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr); - -/// Read data into a streambuf until a regular expression is located. -/** - * This function is used to read data into the specified streambuf until the - * streambuf's get area contains some data that matches a regular expression. - * The call will block until one of the following conditions is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * read_some function. If the streambuf's get area already contains data that - * matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the SyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. - * - * @param expr The regular expression. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes in the streambuf's get area up to and including - * the substring that matches the regular expression. Returns 0 if an error - * occurred. - */ -template -std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - asio::error_code& ec); - -/*@}*/ -/** -* @defgroup async_read_until asio::async_read_until -*/ -/*@{*/ - -/// Start an asynchronous operation to read data into a streambuf until a -/// delimiter is encountered. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains the specified delimiter. - * The function call always returns immediately. The asynchronous operation - * will continue until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains the - * delimiter, the asynchronous operation completes immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param delim The delimiter character. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // The number of bytes in the - * // streambuf's get area up to - * // and including the delimiter. - * // 0 if an error occurred. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To asynchronously read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, '\n', handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, - char delim, ReadHandler handler); - -/// Start an asynchronous operation to read data into a streambuf until a -/// delimiter is encountered. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains the specified delimiter. - * The function call always returns immediately. The asynchronous operation - * will continue until one of the following conditions is true: - * - * @li The get area of the streambuf contains the specified delimiter. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains the - * delimiter, the asynchronous operation completes immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param delim The delimiter string. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // The number of bytes in the - * // streambuf's get area up to - * // and including the delimiter. - * // 0 if an error occurred. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To asynchronously read data into a streambuf until a newline is encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, "\r\n", handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const std::string& delim, - ReadHandler handler); - -/// Start an asynchronous operation to read data into a streambuf until a -/// regular expression is located. -/** - * This function is used to asynchronously read data into the specified - * streambuf until the streambuf's get area contains some data that matches a - * regular expression. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li A substring of the streambuf's get area matches the regular expression. - * - * @li An error occurred. - * - * This operation is implemented in terms of zero or more calls to the stream's - * async_read_some function. If the streambuf's get area already contains data - * that matches the regular expression, the function returns immediately. - * - * @param s The stream from which the data is to be read. The type must support - * the AsyncReadStream concept. - * - * @param b A streambuf object into which the data will be read. Ownership of - * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. - * - * @param expr The regular expression. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // The number of bytes in the - * // streambuf's get area up to - * // and including the substring - * // that matches the regular. - * // expression. 0 if an error - * // occurred. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To asynchronously read data into a streambuf until a CR-LF sequence is - * encountered: - * @code asio::streambuf b; - * ... - * void handler(const asio::error_code& e, std::size_t size) - * { - * if (!e) - * { - * std::istream is(&b); - * std::string line; - * std::getline(is, line); - * ... - * } - * } - * ... - * asio::async_read_until(s, b, boost::regex("\r\n"), handler); @endcode - */ -template -void async_read_until(AsyncReadStream& s, - asio::basic_streambuf& b, const boost::regex& expr, - ReadHandler handler); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/read_until.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_READ_UNTIL_HPP diff --git a/libtorrent/include/libtorrent/asio/resolver_service.hpp b/libtorrent/include/libtorrent/asio/resolver_service.hpp deleted file mode 100644 index bdd8dbfbd..000000000 --- a/libtorrent/include/libtorrent/asio/resolver_service.hpp +++ /dev/null @@ -1,126 +0,0 @@ -// -// resolver_service.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2006 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_RESOLVER_SERVICE_HPP -#define ASIO_RESOLVER_SERVICE_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/io_service.hpp" -#include "asio/detail/resolver_service.hpp" - -namespace asio { - -/// Default service implementation for a resolver. -template -class resolver_service - : public asio::io_service::service -{ -public: - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - - /// The query type. - typedef typename Protocol::resolver_query query_type; - - /// The iterator type. - typedef typename Protocol::resolver_iterator iterator_type; - -private: - // The type of the platform-specific implementation. - typedef detail::resolver_service service_impl_type; - -public: - /// The type of a resolver implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// Construct a new resolver service for the specified io_service. - explicit resolver_service(asio::io_service& io_service) - : asio::io_service::service(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new resolver implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a resolver implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Cancel pending asynchronous operations. - void cancel(implementation_type& impl) - { - service_impl_.cancel(impl); - } - - /// Resolve a query to a list of entries. - template - iterator_type resolve(implementation_type& impl, const query_type& query, - Error_Handler error_handler) - { - return service_impl_.resolve(impl, query, error_handler); - } - - /// Asynchronously resolve a query to a list of entries. - template - void async_resolve(implementation_type& impl, const query_type& query, - Handler handler) - { - service_impl_.async_resolve(impl, query, handler); - } - - /// Resolve an endpoint to a list of entries. - template - iterator_type resolve(implementation_type& impl, - const endpoint_type& endpoint, Error_Handler error_handler) - { - return service_impl_.resolve(impl, endpoint, error_handler); - } - - /// Asynchronously resolve an endpoint to a list of entries. - template - void async_resolve(implementation_type& impl, const endpoint_type& endpoint, - Handler handler) - { - return service_impl_.async_resolve(impl, endpoint, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_RESOLVER_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/socket_acceptor_service.hpp b/libtorrent/include/libtorrent/asio/socket_acceptor_service.hpp deleted file mode 100644 index 965bff39e..000000000 --- a/libtorrent/include/libtorrent/asio/socket_acceptor_service.hpp +++ /dev/null @@ -1,222 +0,0 @@ -// -// socket_acceptor_service.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_SOCKET_ACCEPTOR_SERVICE_HPP -#define ASIO_SOCKET_ACCEPTOR_SERVICE_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/basic_socket.hpp" -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/reactive_socket_service.hpp" -#include "asio/detail/win_iocp_socket_service.hpp" - -namespace asio { - -/// Default service implementation for a socket acceptor. -template -class socket_acceptor_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename protocol_type::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::reactive_socket_service< - Protocol, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_socket_service< - Protocol, detail::kqueue_reactor > service_impl_type; -#else - typedef detail::reactive_socket_service< - Protocol, detail::select_reactor > service_impl_type; -#endif - -public: - /// The native type of the socket acceptor. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native acceptor type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef typename service_impl_type::native_type native_type; -#endif - - /// Construct a new socket acceptor service for the specified io_service. - explicit socket_acceptor_service(asio::io_service& io_service) - : asio::detail::service_base< - socket_acceptor_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new socket acceptor implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a socket acceptor implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a new socket acceptor implementation. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - return service_impl_.open(impl, protocol, ec); - } - - /// Assign an existing native acceptor to a socket acceptor. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_acceptor, - asio::error_code& ec) - { - return service_impl_.assign(impl, protocol, native_acceptor, ec); - } - - /// Determine whether the acceptor is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Cancel all asynchronous operations associated with the acceptor. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Bind the socket acceptor to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.bind(impl, endpoint, ec); - } - - /// Place the socket acceptor into the state where it will listen for new - /// connections. - asio::error_code listen(implementation_type& impl, int backlog, - asio::error_code& ec) - { - return service_impl_.listen(impl, backlog, ec); - } - - /// Close a socket acceptor implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native acceptor implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const SettableSocketOption& option, asio::error_code& ec) - { - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template - asio::error_code get_option(const implementation_type& impl, - GettableSocketOption& option, asio::error_code& ec) const - { - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IoControlCommand& command, asio::error_code& ec) - { - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Accept a new connection. - template - asio::error_code accept(implementation_type& impl, - basic_socket& peer, - endpoint_type* peer_endpoint, asio::error_code& ec) - { - return service_impl_.accept(impl, peer, peer_endpoint, ec); - } - - /// Start an asynchronous accept. - template - void async_accept(implementation_type& impl, - basic_socket& peer, - endpoint_type* peer_endpoint, AcceptHandler handler) - { - service_impl_.async_accept(impl, peer, peer_endpoint, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SOCKET_ACCEPTOR_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/socket_base.hpp b/libtorrent/include/libtorrent/asio/socket_base.hpp deleted file mode 100644 index 1239989a9..000000000 --- a/libtorrent/include/libtorrent/asio/socket_base.hpp +++ /dev/null @@ -1,515 +0,0 @@ -// -// socket_base.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_SOCKET_BASE_HPP -#define ASIO_SOCKET_BASE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/io_control.hpp" -#include "asio/detail/socket_option.hpp" -#include "asio/detail/socket_types.hpp" - -namespace asio { - -/// The socket_base class is used as a base for the basic_stream_socket and -/// basic_datagram_socket class templates so that we have a common place to -/// define the shutdown_type and enum. -class socket_base -{ -public: - /// Different ways a socket may be shutdown. - enum shutdown_type - { -#if defined(GENERATING_DOCUMENTATION) - /// Shutdown the receive side of the socket. - shutdown_receive = implementation_defined, - - /// Shutdown the send side of the socket. - shutdown_send = implementation_defined, - - /// Shutdown both send and receive on the socket. - shutdown_both = implementation_defined -#else - shutdown_receive = asio::detail::shutdown_receive, - shutdown_send = asio::detail::shutdown_send, - shutdown_both = asio::detail::shutdown_both -#endif - }; - - /// Bitmask type for flags that can be passed to send and receive operations. - typedef int message_flags; - -#if defined(GENERATING_DOCUMENTATION) - /// Peek at incoming data without removing it from the input queue. - static const int message_peek = implementation_defined; - - /// Process out-of-band data. - static const int message_out_of_band = implementation_defined; - - /// Specify that the data should not be subject to routing. - static const int message_do_not_route = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, - message_peek = asio::detail::message_peek); - BOOST_STATIC_CONSTANT(int, - message_out_of_band = asio::detail::message_out_of_band); - BOOST_STATIC_CONSTANT(int, - message_do_not_route = asio::detail::message_do_not_route); -#endif - - /// Socket option to permit sending of broadcast messages. - /** - * Implements the SOL_SOCKET/SO_BROADCAST socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::socket_base::broadcast option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::socket_base::broadcast option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined broadcast; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_BROADCAST> broadcast; -#endif - - /// Socket option to enable socket-level debugging. - /** - * Implements the SOL_SOCKET/SO_DEBUG socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::debug option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::debug option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined debug; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_DEBUG> debug; -#endif - - /// Socket option to prevent routing, use local interfaces only. - /** - * Implements the SOL_SOCKET/SO_DONTROUTE socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::socket_base::do_not_route option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::udp::socket socket(io_service); - * ... - * asio::socket_base::do_not_route option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined do_not_route; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_DONTROUTE> do_not_route; -#endif - - /// Socket option to send keep-alives. - /** - * Implements the SOL_SOCKET/SO_KEEPALIVE socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::keep_alive option(true); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::keep_alive option; - * socket.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined keep_alive; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_KEEPALIVE> keep_alive; -#endif - - /// Socket option for the send buffer size of a socket. - /** - * Implements the SOL_SOCKET/SO_SNDBUF socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::send_buffer_size option(8192); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::send_buffer_size option; - * socket.get_option(option); - * int size = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Integer_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined send_buffer_size; -#else - typedef asio::detail::socket_option::integer< - SOL_SOCKET, SO_SNDBUF> send_buffer_size; -#endif - - /// Socket option for the send low watermark. - /** - * Implements the SOL_SOCKET/SO_SNDLOWAT socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::send_low_watermark option(1024); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::send_low_watermark option; - * socket.get_option(option); - * int size = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Integer_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined send_low_watermark; -#else - typedef asio::detail::socket_option::integer< - SOL_SOCKET, SO_SNDLOWAT> send_low_watermark; -#endif - - /// Socket option for the receive buffer size of a socket. - /** - * Implements the SOL_SOCKET/SO_RCVBUF socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::receive_buffer_size option(8192); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::receive_buffer_size option; - * socket.get_option(option); - * int size = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Integer_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined receive_buffer_size; -#else - typedef asio::detail::socket_option::integer< - SOL_SOCKET, SO_RCVBUF> receive_buffer_size; -#endif - - /// Socket option for the receive low watermark. - /** - * Implements the SOL_SOCKET/SO_RCVLOWAT socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::receive_low_watermark option(1024); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::receive_low_watermark option; - * socket.get_option(option); - * int size = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Integer_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined receive_low_watermark; -#else - typedef asio::detail::socket_option::integer< - SOL_SOCKET, SO_RCVLOWAT> receive_low_watermark; -#endif - - /// Socket option to allow the socket to be bound to an address that is - /// already in use. - /** - * Implements the SOL_SOCKET/SO_REUSEADDR socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::socket_base::reuse_address option(true); - * acceptor.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::socket_base::reuse_address option; - * acceptor.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined reuse_address; -#else - typedef asio::detail::socket_option::boolean< - SOL_SOCKET, SO_REUSEADDR> reuse_address; -#endif - - /// Socket option to specify whether the socket lingers on close if unsent - /// data is present. - /** - * Implements the SOL_SOCKET/SO_LINGER socket option. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::linger option(true, 30); - * socket.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::linger option; - * socket.get_option(option); - * bool is_set = option.enabled(); - * unsigned short timeout = option.timeout(); - * @endcode - * - * @par Concepts: - * Socket_Option, Linger_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined linger; -#else - typedef asio::detail::socket_option::linger< - SOL_SOCKET, SO_LINGER> linger; -#endif - - /// Socket option to report aborted connections on accept. - /** - * Implements a custom socket option that determines whether or not an accept - * operation is permitted to fail with asio::error::connection_aborted. - * By default the option is false. - * - * @par Examples - * Setting the option: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::socket_base::enable_connection_aborted option(true); - * acceptor.set_option(option); - * @endcode - * - * @par - * Getting the current option value: - * @code - * asio::ip::tcp::acceptor acceptor(io_service); - * ... - * asio::socket_base::enable_connection_aborted option; - * acceptor.get_option(option); - * bool is_set = option.value(); - * @endcode - * - * @par Concepts: - * Socket_Option, Boolean_Socket_Option. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined enable_connection_aborted; -#else - typedef asio::detail::socket_option::boolean< - asio::detail::custom_socket_option_level, - asio::detail::enable_connection_aborted_option> - enable_connection_aborted; -#endif - - /// IO control command to set the blocking mode of the socket. - /** - * Implements the FIONBIO IO control command. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::non_blocking_io command(true); - * socket.io_control(command); - * @endcode - * - * @par Concepts: - * IO_Control_Command, Boolean_IO_Control_Command. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined non_blocking_io; -#else - typedef asio::detail::io_control::non_blocking_io non_blocking_io; -#endif - - /// IO control command to get the amount of data that can be read without - /// blocking. - /** - * Implements the FIONREAD IO control command. - * - * @par Example - * @code - * asio::ip::tcp::socket socket(io_service); - * ... - * asio::socket_base::bytes_readable command(true); - * socket.io_control(command); - * std::size_t bytes_readable = command.get(); - * @endcode - * - * @par Concepts: - * IO_Control_Command, Size_IO_Control_Command. - */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined bytes_readable; -#else - typedef asio::detail::io_control::bytes_readable bytes_readable; -#endif - - /// The maximum length of the queue of pending incoming connections. -#if defined(GENERATING_DOCUMENTATION) - static const int max_connections = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, max_connections = SOMAXCONN); -#endif - -protected: - /// Protected destructor to prevent deletion through this type. - ~socket_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SOCKET_BASE_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl.hpp b/libtorrent/include/libtorrent/asio/ssl.hpp deleted file mode 100644 index 3f2d2750c..000000000 --- a/libtorrent/include/libtorrent/asio/ssl.hpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// ssl.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_SSL_HPP -#define ASIO_SSL_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/context.hpp" -#include "asio/ssl/context_base.hpp" -#include "asio/ssl/context_service.hpp" -#include "asio/ssl/stream.hpp" -#include "asio/ssl/stream_base.hpp" -#include "asio/ssl/stream_service.hpp" - -#endif // ASIO_SSL_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/basic_context.hpp b/libtorrent/include/libtorrent/asio/ssl/basic_context.hpp deleted file mode 100644 index b85a01c1d..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/basic_context.hpp +++ /dev/null @@ -1,434 +0,0 @@ -// -// basic_context.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005 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_SSL_BASIC_CONTEXT_HPP -#define ASIO_SSL_BASIC_CONTEXT_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/ssl/context_base.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ssl { - -/// SSL context. -template -class basic_context - : public context_base, - private boost::noncopyable -{ -public: - /// The type of the service that will be used to provide context operations. - typedef Service service_type; - - /// The native implementation type of the locking dispatcher. - typedef typename service_type::impl_type impl_type; - - /// Constructor. - basic_context(asio::io_service& io_service, method m) - : service_(asio::use_service(io_service)), - impl_(service_.null()) - { - service_.create(impl_, m); - } - - /// Destructor. - ~basic_context() - { - service_.destroy(impl_); - } - - /// Get the underlying implementation in the native type. - /** - * This function may be used to obtain the underlying implementation of the - * context. This is intended to allow access to context functionality that is - * not otherwise provided. - */ - impl_type impl() - { - return impl_; - } - - /// Set options on the context. - /** - * This function may be used to configure the SSL options used by the context. - * - * @param o A bitmask of options. The available option values are defined in - * the context_base class. The options are bitwise-ored with any existing - * value for the options. - * - * @throws asio::system_error Thrown on failure. - */ - void set_options(options o) - { - asio::error_code ec; - service_.set_options(impl_, o, ec); - asio::detail::throw_error(ec); - } - - /// Set options on the context. - /** - * This function may be used to configure the SSL options used by the context. - * - * @param o A bitmask of options. The available option values are defined in - * the context_base class. The options are bitwise-ored with any existing - * value for the options. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code set_options(options o, - asio::error_code& ec) - { - return service_.set_options(impl_, o, ec); - } - - /// Set the peer verification mode. - /** - * This function may be used to configure the peer verification mode used by - * the context. - * - * @param v A bitmask of peer verification modes. The available verify_mode - * values are defined in the context_base class. - * - * @throws asio::system_error Thrown on failure. - */ - void set_verify_mode(verify_mode v) - { - asio::error_code ec; - service_.set_verify_mode(impl_, v, ec); - asio::detail::throw_error(ec); - } - - /// Set the peer verification mode. - /** - * This function may be used to configure the peer verification mode used by - * the context. - * - * @param v A bitmask of peer verification modes. The available verify_mode - * values are defined in the context_base class. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code set_verify_mode(verify_mode v, - asio::error_code& ec) - { - return service_.set_verify_mode(impl_, v, ec); - } - - /// Load a certification authority file for performing verification. - /** - * This function is used to load one or more trusted certification authorities - * from a file. - * - * @param filename The name of a file containing certification authority - * certificates in PEM format. - * - * @throws asio::system_error Thrown on failure. - */ - void load_verify_file(const std::string& filename) - { - asio::error_code ec; - service_.load_verify_file(impl_, filename, ec); - asio::detail::throw_error(ec); - } - - /// Load a certification authority file for performing verification. - /** - * This function is used to load the certificates for one or more trusted - * certification authorities from a file. - * - * @param filename The name of a file containing certification authority - * certificates in PEM format. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code load_verify_file(const std::string& filename, - asio::error_code& ec) - { - return service_.load_verify_file(impl_, filename, ec); - } - - /// Add a directory containing certificate authority files to be used for - /// performing verification. - /** - * This function is used to specify the name of a directory containing - * certification authority certificates. Each file in the directory must - * contain a single certificate. The files must be named using the subject - * name's hash and an extension of ".0". - * - * @param path The name of a directory containing the certificates. - * - * @throws asio::system_error Thrown on failure. - */ - void add_verify_path(const std::string& path) - { - asio::error_code ec; - service_.add_verify_path(impl_, path, ec); - asio::detail::throw_error(ec); - } - - /// Add a directory containing certificate authority files to be used for - /// performing verification. - /** - * This function is used to specify the name of a directory containing - * certification authority certificates. Each file in the directory must - * contain a single certificate. The files must be named using the subject - * name's hash and an extension of ".0". - * - * @param path The name of a directory containing the certificates. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code add_verify_path(const std::string& path, - asio::error_code& ec) - { - return service_.add_verify_path(impl_, path, ec); - } - - /// Use a certificate from a file. - /** - * This function is used to load a certificate into the context from a file. - * - * @param filename The name of the file containing the certificate. - * - * @param format The file format (ASN.1 or PEM). - * - * @throws asio::system_error Thrown on failure. - */ - void use_certificate_file(const std::string& filename, file_format format) - { - asio::error_code ec; - service_.use_certificate_file(impl_, filename, format, ec); - asio::detail::throw_error(ec); - } - - /// Use a certificate from a file. - /** - * This function is used to load a certificate into the context from a file. - * - * @param filename The name of the file containing the certificate. - * - * @param format The file format (ASN.1 or PEM). - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_certificate_file(const std::string& filename, - file_format format, asio::error_code& ec) - { - return service_.use_certificate_file(impl_, filename, format, ec); - } - - /// Use a certificate chain from a file. - /** - * This function is used to load a certificate chain into the context from a - * file. - * - * @param filename The name of the file containing the certificate. The file - * must use the PEM format. - * - * @throws asio::system_error Thrown on failure. - */ - void use_certificate_chain_file(const std::string& filename) - { - asio::error_code ec; - service_.use_certificate_chain_file(impl_, filename, ec); - asio::detail::throw_error(ec); - } - - /// Use a certificate chain from a file. - /** - * This function is used to load a certificate chain into the context from a - * file. - * - * @param filename The name of the file containing the certificate. The file - * must use the PEM format. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_certificate_chain_file( - const std::string& filename, asio::error_code& ec) - { - return service_.use_certificate_chain_file(impl_, filename, ec); - } - - /// Use a private key from a file. - /** - * This function is used to load a private key into the context from a file. - * - * @param filename The name of the file containing the private key. - * - * @param format The file format (ASN.1 or PEM). - * - * @throws asio::system_error Thrown on failure. - */ - void use_private_key_file(const std::string& filename, file_format format) - { - asio::error_code ec; - service_.use_private_key_file(impl_, filename, format, ec); - asio::detail::throw_error(ec); - } - - /// Use a private key from a file. - /** - * This function is used to load a private key into the context from a file. - * - * @param filename The name of the file containing the private key. - * - * @param format The file format (ASN.1 or PEM). - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_private_key_file(const std::string& filename, - file_format format, asio::error_code& ec) - { - return service_.use_private_key_file(impl_, filename, format, ec); - } - - /// Use an RSA private key from a file. - /** - * This function is used to load an RSA private key into the context from a - * file. - * - * @param filename The name of the file containing the RSA private key. - * - * @param format The file format (ASN.1 or PEM). - * - * @throws asio::system_error Thrown on failure. - */ - void use_rsa_private_key_file(const std::string& filename, file_format format) - { - asio::error_code ec; - service_.use_rsa_private_key_file(impl_, filename, format, ec); - asio::detail::throw_error(ec); - } - - /// Use an RSA private key from a file. - /** - * This function is used to load an RSA private key into the context from a - * file. - * - * @param filename The name of the file containing the RSA private key. - * - * @param format The file format (ASN.1 or PEM). - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_rsa_private_key_file( - const std::string& filename, file_format format, - asio::error_code& ec) - { - return service_.use_rsa_private_key_file(impl_, filename, format, ec); - } - - /// Use the specified file to obtain the temporary Diffie-Hellman parameters. - /** - * This function is used to load Diffie-Hellman parameters into the context - * from a file. - * - * @param filename The name of the file containing the Diffie-Hellman - * parameters. The file must use the PEM format. - * - * @throws asio::system_error Thrown on failure. - */ - void use_tmp_dh_file(const std::string& filename) - { - asio::error_code ec; - service_.use_tmp_dh_file(impl_, filename, ec); - asio::detail::throw_error(ec); - } - - /// Use the specified file to obtain the temporary Diffie-Hellman parameters. - /** - * This function is used to load Diffie-Hellman parameters into the context - * from a file. - * - * @param filename The name of the file containing the Diffie-Hellman - * parameters. The file must use the PEM format. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code use_tmp_dh_file(const std::string& filename, - asio::error_code& ec) - { - return service_.use_tmp_dh_file(impl_, filename, ec); - } - - /// Set the password callback. - /** - * This function is used to specify a callback function to obtain password - * information about an encrypted key in PEM format. - * - * @param callback The function object to be used for obtaining the password. - * The function signature of the handler must be: - * @code std::string password_callback( - * std::size_t max_length, // The maximum size for a password. - * password_purpose purpose // Whether password is for reading or writing. - * ); @endcode - * The return value of the callback is a string containing the password. - * - * @throws asio::system_error Thrown on failure. - */ - template - void set_password_callback(PasswordCallback callback) - { - asio::error_code ec; - service_.set_password_callback(impl_, callback, ec); - asio::detail::throw_error(ec); - } - - /// Set the password callback. - /** - * This function is used to specify a callback function to obtain password - * information about an encrypted key in PEM format. - * - * @param callback The function object to be used for obtaining the password. - * The function signature of the handler must be: - * @code std::string password_callback( - * std::size_t max_length, // The maximum size for a password. - * password_purpose purpose // Whether password is for reading or writing. - * ); @endcode - * The return value of the callback is a string containing the password. - * - * @param ec Set to indicate what error occurred, if any. - */ - template - asio::error_code set_password_callback(PasswordCallback callback, - asio::error_code& ec) - { - return service_.set_password_callback(impl_, callback, ec); - } - -private: - /// The backend service implementation. - service_type& service_; - - /// The underlying native implementation. - impl_type impl_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_BASIC_CONTEXT_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/context.hpp b/libtorrent/include/libtorrent/asio/ssl/context.hpp deleted file mode 100644 index 86e249cbc..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/context.hpp +++ /dev/null @@ -1,35 +0,0 @@ -// -// context.hpp -// ~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005 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_SSL_CONTEXT_HPP -#define ASIO_SSL_CONTEXT_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/ssl/basic_context.hpp" -#include "asio/ssl/context_service.hpp" - -namespace asio { -namespace ssl { - -/// Typedef for the typical usage of context. -typedef basic_context context; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_CONTEXT_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/context_base.hpp b/libtorrent/include/libtorrent/asio/ssl/context_base.hpp deleted file mode 100644 index 0811d8ba5..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/context_base.hpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// context_base.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 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_SSL_CONTEXT_BASE_HPP -#define ASIO_SSL_CONTEXT_BASE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { - -/// The context_base class is used as a base for the basic_context class -/// template so that we have a common place to define various enums. -class context_base -{ -public: - /// Different methods supported by a context. - enum method - { - /// Generic SSL version 2. - sslv2, - - /// SSL version 2 client. - sslv2_client, - - /// SSL version 2 server. - sslv2_server, - - /// Generic SSL version 3. - sslv3, - - /// SSL version 3 client. - sslv3_client, - - /// SSL version 3 server. - sslv3_server, - - /// Generic TLS version 1. - tlsv1, - - /// TLS version 1 client. - tlsv1_client, - - /// TLS version 1 server. - tlsv1_server, - - /// Generic SSL/TLS. - sslv23, - - /// SSL/TLS client. - sslv23_client, - - /// SSL/TLS server. - sslv23_server - }; - - /// Bitmask type for SSL options. - typedef int options; - -#if defined(GENERATING_DOCUMENTATION) - /// Implement various bug workarounds. - static const int default_workarounds = implementation_defined; - - /// Always create a new key when using tmp_dh parameters. - static const int single_dh_use = implementation_defined; - - /// Disable SSL v2. - static const int no_sslv2 = implementation_defined; - - /// Disable SSL v3. - static const int no_sslv3 = implementation_defined; - - /// Disable TLS v1. - static const int no_tlsv1 = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, default_workarounds = SSL_OP_ALL); - BOOST_STATIC_CONSTANT(int, single_dh_use = SSL_OP_SINGLE_DH_USE); - BOOST_STATIC_CONSTANT(int, no_sslv2 = SSL_OP_NO_SSLv2); - BOOST_STATIC_CONSTANT(int, no_sslv3 = SSL_OP_NO_SSLv3); - BOOST_STATIC_CONSTANT(int, no_tlsv1 = SSL_OP_NO_TLSv1); -#endif - - /// File format types. - enum file_format - { - /// ASN.1 file. - asn1, - - /// PEM file. - pem - }; - - /// Bitmask type for peer verification. - typedef int verify_mode; - -#if defined(GENERATING_DOCUMENTATION) - /// No verification. - static const int verify_none = implementation_defined; - - /// Verify the peer. - static const int verify_peer = implementation_defined; - - /// Fail verification if the peer has no certificate. Ignored unless - /// verify_peer is set. - static const int verify_fail_if_no_peer_cert = implementation_defined; - - /// Do not request client certificate on renegotiation. Ignored unless - /// verify_peer is set. - static const int verify_client_once = implementation_defined; -#else - BOOST_STATIC_CONSTANT(int, verify_none = SSL_VERIFY_NONE); - BOOST_STATIC_CONSTANT(int, verify_peer = SSL_VERIFY_PEER); - BOOST_STATIC_CONSTANT(int, - verify_fail_if_no_peer_cert = SSL_VERIFY_FAIL_IF_NO_PEER_CERT); - BOOST_STATIC_CONSTANT(int, verify_client_once = SSL_VERIFY_CLIENT_ONCE); -#endif - - /// Purpose of PEM password. - enum password_purpose - { - /// The password is needed for reading/decryption. - for_reading, - - /// The password is needed for writing/encryption. - for_writing - }; - -protected: - /// Protected destructor to prevent deletion through this type. - ~context_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_CONTEXT_BASE_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/context_service.hpp b/libtorrent/include/libtorrent/asio/ssl/context_service.hpp deleted file mode 100644 index f0698a58f..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/context_service.hpp +++ /dev/null @@ -1,175 +0,0 @@ -// -// context_service.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005 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_SSL_CONTEXT_SERVICE_HPP -#define ASIO_SSL_CONTEXT_SERVICE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/ssl/context_base.hpp" -#include "asio/ssl/detail/openssl_context_service.hpp" - -namespace asio { -namespace ssl { - -/// Default service implementation for a context. -class context_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base -#endif -{ -private: - // The type of the platform-specific implementation. - typedef detail::openssl_context_service service_impl_type; - -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The type of the context. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined impl_type; -#else - typedef service_impl_type::impl_type impl_type; -#endif - - /// Constructor. - explicit context_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Return a null context implementation. - impl_type null() const - { - return service_impl_.null(); - } - - /// Create a new context implementation. - void create(impl_type& impl, context_base::method m) - { - service_impl_.create(impl, m); - } - - /// Destroy a context implementation. - void destroy(impl_type& impl) - { - service_impl_.destroy(impl); - } - - /// Set options on the context. - asio::error_code set_options(impl_type& impl, - context_base::options o, asio::error_code& ec) - { - return service_impl_.set_options(impl, o, ec); - } - - /// Set peer verification mode. - asio::error_code set_verify_mode(impl_type& impl, - context_base::verify_mode v, asio::error_code& ec) - { - return service_impl_.set_verify_mode(impl, v, ec); - } - - /// Load a certification authority file for performing verification. - asio::error_code load_verify_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - return service_impl_.load_verify_file(impl, filename, ec); - } - - /// Add a directory containing certification authority files to be used for - /// performing verification. - asio::error_code add_verify_path(impl_type& impl, - const std::string& path, asio::error_code& ec) - { - return service_impl_.add_verify_path(impl, path, ec); - } - - /// Use a certificate from a file. - asio::error_code use_certificate_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - return service_impl_.use_certificate_file(impl, filename, format, ec); - } - - /// Use a certificate chain from a file. - asio::error_code use_certificate_chain_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - return service_impl_.use_certificate_chain_file(impl, filename, ec); - } - - /// Use a private key from a file. - asio::error_code use_private_key_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - return service_impl_.use_private_key_file(impl, filename, format, ec); - } - - /// Use an RSA private key from a file. - asio::error_code use_rsa_private_key_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - return service_impl_.use_rsa_private_key_file(impl, filename, format, ec); - } - - /// Use the specified file to obtain the temporary Diffie-Hellman parameters. - asio::error_code use_tmp_dh_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - return service_impl_.use_tmp_dh_file(impl, filename, ec); - } - - /// Set the password callback. - template - asio::error_code set_password_callback(impl_type& impl, - PasswordCallback callback, asio::error_code& ec) - { - return service_impl_.set_password_callback(impl, callback, ec); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_CONTEXT_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_context_service.hpp b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_context_service.hpp deleted file mode 100644 index 96d610801..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_context_service.hpp +++ /dev/null @@ -1,379 +0,0 @@ -// -// openssl_context_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005 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_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP -#define ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/ssl/context_base.hpp" -#include "asio/ssl/detail/openssl_init.hpp" -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -class openssl_context_service - : public asio::detail::service_base -{ -public: - // The native type of the context. - typedef ::SSL_CTX* impl_type; - - // The type for the password callback function object. - typedef boost::function password_callback_type; - - // Constructor. - openssl_context_service(asio::io_service& io_service) - : asio::detail::service_base(io_service) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Return a null context implementation. - static impl_type null() - { - return 0; - } - - // Create a new context implementation. - void create(impl_type& impl, context_base::method m) - { - ::SSL_METHOD* ssl_method = 0; - switch (m) - { - case context_base::sslv2: - ssl_method = ::SSLv2_method(); - break; - case context_base::sslv2_client: - ssl_method = ::SSLv2_client_method(); - break; - case context_base::sslv2_server: - ssl_method = ::SSLv2_server_method(); - break; - case context_base::sslv3: - ssl_method = ::SSLv3_method(); - break; - case context_base::sslv3_client: - ssl_method = ::SSLv3_client_method(); - break; - case context_base::sslv3_server: - ssl_method = ::SSLv3_server_method(); - break; - case context_base::tlsv1: - ssl_method = ::TLSv1_method(); - break; - case context_base::tlsv1_client: - ssl_method = ::TLSv1_client_method(); - break; - case context_base::tlsv1_server: - ssl_method = ::TLSv1_server_method(); - break; - case context_base::sslv23: - ssl_method = ::SSLv23_method(); - break; - case context_base::sslv23_client: - ssl_method = ::SSLv23_client_method(); - break; - case context_base::sslv23_server: - ssl_method = ::SSLv23_server_method(); - break; - default: - break; - } - impl = ::SSL_CTX_new(ssl_method); - } - - // Destroy a context implementation. - void destroy(impl_type& impl) - { - if (impl != null()) - { - if (impl->default_passwd_callback_userdata) - { - password_callback_type* callback = - static_cast( - impl->default_passwd_callback_userdata); - delete callback; - impl->default_passwd_callback_userdata = 0; - } - - ::SSL_CTX_free(impl); - impl = null(); - } - } - - // Set options on the context. - asio::error_code set_options(impl_type& impl, - context_base::options o, asio::error_code& ec) - { - ::SSL_CTX_set_options(impl, o); - - ec = asio::error_code(); - return ec; - } - - // Set peer verification mode. - asio::error_code set_verify_mode(impl_type& impl, - context_base::verify_mode v, asio::error_code& ec) - { - ::SSL_CTX_set_verify(impl, v, 0); - - ec = asio::error_code(); - return ec; - } - - // Load a certification authority file for performing verification. - asio::error_code load_verify_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - if (::SSL_CTX_load_verify_locations(impl, filename.c_str(), 0) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Add a directory containing certification authority files to be used for - // performing verification. - asio::error_code add_verify_path(impl_type& impl, - const std::string& path, asio::error_code& ec) - { - if (::SSL_CTX_load_verify_locations(impl, 0, path.c_str()) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use a certificate from a file. - asio::error_code use_certificate_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - int file_type; - switch (format) - { - case context_base::asn1: - file_type = SSL_FILETYPE_ASN1; - break; - case context_base::pem: - file_type = SSL_FILETYPE_PEM; - break; - default: - { - ec = asio::error::invalid_argument; - return ec; - } - } - - if (::SSL_CTX_use_certificate_file(impl, filename.c_str(), file_type) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use a certificate chain from a file. - asio::error_code use_certificate_chain_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - if (::SSL_CTX_use_certificate_chain_file(impl, filename.c_str()) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use a private key from a file. - asio::error_code use_private_key_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - int file_type; - switch (format) - { - case context_base::asn1: - file_type = SSL_FILETYPE_ASN1; - break; - case context_base::pem: - file_type = SSL_FILETYPE_PEM; - break; - default: - { - ec = asio::error::invalid_argument; - return ec; - } - } - - if (::SSL_CTX_use_PrivateKey_file(impl, filename.c_str(), file_type) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use an RSA private key from a file. - asio::error_code use_rsa_private_key_file(impl_type& impl, - const std::string& filename, context_base::file_format format, - asio::error_code& ec) - { - int file_type; - switch (format) - { - case context_base::asn1: - file_type = SSL_FILETYPE_ASN1; - break; - case context_base::pem: - file_type = SSL_FILETYPE_PEM; - break; - default: - { - ec = asio::error::invalid_argument; - return ec; - } - } - - if (::SSL_CTX_use_RSAPrivateKey_file( - impl, filename.c_str(), file_type) != 1) - { - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Use the specified file to obtain the temporary Diffie-Hellman parameters. - asio::error_code use_tmp_dh_file(impl_type& impl, - const std::string& filename, asio::error_code& ec) - { - ::BIO* bio = ::BIO_new_file(filename.c_str(), "r"); - if (!bio) - { - ec = asio::error::invalid_argument; - return ec; - } - - ::DH* dh = ::PEM_read_bio_DHparams(bio, 0, 0, 0); - if (!dh) - { - ::BIO_free(bio); - ec = asio::error::invalid_argument; - return ec; - } - - ::BIO_free(bio); - int result = ::SSL_CTX_set_tmp_dh(impl, dh); - if (result != 1) - { - ::DH_free(dh); - ec = asio::error::invalid_argument; - return ec; - } - - ec = asio::error_code(); - return ec; - } - - static int password_callback(char* buf, int size, int purpose, void* data) - { - using namespace std; // For strncat and strlen. - - if (data) - { - password_callback_type* callback = - static_cast(data); - std::string passwd = (*callback)(static_cast(size), - purpose ? context_base::for_writing : context_base::for_reading); - *buf = '\0'; - strncat(buf, passwd.c_str(), size); - return strlen(buf); - } - - return 0; - } - - // Set the password callback. - template - asio::error_code set_password_callback(impl_type& impl, - Password_Callback callback, asio::error_code& ec) - { - // Allocate callback function object if not already present. - if (impl->default_passwd_callback_userdata) - { - password_callback_type* callback_function = - static_cast( - impl->default_passwd_callback_userdata); - *callback_function = callback; - } - else - { - password_callback_type* callback_function = - new password_callback_type(callback); - impl->default_passwd_callback_userdata = callback_function; - } - - // Set the password callback. - SSL_CTX_set_default_passwd_cb(impl, - &openssl_context_service::password_callback); - - ec = asio::error_code(); - return ec; - } - -private: - // Ensure openssl is initialised. - openssl_init<> init_; -}; - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_init.hpp b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_init.hpp deleted file mode 100644 index 06fbf86fe..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_init.hpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// openssl_init.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005 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_SSL_DETAIL_OPENSSL_INIT_HPP -#define ASIO_SSL_DETAIL_OPENSSL_INIT_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/mutex.hpp" -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -template -class openssl_init - : private boost::noncopyable -{ -private: - // Structure to perform the actual initialisation. - class do_init - { - public: - do_init() - { - if (Do_Init) - { - ::SSL_library_init(); - ::SSL_load_error_strings(); - ::OpenSSL_add_ssl_algorithms(); - - mutexes_.resize(::CRYPTO_num_locks()); - for (size_t i = 0; i < mutexes_.size(); ++i) - mutexes_[i].reset(new asio::detail::mutex); - ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func); - } - } - - ~do_init() - { - if (Do_Init) - { - ::CRYPTO_set_locking_callback(0); - ::ERR_free_strings(); - ::ERR_remove_state(0); - ::EVP_cleanup(); - ::CRYPTO_cleanup_all_ex_data(); - ::CONF_modules_unload(1); - ::ENGINE_cleanup(); - } - } - - // Helper function to manage a do_init singleton. The static instance of the - // openssl_init object ensures that this function is always called before - // main, and therefore before any other threads can get started. The do_init - // instance must be static in this function to ensure that it gets - // initialised before any other global objects try to use it. - static boost::shared_ptr instance() - { - static boost::shared_ptr init(new do_init); - return init; - } - - private: - static void openssl_locking_func(int mode, int n, - const char *file, int line) - { - if (mode & CRYPTO_LOCK) - instance()->mutexes_[n]->lock(); - else - instance()->mutexes_[n]->unlock(); - } - - // Mutexes to be used in locking callbacks. - std::vector > mutexes_; - }; - -public: - // Constructor. - openssl_init() - : ref_(do_init::instance()) - { - while (&instance_ == 0); // Ensure openssl_init::instance_ is linked in. - } - - // Destructor. - ~openssl_init() - { - } - -private: - // Instance to force initialisation of openssl at global scope. - static openssl_init instance_; - - // Reference to singleton do_init object to ensure that openssl does not get - // cleaned up until the last user has finished with it. - boost::shared_ptr ref_; -}; - -template -openssl_init openssl_init::instance_; - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_INIT_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp deleted file mode 100644 index b7a564464..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_operation.hpp +++ /dev/null @@ -1,482 +0,0 @@ -// -// openssl_operation.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster 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_SSL_DETAIL_OPENSSL_OPERATION_HPP -#define ASIO_SSL_DETAIL_OPENSSL_OPERATION_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/buffer.hpp" -#include "asio/placeholders.hpp" -#include "asio/write.hpp" -#include "asio/detail/socket_ops.hpp" -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -typedef boost::function ssl_primitive_func; -typedef boost::function - user_handler_func; - -// Network send_/recv buffer implementation -// -// -class net_buffer -{ - static const int NET_BUF_SIZE = 16*1024 + 256; // SSL record size + spare - - unsigned char buf_[NET_BUF_SIZE]; - unsigned char* data_start_; - unsigned char* data_end_; - -public: - net_buffer() - { - data_start_ = data_end_ = buf_; - } - unsigned char* get_unused_start() { return data_end_; } - unsigned char* get_data_start() { return data_start_; } - size_t get_unused_len() { return (NET_BUF_SIZE - (data_end_ - buf_)); } - size_t get_data_len() { return (data_end_ - data_start_); } - void data_added(size_t count) - { - data_end_ += count; - data_end_ = data_end_ > (buf_ + NET_BUF_SIZE)? - (buf_ + NET_BUF_SIZE): - data_end_; - } - void data_removed(size_t count) - { - data_start_ += count; - if (data_start_ >= data_end_) reset(); - } - void reset() { data_start_ = buf_; data_end_ = buf_; } - bool has_data() { return (data_start_ < data_end_); } -}; // class net_buffer - -// -// Operation class -// -// -template -class openssl_operation -{ -public: - - // Constructor for asynchronous operations - openssl_operation(ssl_primitive_func primitive, - Stream& socket, - net_buffer& recv_buf, - SSL* session, - BIO* ssl_bio, - user_handler_func handler - ) - : primitive_(primitive) - , user_handler_(handler) - , recv_buf_(recv_buf) - , socket_(socket) - , ssl_bio_(ssl_bio) - , session_(session) - { - write_ = boost::bind( - &openssl_operation::do_async_write, - this, boost::arg<1>(), boost::arg<2>() - ); - handler_= boost::bind( - &openssl_operation::async_user_handler, - this, boost::arg<1>(), boost::arg<2>() - ); - } - - // Constructor for synchronous operations - openssl_operation(ssl_primitive_func primitive, - Stream& socket, - net_buffer& recv_buf, - SSL* session, - BIO* ssl_bio) - : primitive_(primitive) - , recv_buf_(recv_buf) - , socket_(socket) - , ssl_bio_(ssl_bio) - , session_(session) - { - write_ = boost::bind( - &openssl_operation::do_sync_write, - this, boost::arg<1>(), boost::arg<2>() - ); - handler_ = boost::bind( - &openssl_operation::sync_user_handler, - this, boost::arg<1>(), boost::arg<2>() - ); - } - - // Start operation - // In case of asynchronous it returns 0, in sync mode returns success code - // or throws an error... - int start() - { - int rc = primitive_( session_ ); - int sys_error_code = ERR_get_error(); - bool is_operation_done = (rc > 0); - // For connect/accept/shutdown, the operation - // is done, when return code is 1 - // for write, it is done, when is retcode > 0 - // for read, is is done when retcode > 0 - - int error_code = !is_operation_done ? - ::SSL_get_error( session_, rc ) : - 0; - bool is_read_needed = (error_code == SSL_ERROR_WANT_READ); - bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE || - ::BIO_ctrl_pending( ssl_bio_ )); - bool is_shut_down_received = - ((::SSL_get_shutdown( session_ ) & SSL_RECEIVED_SHUTDOWN) == - SSL_RECEIVED_SHUTDOWN); - bool is_shut_down_sent = - ((::SSL_get_shutdown( session_ ) & SSL_SENT_SHUTDOWN) == - SSL_SENT_SHUTDOWN); - - if (is_shut_down_sent && is_shut_down_received && is_operation_done) - // SSL connection is shut down cleanly - return handler_(asio::error_code(), 1); - - if (is_shut_down_received && !is_write_needed) - return handler_(asio::error::eof, 0); - - if (is_shut_down_received) - // Shutdown has been requested, while we were reading or writing... - // abort our action... - return handler_(asio::error::shut_down, 0); - - if (!is_operation_done && !is_read_needed && !is_write_needed - && !is_shut_down_sent) - { - // The operation has failed... It is not completed and does - // not want network communication nor does want to send shutdown out... - if (error_code == SSL_ERROR_SYSCALL) - { - return handler_(asio::error_code( - sys_error_code, asio::native_ecat), rc); - } - else - { - return handler_(asio::error_code( - error_code, asio::ssl_ecat), rc); - } - } - - if (!is_operation_done && !is_write_needed) - { - // We may have left over data that we can pass to SSL immediately - if (recv_buf_.get_data_len() > 0) - { - // Pass the buffered data to SSL - int written = ::BIO_write - ( - ssl_bio_, - recv_buf_.get_data_start(), - recv_buf_.get_data_len() - ); - - if (written > 0) - { - recv_buf_.data_removed(written); - } - else if (written < 0) - { - if (!BIO_should_retry(ssl_bio_)) - { - // Some serios error with BIO.... - return handler_(asio::error::no_recovery, 0); - } - } - - return start(); - } - } - - // Continue with operation, flush any SSL data out to network... - return write_(is_operation_done, rc); - } - -// Private implementation -private: - typedef boost::function - int_handler_func; - typedef boost::function write_func; - - ssl_primitive_func primitive_; - user_handler_func user_handler_; - write_func write_; - int_handler_func handler_; - - net_buffer send_buf_; // buffers for network IO - - // The recv buffer is owned by the stream, not the operation, since there can - // be left over bytes after passing the data up to the application, and these - // bytes need to be kept around for the next read operation issued by the - // application. - net_buffer& recv_buf_; - - Stream& socket_; - BIO* ssl_bio_; - SSL* session_; - - // - int sync_user_handler(const asio::error_code& error, int rc) - { - if (!error) - return rc; - - throw asio::system_error(error); - } - - int async_user_handler(const asio::error_code& error, int rc) - { - user_handler_(error, rc); - return 0; - } - - // Writes bytes asynchronously from SSL to NET - int do_async_write(bool is_operation_done, int rc) - { - int len = ::BIO_ctrl_pending( ssl_bio_ ); - if ( len ) - { - // There is something to write into net, do it... - len = (int)send_buf_.get_unused_len() > len? - len: - send_buf_.get_unused_len(); - - if (len == 0) - { - // In case our send buffer is full, we have just to wait until - // previous send to complete... - return 0; - } - - // Read outgoing data from bio - len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len); - - if (len > 0) - { - unsigned char *data_start = send_buf_.get_unused_start(); - send_buf_.data_added(len); - - asio::async_write - ( - socket_, - asio::buffer(data_start, len), - boost::bind - ( - &openssl_operation::async_write_handler, - this, - is_operation_done, - rc, - asio::placeholders::error, - asio::placeholders::bytes_transferred - ) - ); - - return 0; - } - else if (!BIO_should_retry(ssl_bio_)) - { - // Seems like fatal error - // reading from SSL BIO has failed... - handler_(asio::error::no_recovery, 0); - return 0; - } - } - - if (is_operation_done) - { - // Finish the operation, with success - handler_(asio::error_code(), rc); - return 0; - } - - // OPeration is not done and writing to net has been made... - // start reading... - do_async_read(); - - return 0; - } - - void async_write_handler(bool is_operation_done, int rc, - const asio::error_code& error, size_t bytes_sent) - { - if (!error) - { - // Remove data from send buffer - send_buf_.data_removed(bytes_sent); - - if (is_operation_done) - handler_(asio::error_code(), rc); - else - // Since the operation was not completed, try it again... - start(); - } - else - handler_(error, rc); - } - - void do_async_read() - { - // Wait for new data - socket_.async_read_some - ( - asio::buffer(recv_buf_.get_unused_start(), - recv_buf_.get_unused_len()), - boost::bind - ( - &openssl_operation::async_read_handler, - this, - asio::placeholders::error, - asio::placeholders::bytes_transferred - ) - ); - } - - void async_read_handler(const asio::error_code& error, - size_t bytes_recvd) - { - if (!error) - { - recv_buf_.data_added(bytes_recvd); - - // Pass the received data to SSL - int written = ::BIO_write - ( - ssl_bio_, - recv_buf_.get_data_start(), - recv_buf_.get_data_len() - ); - - if (written > 0) - { - recv_buf_.data_removed(written); - } - else if (written < 0) - { - if (!BIO_should_retry(ssl_bio_)) - { - // Some serios error with BIO.... - handler_(asio::error::no_recovery, 0); - return; - } - } - - // and try the SSL primitive again - start(); - } - else - { - // Error in network level... - // SSL can't continue either... - handler_(error, 0); - } - } - - // Syncronous functions... - int do_sync_write(bool is_operation_done, int rc) - { - int len = ::BIO_ctrl_pending( ssl_bio_ ); - if ( len ) - { - // There is something to write into net, do it... - len = (int)send_buf_.get_unused_len() > len? - len: - send_buf_.get_unused_len(); - - // Read outgoing data from bio - len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len); - - if (len > 0) - { - size_t sent_len = asio::write( - socket_, - asio::buffer(send_buf_.get_unused_start(), len) - ); - - send_buf_.data_added(len); - send_buf_.data_removed(sent_len); - } - else if (!BIO_should_retry(ssl_bio_)) - { - // Seems like fatal error - // reading from SSL BIO has failed... - throw asio::system_error(asio::error::no_recovery); - } - } - - if (is_operation_done) - // Finish the operation, with success - return rc; - - // Operation is not finished, read data from net... - return do_sync_read(); - } - - int do_sync_read() - { - size_t len = socket_.read_some - ( - asio::buffer(recv_buf_.get_unused_start(), - recv_buf_.get_unused_len()) - ); - - // Write data to ssl - recv_buf_.data_added(len); - - // Pass the received data to SSL - int written = ::BIO_write - ( - ssl_bio_, - recv_buf_.get_data_start(), - recv_buf_.get_data_len() - ); - - if (written > 0) - { - recv_buf_.data_removed(written); - } - else if (written < 0) - { - if (!BIO_should_retry(ssl_bio_)) - { - // Some serios error with BIO.... - throw asio::system_error(asio::error::no_recovery); - } - } - - // Try the operation again - return start(); - } -}; // class openssl_operation - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp deleted file mode 100644 index d90b588ef..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_stream_service.hpp +++ /dev/null @@ -1,504 +0,0 @@ -// -// stream_service.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005 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_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP -#define ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_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/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/stream_base.hpp" -#include "asio/ssl/detail/openssl_operation.hpp" -#include "asio/ssl/detail/openssl_types.hpp" - -namespace asio { -namespace ssl { -namespace detail { - -class openssl_stream_service - : public asio::detail::service_base -{ -private: - //Base handler for asyncrhonous operations - template - class base_handler - { - public: - typedef boost::function< - void (const asio::error_code&, size_t)> func_t; - - base_handler(asio::io_service& io_service) - : op_(NULL) - , io_service_(io_service) - , work_(io_service) - {} - - void do_func(const asio::error_code& error, size_t size) - { - func_(error, size); - } - - void set_operation(openssl_operation* op) { op_ = op; } - void set_func(func_t func) { func_ = func; } - - ~base_handler() - { - delete op_; - } - - private: - func_t func_; - openssl_operation* op_; - asio::io_service& io_service_; - asio::io_service::work work_; - }; // class base_handler - - // Handler for asynchronous IO (write/read) operations - template - class io_handler - : public base_handler - { - public: - io_handler(Handler handler, asio::io_service& io_service) - : base_handler(io_service) - , handler_(handler) - { - set_func(boost::bind( - &io_handler::handler_impl, - this, boost::arg<1>(), boost::arg<2>() )); - } - - private: - Handler handler_; - void handler_impl(const asio::error_code& error, size_t size) - { - handler_(error, size); - delete this; - } - }; // class io_handler - - // Handler for asyncrhonous handshake (connect, accept) functions - template - class handshake_handler - : public base_handler - { - public: - handshake_handler(Handler handler, asio::io_service& io_service) - : base_handler(io_service) - , handler_(handler) - { - set_func(boost::bind( - &handshake_handler::handler_impl, - this, boost::arg<1>(), boost::arg<2>() )); - } - - private: - Handler handler_; - void handler_impl(const asio::error_code& error, size_t) - { - handler_(error); - delete this; - } - - }; // class handshake_handler - - // Handler for asyncrhonous shutdown - template - class shutdown_handler - : public base_handler - { - public: - shutdown_handler(Handler handler, asio::io_service& io_service) - : base_handler(io_service), - handler_(handler) - { - set_func(boost::bind( - &shutdown_handler::handler_impl, - this, boost::arg<1>(), boost::arg<2>() )); - } - - private: - Handler handler_; - void handler_impl(const asio::error_code& error, size_t) - { - handler_(error); - delete this; - } - }; // class shutdown_handler - -public: - // The implementation type. - typedef struct impl_struct - { - ::SSL* ssl; - ::BIO* ext_bio; - net_buffer recv_buf; - } * impl_type; - - // Construct a new stream socket service for the specified io_service. - explicit openssl_stream_service(asio::io_service& io_service) - : asio::detail::service_base(io_service) - { - } - - // Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - // Return a null stream implementation. - impl_type null() const - { - return 0; - } - - // Create a new stream implementation. - template - void create(impl_type& impl, Stream& next_layer, - basic_context& context) - { - impl = new impl_struct; - impl->ssl = ::SSL_new(context.impl()); - ::SSL_set_mode(impl->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); - ::SSL_set_mode(impl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - ::BIO* int_bio = 0; - impl->ext_bio = 0; - ::BIO_new_bio_pair(&int_bio, 8192, &impl->ext_bio, 8192); - ::SSL_set_bio(impl->ssl, int_bio, int_bio); - } - - // Destroy a stream implementation. - template - void destroy(impl_type& impl, Stream& next_layer) - { - if (impl != 0) - { - ::BIO_free(impl->ext_bio); - ::SSL_free(impl->ssl); - delete impl; - impl = 0; - } - } - - // Perform SSL handshaking. - template - asio::error_code handshake(impl_type& impl, Stream& next_layer, - stream_base::handshake_type type, asio::error_code& ec) - { - try - { - openssl_operation op( - type == stream_base::client ? - &ssl_wrap::SSL_connect: - &ssl_wrap::SSL_accept, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio); - op.start(); - } - catch (asio::system_error& e) - { - ec = e.code(); - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Start an asynchronous SSL handshake. - template - void async_handshake(impl_type& impl, Stream& next_layer, - stream_base::handshake_type type, Handler handler) - { - typedef handshake_handler connect_handler; - - connect_handler* local_handler = - new connect_handler(handler, io_service()); - - openssl_operation* op = new openssl_operation - ( - type == stream_base::client ? - &ssl_wrap::SSL_connect: - &ssl_wrap::SSL_accept, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio, - boost::bind - ( - &base_handler::do_func, - local_handler, - boost::arg<1>(), - boost::arg<2>() - ) - ); - local_handler->set_operation(op); - - io_service().post(boost::bind(&openssl_operation::start, op)); - } - - // Shut down SSL on the stream. - template - asio::error_code shutdown(impl_type& impl, Stream& next_layer, - asio::error_code& ec) - { - try - { - openssl_operation op( - &ssl_wrap::SSL_shutdown, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio); - op.start(); - } - catch (asio::system_error& e) - { - ec = e.code(); - return ec; - } - - ec = asio::error_code(); - return ec; - } - - // Asynchronously shut down SSL on the stream. - template - void async_shutdown(impl_type& impl, Stream& next_layer, Handler handler) - { - typedef shutdown_handler disconnect_handler; - - disconnect_handler* local_handler = - new disconnect_handler(handler, io_service()); - - openssl_operation* op = new openssl_operation - ( - &ssl_wrap::SSL_shutdown, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio, - boost::bind - ( - &base_handler::do_func, - local_handler, - boost::arg<1>(), - boost::arg<2>() - ) - ); - local_handler->set_operation(op); - - io_service().post(boost::bind(&openssl_operation::start, op)); - } - - // Write some data to the stream. - template - std::size_t write_some(impl_type& impl, Stream& next_layer, - const Const_Buffers& buffers, asio::error_code& ec) - { - size_t bytes_transferred = 0; - try - { - boost::function send_func = - boost::bind(&::SSL_write, boost::arg<1>(), - asio::buffer_cast(*buffers.begin()), - static_cast(asio::buffer_size(*buffers.begin()))); - openssl_operation op( - send_func, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio - ); - bytes_transferred = static_cast(op.start()); - } - catch (asio::system_error& e) - { - ec = e.code(); - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - // Start an asynchronous write. - template - void async_write_some(impl_type& impl, Stream& next_layer, - const Const_Buffers& buffers, Handler handler) - { - typedef io_handler send_handler; - - send_handler* local_handler = new send_handler(handler, io_service()); - - boost::function send_func = - boost::bind(&::SSL_write, boost::arg<1>(), - asio::buffer_cast(*buffers.begin()), - static_cast(asio::buffer_size(*buffers.begin()))); - - openssl_operation* op = new openssl_operation - ( - send_func, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio, - boost::bind - ( - &base_handler::do_func, - local_handler, - boost::arg<1>(), - boost::arg<2>() - ) - ); - local_handler->set_operation(op); - - io_service().post(boost::bind(&openssl_operation::start, op)); - } - - // Read some data from the stream. - template - std::size_t read_some(impl_type& impl, Stream& next_layer, - const Mutable_Buffers& buffers, asio::error_code& ec) - { - size_t bytes_transferred = 0; - try - { - boost::function recv_func = - boost::bind(&::SSL_read, boost::arg<1>(), - asio::buffer_cast(*buffers.begin()), - asio::buffer_size(*buffers.begin())); - openssl_operation op(recv_func, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio - ); - - bytes_transferred = static_cast(op.start()); - } - catch (asio::system_error& e) - { - ec = e.code(); - return 0; - } - - ec = asio::error_code(); - return bytes_transferred; - } - - // Start an asynchronous read. - template - void async_read_some(impl_type& impl, Stream& next_layer, - const Mutable_Buffers& buffers, Handler handler) - { - typedef io_handler recv_handler; - - recv_handler* local_handler = new recv_handler(handler, io_service()); - - boost::function recv_func = - boost::bind(&::SSL_read, boost::arg<1>(), - asio::buffer_cast(*buffers.begin()), - asio::buffer_size(*buffers.begin())); - - openssl_operation* op = new openssl_operation - ( - recv_func, - next_layer, - impl->recv_buf, - impl->ssl, - impl->ext_bio, - boost::bind - ( - &base_handler::do_func, - local_handler, - boost::arg<1>(), - boost::arg<2>() - ) - ); - local_handler->set_operation(op); - - io_service().post(boost::bind(&openssl_operation::start, op)); - } - - // Peek at the incoming data on the stream. - template - std::size_t peek(impl_type& impl, Stream& next_layer, - const Mutable_Buffers& buffers, asio::error_code& ec) - { - ec = asio::error_code(); - return 0; - } - - // Determine the amount of data that may be read without blocking. - template - std::size_t in_avail(impl_type& impl, Stream& next_layer, - asio::error_code& ec) - { - ec = asio::error_code(); - return 0; - } - -private: - typedef asio::detail::mutex mutex_type; - - template - struct ssl_wrap - { - static Mutex ssl_mutex_; - - static int SSL_accept(SSL *ssl) - { - typename Mutex::scoped_lock lock(ssl_mutex_); - return ::SSL_accept(ssl); - } - - static int SSL_connect(SSL *ssl) - { - typename Mutex::scoped_lock lock(ssl_mutex_); - return ::SSL_connect(ssl); - } - - static int SSL_shutdown(SSL *ssl) - { - typename Mutex::scoped_lock lock(ssl_mutex_); - return ::SSL_shutdown(ssl); - } - }; -}; - -template -Mutex openssl_stream_service::ssl_wrap::ssl_mutex_; - -} // namespace detail -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_types.hpp b/libtorrent/include/libtorrent/asio/ssl/detail/openssl_types.hpp deleted file mode 100644 index d193b3a0c..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/detail/openssl_types.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// openssl_types.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 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_SSL_DETAIL_OPENSSL_TYPES_HPP -#define ASIO_SSL_DETAIL_OPENSSL_TYPES_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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/stream.hpp b/libtorrent/include/libtorrent/asio/ssl/stream.hpp deleted file mode 100644 index a6af16101..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/stream.hpp +++ /dev/null @@ -1,490 +0,0 @@ -// -// stream.hpp -// ~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005 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_SSL_STREAM_HPP -#define ASIO_SSL_STREAM_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/push_options.hpp" -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/stream_base.hpp" -#include "asio/ssl/stream_service.hpp" -#include "asio/detail/throw_error.hpp" - -namespace asio { -namespace ssl { - -/// Provides stream-oriented functionality using SSL. -/** - * The stream class template provides asynchronous and blocking stream-oriented - * functionality using SSL. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Example - * To use the SSL stream template with a stream_socket, you would write: - * @code - * asio::io_service io_service; - * asio::ssl::context context(io_service, asio::ssl::context::sslv23); - * asio::ssl::stream sock(io_service, context); - * @endcode - * - * @par Concepts: - * Async_Object, Async_Read_Stream, Async_Write_Stream, Error_Source, Stream, - * Sync_Read_Stream, Sync_Write_Stream. - */ -template -class stream - : public stream_base, - private boost::noncopyable -{ -public: - /// The type of the next layer. - typedef typename boost::remove_reference::type next_layer_type; - - /// The type of the lowest layer. - typedef typename next_layer_type::lowest_layer_type lowest_layer_type; - - /// The type of the service that will be used to provide stream operations. - typedef Service service_type; - - /// The native implementation type of the stream. - typedef typename service_type::impl_type impl_type; - - /// Construct a stream. - /** - * This constructor creates a stream and initialises the underlying stream - * object. - * - * @param arg The argument to be passed to initialise the underlying stream. - * - * @param context The SSL context to be used for the stream. - */ - template - explicit stream(Arg& arg, basic_context& context) - : next_layer_(arg), - service_(asio::use_service(next_layer_.io_service())), - impl_(service_.null()) - { - service_.create(impl_, next_layer_, context); - } - - /// Destructor. - ~stream() - { - service_.destroy(impl_, next_layer_); - } - - /// Get the io_service associated with the object. - /** - * This function may be used to obtain the io_service object that the stream - * uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that stream will use to - * dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& io_service() - { - return next_layer_.io_service(); - } - - /// Get a reference to the next layer. - /** - * This function returns a reference to the next layer in a stack of stream - * layers. - * - * @return A reference to the next layer in the stack of stream layers. - * Ownership is not transferred to the caller. - */ - next_layer_type& next_layer() - { - return next_layer_; - } - - /// Get a reference to the lowest layer. - /** - * This function returns a reference to the lowest layer in a stack of - * stream layers. - * - * @return A reference to the lowest layer in the stack of stream layers. - * Ownership is not transferred to the caller. - */ - lowest_layer_type& lowest_layer() - { - return next_layer_.lowest_layer(); - } - - /// Get the underlying implementation in the native type. - /** - * This function may be used to obtain the underlying implementation of the - * context. This is intended to allow access to stream functionality that is - * not otherwise provided. - */ - impl_type impl() - { - return impl_; - } - - /// Perform SSL handshaking. - /** - * This function is used to perform SSL handshaking on the stream. The - * function call will block until handshaking is complete or an error occurs. - * - * @param type The type of handshaking to be performed, i.e. as a client or as - * a server. - * - * @throws asio::system_error Thrown on failure. - */ - void handshake(handshake_type type) - { - asio::error_code ec; - service_.handshake(impl_, next_layer_, type, ec); - asio::detail::throw_error(ec); - } - - /// Perform SSL handshaking. - /** - * This function is used to perform SSL handshaking on the stream. The - * function call will block until handshaking is complete or an error occurs. - * - * @param type The type of handshaking to be performed, i.e. as a client or as - * a server. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code handshake(handshake_type type, - asio::error_code& ec) - { - return service_.handshake(impl_, next_layer_, type, ec); - } - - /// Start an asynchronous SSL handshake. - /** - * This function is used to asynchronously perform an SSL handshake on the - * stream. This function call always returns immediately. - * - * @param type The type of handshaking to be performed, i.e. as a client or as - * a server. - * - * @param handler The handler to be called when the handshake operation - * completes. Copies will be made of the handler as required. The equivalent - * function signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - */ - template - void async_handshake(handshake_type type, HandshakeHandler handler) - { - service_.async_handshake(impl_, next_layer_, type, handler); - } - - /// Shut down SSL on the stream. - /** - * This function is used to shut down SSL on the stream. The function call - * will block until SSL has been shut down or an error occurs. - * - * @throws asio::system_error Thrown on failure. - */ - void shutdown() - { - asio::error_code ec; - service_.shutdown(impl_, next_layer_, ec); - asio::detail::throw_error(ec); - } - - /// Shut down SSL on the stream. - /** - * This function is used to shut down SSL on the stream. The function call - * will block until SSL has been shut down or an error occurs. - * - * @param ec Set to indicate what error occurred, if any. - */ - asio::error_code shutdown(asio::error_code& ec) - { - return service_.shutdown(impl_, next_layer_, ec); - } - - /// Asynchronously shut down SSL on the stream. - /** - * This function is used to asynchronously shut down SSL on the stream. This - * function call always returns immediately. - * - * @param handler The handler to be called when the handshake operation - * completes. Copies will be made of the handler as required. The equivalent - * function signature of the handler must be: - * @code void handler( - * const asio::error_code& error // Result of operation. - * ); @endcode - */ - template - void async_shutdown(ShutdownHandler handler) - { - service_.async_shutdown(impl_, next_layer_, handler); - } - - /// Write some data to the stream. - /** - * This function is used to write data on the stream. The function call will - * block until one or more bytes of data has been written successfully, or - * until an error occurs. - * - * @param buffers The data to be written. - * - * @returns The number of bytes written. - * - * @throws asio::system_error Thrown on failure. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that all - * data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = service_.write_some(impl_, next_layer_, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Write some data to the stream. - /** - * This function is used to write data on the stream. The function call will - * block until one or more bytes of data has been written successfully, or - * until an error occurs. - * - * @param buffers The data to be written to the stream. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. Returns 0 if an error occurred. - * - * @note The write_some operation may not transmit all of the data to the - * peer. Consider using the @ref write function if you need to ensure that all - * data is written before the blocking operation completes. - */ - template - std::size_t write_some(const ConstBufferSequence& buffers, - asio::error_code& ec) - { - return service_.write_some(impl_, next_layer_, buffers, ec); - } - - /// Start an asynchronous write. - /** - * This function is used to asynchronously write one or more bytes of data to - * the stream. The function call always returns immediately. - * - * @param buffers The data to be written to the stream. Although the buffers - * object may be copied as necessary, ownership of the underlying buffers is - * retained by the caller, which must guarantee that they remain valid until - * the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The equivalent function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. - * ); @endcode - * - * @note The async_write_some operation may not transmit all of the data to - * the peer. Consider using the @ref async_write function if you need to - * ensure that all data is written before the blocking operation completes. - */ - template - void async_write_some(const ConstBufferSequence& buffers, - WriteHandler handler) - { - service_.async_write_some(impl_, next_layer_, buffers, handler); - } - - /// Read some data from the stream. - /** - * This function is used to read data from the stream. The function call will - * block until one or more bytes of data has been read successfully, or until - * an error occurs. - * - * @param buffers The buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = service_.read_some(impl_, next_layer_, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Read some data from the stream. - /** - * This function is used to read data from the stream. The function call will - * block until one or more bytes of data has been read successfully, or until - * an error occurs. - * - * @param buffers The buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - * - * @note The read_some operation may not read all of the requested number of - * bytes. Consider using the @ref read function if you need to ensure that the - * requested amount of data is read before the blocking operation completes. - */ - template - std::size_t read_some(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return service_.read_some(impl_, next_layer_, buffers, ec); - } - - /// Start an asynchronous read. - /** - * This function is used to asynchronously read one or more bytes of data from - * the stream. The function call always returns immediately. - * - * @param buffers The buffers into which the data will be read. Although the - * buffers object may be copied as necessary, ownership of the underlying - * buffers is retained by the caller, which must guarantee that they remain - * valid until the handler is called. - * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The equivalent function - * signature of the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. - * ); @endcode - * - * @note The async_read_some operation may not read all of the requested - * number of bytes. Consider using the @ref async_read function if you need to - * ensure that the requested amount of data is read before the asynchronous - * operation completes. - */ - template - void async_read_some(const MutableBufferSequence& buffers, - ReadHandler handler) - { - service_.async_read_some(impl_, next_layer_, buffers, handler); - } - - /// Peek at the incoming data on the stream. - /** - * This function is used to peek at the incoming data on the stream, without - * removing it from the input queue. The function call will block until data - * has been read successfully or an error occurs. - * - * @param buffers The buffers into which the data will be read. - * - * @returns The number of bytes read. - * - * @throws asio::system_error Thrown on failure. - */ - template - std::size_t peek(const MutableBufferSequence& buffers) - { - asio::error_code ec; - std::size_t s = service_.peek(impl_, next_layer_, buffers, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Peek at the incoming data on the stream. - /** - * This function is used to peek at the incoming data on the stream, withoutxi - * removing it from the input queue. The function call will block until data - * has been read successfully or an error occurs. - * - * @param buffers The buffers into which the data will be read. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes read. Returns 0 if an error occurred. - */ - template - std::size_t peek(const MutableBufferSequence& buffers, - asio::error_code& ec) - { - return service_.peek(impl_, next_layer_, buffers, ec); - } - - /// Determine the amount of data that may be read without blocking. - /** - * This function is used to determine the amount of data, in bytes, that may - * be read from the stream without blocking. - * - * @returns The number of bytes of data that can be read without blocking. - * - * @throws asio::system_error Thrown on failure. - */ - std::size_t in_avail() - { - asio::error_code ec; - std::size_t s = service_.in_avail(impl_, next_layer_, ec); - asio::detail::throw_error(ec); - return s; - } - - /// Determine the amount of data that may be read without blocking. - /** - * This function is used to determine the amount of data, in bytes, that may - * be read from the stream without blocking. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes of data that can be read without blocking. - */ - std::size_t in_avail(asio::error_code& ec) - { - return service_.in_avail(impl_, next_layer_, ec); - } - -private: - /// The next layer. - Stream next_layer_; - - /// The backend service implementation. - service_type& service_; - - /// The underlying native implementation. - impl_type impl_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_STREAM_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/stream_base.hpp b/libtorrent/include/libtorrent/asio/ssl/stream_base.hpp deleted file mode 100644 index 89c4b65a9..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/stream_base.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// stream_base.hpp -// ~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 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_SSL_STREAM_BASE_HPP -#define ASIO_SSL_STREAM_BASE_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/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { -namespace ssl { - -/// The stream_base class is used as a base for the asio::ssl::stream -/// class template so that we have a common place to define various enums. -class stream_base -{ -public: - /// Different handshake types. - enum handshake_type - { - /// Perform handshaking as a client. - client, - - /// Perform handshaking as a server. - server - }; - -protected: - /// Protected destructor to prevent deletion through this type. - ~stream_base() - { - } - -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -private: - // Workaround to enable the empty base optimisation with Borland C++. - char dummy_; -#endif -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_STREAM_BASE_HPP diff --git a/libtorrent/include/libtorrent/asio/ssl/stream_service.hpp b/libtorrent/include/libtorrent/asio/ssl/stream_service.hpp deleted file mode 100644 index d96e68aec..000000000 --- a/libtorrent/include/libtorrent/asio/ssl/stream_service.hpp +++ /dev/null @@ -1,186 +0,0 @@ -// -// stream_service.hpp -// ~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005 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_SSL_STREAM_SERVICE_HPP -#define ASIO_SSL_STREAM_SERVICE_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/push_options.hpp" -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/io_service.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/ssl/basic_context.hpp" -#include "asio/ssl/stream_base.hpp" -#include "asio/ssl/detail/openssl_stream_service.hpp" - -namespace asio { -namespace ssl { - -/// Default service implementation for an SSL stream. -class stream_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base -#endif -{ -private: - // The type of the platform-specific implementation. - typedef detail::openssl_stream_service service_impl_type; - -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The type of a stream implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined impl_type; -#else - typedef service_impl_type::impl_type impl_type; -#endif - - /// Construct a new stream service for the specified io_service. - explicit stream_service(asio::io_service& io_service) - : asio::detail::service_base(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Return a null stream implementation. - impl_type null() const - { - return service_impl_.null(); - } - - /// Create a new stream implementation. - template - void create(impl_type& impl, Stream& next_layer, - basic_context& context) - { - service_impl_.create(impl, next_layer, context); - } - - /// Destroy a stream implementation. - template - void destroy(impl_type& impl, Stream& next_layer) - { - service_impl_.destroy(impl, next_layer); - } - - /// Perform SSL handshaking. - template - asio::error_code handshake(impl_type& impl, Stream& next_layer, - stream_base::handshake_type type, asio::error_code& ec) - { - return service_impl_.handshake(impl, next_layer, type, ec); - } - - /// Start an asynchronous SSL handshake. - template - void async_handshake(impl_type& impl, Stream& next_layer, - stream_base::handshake_type type, HandshakeHandler handler) - { - service_impl_.async_handshake(impl, next_layer, type, handler); - } - - /// Shut down SSL on the stream. - template - asio::error_code shutdown(impl_type& impl, Stream& next_layer, - asio::error_code& ec) - { - return service_impl_.shutdown(impl, next_layer, ec); - } - - /// Asynchronously shut down SSL on the stream. - template - void async_shutdown(impl_type& impl, Stream& next_layer, - ShutdownHandler handler) - { - service_impl_.async_shutdown(impl, next_layer, handler); - } - - /// Write some data to the stream. - template - std::size_t write_some(impl_type& impl, Stream& next_layer, - const ConstBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.write_some(impl, next_layer, buffers, ec); - } - - /// Start an asynchronous write. - template - void async_write_some(impl_type& impl, Stream& next_layer, - const ConstBufferSequence& buffers, WriteHandler handler) - { - service_impl_.async_write_some(impl, next_layer, buffers, handler); - } - - /// Read some data from the stream. - template - std::size_t read_some(impl_type& impl, Stream& next_layer, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.read_some(impl, next_layer, buffers, ec); - } - - /// Start an asynchronous read. - template - void async_read_some(impl_type& impl, Stream& next_layer, - const MutableBufferSequence& buffers, ReadHandler handler) - { - service_impl_.async_read_some(impl, next_layer, buffers, handler); - } - - /// Peek at the incoming data on the stream. - template - std::size_t peek(impl_type& impl, Stream& next_layer, - const MutableBufferSequence& buffers, asio::error_code& ec) - { - return service_impl_.peek(impl, next_layer, buffers, ec); - } - - /// Determine the amount of data that may be read without blocking. - template - std::size_t in_avail(impl_type& impl, Stream& next_layer, - asio::error_code& ec) - { - return service_impl_.in_avail(impl, next_layer, ec); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace ssl -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SSL_STREAM_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/strand.hpp b/libtorrent/include/libtorrent/asio/strand.hpp deleted file mode 100644 index 948921e10..000000000 --- a/libtorrent/include/libtorrent/asio/strand.hpp +++ /dev/null @@ -1,166 +0,0 @@ -// -// strand.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_STRAND_HPP -#define ASIO_STRAND_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/io_service.hpp" -#include "asio/detail/strand_service.hpp" -#include "asio/detail/wrapped_handler.hpp" - -namespace asio { - -/// Provides serialised handler execution. -/** - * The io_service::strand class provides the ability to post and dispatch - * handlers with the guarantee that none of those handlers will execute - * concurrently. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Safe. - * - * @par Concepts: - * Dispatcher. - */ -class io_service::strand -{ -public: - /// Constructor. - /** - * Constructs the strand. - * - * @param io_service The io_service object that the strand will use to - * dispatch handlers that are ready to be run. - */ - explicit strand(asio::io_service& io_service) - : service_(asio::use_service< - asio::detail::strand_service>(io_service)) - { - service_.construct(impl_); - } - - /// Destructor. - ~strand() - { - service_.destroy(impl_); - } - - /// Get the io_service associated with the strand. - /** - * This function may be used to obtain the io_service object that the strand - * uses to dispatch handlers for asynchronous operations. - * - * @return A reference to the io_service object that the strand will use to - * dispatch handlers. Ownership is not transferred to the caller. - */ - asio::io_service& io_service() - { - return service_.io_service(); - } - - /// Request the strand to invoke the given handler. - /** - * This function is used to ask the strand to execute the given handler. - * - * The strand object guarantees that handlers posted or dispatched through - * the strand will not be executed concurrently. The handler may be executed - * inside this function if the guarantee can be met. If this function is - * called from within a handler that was posted or dispatched through the same - * strand, then the new handler will be executed immediately. - * - * The strand's guarantee is in addition to the guarantee provided by the - * underlying io_service. The io_service guarantees that the handler will only - * be called in a thread in which the io_service's run member function is - * currently being invoked. - * - * @param handler The handler to be called. The strand will make a copy of the - * handler object as required. The function signature of the handler must be: - * @code void handler(); @endcode - */ - template - void dispatch(Handler handler) - { - service_.dispatch(impl_, handler); - } - - /// Request the strand to invoke the given handler and return - /// immediately. - /** - * This function is used to ask the strand to execute the given handler, but - * without allowing the strand to call the handler from inside this function. - * - * The strand object guarantees that handlers posted or dispatched through - * the strand will not be executed concurrently. The strand's guarantee is in - * addition to the guarantee provided by the underlying io_service. The - * io_service guarantees that the handler will only be called in a thread in - * which the io_service's run member function is currently being invoked. - * - * @param handler The handler to be called. The strand will make a copy of the - * handler object as required. The function signature of the handler must be: - * @code void handler(); @endcode - */ - template - void post(Handler handler) - { - service_.post(impl_, handler); - } - - /// Create a new handler that automatically dispatches the wrapped handler - /// on the strand. - /** - * This function is used to create a new handler function object that, when - * invoked, will automatically pass the wrapped handler to the strand's - * dispatch function. - * - * @param handler The handler to be wrapped. The strand will make a copy of - * the handler object as required. The function signature of the handler must - * be: @code void handler(A1 a1, ... An an); @endcode - * - * @return A function object that, when invoked, passes the wrapped handler to - * the strand's dispatch function. Given a function object with the signature: - * @code R f(A1 a1, ... An an); @endcode - * If this function object is passed to the wrap function like so: - * @code strand.wrap(f); @endcode - * then the return value is a function object with the signature - * @code void g(A1 a1, ... An an); @endcode - * that, when invoked, executes code equivalent to: - * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode - */ - template -#if defined(GENERATING_DOCUMENTATION) - unspecified -#else - detail::wrapped_handler -#endif - wrap(Handler handler) - { - return detail::wrapped_handler(*this, handler); - } - -private: - asio::detail::strand_service& service_; - asio::detail::strand_service::implementation_type impl_; -}; - -/// Typedef for backwards compatibility. -typedef asio::io_service::strand strand; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_STRAND_HPP diff --git a/libtorrent/include/libtorrent/asio/stream_socket_service.hpp b/libtorrent/include/libtorrent/asio/stream_socket_service.hpp deleted file mode 100644 index d7915aaf4..000000000 --- a/libtorrent/include/libtorrent/asio/stream_socket_service.hpp +++ /dev/null @@ -1,283 +0,0 @@ -// -// stream_socket_service.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_STREAM_SOCKET_SERVICE_HPP -#define ASIO_STREAM_SOCKET_SERVICE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error.hpp" -#include "asio/io_service.hpp" -#include "asio/detail/epoll_reactor.hpp" -#include "asio/detail/kqueue_reactor.hpp" -#include "asio/detail/select_reactor.hpp" -#include "asio/detail/service_base.hpp" -#include "asio/detail/win_iocp_socket_service.hpp" -#include "asio/detail/reactive_socket_service.hpp" - -namespace asio { - -/// Default service implementation for a stream socket. -template -class stream_socket_service -#if defined(GENERATING_DOCUMENTATION) - : public asio::io_service::service -#else - : public asio::detail::service_base > -#endif -{ -public: -#if defined(GENERATING_DOCUMENTATION) - /// The unique service identifier. - static asio::io_service::id id; -#endif - - /// The protocol type. - typedef Protocol protocol_type; - - /// The endpoint type. - typedef typename Protocol::endpoint endpoint_type; - -private: - // The type of the platform-specific implementation. -#if defined(ASIO_HAS_IOCP) - typedef detail::win_iocp_socket_service service_impl_type; -#elif defined(ASIO_HAS_EPOLL) - typedef detail::reactive_socket_service< - Protocol, detail::epoll_reactor > service_impl_type; -#elif defined(ASIO_HAS_KQUEUE) - typedef detail::reactive_socket_service< - Protocol, detail::kqueue_reactor > service_impl_type; -#else - typedef detail::reactive_socket_service< - Protocol, detail::select_reactor > service_impl_type; -#endif - -public: - /// The type of a stream socket implementation. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined implementation_type; -#else - typedef typename service_impl_type::implementation_type implementation_type; -#endif - - /// The native socket type. -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined native_type; -#else - typedef typename service_impl_type::native_type native_type; -#endif - - /// Construct a new stream socket service for the specified io_service. - explicit stream_socket_service(asio::io_service& io_service) - : asio::detail::service_base< - stream_socket_service >(io_service), - service_impl_(asio::use_service(io_service)) - { - } - - /// Destroy all user-defined handler objects owned by the service. - void shutdown_service() - { - } - - /// Construct a new stream socket implementation. - void construct(implementation_type& impl) - { - service_impl_.construct(impl); - } - - /// Destroy a stream socket implementation. - void destroy(implementation_type& impl) - { - service_impl_.destroy(impl); - } - - /// Open a stream socket. - asio::error_code open(implementation_type& impl, - const protocol_type& protocol, asio::error_code& ec) - { - if (protocol.type() == SOCK_STREAM) - service_impl_.open(impl, protocol, ec); - else - ec = asio::error::invalid_argument; - return ec; - } - - /// Assign an existing native socket to a stream socket. - asio::error_code assign(implementation_type& impl, - const protocol_type& protocol, const native_type& native_socket, - asio::error_code& ec) - { - return service_impl_.assign(impl, protocol, native_socket, ec); - } - - /// Determine whether the socket is open. - bool is_open(const implementation_type& impl) const - { - return service_impl_.is_open(impl); - } - - /// Close a stream socket implementation. - asio::error_code close(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.close(impl, ec); - } - - /// Get the native socket implementation. - native_type native(implementation_type& impl) - { - return service_impl_.native(impl); - } - - /// Cancel all asynchronous operations associated with the socket. - asio::error_code cancel(implementation_type& impl, - asio::error_code& ec) - { - return service_impl_.cancel(impl, ec); - } - - /// Determine whether the socket is at the out-of-band data mark. - bool at_mark(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.at_mark(impl, ec); - } - - /// Determine the number of bytes available for reading. - std::size_t available(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.available(impl, ec); - } - - /// Bind the stream socket to the specified local endpoint. - asio::error_code bind(implementation_type& impl, - const endpoint_type& endpoint, asio::error_code& ec) - { - return service_impl_.bind(impl, endpoint, ec); - } - - /// Connect the stream socket to the specified endpoint. - asio::error_code connect(implementation_type& impl, - const endpoint_type& peer_endpoint, asio::error_code& ec) - { - return service_impl_.connect(impl, peer_endpoint, ec); - } - - /// Start an asynchronous connect. - template - void async_connect(implementation_type& impl, - const endpoint_type& peer_endpoint, ConnectHandler handler) - { - service_impl_.async_connect(impl, peer_endpoint, handler); - } - - /// Set a socket option. - template - asio::error_code set_option(implementation_type& impl, - const SettableSocketOption& option, asio::error_code& ec) - { - return service_impl_.set_option(impl, option, ec); - } - - /// Get a socket option. - template - asio::error_code get_option(const implementation_type& impl, - GettableSocketOption& option, asio::error_code& ec) const - { - return service_impl_.get_option(impl, option, ec); - } - - /// Perform an IO control command on the socket. - template - asio::error_code io_control(implementation_type& impl, - IoControlCommand& command, asio::error_code& ec) - { - return service_impl_.io_control(impl, command, ec); - } - - /// Get the local endpoint. - endpoint_type local_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.local_endpoint(impl, ec); - } - - /// Get the remote endpoint. - endpoint_type remote_endpoint(const implementation_type& impl, - asio::error_code& ec) const - { - return service_impl_.remote_endpoint(impl, ec); - } - - /// Disable sends or receives on the socket. - asio::error_code shutdown(implementation_type& impl, - socket_base::shutdown_type what, asio::error_code& ec) - { - return service_impl_.shutdown(impl, what, ec); - } - - /// Send the given data to the peer. - template - std::size_t send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.send(impl, buffers, flags, ec); - } - - /// Start an asynchronous send. - template - void async_send(implementation_type& impl, - const ConstBufferSequence& buffers, - socket_base::message_flags flags, WriteHandler handler) - { - service_impl_.async_send(impl, buffers, flags, handler); - } - - /// Receive some data from the peer. - template - std::size_t receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, asio::error_code& ec) - { - return service_impl_.receive(impl, buffers, flags, ec); - } - - /// Start an asynchronous receive. - template - void async_receive(implementation_type& impl, - const MutableBufferSequence& buffers, - socket_base::message_flags flags, ReadHandler handler) - { - service_impl_.async_receive(impl, buffers, flags, handler); - } - -private: - // The service that provides the platform-specific implementation. - service_impl_type& service_impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_STREAM_SOCKET_SERVICE_HPP diff --git a/libtorrent/include/libtorrent/asio/streambuf.hpp b/libtorrent/include/libtorrent/asio/streambuf.hpp deleted file mode 100644 index fdcc94a00..000000000 --- a/libtorrent/include/libtorrent/asio/streambuf.hpp +++ /dev/null @@ -1,31 +0,0 @@ -// -// streambuf.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_STREAMBUF_HPP -#define ASIO_STREAMBUF_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/basic_streambuf.hpp" - -namespace asio { - -/// Typedef for the typical usage of basic_streambuf. -typedef basic_streambuf<> streambuf; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_STREAMBUF_HPP diff --git a/libtorrent/include/libtorrent/asio/system_error.hpp b/libtorrent/include/libtorrent/asio/system_error.hpp deleted file mode 100644 index 95f9f540e..000000000 --- a/libtorrent/include/libtorrent/asio/system_error.hpp +++ /dev/null @@ -1,117 +0,0 @@ -// -// system_error.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_SYSTEM_ERROR_HPP -#define ASIO_SYSTEM_ERROR_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/push_options.hpp" -#include -#include -#include -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/error_code.hpp" - -namespace asio { - -/// The system_error class is used to represent system conditions that -/// prevent the library from operating correctly. -class system_error - : public std::exception -{ -public: - /// Construct with an error code. - system_error(const error_code& code) - : code_(code), - context_() - { - } - - /// Construct with an error code and context. - system_error(const error_code& code, const std::string& context) - : code_(code), - context_(context) - { - } - - /// Copy constructor. - system_error(const system_error& other) - : std::exception(other), - code_(other.code_), - context_(other.context_), - what_() - { - } - - /// Destructor. - virtual ~system_error() throw () - { - } - - /// Assignment operator. - system_error& operator=(const system_error& e) - { - context_ = e.context_; - code_ = e.code_; - what_.reset(); - return *this; - } - - /// Get a string representation of the exception. - virtual const char* what() const throw () - { - try - { - if (!what_) - { - std::string tmp(context_); - if (tmp.length()) - tmp += ": "; - tmp += code_.message(); - what_.reset(new std::string(tmp)); - } - return what_->c_str(); - } - catch (std::exception&) - { - return "system_error"; - } - } - - /// Get the error code associated with the exception. - error_code code() const - { - return code_; - } - -private: - // The code associated with the error. - error_code code_; - - // The context associated with the error. - std::string context_; - - // The string representation of the error. - mutable boost::scoped_ptr what_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SYSTEM_ERROR_HPP diff --git a/libtorrent/include/libtorrent/asio/system_exception.hpp b/libtorrent/include/libtorrent/asio/system_exception.hpp deleted file mode 100644 index 599e22712..000000000 --- a/libtorrent/include/libtorrent/asio/system_exception.hpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// error.hpp -// ~~~~~~~~~ -// -// Copyright (c) 2003-2006 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_SYSTEM_EXCEPTION_HPP -#define ASIO_SYSTEM_EXCEPTION_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/push_options.hpp" -#include -#include -#include -#include -#include -#include -#include -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -# include -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -#include "asio/detail/pop_options.hpp" - -#include "asio/detail/win_local_free_on_block_exit.hpp" - -namespace asio { - -/// The system_exception class is used to represent system conditions that -/// prevent the library from operating correctly. -class system_exception - : public std::exception -{ -public: - /// Construct with a specific context and error code. - system_exception(const std::string& context, int code) - : context_(context), - code_(code) - { - } - - /// Copy constructor. - system_exception(const system_exception& e) - : std::exception(e), - context_(e.context_), - code_(e.code_) - { - } - - /// Destructor. - virtual ~system_exception() throw () - { - } - - /// Assignment operator. - system_exception& operator=(const system_exception& e) - { - context_ = e.context_; - code_ = e.code_; - what_.reset(); - return *this; - } - - /// Get a string representation of the exception. - virtual const char* what() const throw () - { -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) - try - { - if (!what_) - { - char* msg = 0; - DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER - | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, 0, code_, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0); - detail::win_local_free_on_block_exit local_free_obj(msg); - if (length && msg[length - 1] == '\n') - msg[--length] = '\0'; - if (length && msg[length - 1] == '\r') - msg[--length] = '\0'; - if (length) - { - std::string tmp(context_); - tmp += ": "; - tmp += msg; - what_.reset(new std::string(tmp)); - } - else - { - return "asio system_exception"; - } - } - return what_->c_str(); - } - catch (std::exception&) - { - return "asio system_exception"; - } -#elif defined(__sun) || defined(__QNX__) - return strerror(code_); -#elif defined(__MACH__) && defined(__APPLE__) \ - || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) - try - { - char buf[256] = ""; - strerror_r(code_, buf, sizeof(buf)); - std::string tmp(context_); - tmp += ": "; - tmp += buf; - what_.reset(new std::string(tmp)); - return what_->c_str(); - } - catch (std::exception&) - { - return "asio system_exception"; - } -#else - try - { - char buf[256] = ""; - std::string tmp(context_); - tmp += ": "; - tmp += strerror_r(code_, buf, sizeof(buf)); - what_.reset(new std::string(tmp)); - return what_->c_str(); - } - catch (std::exception&) - { - return "asio system_exception"; - } -#endif - } - - /// Get the implementation-defined context associated with the exception. - const std::string& context() const - { - return context_; - } - - /// Get the implementation-defined code associated with the exception. - int code() const - { - return code_; - } - -private: - // The context associated with the error. - std::string context_; - - // The code associated with the error. - int code_; - - // The string representation of the error. - mutable boost::scoped_ptr what_; -}; - -/// Output the string associated with a system exception. -/** - * Used to output a human-readable string that is associated with a system - * exception. - * - * @param os The output stream to which the string will be written. - * - * @param e The exception to be written. - * - * @return The output stream. - * - * @relates asio::system_exception - */ -#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -std::ostream& operator<<(std::ostream& os, const system_exception& e) -{ - os << e.what(); - return os; -} -#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) -template -Ostream& operator<<(Ostream& os, const system_exception& e) -{ - os << e.what(); - return os; -} -#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_SYSTEM_EXCEPTION_HPP diff --git a/libtorrent/include/libtorrent/asio/thread.hpp b/libtorrent/include/libtorrent/asio/thread.hpp deleted file mode 100644 index b8bc81bab..000000000 --- a/libtorrent/include/libtorrent/asio/thread.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// thread.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_THREAD_HPP -#define ASIO_THREAD_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/noncopyable.hpp" -#include "asio/detail/thread.hpp" - -namespace asio { - -/// A simple abstraction for starting threads. -/** - * The asio::thread class implements the smallest possible subset of the - * functionality of boost::thread. It is intended to be used only for starting - * a thread and waiting for it to exit. If more extensive threading - * capabilities are required, you are strongly advised to use something else. - * - * @par Thread Safety - * @e Distinct @e objects: Safe.@n - * @e Shared @e objects: Unsafe. - * - * @par Example - * A typical use of asio::thread would be to launch a thread to run an - * io_service's event processing loop: - * - * @par - * @code asio::io_service io_service; - * // ... - * asio::thread t(boost::bind(&asio::io_service::run, &io_service)); - * // ... - * t.join(); @endcode - */ -class thread - : private noncopyable -{ -public: - /// Start a new thread that executes the supplied function. - /** - * This constructor creates a new thread that will execute the given function - * or function object. - * - * @param f The function or function object to be run in the thread. The - * function signature must be: @code void f(); @endcode - */ - template - explicit thread(Function f) - : impl_(f) - { - } - - /// Destructor. - ~thread() - { - } - - /// Wait for the thread to exit. - /** - * This function will block until the thread has exited. - * - * If this function is not called before the thread object is destroyed, the - * thread itself will continue to run until completion. You will, however, - * no longer have the ability to wait for it to exit. - */ - void join() - { - impl_.join(); - } - -private: - detail::thread impl_; -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_THREAD_HPP diff --git a/libtorrent/include/libtorrent/asio/time_traits.hpp b/libtorrent/include/libtorrent/asio/time_traits.hpp deleted file mode 100644 index d3c910e53..000000000 --- a/libtorrent/include/libtorrent/asio/time_traits.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// time_traits.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_TIME_TRAITS_HPP -#define ASIO_TIME_TRAITS_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/socket_types.hpp" // Must come before posix_time. - -#include "asio/detail/push_options.hpp" -#include -#include "asio/detail/pop_options.hpp" - -namespace asio { - -/// Time traits suitable for use with the deadline timer. -template -struct time_traits; - -/// Time traits specialised for posix_time. -template <> -struct time_traits -{ - /// The time type. - typedef boost::posix_time::ptime time_type; - - /// The duration type. - typedef boost::posix_time::time_duration duration_type; - - /// Get the current time. - static time_type now() - { - return boost::posix_time::microsec_clock::universal_time(); - } - - /// Add a duration to a time. - static time_type add(const time_type& t, const duration_type& d) - { - return t + d; - } - - /// Subtract one time from another. - static duration_type subtract(const time_type& t1, const time_type& t2) - { - return t1 - t2; - } - - /// Test whether one time is less than another. - static bool less_than(const time_type& t1, const time_type& t2) - { - return t1 < t2; - } - - /// Convert to POSIX duration type. - static boost::posix_time::time_duration to_posix_duration( - const duration_type& d) - { - return d; - } -}; - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TIME_TRAITS_HPP diff --git a/libtorrent/include/libtorrent/asio/write.hpp b/libtorrent/include/libtorrent/asio/write.hpp deleted file mode 100644 index 5d643626a..000000000 --- a/libtorrent/include/libtorrent/asio/write.hpp +++ /dev/null @@ -1,515 +0,0 @@ -// -// write.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_WRITE_HPP -#define ASIO_WRITE_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/push_options.hpp" -#include -#include -#include "asio/detail/pop_options.hpp" - -#include "asio/basic_streambuf.hpp" -#include "asio/error.hpp" - -namespace asio { - -/** - * @defgroup write asio::write - */ -/*@{*/ - -/// Write all of the supplied data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * stream. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::write(s, asio::buffer(data, size)); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - * - * @note This overload is equivalent to calling: - * @code asio::write( - * s, buffers, - * asio::transfer_all()); @endcode - */ -template -std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * stream. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's write_some function are - * required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::write(s, asio::buffer(data, size), - * asio::transfer_at_least(32)); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. The sum - * of the buffer sizes indicates the maximum number of bytes to write to the - * stream. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's write_some function are - * required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, asio::error_code& ec); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param b The basic_streambuf object from which data will be written. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - * - * @note This overload is equivalent to calling: - * @code asio::write( - * s, b, - * asio::transfer_all()); @endcode - */ -template -std::size_t write(SyncWriteStream& s, basic_streambuf& b); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param b The basic_streambuf object from which data will be written. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's write_some function are - * required. - * - * @returns The number of bytes transferred. - * - * @throws asio::system_error Thrown on failure. - */ -template -std::size_t write(SyncWriteStream& s, basic_streambuf& b, - CompletionCondition completion_condition); - -/// Write a certain amount of data to a stream before returning. -/** - * This function is used to write a certain number of bytes of data to a stream. - * The call will block until one of the following conditions is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the SyncWriteStream concept. - * - * @param b The basic_streambuf object from which data will be written. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's write_some function are - * required. - * - * @param ec Set to indicate what error occurred, if any. - * - * @returns The number of bytes written. If an error occurs, returns the total - * number of bytes successfully transferred prior to the error. - */ -template -std::size_t write(SyncWriteStream& s, basic_streambuf& b, - CompletionCondition completion_condition, asio::error_code& ec); - -/*@}*/ -/** - * @defgroup async_write asio::async_write - */ -/*@{*/ - -/// Start an asynchronous operation to write of all of the supplied data to a -/// stream. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the AsyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code - * asio::async_write(s, asio::buffer(data, size), handler); - * @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - WriteHandler handler); - -/// Start an asynchronous operation to write a certain amount of data to a -/// stream. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li All of the data in the supplied buffers has been written. That is, the - * bytes transferred is equal to the sum of the buffer sizes. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the AsyncWriteStream concept. - * - * @param buffers One or more buffers containing the data to be written. - * Although the buffers object may be copied as necessary, ownership of the - * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's async_write_some function are - * required. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - * - * @par Example - * To write a single data buffer use the @ref buffer function as follows: - * @code asio::async_write(s, - * asio::buffer(data, size), - * asio::transfer_at_least(32), - * handler); @endcode - * See the @ref buffer documentation for information on writing multiple - * buffers in one go, and how to use it with arrays, boost::array or - * std::vector. - */ -template -void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, WriteHandler handler); - -/// Start an asynchronous operation to write a certain amount of data to a -/// stream. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li An error occurred. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the AsyncWriteStream concept. - * - * @param b A basic_streambuf object from which data will be written. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_write(AsyncWriteStream& s, basic_streambuf& b, - WriteHandler handler); - -/// Start an asynchronous operation to write a certain amount of data to a -/// stream. -/** - * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: - * - * @li All of the data in the supplied basic_streambuf has been written. - * - * @li The completion_condition function object returns true. - * - * This operation is implemented in terms of one or more calls to the stream's - * async_write_some function. - * - * @param s The stream to which the data is to be written. The type must support - * the AsyncWriteStream concept. - * - * @param b A basic_streambuf object from which data will be written. Ownership - * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. - * - * @param completion_condition The function object to be called to determine - * whether the write operation is complete. The signature of the function object - * must be: - * @code bool completion_condition( - * const asio::error_code& error, // Result of latest write_some - * // operation. - * - * std::size_t bytes_transferred // Number of bytes transferred - * // so far. - * ); @endcode - * A return value of true indicates that the write operation is complete. False - * indicates that further calls to the stream's async_write_some function are - * required. - * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: - * @code void handler( - * const asio::error_code& error, // Result of operation. - * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. - * ); @endcode - * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. Invocation of - * the handler will be performed in a manner equivalent to using - * asio::io_service::post(). - */ -template -void async_write(AsyncWriteStream& s, basic_streambuf& b, - CompletionCondition completion_condition, WriteHandler handler); - -/*@}*/ - -} // namespace asio - -#include "asio/impl/write.ipp" - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_WRITE_HPP diff --git a/libtorrent/include/libtorrent/aux_/allocate_resources_impl.hpp b/libtorrent/include/libtorrent/aux_/allocate_resources_impl.hpp deleted file mode 100644 index 31865d40a..000000000 --- a/libtorrent/include/libtorrent/aux_/allocate_resources_impl.hpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - -Copyright (c) 2003, Magnus Jonsson -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_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED -#define TORRENT_ALLOCATE_RESOURCES_IMPL_HPP_INCLUDED - -#include -#include - -#include - -#include "libtorrent/resource_request.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/size_type.hpp" - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -namespace libtorrent -{ - - int saturated_add(int a, int b); - - namespace aux - { - // give num_resources to r, - // return how how many were actually accepted. - inline int give(resource_request& r, int num_resources) - { - assert(num_resources >= 0); - assert(r.given <= r.max); - - int accepted = (std::min)(num_resources, r.max - r.given); - assert(accepted >= 0); - - r.given += accepted; - assert(r.given <= r.max); - - return accepted; - } - - inline int div_round_up(int numerator, int denominator) - { - return (numerator + denominator - 1) / denominator; - } - -#ifndef NDEBUG - - template - class allocate_resources_contract_check - { - int m_resources; - It m_start; - It m_end; - resource_request T::* m_res; - - public: - allocate_resources_contract_check( - int resources - , It start - , It end - , resource_request T::* res) - : m_resources(resources) - , m_start(start) - , m_end(end) - , m_res(res) - { - assert(m_resources >= 0); - for (It i = m_start, end(m_end); i != end; ++i) - { - assert(((*i).*m_res).max >= 0); - assert(((*i).*m_res).given >= 0); - } - } - - ~allocate_resources_contract_check() - { - int sum_given = 0; - int sum_max = 0; - int sum_min = 0; - for (It i = m_start, end(m_end); i != end; ++i) - { - assert(((*i).*m_res).max >= 0); - assert(((*i).*m_res).min >= 0); - assert(((*i).*m_res).max >= ((*i).*m_res).min); - assert(((*i).*m_res).given >= 0); - assert(((*i).*m_res).given <= ((*i).*m_res).max); - - sum_given = saturated_add(sum_given, ((*i).*m_res).given); - sum_max = saturated_add(sum_max, ((*i).*m_res).max); - sum_min = saturated_add(sum_min, ((*i).*m_res).min); - } - if (sum_given != (std::min)(std::max(m_resources, sum_min), sum_max)) - { - std::cerr << sum_given << " " << m_resources << " " << sum_min << " " << sum_max << std::endl; - assert(false); - } - } - }; - -#endif - - template - void allocate_resources_impl( - int resources - , It start - , It end - , resource_request T::* res) - { - assert(resources >= 0); - #ifndef NDEBUG - allocate_resources_contract_check contract_check( - resources - , start - , end - , res); - #endif - - for (It i = start; i != end; ++i) - { - resource_request& r = (*i).*res; - r.leftovers = (std::max)(r.used - r.given, 0); - } - - if (resources == resource_request::inf) - { - // No competition for resources. - // Just give everyone what they want. - for (It i = start; i != end; ++i) - { - ((*i).*res).given = ((*i).*res).max; - } - return; - } - - // Resources are scarce - - int sum_max = 0; - int sum_min = 0; - // the number of consumer that saturated their - // quota last time slice - int num_saturated = 0; - // the total resources that those saturated their - // quota used. This is used to calculate the mean - // of the saturating consumers, in order to - // balance their quotas for the next time slice. - size_type saturated_sum = 0; - for (It i = start; i != end; ++i) - { - resource_request& r = (*i).*res; - sum_max = saturated_add(sum_max, r.max); - assert(r.min < resource_request::inf); - assert(r.min >= 0); - assert(r.min <= r.max); - sum_min += r.min; - - // a consumer that uses 95% or more of its assigned - // quota is considered saturating - size_type used = r.used; - if (r.given == 0) continue; - if (used * 20 / r.given >= 19) - { - ++num_saturated; - saturated_sum += r.given; - } - } - - if (sum_max <= resources) - { - // it turns out that there's no competition for resources - // after all. - for (It i = start; i != end; ++i) - { - ((*i).*res).given = ((*i).*res).max; - } - return; - } - - if (sum_min >= resources) - { - // the amount of resources is smaller than - // the minimum resources to distribute, so - // give everyone the minimum - for (It i = start; i != end; ++i) - { - ((*i).*res).given = ((*i).*res).min; - } - return; - } - - // now, the "used" field will be used as a target value. - // the algorithm following this loop will then scale the - // used values to fit the available resources and store - // the scaled values as given. So, the ratios of the - // used values will be maintained. - for (It i = start; i != end; ++i) - { - resource_request& r = (*i).*res; - - int target; - size_type used = r.used; - if (r.given > 0 && used * 20 / r.given >= 19) - { - assert(num_saturated > 0); - target = div_round_up(saturated_sum, num_saturated); - target += div_round_up(target, 10); - } - else - { - target = r.used; - } - if (target > r.max) target = r.max; - else if (target < r.min) target = r.min; - - // move 12.5% towards the the target value - r.used = r.given + div_round_up(target - r.given, 8); - r.given = r.min; - } - - - resources = (std::max)(resources, sum_min); - int resources_to_distribute = (std::min)(resources, sum_max) - sum_min; - assert(resources_to_distribute >= 0); -#ifndef NDEBUG - int prev_resources_to_distribute = resources_to_distribute; -#endif - while (resources_to_distribute > 0) - { - // in order to scale, we need to calculate the sum of - // all the used values. - size_type total_used = 0; - size_type max_used = 0; - for (It i = start; i != end; ++i) - { - resource_request& r = (*i).*res; - if (r.given == r.max) continue; - - assert(r.given < r.max); - - max_used = (std::max)(max_used, (size_type)r.used + 1); - total_used += (size_type)r.used + 1; - } - - - size_type kNumer = resources_to_distribute; - size_type kDenom = total_used; - assert(kNumer >= 0); - assert(kDenom >= 0); - assert(kNumer <= (std::numeric_limits::max)()); - - if (kNumer * max_used <= kDenom) - { - kNumer = 1; - kDenom = max_used; - assert(kDenom >= 0); - } - - for (It i = start; i != end && resources_to_distribute > 0; ++i) - { - resource_request& r = (*i).*res; - if (r.given == r.max) continue; - - assert(r.given < r.max); - - size_type used = (size_type)r.used + 1; - if (used < 1) used = 1; - size_type to_give = used * kNumer / kDenom; - if (to_give > resources_to_distribute) - to_give = resources_to_distribute; - assert(to_give >= 0); - assert(to_give <= resources_to_distribute); -#ifndef NDEBUG - int tmp = resources_to_distribute; -#endif - resources_to_distribute -= give(r, (int)to_give); - assert(resources_to_distribute <= tmp); - assert(resources_to_distribute >= 0); - } - - assert(resources_to_distribute >= 0); - assert(resources_to_distribute < prev_resources_to_distribute); -#ifndef NDEBUG - prev_resources_to_distribute = resources_to_distribute; -#endif - } - assert(resources_to_distribute == 0); - } - - } // namespace libtorrent::aux -} - - -#endif diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp deleted file mode 100644 index c878eb95c..000000000 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ /dev/null @@ -1,532 +0,0 @@ -/* - -Copyright (c) 2006, 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_SESSION_IMPL_HPP_INCLUDED -#define TORRENT_SESSION_IMPL_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/peer_info.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/debug.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/ip_filter.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" -#include "libtorrent/session_status.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/bandwidth_manager.hpp" -#include "libtorrent/natpmp.hpp" -#include "libtorrent/upnp.hpp" -#include "libtorrent/lsd.hpp" -#include "libtorrent/socket_type.hpp" -#include "libtorrent/connection_queue.hpp" - -namespace libtorrent -{ - - namespace aux - { - struct session_impl; - - // this data is shared between the main thread and the - // thread that initialize pieces - struct piece_checker_data - { - piece_checker_data() - : processing(false), progress(0.f), abort(false) {} - - boost::shared_ptr torrent_ptr; - boost::filesystem::path save_path; - - sha1_hash info_hash; - - void parse_resume_data( - const entry& rd - , const torrent_info& info - , std::string& error); - - std::vector piece_map; - std::vector unfinished_pieces; - std::vector block_info; - std::vector peers; - entry resume_data; - - // this is true if this torrent is being processed (checked) - // if it is not being processed, then it can be removed from - // the queue without problems, otherwise the abort flag has - // to be set. - bool processing; - - // is filled in by storage::initialize_pieces() - // and represents the progress. It should be a - // value in the range [0, 1] - float progress; - - // abort defaults to false and is typically - // filled in by torrent_handle when the user - // aborts the torrent - bool abort; - }; - - struct checker_impl: boost::noncopyable - { - checker_impl(session_impl& s): m_ses(s), m_abort(false) {} - void operator()(); - piece_checker_data* find_torrent(const sha1_hash& info_hash); - void remove_torrent(sha1_hash const& info_hash); - -#ifndef NDEBUG - void check_invariant() const; -#endif - - // when the files has been checked - // the torrent is added to the session - session_impl& m_ses; - - mutable boost::mutex m_mutex; - boost::condition m_cond; - - // a list of all torrents that are currently in queue - // or checking their files - std::deque > m_torrents; - std::deque > m_processing; - - bool m_abort; - }; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - struct tracker_logger; -#endif - - // this is the link between the main thread and the - // thread started to run the main downloader loop - struct session_impl: boost::noncopyable - { -#ifndef NDEBUG - friend class ::libtorrent::peer_connection; -#endif - friend struct checker_impl; - friend class invariant_access; - typedef std::map - , boost::intrusive_ptr > - connection_map; - typedef std::map > torrent_map; - - session_impl( - std::pair listen_port_range - , fingerprint const& cl_fprint - , char const* listen_interface = "0.0.0.0"); - ~session_impl(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::function(torrent*)> ext); -#endif - void operator()(); - - void open_listen_port(); - - void async_accept(); - void on_incoming_connection(boost::shared_ptr const& s - , boost::weak_ptr const& as, asio::error_code const& e); - - // must be locked to access the data - // in this struct - typedef boost::recursive_mutex mutex_t; - mutable mutex_t m_mutex; - - boost::weak_ptr find_torrent(const sha1_hash& info_hash); - peer_id const& get_peer_id() const { return m_peer_id; } - - void close_connection(boost::intrusive_ptr const& p); - void connection_failed(boost::shared_ptr const& s - , tcp::endpoint const& a, char const* message); - - void set_settings(session_settings const& s); - session_settings const& settings() const { return m_settings; } - -#ifndef TORRENT_DISABLE_DHT - void add_dht_node(std::pair const& node); - void add_dht_node(udp::endpoint n); - void add_dht_router(std::pair const& node); - void set_dht_settings(dht_settings const& s); - dht_settings const& get_dht_settings() const { return m_dht_settings; } - void start_dht(entry const& startup_state); - void stop_dht(); - entry dht_state() const; -#endif - - // called when a port mapping is successful, or a router returns - // a failure to map a port - void on_port_mapping(int tcp_port, int udp_port, std::string const& errmsg); - - bool is_aborted() const { return m_abort; } - - void set_ip_filter(ip_filter const& f); - - bool listen_on( - std::pair const& port_range - , const char* net_interface = 0); - bool is_listening() const; - - torrent_handle add_torrent( - torrent_info const& ti - , boost::filesystem::path const& save_path - , entry const& resume_data - , bool compact_mode - , int block_size - , storage_constructor_type sc); - - torrent_handle add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , boost::filesystem::path const& save_path - , entry const& resume_data - , bool compact_mode - , int block_size - , storage_constructor_type sc); - - void remove_torrent(torrent_handle const& h); - - std::vector get_torrents(); - - void set_severity_level(alert::severity_t s); - std::auto_ptr pop_alert(); - - int upload_rate_limit() const; - int download_rate_limit() const; - - void set_download_rate_limit(int bytes_per_second); - void set_upload_rate_limit(int bytes_per_second); - void set_max_half_open_connections(int limit); - void set_max_connections(int limit); - void set_max_uploads(int limit); - - int num_uploads() const; - int num_connections() const; - - session_status status() const; - void set_peer_id(peer_id const& id); - void set_key(int key); - unsigned short listen_port() const; - - void abort(); - - torrent_handle find_torrent_handle(sha1_hash const& info_hash); - - void announce_lsd(sha1_hash const& ih); - - void set_peer_proxy(proxy_settings const& s) - { m_peer_proxy = s; } - void set_web_seed_proxy(proxy_settings const& s) - { m_web_seed_proxy = s; } - void set_tracker_proxy(proxy_settings const& s) - { m_tracker_proxy = s; } - - proxy_settings const& peer_proxy() const - { return m_peer_proxy; } - proxy_settings const& web_seed_proxy() const - { return m_web_seed_proxy; } - proxy_settings const& tracker_proxy() const - { return m_tracker_proxy; } - -#ifndef TORRENT_DISABLE_DHT - void set_dht_proxy(proxy_settings const& s) - { m_dht_proxy = s; } - proxy_settings const& dht_proxy() const - { return m_dht_proxy; } -#endif - - // handles delayed alerts - alert_manager m_alerts; - -// private: - - void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); - - // this is where all active sockets are stored. - // the selector can sleep while there's no activity on - // them - io_service m_io_service; - asio::strand m_strand; - - // the file pool that all storages in this session's - // torrents uses. It sets a limit on the number of - // open files by this session. - // file pool must be destructed after the torrents - // since they will still have references to it - // when they are destructed. - file_pool m_files; - - // this is a list of half-open tcp connections - // (only outgoing connections) - // this has to be one of the last - // members to be destructed - connection_queue m_half_open; - - // the bandwidth manager is responsible for - // handing out bandwidth to connections that - // asks for it, it can also throttle the - // rate. - bandwidth_manager m_dl_bandwidth_manager; - bandwidth_manager m_ul_bandwidth_manager; - - tracker_manager m_tracker_manager; - torrent_map m_torrents; - - // this maps sockets to their peer_connection - // object. It is the complete list of all connected - // peers. - connection_map m_connections; - - // filters incoming connections - ip_filter m_ip_filter; - - // the peer id that is generated at the start of the session - peer_id m_peer_id; - - // the key is an id that is used to identify the - // client with the tracker only. It is randomized - // at startup - int m_key; - - // the range of ports we try to listen on - std::pair m_listen_port_range; - - // the ip-address of the interface - // we are supposed to listen on. - // if the ip is set to zero, it means - // that we should let the os decide which - // interface to listen on - tcp::endpoint m_listen_interface; - - // this is typically set to the same as the local - // listen port. In case a NAT port forward was - // successfully opened, this will be set to the - // port that is open on the external (NAT) interface - // on the NAT box itself. This is the port that has - // to be published to peers, since this is the port - // the client is reachable through. - int m_external_listen_port; - - boost::shared_ptr m_listen_socket; - - // the settings for the client - session_settings m_settings; - // the proxy settings for different - // kinds of connections - proxy_settings m_peer_proxy; - proxy_settings m_web_seed_proxy; - proxy_settings m_tracker_proxy; -#ifndef TORRENT_DISABLE_DHT - proxy_settings m_dht_proxy; -#endif - - // set to true when the session object - // is being destructed and the thread - // should exit - volatile bool m_abort; - - int m_max_uploads; - int m_max_connections; - - // statistics gathered from all torrents. - stat m_stat; - - // is false by default and set to true when - // the first incoming connection is established - // this is used to know if the client is behind - // NAT or not. - bool m_incoming_connection; - - void second_tick(asio::error_code const& e); - ptime m_last_tick; - -#ifndef TORRENT_DISABLE_DHT - boost::intrusive_ptr m_dht; - dht_settings m_dht_settings; - // if this is set to true, the dht listen port - // will be set to the same as the tcp listen port - // and will be synchronlized with it as it changes - // it defaults to true - bool m_dht_same_port; - - // see m_external_listen_port. This is the same - // but for the udp port used by the DHT. - int m_external_udp_port; -#endif - natpmp m_natpmp; - upnp m_upnp; - lsd m_lsd; - - // the timer used to fire the second_tick - deadline_timer m_timer; - - // the index of the torrent that will be offered to - // connect to a peer next time second_tick is called. - // This implements a round robin. - int m_next_connect_torrent; -#ifndef NDEBUG - void check_invariant(const char *place = 0); -#endif - -#ifdef TORRENT_STATS - // logger used to write bandwidth usage statistics - std::ofstream m_stats_logger; - int m_second_counter; -#endif -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr create_log(std::string const& name - , int instance, bool append = true); - - // this list of tracker loggers serves as tracker_callbacks when - // shutting down. This list is just here to keep them alive during - // whe shutting down process - std::list > m_tracker_loggers; - - public: - boost::shared_ptr m_logger; - private: -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::list(torrent*)> > extension_list_t; - - extension_list_t m_extensions; -#endif - - // data shared between the main thread - // and the checker thread - checker_impl m_checker_impl; - - // the main working thread - boost::scoped_ptr m_thread; - - // the thread that calls initialize_pieces() - // on all torrents before they start downloading - boost::scoped_ptr m_checker_thread; - }; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - struct tracker_logger : request_callback - { - tracker_logger(session_impl& ses): m_ses(ses) {} - void tracker_warning(std::string const& str) - { - debug_log("*** tracker warning: " + str); - } - - void tracker_response(tracker_request const& - , std::vector& peers - , int interval - , int complete - , int incomplete) - { - std::stringstream s; - s << "TRACKER RESPONSE:\n" - "interval: " << interval << "\n" - "peers:\n"; - for (std::vector::const_iterator i = peers.begin(); - i != peers.end(); ++i) - { - s << " " << std::setfill(' ') << std::setw(16) << i->ip - << " " << std::setw(5) << std::dec << i->port << " "; - if (!i->pid.is_all_zeros()) s << " " << i->pid; - s << "\n"; - } - debug_log(s.str()); - } - - void tracker_request_timed_out( - tracker_request const&) - { - debug_log("*** tracker timed out"); - } - - void tracker_request_error( - tracker_request const& - , int response_code - , const std::string& str) - { - debug_log(std::string("*** tracker error: ") - + boost::lexical_cast(response_code) + ": " - + str); - } - - void debug_log(const std::string& line) - { - (*m_ses.m_logger) << line << "\n"; - } - session_impl& m_ses; - }; -#endif - - } -} - - -#endif - diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp deleted file mode 100644 index dbf93aa77..000000000 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - -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_BANDWIDTH_MANAGER_HPP_INCLUDED -#define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED - -#include "libtorrent/socket.hpp" - -#include -#include -#include -#include -#include -#include -#include - -using boost::weak_ptr; -using boost::shared_ptr; -using boost::intrusive_ptr; -using boost::bind; - -namespace libtorrent -{ - - class peer_connection; - class torrent; - - // the maximum block of bandwidth quota to - // hand out is 33kB. The block size may - // be smaller on lower limits - const int max_bandwidth_block_size = 33000; - const int min_bandwidth_block_size = 4000; - -#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING - namespace aux - { - struct session_impl; - } -#endif - -struct history_entry -{ - history_entry(intrusive_ptr p, weak_ptr t - , int a, ptime exp); - ptime expires_at; - int amount; - intrusive_ptr peer; - weak_ptr tor; -}; - -struct bw_queue_entry -{ - bw_queue_entry(boost::intrusive_ptr const& pe, bool no_prio); - boost::intrusive_ptr peer; - bool non_prioritized; -}; - -// member of peer_connection -struct bandwidth_limit -{ - static const int inf = boost::integer_traits::const_max; - - bandwidth_limit() - : m_quota_left(0) - , m_local_limit(inf) - , m_current_rate(0) - {} - - void throttle(int limit) - { - m_local_limit = limit; - } - - int throttle() const - { - return m_local_limit; - } - - void assign(int amount) - { - assert(amount > 0); - m_current_rate += amount; - m_quota_left += amount; - } - - void use_quota(int amount) - { - assert(amount <= m_quota_left); - m_quota_left -= amount; - } - - int quota_left() const - { - return (std::max)(m_quota_left, 0); - } - - void expire(int amount) - { - assert(amount >= 0); - m_current_rate -= amount; - } - - int max_assignable() const - { - if (m_local_limit == inf) return inf; - if (m_local_limit <= m_current_rate) return 0; - return m_local_limit - m_current_rate; - } - -private: - - // this is the amount of bandwidth we have - // been assigned without using yet. i.e. - // the bandwidth that we use up every time - // we receive or send a message. Once this - // hits zero, we need to request more - // bandwidth from the torrent which - // in turn will request bandwidth from - // the bandwidth manager - int m_quota_left; - - // the local limit is the number of bytes - // per window size we are allowed to use. - int m_local_limit; - - // the current rate is the number of - // bytes we have been assigned within - // the window size. - int m_current_rate; -}; - -struct bandwidth_manager -{ - bandwidth_manager(io_service& ios, int channel); - - void throttle(int limit) - { - mutex_t::scoped_lock l(m_mutex); - assert(limit >= 0); - m_limit = limit; - } - - int throttle() const - { - mutex_t::scoped_lock l(m_mutex); - return m_limit; - } - - // non prioritized means that, if there's a line for bandwidth, - // others will cut in front of the non-prioritized peers. - // this is used by web seeds - void request_bandwidth(intrusive_ptr peer - , bool non_prioritized); - -#ifndef NDEBUG - void check_invariant() const; -#endif -#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING - aux::session_impl* m_ses; -#endif - -private: - - void add_history_entry(history_entry const& e); - void on_history_expire(asio::error_code const& e); - void hand_out_bandwidth(); - - typedef boost::mutex mutex_t; - mutable mutex_t m_mutex; - - // the io_service used for the timer - io_service& m_ios; - - // the timer that is waiting for the entries - // in the history queue to expire (slide out - // of the history window) - deadline_timer m_history_timer; - - // the rate limit (bytes per second) - int m_limit; - - // the sum of all recently handed out bandwidth blocks - int m_current_quota; - - // these are the consumers that want bandwidth - std::deque m_queue; - - // these are the consumers that have received bandwidth - // that will expire - std::deque m_history; - - // this is the channel within the consumers - // that bandwidth is assigned to (upload or download) - int m_channel; -}; - -} - -#endif diff --git a/libtorrent/include/libtorrent/bencode.hpp b/libtorrent/include/libtorrent/bencode.hpp deleted file mode 100644 index a142b5864..000000000 --- a/libtorrent/include/libtorrent/bencode.hpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - -Copyright (c) 2003, 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_BENCODE_HPP_INCLUDED -#define TORRENT_BENCODE_HPP_INCLUDED - - - -/* - * This file declares the following functions: - * - *---------------------------------- - * template - * void libtorrent::bencode(OutIt out, const libtorrent::entry& e); - * - * Encodes a message entry with bencoding into the output - * iterator given. The bencoding is described in the BitTorrent - * protocol description document OutIt must be an OutputIterator - * of type char. This may throw libtorrent::invalid_encoding if - * the entry contains invalid nodes (undefined_t for example). - * - *---------------------------------- - * template - * libtorrent::entry libtorrent::bdecode(InIt start, InIt end); - * - * Decodes the buffer given by the start and end iterators - * and returns the decoded entry. InIt must be an InputIterator - * of type char. May throw libtorrent::invalid_encoding if - * the string is not correctly bencoded. - * - */ - - - - -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/entry.hpp" -#include "libtorrent/config.hpp" - -#if defined(_MSC_VER) -namespace std -{ - using ::isdigit; - using ::atoi; -}; - -#define for if (false) {} else for -#endif - - -namespace libtorrent -{ - - struct TORRENT_EXPORT invalid_encoding: std::exception - { - virtual const char* what() const throw() { return "invalid bencoding"; } - }; - - namespace detail - { - template - void write_string(OutIt& out, const std::string& val) - { - std::string::const_iterator end = val.begin() + val.length(); - std::copy(val.begin(), end, out); - } - - TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val); - - template - void write_integer(OutIt& out, entry::integer_type val) - { - // the stack allocated buffer for keeping the - // decimal representation of the number can - // not hold number bigger than this: - BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8); - char buf[21]; - for (char const* str = integer_to_str(buf, 21, val); - *str != 0; ++str) - { - *out = *str; - ++out; - } - } - - template - void write_char(OutIt& out, char c) - { - *out = c; - ++out; - } - - template - std::string read_until(InIt& in, InIt end, char end_token) - { - if (in == end) throw invalid_encoding(); - std::string ret; - while (*in != end_token) - { - ret += *in; - ++in; - if (in == end) throw invalid_encoding(); - } - return ret; - } - - template - void read_string(InIt& in, InIt end, int len, std::string& str) - { - assert(len >= 0); - for (int i = 0; i < len; ++i) - { - if (in == end) throw invalid_encoding(); - str += *in; - ++in; - } - } - - template - void bencode_recursive(OutIt& out, const entry& e) - { - switch(e.type()) - { - case entry::int_t: - write_char(out, 'i'); - write_integer(out, e.integer()); - write_char(out, 'e'); - break; - case entry::string_t: - write_integer(out, e.string().length()); - write_char(out, ':'); - write_string(out, e.string()); - break; - case entry::list_t: - write_char(out, 'l'); - for (entry::list_type::const_iterator i = e.list().begin(); i != e.list().end(); ++i) - bencode_recursive(out, *i); - write_char(out, 'e'); - break; - case entry::dictionary_t: - write_char(out, 'd'); - for (entry::dictionary_type::const_iterator i = e.dict().begin(); - i != e.dict().end(); ++i) - { - // write key - write_integer(out, i->first.length()); - write_char(out, ':'); - write_string(out, i->first); - // write value - bencode_recursive(out, i->second); - } - write_char(out, 'e'); - break; - default: - // do nothing - break; - } - } - - template - void bdecode_recursive(InIt& in, InIt end, entry& ret) - { - if (in == end) throw invalid_encoding(); - switch (*in) - { - - // ---------------------------------------------- - // integer - case 'i': - { - ++in; // 'i' - std::string val = read_until(in, end, 'e'); - assert(*in == 'e'); - ++in; // 'e' - ret = entry(entry::int_t); - ret.integer() = boost::lexical_cast(val); - } break; - - // ---------------------------------------------- - // list - case 'l': - { - ret = entry(entry::list_t); - ++in; // 'l' - while (*in != 'e') - { - ret.list().push_back(entry()); - entry& e = ret.list().back(); - bdecode_recursive(in, end, e); - if (in == end) throw invalid_encoding(); - } - assert(*in == 'e'); - ++in; // 'e' - } break; - - // ---------------------------------------------- - // dictionary - case 'd': - { - ret = entry(entry::dictionary_t); - ++in; // 'd' - while (*in != 'e') - { - entry key; - bdecode_recursive(in, end, key); - entry& e = ret[key.string()]; - bdecode_recursive(in, end, e); - if (in == end) throw invalid_encoding(); - } - assert(*in == 'e'); - ++in; // 'e' - } break; - - // ---------------------------------------------- - // string - default: - if (isdigit((unsigned char)*in)) - { - std::string len_s = read_until(in, end, ':'); - assert(*in == ':'); - ++in; // ':' - int len = std::atoi(len_s.c_str()); - ret = entry(entry::string_t); - read_string(in, end, len, ret.string()); - } - else - { - throw invalid_encoding(); - } - } - } - } - - template - void bencode(OutIt out, const entry& e) - { - detail::bencode_recursive(out, e); - } - - template - entry bdecode(InIt start, InIt end) - { - try - { - entry e; - detail::bdecode_recursive(start, end, e); - return e; - } - catch(type_error&) - { - throw invalid_encoding(); - } - } - -} - -#endif // TORRENT_BENCODE_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/bt_peer_connection.hpp b/libtorrent/include/libtorrent/bt_peer_connection.hpp deleted file mode 100644 index 223bf2650..000000000 --- a/libtorrent/include/libtorrent/bt_peer_connection.hpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - -Copyright (c) 2003, 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_BT_PEER_CONNECTION_HPP_INCLUDED -#define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include -#include - -#include "libtorrent/debug.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/buffer.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/allocate_resources.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - class torrent; - - namespace detail - { - struct session_impl; - } - - class TORRENT_EXPORT bt_peer_connection - : public peer_connection - { - friend class invariant_access; - public: - - // this is the constructor where the we are the active part. - // The peer_conenction should handshake and verify that the - // other end has the correct id - bt_peer_connection( - aux::session_impl& ses - , boost::weak_ptr t - , boost::shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo); - - // with this constructor we have been contacted and we still don't - // know which torrent the connection belongs to - bt_peer_connection( - aux::session_impl& ses - , boost::shared_ptr s - , policy::peer* peerinfo); - - ~bt_peer_connection(); - - enum message_type - { - // standard messages - msg_choke = 0, - msg_unchoke, - msg_interested, - msg_not_interested, - msg_have, - msg_bitfield, - msg_request, - msg_piece, - msg_cancel, - msg_dht_port, - // extension protocol message - msg_extended = 20, - - num_supported_messages - }; - - // called from the main loop when this connection has any - // work to do. - - void on_sent(asio::error_code const& error - , std::size_t bytes_transferred); - void on_receive(asio::error_code const& error - , std::size_t bytes_transferred); - - virtual void get_peer_info(peer_info& p) const; - virtual bool in_handshake() const; - -#ifndef TORRENT_DISABLE_EXTENSIONS - bool support_extensions() const { return m_supports_extensions; } - - template - T* supports_extension() const - { - for (extension_list_t::const_iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - T* ret = dynamic_cast(i->get()); - if (ret) return ret; - } - return 0; - } -#endif - - // the message handlers are called - // each time a recv() returns some new - // data, the last time it will be called - // is when the entire packet has been - // received, then it will no longer - // be called. i.e. most handlers need - // to check how much of the packet they - // have received before any processing - void on_keepalive(); - void on_choke(int received); - void on_unchoke(int received); - void on_interested(int received); - void on_not_interested(int received); - void on_have(int received); - void on_bitfield(int received); - void on_request(int received); - void on_piece(int received); - void on_cancel(int received); - void on_dht_port(int received); - - void on_extended(int received); - - void on_extended_handshake(); - - typedef void (bt_peer_connection::*message_handler)(int received); - - // the following functions appends messages - // to the send buffer - void write_choke(); - void write_unchoke(); - void write_interested(); - void write_not_interested(); - void write_request(peer_request const& r); - void write_cancel(peer_request const& r); - void write_bitfield(std::vector const& bitfield); - void write_have(int index); - void write_piece(peer_request const& r); - void write_handshake(); -#ifndef TORRENT_DISABLE_EXTENSIONS - void write_extensions(); -#endif - void write_chat_message(const std::string& msg); - void write_metadata(std::pair req); - void write_metadata_request(std::pair req); - void write_keepalive(); - void write_dht_port(int listen_port); - void on_connected() {} - void on_metadata(); - -#ifndef NDEBUG - void check_invariant() const; - ptime m_last_choke; -#endif - - private: - - bool dispatch_message(int received); - // returns the block currently being - // downloaded. And the progress of that - // block. If the peer isn't downloading - // a piece for the moment, the boost::optional - // will be invalid. - boost::optional downloading_piece_progress() const; - - enum state - { - read_protocol_length = 0, - read_protocol_string, - read_info_hash, - read_peer_id, - - read_packet_size, - read_packet - }; - - std::string m_client_version; - - state m_state; - - // the timeout in seconds - int m_timeout; - - static const message_handler m_message_handler[num_supported_messages]; - - // this is a queue of ranges that describes - // where in the send buffer actual payload - // data is located. This is currently - // only used to be able to gather statistics - // seperately on payload and protocol data. - struct range - { - range(int s, int l) - : start(s) - , length(l) - { - assert(s >= 0); - assert(l > 0); - } - int start; - int length; - }; - static bool range_below_zero(const range& r) - { return r.start < 0; } - std::deque m_payloads; - -#ifndef TORRENT_DISABLE_EXTENSIONS - // this is set to true if the handshake from - // the peer indicated that it supports the - // extension protocol - bool m_supports_extensions; -#endif - bool m_supports_dht_port; - -#ifndef NDEBUG - // this is set to true when the client's - // bitfield is sent to this peer - bool m_sent_bitfield; - - bool m_in_constructor; -#endif - }; -} - -#endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/buffer.hpp b/libtorrent/include/libtorrent/buffer.hpp deleted file mode 100644 index 91ef58874..000000000 --- a/libtorrent/include/libtorrent/buffer.hpp +++ /dev/null @@ -1,447 +0,0 @@ -/* -Copyright (c) 2003 - 2005, Arvid Norberg, Daniel Wallin -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 Rasterbar Software 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 LIBTORRENT_BUFFER_HPP -#define LIBTORRENT_BUFFER_HPP - -//#define TORRENT_BUFFER_DEBUG - -#include "libtorrent/invariant_check.hpp" -#include - -namespace libtorrent { - -class buffer -{ -public: - struct interval - { - interval(char* begin, char* end) - : begin(begin) - , end(end) - {} - - char operator[](int index) const - { - assert(begin + index < end); - return begin[index]; - } - - int left() const { assert(end >= begin); return end - begin; } - - char* begin; - char* end; - }; - - struct const_interval - { - const_interval(char const* begin, char const* end) - : begin(begin) - , end(end) - {} - - char operator[](int index) const - { - assert(begin + index < end); - return begin[index]; - } - - int left() const { assert(end >= begin); return end - begin; } - - char const* begin; - char const* end; - }; - - typedef std::pair interval_type; - - buffer(std::size_t n = 0); - ~buffer(); - - interval allocate(std::size_t n); - void insert(char const* first, char const* last); - void erase(std::size_t n); - std::size_t size() const; - std::size_t capacity() const; - void reserve(std::size_t n); - interval_type data() const; - bool empty() const; - - std::size_t space_left() const; - - char const* raw_data() const - { - return m_first; - } - -#ifndef NDEBUG - void check_invariant() const; -#endif - -private: - char* m_first; - char* m_last; - char* m_write_cursor; - char* m_read_cursor; - char* m_read_end; - bool m_empty; -#ifdef TORRENT_BUFFER_DEBUG - mutable std::vector m_debug; - mutable int m_pending_copy; -#endif -}; - -inline buffer::buffer(std::size_t n) - : m_first((char*)::operator new(n)) - , m_last(m_first + n) - , m_write_cursor(m_first) - , m_read_cursor(m_first) - , m_read_end(m_last) - , m_empty(true) -{ -#ifdef TORRENT_BUFFER_DEBUG - m_pending_copy = 0; -#endif -} - -inline buffer::~buffer() -{ - ::operator delete (m_first); -} - -inline buffer::interval buffer::allocate(std::size_t n) -{ - assert(m_read_cursor <= m_read_end || m_empty); - - INVARIANT_CHECK; - -#ifdef TORRENT_BUFFER_DEBUG - if (m_pending_copy) - { - std::copy(m_write_cursor - m_pending_copy, m_write_cursor - , m_debug.end() - m_pending_copy); - m_pending_copy = 0; - } - m_debug.resize(m_debug.size() + n); - m_pending_copy = n; -#endif - if (m_read_cursor < m_write_cursor || m_empty) - { - // ..R***W.. - if (m_last - m_write_cursor >= (std::ptrdiff_t)n) - { - interval ret(m_write_cursor, m_write_cursor + n); - m_write_cursor += n; - m_read_end = m_write_cursor; - assert(m_read_cursor <= m_read_end); - if (n) m_empty = false; - return ret; - } - - if (m_read_cursor - m_first >= (std::ptrdiff_t)n) - { - m_read_end = m_write_cursor; - interval ret(m_first, m_first + n); - m_write_cursor = m_first + n; - assert(m_read_cursor <= m_read_end); - if (n) m_empty = false; - return ret; - } - - reserve(capacity() + n - (m_last - m_write_cursor)); - assert(m_last - m_write_cursor >= (std::ptrdiff_t)n); - interval ret(m_write_cursor, m_write_cursor + n); - m_write_cursor += n; - m_read_end = m_write_cursor; - if (n) m_empty = false; - assert(m_read_cursor <= m_read_end); - return ret; - - } - //**W...R** - if (m_read_cursor - m_write_cursor >= (std::ptrdiff_t)n) - { - interval ret(m_write_cursor, m_write_cursor + n); - m_write_cursor += n; - if (n) m_empty = false; - return ret; - } - reserve(capacity() + n - (m_read_cursor - m_write_cursor)); - assert(m_read_cursor - m_write_cursor >= (std::ptrdiff_t)n); - interval ret(m_write_cursor, m_write_cursor + n); - m_write_cursor += n; - if (n) m_empty = false; - return ret; -} - -inline void buffer::insert(char const* first, char const* last) -{ - INVARIANT_CHECK; - - std::size_t n = last - first; - -#ifdef TORRENT_BUFFER_DEBUG - if (m_pending_copy) - { - std::copy(m_write_cursor - m_pending_copy, m_write_cursor - , m_debug.end() - m_pending_copy); - m_pending_copy = 0; - } - m_debug.insert(m_debug.end(), first, last); -#endif - - if (space_left() < n) - { - reserve(capacity() + n); - } - - m_empty = false; - - char const* end = (m_last - m_write_cursor) < (std::ptrdiff_t)n ? - m_last : m_write_cursor + n; - - std::size_t copied = end - m_write_cursor; - std::memcpy(m_write_cursor, first, copied); - - m_write_cursor += copied; - if (m_write_cursor > m_read_end) m_read_end = m_write_cursor; - first += copied; - n -= copied; - - if (n == 0) return; - - assert(m_write_cursor == m_last); - m_write_cursor = m_first; - - memcpy(m_write_cursor, first, n); - m_write_cursor += n; -} - -inline void buffer::erase(std::size_t n) -{ - INVARIANT_CHECK; - - if (n == 0) return; - assert(!m_empty); - -#ifndef NDEBUG - int prev_size = size(); -#endif - assert(m_read_cursor <= m_read_end); - m_read_cursor += n; - if (m_read_cursor > m_read_end) - { - m_read_cursor = m_first + (m_read_cursor - m_read_end); - assert(m_read_cursor <= m_write_cursor); - } - - m_empty = m_read_cursor == m_write_cursor; - - assert(prev_size - n == size()); - -#ifdef TORRENT_BUFFER_DEBUG - m_debug.erase(m_debug.begin(), m_debug.begin() + n); -#endif -} - -inline std::size_t buffer::size() const -{ - // ...R***W. - if (m_read_cursor < m_write_cursor) - { - return m_write_cursor - m_read_cursor; - } - // ***W..R* - else - { - if (m_empty) return 0; - return (m_write_cursor - m_first) + (m_read_end - m_read_cursor); - } -} - -inline std::size_t buffer::capacity() const -{ - return m_last - m_first; -} - -inline void buffer::reserve(std::size_t size) -{ - std::size_t n = (std::size_t)(capacity() * 1.f); - if (n < size) n = size; - - char* buf = (char*)::operator new(n); - char* old = m_first; - - if (m_read_cursor < m_write_cursor) - { - // ...R***W.<>. - std::memcpy( - buf + (m_read_cursor - m_first) - , m_read_cursor - , m_write_cursor - m_read_cursor - ); - - m_write_cursor = buf + (m_write_cursor - m_first); - m_read_cursor = buf + (m_read_cursor - m_first); - m_read_end = m_write_cursor; - m_first = buf; - m_last = buf + n; - } - else - { - // **W..<>.R** - std::size_t skip = n - (m_last - m_first); - - std::memcpy(buf, m_first, m_write_cursor - m_first); - std::memcpy( - buf + (m_read_cursor - m_first) + skip - , m_read_cursor - , m_last - m_read_cursor - ); - - m_write_cursor = buf + (m_write_cursor - m_first); - - if (!m_empty) - { - m_read_cursor = buf + (m_read_cursor - m_first) + skip; - m_read_end = buf + (m_read_end - m_first) + skip; - } - else - { - m_read_cursor = m_write_cursor; - m_read_end = m_write_cursor; - } - - m_first = buf; - m_last = buf + n; - } - - ::operator delete (old); -} - -#ifndef NDEBUG -inline void buffer::check_invariant() const -{ - assert(m_read_end >= m_read_cursor); - assert(m_last >= m_read_cursor); - assert(m_last >= m_write_cursor); - assert(m_last >= m_first); - assert(m_first <= m_read_cursor); - assert(m_first <= m_write_cursor); -#ifdef TORRENT_BUFFER_DEBUG - int a = m_debug.size(); - int b = size(); - (void)a; - (void)b; - assert(m_debug.size() == size()); -#endif -} -#endif - -inline buffer::interval_type buffer::data() const -{ - INVARIANT_CHECK; - -#ifdef TORRENT_BUFFER_DEBUG - if (m_pending_copy) - { - std::copy(m_write_cursor - m_pending_copy, m_write_cursor - , m_debug.end() - m_pending_copy); - m_pending_copy = 0; - } -#endif - - // ...R***W. - if (m_read_cursor < m_write_cursor) - { -#ifdef TORRENT_BUFFER_DEBUG - assert(m_debug.size() == size()); - assert(std::equal(m_debug.begin(), m_debug.end(), m_read_cursor)); -#endif - return interval_type( - const_interval(m_read_cursor, m_write_cursor) - , const_interval(m_last, m_last) - ); - } - // **W...R** - else - { - if (m_read_cursor == m_read_end) - { -#ifdef TORRENT_BUFFER_DEBUG - assert(m_debug.size() == size()); - assert(std::equal(m_debug.begin(), m_debug.end(), m_first)); -#endif - - return interval_type( - const_interval(m_first, m_write_cursor) - , const_interval(m_last, m_last)); - } -#ifdef TORRENT_BUFFER_DEBUG - assert(m_debug.size() == size()); - assert(std::equal(m_debug.begin(), m_debug.begin() + (m_read_end - - m_read_cursor), m_read_cursor)); - assert(std::equal(m_debug.begin() + (m_read_end - m_read_cursor), m_debug.end() - , m_first)); -#endif - - assert(m_read_cursor <= m_read_end || m_empty); - return interval_type( - const_interval(m_read_cursor, m_read_end) - , const_interval(m_first, m_write_cursor) - ); - } -} - -inline bool buffer::empty() const -{ - return m_empty; -} - -inline std::size_t buffer::space_left() const -{ - if (m_empty) return m_last - m_first; - - // ...R***W. - if (m_read_cursor < m_write_cursor) - { - return (m_last - m_write_cursor) + (m_read_cursor - m_first); - } - // ***W..R* - else - { - return m_read_cursor - m_write_cursor; - } -} - -} - -#endif // LIBTORRENT_BUFFER_HPP - diff --git a/libtorrent/include/libtorrent/config.hpp b/libtorrent/include/libtorrent/config.hpp deleted file mode 100644 index c8d86955e..000000000 --- a/libtorrent/include/libtorrent/config.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - -Copyright (c) 2005, 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_CONFIG_HPP_INCLUDED -#define TORRENT_CONFIG_HPP_INCLUDED - -#include - -#if defined(__GNUC__) && __GNUC__ >= 4 - -# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED) -# define TORRENT_EXPORT __attribute__ ((visibility("default"))) -# else -# define TORRENT_EXPORT -# endif - -#elif defined(__GNUC__) - -# define TORRENT_EXPORT - -#elif defined(BOOST_MSVC) - -# if defined(TORRENT_BUILDING_SHARED) -# define TORRENT_EXPORT __declspec(dllexport) -# elif defined(TORRENT_LINKING_SHARED) -# define TORRENT_EXPORT __declspec(dllimport) -# else -# define TORRENT_EXPORT -# endif - -#else -# define TORRENT_EXPORT -#endif - - -#endif // TORRENT_CONFIG_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/connection_queue.hpp b/libtorrent/include/libtorrent/connection_queue.hpp deleted file mode 100644 index 05a8a61fe..000000000 --- a/libtorrent/include/libtorrent/connection_queue.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - -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_CONNECTION_QUEUE -#define TORRENT_CONNECTION_QUEUE - -#include -#include -#include -#include "libtorrent/socket.hpp" -#include "libtorrent/time.hpp" - -namespace libtorrent -{ - -class connection_queue : public boost::noncopyable -{ -public: - connection_queue(io_service& ios); - - bool free_slots() const; - - void enqueue(boost::function const& on_connect - , boost::function const& on_timeout - , time_duration timeout); - void done(int ticket); - void limit(int limit); - int limit() const; - -#ifndef NDEBUG - - void check_invariant() const; - -#endif - -private: - - void try_connect(); - void on_timeout(asio::error_code const& e); - - struct entry - { - entry(): connecting(false), ticket(0), expires(max_time()) {} - // called when the connection is initiated - boost::function on_connect; - // called if done hasn't been called within the timeout - boost::function on_timeout; - bool connecting; - int ticket; - ptime expires; - time_duration timeout; - }; - - std::list m_queue; - - // the next ticket id a connection will be given - int m_next_ticket; - int m_num_connecting; - int m_half_open_limit; - - deadline_timer m_timer; -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/debug.hpp b/libtorrent/include/libtorrent/debug.hpp deleted file mode 100644 index 39c4b0222..000000000 --- a/libtorrent/include/libtorrent/debug.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - -Copyright (c) 2003, 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_DEBUG_HPP_INCLUDED -#define TORRENT_DEBUG_HPP_INCLUDED - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - -namespace libtorrent -{ - // DEBUG API - - struct logger - { - logger(boost::filesystem::path const& filename, int instance, bool append = true) - { - using namespace boost::filesystem; - path dir(complete("libtorrent_logs" + boost::lexical_cast(instance))); - if (!exists(dir)) create_directories(dir); - m_file.open(dir / filename, std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out)); - *this << "\n\n\n*** starting log ***\n"; - } - - template - logger& operator<<(T const& v) - { - m_file << v; - m_file.flush(); - return *this; - } - - boost::filesystem::ofstream m_file; - }; - -} - -#endif // TORRENT_DEBUG_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/entry.hpp b/libtorrent/include/libtorrent/entry.hpp deleted file mode 100644 index 31a78b972..000000000 --- a/libtorrent/include/libtorrent/entry.hpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - -Copyright (c) 2003, 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_ENTRY_HPP_INCLUDED -#define TORRENT_ENTRY_HPP_INCLUDED - -/* - * - * This file declares the entry class. It is a - * variant-type that can be an integer, list, - * dictionary (map) or a string. This type is - * used to hold bdecoded data (which is the - * encoding BitTorrent messages uses). - * - * it has 4 accessors to access the actual - * type of the object. They are: - * integer() - * string() - * list() - * dict() - * The actual type has to match the type you - * are asking for, otherwise you will get an - * assertion failure. - * When you default construct an entry, it is - * uninitialized. You can initialize it through the - * assignment operator, copy-constructor or - * the constructor that takes a data_type enum. - * - * - */ - - -#include -#include -#include -#include -#include -#include - -#include "libtorrent/size_type.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT type_error: std::runtime_error - { - type_error(const char* error): std::runtime_error(error) {} - }; - - namespace detail - { - template - struct max2 { enum { value = v1>v2?v1:v2 }; }; - - template - struct max3 - { - enum - { - temp = max2::value, - value = temp>v3?temp:v3 - }; - }; - - template - struct max4 - { - enum - { - temp = max3::value, - value = temp>v4?temp:v4 - }; - }; - } - - class entry; - - class TORRENT_EXPORT entry - { - public: - - // the key is always a string. If a generic entry would be allowed - // as a key, sorting would become a problem (e.g. to compare a string - // to a list). The definition doesn't mention such a limit though. - typedef std::map dictionary_type; - typedef std::string string_type; - typedef std::list list_type; - typedef size_type integer_type; - - enum data_type - { - int_t, - string_t, - list_t, - dictionary_t, - undefined_t - }; - - data_type type() const; - - entry(dictionary_type const&); - entry(string_type const&); - entry(list_type const&); - entry(integer_type const&); - - entry(); - entry(data_type t); - entry(entry const& e); - ~entry(); - - bool operator==(entry const& e) const; - - void operator=(entry const&); - void operator=(dictionary_type const&); - void operator=(string_type const&); - void operator=(list_type const&); - void operator=(integer_type const&); - - integer_type& integer(); - const integer_type& integer() const; - string_type& string(); - const string_type& string() const; - list_type& list(); - const list_type& list() const; - dictionary_type& dict(); - const dictionary_type& dict() const; - - // these functions requires that the entry - // is a dictionary, otherwise they will throw - entry& operator[](char const* key); - entry& operator[](std::string const& key); - const entry& operator[](char const* key) const; - const entry& operator[](std::string const& key) const; - entry* find_key(char const* key); - entry const* find_key(char const* key) const; - - void print(std::ostream& os, int indent = 0) const; - - private: - - void construct(data_type t); - void copy(const entry& e); - void destruct(); - - data_type m_type; - -#if defined(_MSC_VER) && _MSC_VER < 1310 - // workaround for msvc-bug. - // assumes sizeof(map) == sizeof(map) - // and sizeof(list) == sizeof(list) - union - { - char data[ - detail::max4) - , sizeof(std::map) - , sizeof(string_type) - , sizeof(integer_type)>::value]; - integer_type dummy_aligner; - }; -#else - union - { - char data[detail::max4::value]; - integer_type dummy_aligner; - }; -#endif - - }; - - inline std::ostream& operator<<(std::ostream& os, const entry& e) - { - e.print(os, 0); - return os; - } - - inline entry::data_type entry::type() const { return m_type; } - - inline entry::entry(): m_type(undefined_t) {} - inline entry::entry(data_type t): m_type(t) { construct(t); } - inline entry::entry(const entry& e) { copy(e); } - inline entry::~entry() { destruct(); } - - inline void entry::operator=(const entry& e) - { - destruct(); - copy(e); - } - - inline entry::integer_type& entry::integer() - { - if (m_type == undefined_t) construct(int_t); - if (m_type != int_t) throw type_error("invalid type requested from entry"); - return *reinterpret_cast(data); - } - - inline entry::integer_type const& entry::integer() const - { - if (m_type != int_t) throw type_error("invalid type requested from entry"); - return *reinterpret_cast(data); - } - - inline entry::string_type& entry::string() - { - if (m_type == undefined_t) construct(string_t); - if (m_type != string_t) throw type_error("invalid type requested from entry"); - return *reinterpret_cast(data); - } - - inline entry::string_type const& entry::string() const - { - if (m_type != string_t) throw type_error("invalid type requested from entry"); - return *reinterpret_cast(data); - } - - inline entry::list_type& entry::list() - { - if (m_type == undefined_t) construct(list_t); - if (m_type != list_t) throw type_error("invalid type requested from entry"); - return *reinterpret_cast(data); - } - - inline entry::list_type const& entry::list() const - { - if (m_type != list_t) throw type_error("invalid type requested from entry"); - return *reinterpret_cast(data); - } - - inline entry::dictionary_type& entry::dict() - { - if (m_type == undefined_t) construct(dictionary_t); - if (m_type != dictionary_t) throw type_error("invalid type requested from entry"); - return *reinterpret_cast(data); - } - - inline entry::dictionary_type const& entry::dict() const - { - if (m_type != dictionary_t) throw type_error("invalid type requested from entry"); - return *reinterpret_cast(data); - } - -} - -#endif // TORRENT_ENTRY_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/escape_string.hpp b/libtorrent/include/libtorrent/escape_string.hpp deleted file mode 100644 index e0e743e1e..000000000 --- a/libtorrent/include/libtorrent/escape_string.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - -Copyright (c) 2003, 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_ESCAPE_STRING_HPP_INCLUDED -#define TORRENT_ESCAPE_STRING_HPP_INCLUDED - -#include -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - std::string TORRENT_EXPORT unescape_string(std::string const& s); - std::string TORRENT_EXPORT escape_string(const char* str, int len); - std::string TORRENT_EXPORT escape_path(const char* str, int len); -} - -#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/extensions.hpp b/libtorrent/include/libtorrent/extensions.hpp deleted file mode 100644 index 5f8172649..000000000 --- a/libtorrent/include/libtorrent/extensions.hpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - -Copyright (c) 2006, 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_EXTENSIONS_HPP_INCLUDED -#define TORRENT_EXTENSIONS_HPP_INCLUDED - -#ifndef TORRENT_DISABLE_EXTENSIONS - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include -#include "libtorrent/config.hpp" -#include "libtorrent/buffer.hpp" - -namespace libtorrent -{ - struct peer_plugin; - class bt_peer_connection; - struct peer_request; - class peer_connection; - class entry; - - struct TORRENT_EXPORT torrent_plugin - { - virtual ~torrent_plugin() {} - // throwing an exception closes the connection - // returning a 0 pointer is valid and will not add - // the peer_plugin to the peer_connection - virtual boost::shared_ptr new_connection(peer_connection*) - { return boost::shared_ptr(); } - - virtual void on_piece_pass(int index) {} - virtual void on_piece_failed(int index) {} - - // called aproximately once every second - virtual void tick() {} - - // if true is returned, it means the handler handled the event, - // and no other plugins will have their handlers called, and the - // default behavior will be skipped - virtual bool on_pause() { return false; } - virtual bool on_resume() { return false;} - - // this is called when the initial checking of - // files is completed. - virtual void on_files_checked() {} - }; - - struct TORRENT_EXPORT peer_plugin - { - virtual ~peer_plugin() {} - - // can add entries to the extension handshake - // this is not called for web seeds - virtual void add_handshake(entry&) {} - - // throwing an exception from any of the handlers (except add_handshake) - // closes the connection - - // this is called when the initial BT handshake is received. Returning false - // means that the other end doesn't support this extension and will remove - // it from the list of plugins. - // this is not called for web seeds - virtual bool on_handshake() { return true; } - - // called when the extension handshake from the other end is received - // if this returns false, it means that this extension isn't - // supported by this peer. It will result in this peer_plugin - // being removed from the peer_connection and destructed. - // this is not called for web seeds - virtual bool on_extension_handshake(entry const& h) { return true; } - - // returning true from any of the message handlers - // indicates that the plugin has handeled the message. - // it will break the plugin chain traversing and not let - // anyone else handle the message, including the default - // handler. - - virtual bool on_choke() - { return false; } - - virtual bool on_unchoke() - { return false; } - - virtual bool on_interested() - { return false; } - - virtual bool on_not_interested() - { return false; } - - virtual bool on_have(int index) - { return false; } - - virtual bool on_bitfield(std::vector const& bitfield) - { return false; } - - virtual bool on_request(peer_request const& req) - { return false; } - - virtual bool on_piece(peer_request const& piece, char const* data) - { return false; } - - virtual bool on_cancel(peer_request const& req) - { return false; } - - // called when an extended message is received. If returning true, - // the message is not processed by any other plugin and if false - // is returned the next plugin in the chain will receive it to - // be able to handle it - // this is not called for web seeds - virtual bool on_extended(int length - , int msg, buffer::const_interval body) - { return false; } - - // this is not called for web seeds - virtual bool on_unknown_message(int length, int msg - , buffer::const_interval body) - { return false; } - - // called when a piece that this peer participated in either - // fails or passes the hash_check - virtual void on_piece_pass(int index) {} - virtual void on_piece_failed(int index) {} - - // called aproximately once every second - virtual void tick() {} - - // called each time a request message is to be sent. If true - // is returned, the original request message won't be sent and - // no other plugin will have this function called. - virtual bool write_request(peer_request const& r) { return false; } - }; - -} - -#endif - -#endif // TORRENT_EXTENSIONS_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/extensions/logger.hpp b/libtorrent/include/libtorrent/extensions/logger.hpp deleted file mode 100644 index 42e08fcf6..000000000 --- a/libtorrent/include/libtorrent/extensions/logger.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Copyright (c) 2006, 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_LOGGER_HPP_INCLUDED -#define TORRENT_LOGGER_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - boost::shared_ptr create_logger_plugin(torrent*); -} - -#endif // TORRENT_LOGGER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp b/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp deleted file mode 100644 index 210642161..000000000 --- a/libtorrent/include/libtorrent/extensions/metadata_transfer.hpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - -Copyright (c) 2006, 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_METADATA_TRANSFER_HPP_INCLUDED -#define TORRENT_METADATA_TRANSFER_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include "libtorrent/config.hpp" - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - TORRENT_EXPORT boost::shared_ptr create_metadata_plugin(torrent*); -} - -#endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/extensions/ut_pex.hpp b/libtorrent/include/libtorrent/extensions/ut_pex.hpp deleted file mode 100644 index efd9ab4f6..000000000 --- a/libtorrent/include/libtorrent/extensions/ut_pex.hpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - -Copyright (c) 2006, MassaRoddel -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_UT_PEX_EXTENSION_HPP_INCLUDED -#define TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include "libtorrent/config.hpp" - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - TORRENT_EXPORT boost::shared_ptr create_ut_pex_plugin(torrent*); -} - -#endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/file.hpp b/libtorrent/include/libtorrent/file.hpp deleted file mode 100644 index d11496b28..000000000 --- a/libtorrent/include/libtorrent/file.hpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - -Copyright (c) 2003, 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_FILE_HPP_INCLUDED -#define TORRENT_FILE_HPP_INCLUDED - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/size_type.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT file_error: std::runtime_error - { - file_error(std::string const& msg): std::runtime_error(msg) {} - }; - - class TORRENT_EXPORT file: public boost::noncopyable - { - public: - - class seek_mode - { - friend class file; - private: - seek_mode(int v): m_val(v) {} - int m_val; - }; - - static const seek_mode begin; - static const seek_mode end; - - class open_mode - { - friend class file; - public: - - open_mode(): m_mask(0) {} - - open_mode operator|(open_mode m) const - { return open_mode(m.m_mask | m_mask); } - - open_mode operator&(open_mode m) const - { return open_mode(m.m_mask & m_mask); } - - open_mode operator|=(open_mode m) - { - m_mask |= m.m_mask; - return *this; - } - - bool operator==(open_mode m) const { return m_mask == m.m_mask; } - bool operator!=(open_mode m) const { return m_mask != m.m_mask; } - - private: - - open_mode(int val): m_mask(val) {} - int m_mask; - }; - - static const open_mode in; - static const open_mode out; - - file(); - file(boost::filesystem::path const& p, open_mode m); - ~file(); - - void open(boost::filesystem::path const& p, open_mode m); - void close(); - void set_size(size_type size); - - size_type write(const char*, size_type num_bytes); - size_type read(char*, size_type num_bytes); - - size_type seek(size_type pos, seek_mode m = begin); - size_type tell(); - - private: - - struct impl; - const std::auto_ptr m_impl; - - }; - -} - -#endif // TORRENT_FILE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/file_pool.hpp b/libtorrent/include/libtorrent/file_pool.hpp deleted file mode 100644 index a22c26538..000000000 --- a/libtorrent/include/libtorrent/file_pool.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - -Copyright (c) 2006, 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_FILE_POOL_HPP -#define TORRENT_FILE_POOL_HPP - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/file.hpp" -#include "libtorrent/time.hpp" - -namespace libtorrent -{ - - using boost::multi_index::multi_index_container; - using boost::multi_index::ordered_non_unique; - using boost::multi_index::ordered_unique; - using boost::multi_index::indexed_by; - using boost::multi_index::member; - namespace fs = boost::filesystem; - - struct TORRENT_EXPORT file_pool : boost::noncopyable - { - file_pool(int size = 40): m_size(size) {} - - boost::shared_ptr open_file(void* st, fs::path const& p, file::open_mode m); - void release(void* st); - void resize(int size); - - private: - int m_size; - - struct lru_file_entry - { - lru_file_entry(boost::shared_ptr const& f) - : file_ptr(f) - , last_use(time_now()) {} - mutable boost::shared_ptr file_ptr; - fs::path file_path; - void* key; - ptime last_use; - file::open_mode mode; - }; - - typedef multi_index_container< - lru_file_entry, indexed_by< - ordered_unique > - , ordered_non_unique > - , ordered_non_unique > - > - > file_set; - - file_set m_files; - boost::mutex m_mutex; - }; -} - -#endif diff --git a/libtorrent/include/libtorrent/fingerprint.hpp b/libtorrent/include/libtorrent/fingerprint.hpp deleted file mode 100644 index d7e5a5fc6..000000000 --- a/libtorrent/include/libtorrent/fingerprint.hpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - -Copyright (c) 2003, 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_FINGERPRINT_HPP_INCLUDED -#define TORRENT_FINGERPRINT_HPP_INCLUDED - -#include -#include - -#include "libtorrent/peer_id.hpp" - -namespace libtorrent -{ - - struct fingerprint - { - fingerprint(const char* id_string, int major, int minor, int revision, int tag) - : major_version(major) - , minor_version(minor) - , revision_version(revision) - , tag_version(tag) - { - assert(id_string); - assert(major >= 0); - assert(minor >= 0); - assert(revision >= 0); - assert(tag >= 0); - assert(std::strlen(id_string) == 2); - name[0] = id_string[0]; - name[1] = id_string[1]; - } - - std::string to_string() const - { - std::stringstream s; - s << "-" << name[0] << name[1] - << version_to_char(major_version) - << version_to_char(minor_version) - << version_to_char(revision_version) - << version_to_char(tag_version) << "-"; - return s.str(); - } - - char name[2]; - int major_version; - int minor_version; - int revision_version; - int tag_version; - - private: - - char version_to_char(int v) const - { - if (v >= 0 && v < 10) return '0' + v; - else if (v >= 10) return 'A' + (v - 10); - assert(false); - return '0'; - } - - }; - -} - -#endif // TORRENT_FINGERPRINT_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/hasher.hpp b/libtorrent/include/libtorrent/hasher.hpp deleted file mode 100644 index d1743527a..000000000 --- a/libtorrent/include/libtorrent/hasher.hpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - -Copyright (c) 2003, 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_HASHER_HPP_INCLUDED -#define TORRENT_HASHER_HPP_INCLUDED - -#include -#include - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/config.hpp" -#include "zlib.h" - -#ifdef TORRENT_USE_OPENSSL -extern "C" -{ -#include -} -#else -// from sha1.cpp -struct TORRENT_EXPORT SHA_CTX -{ - boost::uint32_t state[5]; - boost::uint32_t count[2]; - boost::uint8_t buffer[64]; -}; - -TORRENT_EXPORT void SHA1_Init(SHA_CTX* context); -TORRENT_EXPORT void SHA1_Update(SHA_CTX* context, boost::uint8_t const* data, boost::uint32_t len); -TORRENT_EXPORT void SHA1_Final(boost::uint8_t* digest, SHA_CTX* context); - -#endif - -namespace libtorrent -{ - - class adler32_crc - { - public: - adler32_crc(): m_adler(adler32(0, 0, 0)) {} - - void update(const char* data, int len) - { - assert(data != 0); - assert(len > 0); - m_adler = adler32(m_adler, (const Bytef*)data, len); - } - unsigned long final() const { return m_adler; } - void reset() { m_adler = adler32(0, 0, 0); } - - private: - - unsigned long m_adler; - - }; - - class hasher - { - public: - - hasher() { SHA1_Init(&m_context); } - hasher(const char* data, int len) - { - SHA1_Init(&m_context); - assert(data != 0); - assert(len > 0); - SHA1_Update(&m_context, reinterpret_cast(data), len); - } - void update(const char* data, int len) - { - assert(data != 0); - assert(len > 0); - SHA1_Update(&m_context, reinterpret_cast(data), len); - } - - sha1_hash final() - { - sha1_hash digest; - SHA1_Final(digest.begin(), &m_context); - return digest; - } - - void reset() { SHA1_Init(&m_context); } - - private: - - SHA_CTX m_context; - - }; -} - -#endif // TORRENT_HASHER_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/http_connection.hpp b/libtorrent/include/libtorrent/http_connection.hpp deleted file mode 100644 index 409213857..000000000 --- a/libtorrent/include/libtorrent/http_connection.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - -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_HTTP_CONNECTION -#define TORRENT_HTTP_CONNECTION - -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/socket.hpp" -#include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/time.hpp" - -namespace libtorrent -{ - -typedef boost::function http_handler; - -// TODO: add bind interface - -// when bottled, the last two arguments to the handler -// will always be 0 -struct http_connection : boost::enable_shared_from_this, boost::noncopyable -{ - http_connection(asio::io_service& ios, connection_queue& cc - , http_handler handler, bool bottled = true) - : m_sock(ios) - , m_read_pos(0) - , m_resolver(ios) - , m_handler(handler) - , m_timer(ios) - , m_last_receive(time_now()) - , m_bottled(bottled) - , m_called(false) - , m_rate_limit(0) - , m_download_quota(0) - , m_limiter_timer_active(false) - , m_limiter_timer(ios) - , m_redirect(true) - , m_connection_ticket(-1) - , m_cc(cc) - { - assert(!m_handler.empty()); - } - - void rate_limit(int limit); - - int rate_limit() const - { return m_rate_limit; } - - std::string sendbuffer; - - void get(std::string const& url, time_duration timeout = seconds(30) - , bool handle_redirect = true); - - void start(std::string const& hostname, std::string const& port - , time_duration timeout, bool handle_redirect = true); - void close(); - -private: - - void on_resolve(asio::error_code const& e - , tcp::resolver::iterator i); - void connect(int ticket, tcp::endpoint target_address); - void on_connect_timeout(); - void on_connect(asio::error_code const& e -/* , tcp::resolver::iterator i*/); - void on_write(asio::error_code const& e); - void on_read(asio::error_code const& e, std::size_t bytes_transferred); - static void on_timeout(boost::weak_ptr p - , asio::error_code const& e); - void on_assign_bandwidth(asio::error_code const& e); - - std::vector m_recvbuffer; - tcp::socket m_sock; - int m_read_pos; - tcp::resolver m_resolver; - http_parser m_parser; - http_handler m_handler; - deadline_timer m_timer; - time_duration m_timeout; - ptime m_last_receive; - // bottled means that the handler is called once, when - // everything is received (and buffered in memory). - // non bottled means that once the headers have been - // received, data is streamed to the handler - bool m_bottled; - // set to true the first time the handler is called - bool m_called; - std::string m_hostname; - std::string m_port; - - // the current download limit, in bytes per second - // 0 is unlimited. - int m_rate_limit; - - // the number of bytes we are allowed to receive - int m_download_quota; - - // only hand out new quota 4 times a second if the - // quota is 0. If it isn't 0 wait for it to reach - // 0 and continue to hand out quota at that time. - bool m_limiter_timer_active; - - // the timer fires every 250 millisecond as long - // as all the quota was used. - deadline_timer m_limiter_timer; - - // if set to true, the connection should handle - // HTTP redirects. - bool m_redirect; - - int m_connection_ticket; - connection_queue& m_cc; -}; - -} - -#endif diff --git a/libtorrent/include/libtorrent/http_stream.hpp b/libtorrent/include/libtorrent/http_stream.hpp deleted file mode 100644 index 2bd124b43..000000000 --- a/libtorrent/include/libtorrent/http_stream.hpp +++ /dev/null @@ -1,193 +0,0 @@ -#include "libtorrent/io.hpp" -#include "libtorrent/socket.hpp" -#include -#include -#include -#include -#include - - -namespace libtorrent { - -class http_stream : boost::noncopyable -{ -public: - - typedef stream_socket::lowest_layer_type lowest_layer_type; - typedef stream_socket::endpoint_type endpoint_type; - typedef stream_socket::protocol_type protocol_type; - - explicit http_stream(asio::io_service& io_service) - : m_sock(io_service) - , m_resolver(io_service) - , m_no_connect(false) - {} - - void set_no_connect(bool c) { m_no_connect = c; } - - void set_proxy(std::string hostname, int port) - { - m_hostname = hostname; - m_port = port; - } - - void set_username(std::string const& user - , std::string const& password) - { - m_user = user; - m_password = password; - } - - template - void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) - { - m_sock.async_read_some(buffers, handler); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec) - { - return m_sock.read_some(buffers, ec); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers) - { - return m_sock.read_some(buffers); - } - - template - void io_control(IO_Control_Command& ioc) - { - m_sock.io_control(ioc); - } - - template - void io_control(IO_Control_Command& ioc, asio::error_code& ec) - { - m_sock.io_control(ioc, ec); - } - - template - void async_write_some(Const_Buffers const& buffers, Handler const& handler) - { - m_sock.async_write_some(buffers, handler); - } - - void bind(endpoint_type const& endpoint) - { - m_sock.bind(endpoint); - } - - template - void bind(endpoint_type const& endpoint, Error_Handler const& error_handler) - { - m_sock.bind(endpoint, error_handler); - } - - void open(protocol_type const& p) - { - m_sock.open(p); - } - - template - void open(protocol_type const& p, Error_Handler const& error_handler) - { - m_sock.open(p, error_handler); - } - - void close() - { - m_remote_endpoint = endpoint_type(); - m_sock.close(); - } - - template - void close(Error_Handler const& error_handler) - { - m_sock.close(error_handler); - } - - endpoint_type remote_endpoint() - { - return m_remote_endpoint; - } - - template - endpoint_type remote_endpoint(Error_Handler const& error_handler) - { - return m_remote_endpoint; - } - - endpoint_type local_endpoint() - { - return m_sock.local_endpoint(); - } - - template - endpoint_type local_endpoint(Error_Handler const& error_handler) - { - return m_sock.local_endpoint(error_handler); - } - - asio::io_service& io_service() - { - return m_sock.io_service(); - } - - lowest_layer_type& lowest_layer() - { - return m_sock.lowest_layer(); - } - - typedef boost::function handler_type; - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - m_remote_endpoint = endpoint; - - // the connect is split up in the following steps: - // 1. resolve name of proxy server - // 2. connect to proxy server - // 3. send HTTP CONNECT method and possibly username+password - // 4. read CONNECT response - - // to avoid unnecessary copying of the handler, - // store it in a shaed_ptr - boost::shared_ptr h(new handler_type(handler)); - - tcp::resolver::query q(m_hostname - , boost::lexical_cast(m_port)); - m_resolver.async_resolve(q, boost::bind( - &http_stream::name_lookup, this, _1, _2, h)); - } - -private: - - void name_lookup(asio::error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h); - void connected(asio::error_code const& e, boost::shared_ptr h); - void handshake1(asio::error_code const& e, boost::shared_ptr h); - void handshake2(asio::error_code const& e, boost::shared_ptr h); - - stream_socket m_sock; - // the http proxy - std::string m_hostname; - int m_port; - // send and receive buffer - std::vector m_buffer; - // proxy authentication - std::string m_user; - std::string m_password; - - endpoint_type m_remote_endpoint; - - tcp::resolver m_resolver; - // this is true if the connection is HTTP based and - // want to talk directly to the proxy - bool m_no_connect; -}; - -} - diff --git a/libtorrent/include/libtorrent/http_tracker_connection.hpp b/libtorrent/include/libtorrent/http_tracker_connection.hpp deleted file mode 100644 index 35d529504..000000000 --- a/libtorrent/include/libtorrent/http_tracker_connection.hpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - -Copyright (c) 2003, 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_HTTP_TRACKER_CONNECTION_HPP_INCLUDED -#define TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/socket.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/peer.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/buffer.hpp" -#include "libtorrent/socket_type.hpp" -#include "libtorrent/connection_queue.hpp" - -namespace libtorrent -{ - - class http_parser - { - public: - http_parser(); - template - T header(char const* key) const; - std::string const& protocol() const { return m_protocol; } - int status_code() const { return m_status_code; } - std::string message() const { return m_server_message; } - buffer::const_interval get_body() const; - bool header_finished() const { return m_state == read_body; } - bool finished() const { return m_finished; } - boost::tuple incoming(buffer::const_interval recv_buffer); - int body_start() const { return m_body_start_pos; } - int content_length() const { return m_content_length; } - - void reset(); - private: - int m_recv_pos; - int m_status_code; - std::string m_protocol; - std::string m_server_message; - - int m_content_length; - - enum { read_status, read_header, read_body } m_state; - - std::map m_header; - buffer::const_interval m_recv_buffer; - int m_body_start_pos; - - bool m_finished; - }; - - template - T http_parser::header(char const* key) const - { - std::map::const_iterator i - = m_header.find(key); - if (i == m_header.end()) return T(); - return boost::lexical_cast(i->second); - } - - class TORRENT_EXPORT http_tracker_connection - : public tracker_connection - { - friend class tracker_manager; - public: - - http_tracker_connection( - asio::strand& str - , connection_queue& cc - , tracker_manager& man - , tracker_request const& req - , std::string const& hostname - , unsigned short port - , std::string request - , address bind_infc - , boost::weak_ptr c - , session_settings const& stn - , proxy_settings const& ps - , std::string const& password = ""); - - private: - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - void on_response(); - - void init_send_buffer( - std::string const& hostname - , std::string const& request); - - void name_lookup(asio::error_code const& error, tcp::resolver::iterator i); - void connect(int ticket, tcp::endpoint target_address); - void connected(asio::error_code const& error); - void sent(asio::error_code const& error); - void receive(asio::error_code const& error - , std::size_t bytes_transferred); - - virtual void on_timeout(); - - void parse(const entry& e); - peer_entry extract_peer_info(const entry& e); - - tracker_manager& m_man; - http_parser m_parser; - - asio::strand& m_strand; - tcp::resolver m_name_lookup; - int m_port; - boost::shared_ptr m_socket; - int m_recv_pos; - std::vector m_buffer; - std::string m_send_buffer; - - session_settings const& m_settings; - proxy_settings const& m_proxy; - std::string m_password; - - bool m_timed_out; - - int m_connection_ticket; - connection_queue& m_cc; - }; - -} - -#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/identify_client.hpp b/libtorrent/include/libtorrent/identify_client.hpp deleted file mode 100644 index e8cb3b930..000000000 --- a/libtorrent/include/libtorrent/identify_client.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - -Copyright (c) 2003, 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_IDENTIFY_CLIENT_HPP_INCLUDED -#define TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - TORRENT_EXPORT std::string identify_client(const peer_id& p); - TORRENT_EXPORT boost::optional client_fingerprint(peer_id const& p); - -} - -#endif // TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/instantiate_connection.hpp b/libtorrent/include/libtorrent/instantiate_connection.hpp deleted file mode 100644 index 49cb1fe18..000000000 --- a/libtorrent/include/libtorrent/instantiate_connection.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - -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_INSTANTIATE_CONNECTION -#define TORRENT_INSTANTIATE_CONNECTION - -#include "libtorrent/socket_type.hpp" -#include -#include - -namespace libtorrent -{ - struct proxy_settings; - - boost::shared_ptr instantiate_connection( - asio::io_service& ios, proxy_settings const& ps); -} - -#endif - diff --git a/libtorrent/include/libtorrent/invariant_check.hpp b/libtorrent/include/libtorrent/invariant_check.hpp deleted file mode 100644 index c6eacf338..000000000 --- a/libtorrent/include/libtorrent/invariant_check.hpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright Daniel Wallin 2004. Use, modification and distribution is -// subject to 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 TORRENT_INVARIANT_ACCESS_HPP_INCLUDED -#define TORRENT_INVARIANT_ACCESS_HPP_INCLUDED - -#include - -namespace libtorrent -{ - - class invariant_access - { - public: - template - static void check_invariant(T const& self) - { - self.check_invariant(); - } - }; - - template - void check_invariant(T const& x) - { - invariant_access::check_invariant(x); - } - - struct invariant_checker {}; - - template - struct invariant_checker_impl : invariant_checker - { - invariant_checker_impl(T const& self_) - : self(self_) - { - try - { - check_invariant(self); - } - catch (...) - { - assert(false); - } - } - - ~invariant_checker_impl() - { - try - { - check_invariant(self); - } - catch (...) - { - assert(false); - } - } - - T const& self; - }; - - template - invariant_checker_impl make_invariant_checker(T const& x) - { - return invariant_checker_impl(x); - } -} - -#ifndef NDEBUG -#define INVARIANT_CHECK \ - invariant_checker const& _invariant_check = make_invariant_checker(*this); \ - (void)_invariant_check; \ - do {} while (false) -#else -#define INVARIANT_CHECK do {} while (false) -#endif - -#endif // TORRENT_INVARIANT_ACCESS_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/io.hpp b/libtorrent/include/libtorrent/io.hpp deleted file mode 100644 index f73c3e290..000000000 --- a/libtorrent/include/libtorrent/io.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - -Copyright (c) 2003, 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_IO_HPP_INCLUDED -#define TORRENT_IO_HPP_INCLUDED - -#include -#include - -namespace libtorrent -{ - namespace detail - { - template struct type {}; - - // reads an integer from a byte stream - // in big endian byte order and converts - // it to native endianess - template - inline T read_impl(InIt& start, type) - { - T ret = 0; - for (int i = 0; i < (int)sizeof(T); ++i) - { - ret <<= 8; - ret |= static_cast(*start); - ++start; - } - return ret; - } - - template - inline void write_impl(T val, OutIt& start) - { - for (int i = (int)sizeof(T)-1; i >= 0; --i) - { - *start = static_cast((val >> (i * 8)) & 0xff); - ++start; - } - } - - // -- adaptors - - template - boost::int64_t read_int64(InIt& start) - { return read_impl(start, type()); } - - template - boost::uint64_t read_uint64(InIt& start) - { return read_impl(start, type()); } - - template - boost::uint32_t read_uint32(InIt& start) - { return read_impl(start, type()); } - - template - boost::int32_t read_int32(InIt& start) - { return read_impl(start, type()); } - - template - boost::int16_t read_int16(InIt& start) - { return read_impl(start, type()); } - - template - boost::uint16_t read_uint16(InIt& start) - { return read_impl(start, type()); } - - template - boost::int8_t read_int8(InIt& start) - { return read_impl(start, type()); } - - template - boost::uint8_t read_uint8(InIt& start) - { return read_impl(start, type()); } - - - template - void write_uint64(boost::uint64_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_int64(boost::int64_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_uint32(boost::uint32_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_int32(boost::int32_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_uint16(boost::uint16_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_int16(boost::int16_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_uint8(boost::uint8_t val, OutIt& start) - { write_impl(val, start); } - - template - void write_int8(boost::int8_t val, OutIt& start) - { write_impl(val, start); } - - inline void write_string(std::string const& str, char*& start) - { - std::copy(str.begin(), str.end(), start); - start += str.size(); - } - - template - void write_string(std::string const& str, OutIt& start) - { - std::copy(str.begin(), str.end(), start); - } - - } -} - -#endif // TORRENT_IO_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/ip_filter.hpp b/libtorrent/include/libtorrent/ip_filter.hpp deleted file mode 100644 index 1c62c553b..000000000 --- a/libtorrent/include/libtorrent/ip_filter.hpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - -Copyright (c) 2005, 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_IP_FILTER_HPP -#define TORRENT_IP_FILTER_HPP - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - -#include "libtorrent/config.hpp" -#include "libtorrent/socket.hpp" -#include -#include - -namespace libtorrent -{ - -inline bool operator<=(address const& lhs - , address const& rhs) -{ - return lhs < rhs || lhs == rhs; -} - -template -struct ip_range -{ - Addr first; - Addr last; - int flags; -}; - -namespace detail -{ - - // this is the generic implementation of - // a filter for a specific address type. - // it works with IPv4 and IPv6 - template - class TORRENT_EXPORT filter_impl - { - public: - - filter_impl() - { - typename Addr::bytes_type zero; - std::fill(zero.begin(), zero.end(), 0); - // make the entire ip-range non-blocked - m_access_list.insert(range(Addr(zero), 0)); - } - - void add_rule(Addr first, Addr last, int flags) - { - using boost::next; - using boost::prior; - - assert(!m_access_list.empty()); - assert(first < last || first == last); - - typename range_t::iterator i = m_access_list.upper_bound(first); - typename range_t::iterator j = m_access_list.upper_bound(last); - - if (i != m_access_list.begin()) --i; - - assert(j != m_access_list.begin()); - assert(j != i); - - int first_access = i->access; - int last_access = prior(j)->access; - - if (i->start != first && first_access != flags) - { - i = m_access_list.insert(i, range(first, flags)); - } - else if (i != m_access_list.begin() && prior(i)->access == flags) - { - --i; - first_access = i->access; - } - assert(!m_access_list.empty()); - assert(i != m_access_list.end()); - - if (i != j) m_access_list.erase(next(i), j); - if (i->start == first) - { - // we can do this const-cast because we know that the new - // start address will keep the set correctly ordered - const_cast(i->start) = first; - const_cast(i->access) = flags; - } - else if (first_access != flags) - { - m_access_list.insert(i, range(first, flags)); - } - - if ((j != m_access_list.end() - && minus_one(j->start) != last) - || (j == m_access_list.end() - && last != max_addr())) - { - assert(j == m_access_list.end() || last < minus_one(j->start)); - if (last_access != flags) - j = m_access_list.insert(j, range(plus_one(last), last_access)); - } - - if (j != m_access_list.end() && j->access == flags) m_access_list.erase(j); - assert(!m_access_list.empty()); - } - - int access(Addr const& addr) const - { - assert(!m_access_list.empty()); - typename range_t::const_iterator i = m_access_list.upper_bound(addr); - if (i != m_access_list.begin()) --i; - assert(i != m_access_list.end()); - assert(i->start <= addr && (boost::next(i) == m_access_list.end() - || addr < boost::next(i)->start)); - return i->access; - } - - std::vector > export_filter() const - { - std::vector > ret; - ret.reserve(m_access_list.size()); - - for (typename range_t::const_iterator i = m_access_list.begin() - , end(m_access_list.end()); i != end;) - { - ip_range r; - r.first = i->start; - r.flags = i->access; - - ++i; - if (i == end) - r.last = max_addr(); - else - r.last = minus_one(i->start); - - ret.push_back(r); - } - return ret; - } - - private: - - Addr plus_one(Addr const& a) const - { - typename Addr::bytes_type tmp(a.to_bytes()); - typedef typename Addr::bytes_type::reverse_iterator iter; - for (iter i = tmp.rbegin() - , end(tmp.rend()); i != end; ++i) - { - if (*i < (std::numeric_limits::max)()) - { - *i += 1; - break; - } - *i = 0; - } - return Addr(tmp); - } - - Addr minus_one(Addr const& a) const - { - typename Addr::bytes_type tmp(a.to_bytes()); - typedef typename Addr::bytes_type::reverse_iterator iter; - for (iter i = tmp.rbegin() - , end(tmp.rend()); i != end; ++i) - { - if (*i > 0) - { - *i -= 1; - break; - } - *i = (std::numeric_limits::max)(); - } - return Addr(tmp); - } - - Addr max_addr() const - { - typename Addr::bytes_type tmp; - std::fill(tmp.begin(), tmp.end() - , (std::numeric_limits::max)()); - return Addr(tmp); - } - - struct range - { - range(Addr addr, int access = 0): start(addr), access(access) {} - bool operator<(range const& r) const - { return start < r.start; } - bool operator<(Addr const& a) const - { return start < a; } - Addr start; - // the end of the range is implicit - // and given by the next entry in the set - int access; - }; - - typedef std::set range_t; - range_t m_access_list; - - }; - -} - -class TORRENT_EXPORT ip_filter -{ -public: - - enum access_flags - { - blocked = 1 - }; - - // both addresses MUST be of the same type (i.e. both must - // be either IPv4 or both must be IPv6) - void add_rule(address first, address last, int flags); - int access(address const& addr) const; - - typedef boost::tuple > - , std::vector > > filter_tuple_t; - - filter_tuple_t export_filter() const; - -// void print() const; - -private: - - detail::filter_impl m_filter4; - detail::filter_impl m_filter6; -}; - -} - -#endif - diff --git a/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp b/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp deleted file mode 100644 index 244e4bb38..000000000 --- a/libtorrent/include/libtorrent/kademlia/closest_nodes.hpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -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 CLOSEST_NODES_050323_HPP -#define CLOSEST_NODES_050323_HPP - -#include - -#include -#include -#include -#include -#include - -#include - -namespace libtorrent { namespace dht -{ - -class rpc_manager; - -// -------- closest nodes ----------- - -class closest_nodes : public traversal_algorithm -{ -public: - typedef boost::function< - void(std::vector const&) - > done_callback; - - static void initiate( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback - ); - -private: - void done(); - void invoke(node_id const& id, asio::ip::udp::endpoint addr); - - closest_nodes( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback - ); - - done_callback m_done_callback; -}; - -class closest_nodes_observer : public observer -{ -public: - closest_nodes_observer( - boost::intrusive_ptr const& algorithm - , node_id self - , node_id target) - : observer(algorithm->allocator()) - , m_algorithm(algorithm) - , m_target(target) - , m_self(self) - {} - ~closest_nodes_observer(); - - void send(msg& p) - { - p.info_hash = m_target; - } - - void timeout(); - void reply(msg const&); - void abort() { m_algorithm = 0; } - -private: - boost::intrusive_ptr m_algorithm; - node_id const m_target; - node_id const m_self; -}; - -} } // namespace libtorrent::dht - -#endif // CLOSEST_NODES_050323_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp b/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp deleted file mode 100644 index f61364707..000000000 --- a/libtorrent/include/libtorrent/kademlia/dht_tracker.hpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - -Copyright (c) 2006, 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_DISABLE_DHT - -#ifndef TORRENT_DHT_TRACKER -#define TORRENT_DHT_TRACKER - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/kademlia/node.hpp" -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/kademlia/traversal_algorithm.hpp" -#include "libtorrent/kademlia/packet_iterator.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/session_status.hpp" - -namespace libtorrent { namespace dht -{ - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_DECLARE_LOG(dht_tracker); -#endif - - struct dht_tracker; - - TORRENT_EXPORT void intrusive_ptr_add_ref(dht_tracker const*); - TORRENT_EXPORT void intrusive_ptr_release(dht_tracker const*); - - struct dht_tracker - { - friend void intrusive_ptr_add_ref(dht_tracker const*); - friend void intrusive_ptr_release(dht_tracker const*); - dht_tracker(asio::io_service& ios, dht_settings const& settings - , asio::ip::address listen_interface, entry const& bootstrap); - void stop(); - - void add_node(udp::endpoint node); - void add_node(std::pair const& node); - void add_router_node(std::pair const& node); - - void rebind(asio::ip::address listen_interface, int listen_port); - - entry state() const; - - void announce(sha1_hash const& ih, int listen_port - , boost::function const& - , sha1_hash const&)> f); - - void dht_status(session_status& s); - - private: - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - void on_name_lookup(asio::error_code const& e - , udp::resolver::iterator host); - void on_router_name_lookup(asio::error_code const& e - , udp::resolver::iterator host); - void connection_timeout(asio::error_code const& e); - void refresh_timeout(asio::error_code const& e); - void tick(asio::error_code const& e); - - // translate bittorrent kademlia message into the generic kademlia message - // used by the library - void on_receive(asio::error_code const& error, size_t bytes_transferred); - void on_bootstrap(); - void send_packet(msg const& m); - - asio::strand m_strand; - asio::ip::udp::socket m_socket; - - node_impl m_dht; - - // this is the index of the receive buffer we are currently receiving to - // the other buffer is the one containing the last message - int m_buffer; - std::vector m_in_buf[2]; - udp::endpoint m_remote_endpoint[2]; - std::vector m_send_buf; - - ptime m_last_new_key; - deadline_timer m_timer; - deadline_timer m_connection_timer; - deadline_timer m_refresh_timer; - dht_settings const& m_settings; - int m_refresh_bucket; - - // used to resolve hostnames for nodes - udp::resolver m_host_resolver; - - // reference counter for intrusive_ptr - mutable boost::detail::atomic_count m_refs; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - int m_replies_sent[5]; - int m_queries_received[5]; - int m_replies_bytes_sent[5]; - int m_queries_bytes_received[5]; - int m_counter; - int m_announces; - int m_failed_announces; - - int m_total_message_input; - int m_ut_message_input; - int m_lt_message_input; - int m_mp_message_input; - int m_gr_message_input; - int m_mo_message_input; - - int m_total_in_bytes; - int m_total_out_bytes; - - int m_queries_out_bytes; -#endif - }; -}} - -#endif -#endif diff --git a/libtorrent/include/libtorrent/kademlia/find_data.hpp b/libtorrent/include/libtorrent/kademlia/find_data.hpp deleted file mode 100644 index 17d77c9d8..000000000 --- a/libtorrent/include/libtorrent/kademlia/find_data.hpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -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 FIND_DATA_050323_HPP -#define FIND_DATA_050323_HPP - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace libtorrent { namespace dht -{ - -using asio::ip::udp; - -typedef std::vector packet_t; - -class rpc_manager; - -// -------- find data ----------- - -class find_data : public traversal_algorithm -{ -public: - typedef boost::function done_callback; - - static void initiate( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback - ); - - void got_data(msg const* m); - -private: - void done(); - void invoke(node_id const& id, udp::endpoint addr); - - find_data( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback - ); - - done_callback m_done_callback; - boost::shared_ptr m_packet; - bool m_done; -}; - -class find_data_observer : public observer -{ -public: - find_data_observer( - boost::intrusive_ptr const& algorithm - , node_id self - , node_id target) - : observer(algorithm->allocator()) - , m_algorithm(algorithm) - , m_target(target) - , m_self(self) - {} - ~find_data_observer(); - - void send(msg& m) - { - m.reply = false; - m.message_id = messages::get_peers; - m.info_hash = m_target; - } - - void timeout(); - void reply(msg const&); - void abort() { m_algorithm = 0; } - -private: - boost::intrusive_ptr m_algorithm; - node_id const m_target; - node_id const m_self; -}; - -} } // namespace libtorrent::dht - -#endif // FIND_DATA_050323_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/logging.hpp b/libtorrent/include/libtorrent/kademlia/logging.hpp deleted file mode 100644 index c0cbb31a4..000000000 --- a/libtorrent/include/libtorrent/kademlia/logging.hpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -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_LOGGING_HPP -#define TORRENT_LOGGING_HPP - -#include -#include - -namespace libtorrent { namespace dht -{ - -class log -{ -public: - log(char const* id, std::ostream& stream) - : m_id(id) - , m_enabled(true) - , m_stream(stream) - { - } - - char const* id() const - { - return m_id; - } - - bool enabled() const - { - return m_enabled; - } - - void enable(bool e) - { - m_enabled = e; - } - - void flush() { m_stream.flush(); } - - template - log& operator<<(T const& x) - { - m_stream << x; - return *this; - } - -private: - char const* m_id; - bool m_enabled; - std::ostream& m_stream; -}; - -class log_event -{ -public: - log_event(log& log) - : log_(log) - { - if (log_.enabled()) - log_ << '[' << log.id() << "] "; - } - - ~log_event() - { - if (log_.enabled()) - { - log_ << "\n"; - log_.flush(); - } - } - - template - log_event& operator<<(T const& x) - { - log_ << x; - return *this; - } - - operator bool() const - { - return log_.enabled(); - } - -private: - log& log_; -}; - -class inverted_log_event : public log_event -{ -public: - inverted_log_event(log& log) : log_event(log) {} - - operator bool() const - { - return !log_event::operator bool(); - } -}; - -} } // namespace libtorrent::dht - -#define TORRENT_DECLARE_LOG(name) \ - libtorrent::dht::log& name ## _log() - -#define TORRENT_DEFINE_LOG(name) \ - libtorrent::dht::log& name ## _log() \ - { \ - static std::ofstream log_file("dht.log", std::ios::app); \ - static libtorrent::dht::log instance(#name, log_file); \ - return instance; \ - } - -#define TORRENT_LOG(name) \ - if (libtorrent::dht::inverted_log_event event_object__ = name ## _log()); \ - else static_cast(event_object__) - -#endif - diff --git a/libtorrent/include/libtorrent/kademlia/node.hpp b/libtorrent/include/libtorrent/kademlia/node.hpp deleted file mode 100644 index 850333043..000000000 --- a/libtorrent/include/libtorrent/kademlia/node.hpp +++ /dev/null @@ -1,259 +0,0 @@ -/* - -Copyright (c) 2006, 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 NODE_HPP -#define NODE_HPP - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "libtorrent/socket.hpp" - -namespace libtorrent { namespace dht -{ - -using asio::ip::udp; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(node); -#endif - -// this is the entry for every peer -// the timestamp is there to make it possible -// to remove stale peers -struct peer_entry -{ - tcp::endpoint addr; - ptime added; -}; - -// this is a group. It contains a set of group members -struct torrent_entry -{ - std::set peers; -}; - -inline bool operator<(peer_entry const& lhs, peer_entry const& rhs) -{ - return lhs.addr.address() == rhs.addr.address() - ? lhs.addr.port() < rhs.addr.port() - : lhs.addr.address() < rhs.addr.address(); -} - -struct null_type {}; - -class announce_observer : public observer -{ -public: - announce_observer(boost::pool<>& allocator - , sha1_hash const& info_hash - , int listen_port - , entry const& write_token) - : observer(allocator) - , m_info_hash(info_hash) - , m_listen_port(listen_port) - , m_token(write_token) - {} - - void send(msg& m) - { - m.port = m_listen_port; - m.info_hash = m_info_hash; - m.write_token = m_token; - } - - void timeout() {} - void reply(msg const&) {} - void abort() {} - -private: - sha1_hash m_info_hash; - int m_listen_port; - entry m_token; -}; - -class get_peers_observer : public observer -{ -public: - get_peers_observer(sha1_hash const& info_hash - , int listen_port - , rpc_manager& rpc - , boost::function const&, sha1_hash const&)> f) - : observer(rpc.allocator()) - , m_info_hash(info_hash) - , m_listen_port(listen_port) - , m_rpc(rpc) - , m_fun(f) - {} - - void send(msg& m) - { - m.port = m_listen_port; - m.info_hash = m_info_hash; - } - - void timeout() {} - void reply(msg const& r) - { - m_rpc.invoke(messages::announce_peer, r.addr - , observer_ptr(new (m_rpc.allocator().malloc()) announce_observer( - m_rpc.allocator(), m_info_hash, m_listen_port, r.write_token))); - m_fun(r.peers, m_info_hash); - } - void abort() {} - -private: - sha1_hash m_info_hash; - int m_listen_port; - rpc_manager& m_rpc; - boost::function const&, sha1_hash const&)> m_fun; -}; - - - -class node_impl : boost::noncopyable -{ -typedef std::map table_t; -public: - node_impl(boost::function const& f - , dht_settings const& settings, boost::optional node_id); - - virtual ~node_impl() {} - - void refresh(node_id const& id, boost::function0 f); - void bootstrap(std::vector const& nodes - , boost::function0 f); - void find_node(node_id const& id, boost::function< - void(std::vector const&)> f); - void add_router_node(udp::endpoint router); - - void incoming(msg const& m); - - void refresh(); - void refresh_bucket(int bucket); - int bucket_size(int bucket); - - typedef routing_table::iterator iterator; - - iterator begin() const { return m_table.begin(); } - iterator end() const { return m_table.end(); } - - typedef table_t::iterator data_iterator; - - node_id const& nid() const { return m_id; } - boost::tuple size() const{ return m_table.size(); } - size_type num_global_nodes() const - { return m_table.num_global_nodes(); } - - data_iterator begin_data() { return m_map.begin(); } - data_iterator end_data() { return m_map.end(); } - int data_size() const { return int(m_map.size()); } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - void print_state(std::ostream& os) const - { m_table.print_state(os); } -#endif - - void announce(sha1_hash const& info_hash, int listen_port - , boost::function const& - , sha1_hash const&)> f); - - bool verify_token(msg const& m); - entry generate_token(msg const& m); - - // the returned time is the delay until connection_timeout() - // should be called again the next time - time_duration connection_timeout(); - time_duration refresh_timeout(); - - // generates a new secret number used to generate write tokens - void new_write_key(); - - // pings the given node, and adds it to - // the routing table if it respons and if the - // bucket is not full. - void add_node(udp::endpoint node); - - void replacement_cache(bucket_t& nodes) const - { m_table.replacement_cache(nodes); } - -protected: - // is called when a find data request is received. Should - // return false if the data is not stored on this node. If - // the data is stored, it should be serialized into 'data'. - bool on_find(msg const& m, std::vector& peers) const; - - // this is called when a store request is received. The data - // is store-parameters and the data to be stored. - void on_announce(msg const& m, msg& reply); - - dht_settings const& m_settings; - - // the maximum number of peers to send in a get_peers - // reply. Ordinary trackers usually limit this to 50. - // 50 => 6 * 50 = 250 bytes + packet overhead - int m_max_peers_reply; - -private: - void incoming_request(msg const& h); - - node_id m_id; - routing_table m_table; - rpc_manager m_rpc; - table_t m_map; - - ptime m_last_tracker_tick; - - // secret random numbers used to create write tokens - int m_secret[2]; -}; - - -} } // namespace libtorrent::dht - -#endif // NODE_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/node_entry.hpp b/libtorrent/include/libtorrent/kademlia/node_entry.hpp deleted file mode 100644 index edc5dff80..000000000 --- a/libtorrent/include/libtorrent/kademlia/node_entry.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - -Copyright (c) 2006, 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 KADEMLIA_NODE_ENTRY_HPP -#define KADEMLIA_NODE_ENTRY_HPP - -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/socket.hpp" - -namespace libtorrent { namespace dht -{ - -struct node_entry -{ - node_entry(node_id const& id_, asio::ip::udp::endpoint addr_) - : id(id_) - , addr(addr_) - , fail_count(0) {} - node_entry(asio::ip::udp::endpoint addr_) - : id(0) - , addr(addr_) - , fail_count(0) {} - - node_id id; - udp::endpoint addr; - // the number of times this node has failed to - // respond in a row - int fail_count; -}; - -} } // namespace libtorrent::dht - -#endif - diff --git a/libtorrent/include/libtorrent/kademlia/node_id.hpp b/libtorrent/include/libtorrent/kademlia/node_id.hpp deleted file mode 100644 index eb4d6c539..000000000 --- a/libtorrent/include/libtorrent/kademlia/node_id.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - -Copyright (c) 2006, 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 NODE_ID_HPP -#define NODE_ID_HPP - -#include -#include - -#include -#include "libtorrent/peer_id.hpp" - -namespace libtorrent { namespace dht -{ - -typedef libtorrent::big_number node_id; - -// returns the distance between the two nodes -// using the kademlia XOR-metric -node_id distance(node_id const& n1, node_id const& n2); - -// returns true if: distance(n1, ref) < distance(n2, ref) -bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref); - -// returns n in: 2^n <= distance(n1, n2) < 2^(n+1) -// usefult for finding out which bucket a node belongs to -int distance_exp(node_id const& n1, node_id const& n2); - -} } // namespace libtorrent::dht - -#endif // NODE_ID_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/packet_iterator.hpp b/libtorrent/include/libtorrent/kademlia/packet_iterator.hpp deleted file mode 100644 index e906a90bf..000000000 --- a/libtorrent/include/libtorrent/kademlia/packet_iterator.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - -Copyright (c) 2006, 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 PACKET_ITERATOR_HPP -#define PACKET_ITERATOR_HPP - -#include -#include -#include - -namespace libtorrent { namespace dht -{ - -class packet_iterator: public boost::iterator_facade< - packet_iterator, const char, boost::forward_traversal_tag> -{ -public: - typedef std::vector::const_iterator base_iterator; - - packet_iterator() {} - - packet_iterator(std::vector::const_iterator start - , std::vector::const_iterator end - , std::string const& error_msg = "") - : m_base(start) - , m_end(end) - , m_msg(error_msg) - {} - - base_iterator base() const - { return m_base; } - - base_iterator end() const - { return m_end; } - - int left() const { return int(m_end - m_base); } - -private: - friend class boost::iterator_core_access; - - bool equal(packet_iterator const& other) const - { return m_base == other.m_base; } - - void advance(int n) - { - m_base += n; - } - - void increment() - { ++m_base; } - - char const& dereference() const - { - if (m_base == m_end) throw std::runtime_error(m_msg); - return *m_base; - } - - base_iterator m_base; - base_iterator m_end; - std::string m_msg; -}; - -} } // namespace libtorrent::dht - -#endif // PACKET_ITERATOR_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/refresh.hpp b/libtorrent/include/libtorrent/kademlia/refresh.hpp deleted file mode 100644 index 953c4d871..000000000 --- a/libtorrent/include/libtorrent/kademlia/refresh.hpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -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 REFRESH_050324_HPP -#define REFRESH_050324_HPP - -#include - -#include -#include -#include -#include - -#include - -namespace libtorrent { namespace dht -{ - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(refresh); -#endif - -class routing_table; -class rpc_manager; - -class refresh : public traversal_algorithm -{ -public: - typedef boost::function done_callback; - - template - static void initiate( - node_id target - , int branch_factor - , int max_active_pings - , int max_results - , routing_table& table - , InIt first - , InIt last - , rpc_manager& rpc - , done_callback const& callback - ); - - void ping_reply(node_id id); - void ping_timeout(node_id id, bool prevent_request = false); - -private: - template - refresh( - node_id target - , int branch_factor - , int max_active_pings - , int max_results - , routing_table& table - , InIt first - , InIt last - , rpc_manager& rpc - , done_callback const& callback - ); - - void done(); - void invoke(node_id const& id, udp::endpoint addr); - - void invoke_pings_or_finish(bool prevent_request = false); - - int m_max_active_pings; - int m_active_pings; - - done_callback m_done_callback; - - std::vector::iterator m_leftover_nodes_iterator; -}; - -class refresh_observer : public observer -{ -public: - refresh_observer( - boost::intrusive_ptr const& algorithm - , node_id self - , node_id target) - : observer(algorithm->allocator()) - , m_target(target) - , m_self(self) - , m_algorithm(algorithm) - {} - ~refresh_observer(); - - void send(msg& m) - { - m.info_hash = m_target; - } - - void timeout(); - void reply(msg const& m); - void abort() { m_algorithm = 0; } - - -private: - node_id const m_target; - node_id const m_self; - boost::intrusive_ptr m_algorithm; -}; - -class ping_observer : public observer -{ -public: - ping_observer( - boost::intrusive_ptr const& algorithm - , node_id self) - : observer(algorithm->allocator()) - , m_self(self) - , m_algorithm(algorithm) - {} - ~ping_observer(); - - void send(msg& p) {} - void timeout(); - void reply(msg const& m); - void abort() { m_algorithm = 0; } - - -private: - node_id const m_self; - boost::intrusive_ptr m_algorithm; -}; - -template -inline refresh::refresh( - node_id target - , int branch_factor - , int max_active_pings - , int max_results - , routing_table& table - , InIt first - , InIt last - , rpc_manager& rpc - , done_callback const& callback -) - : traversal_algorithm( - target - , branch_factor - , max_results - , table - , rpc - , first - , last - ) - , m_max_active_pings(max_active_pings) - , m_active_pings(0) - , m_done_callback(callback) -{ - boost::intrusive_ptr self(this); - add_requests(); -} - -template -inline void refresh::initiate( - node_id target - , int branch_factor - , int max_active_pings - , int max_results - , routing_table& table - , InIt first - , InIt last - , rpc_manager& rpc - , done_callback const& callback -) -{ - new refresh( - target - , branch_factor - , max_active_pings - , max_results - , table - , first - , last - , rpc - , callback - ); -} - -} } // namespace libtorrent::dht - -#endif // REFRESH_050324_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/routing_table.hpp b/libtorrent/include/libtorrent/kademlia/routing_table.hpp deleted file mode 100644 index 45a7dd762..000000000 --- a/libtorrent/include/libtorrent/kademlia/routing_table.hpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - -Copyright (c) 2006, 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 ROUTING_TABLE_HPP -#define ROUTING_TABLE_HPP - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -namespace libtorrent { namespace dht -{ - -using asio::ip::udp; - -//TORRENT_DECLARE_LOG(table); - -typedef std::vector bucket_t; - -// differences in the implementation from the description in -// the paper: -// -// * The routing table tree is not allocated dynamically, there -// are always 160 buckets. -// * Nodes are not marked as being stale, they keep a counter -// that tells how many times in a row they have failed. When -// a new node is to be inserted, the node that has failed -// the most times is replaced. If none of the nodes in the -// bucket has failed, then it is put in the replacement -// cache (just like in the paper). - -class routing_table; - -namespace aux -{ - - // Iterates over a flattened routing_table structure. - class routing_table_iterator - : public boost::iterator_facade< - routing_table_iterator - , node_entry const - , boost::forward_traversal_tag - > - { - public: - routing_table_iterator() - { - } - - private: - friend class libtorrent::dht::routing_table; - friend class boost::iterator_core_access; - - typedef boost::array, 160>::const_iterator - bucket_iterator_t; - - routing_table_iterator( - bucket_iterator_t begin - , bucket_iterator_t end) - : m_bucket_iterator(begin) - , m_bucket_end(end) - , m_iterator(begin != end ? begin->first.begin() : bucket_t::const_iterator()) - { - if (m_bucket_iterator == m_bucket_end) return; - while (m_iterator == m_bucket_iterator->first.end()) - { - if (++m_bucket_iterator == m_bucket_end) - break; - m_iterator = m_bucket_iterator->first.begin(); - } - } - - bool equal(routing_table_iterator const& other) const - { - return m_bucket_iterator == other.m_bucket_iterator - && (m_bucket_iterator == m_bucket_end - || m_iterator == other.m_iterator); - } - - void increment() - { - assert(m_bucket_iterator != m_bucket_end); - ++m_iterator; - while (m_iterator == m_bucket_iterator->first.end()) - { - if (++m_bucket_iterator == m_bucket_end) - break; - m_iterator = m_bucket_iterator->first.begin(); - } - } - - node_entry const& dereference() const - { - assert(m_bucket_iterator != m_bucket_end); - return *m_iterator; - } - - bucket_iterator_t m_bucket_iterator; - bucket_iterator_t m_bucket_end; - bucket_t::const_iterator m_iterator; - }; - -} // namespace aux - -class routing_table -{ -public: - typedef aux::routing_table_iterator iterator; - typedef iterator const_iterator; - - routing_table(node_id const& id, int bucket_size - , dht_settings const& settings); - - void node_failed(node_id const& id); - - // adds an endpoint that will never be added to - // the routing table - void add_router_node(udp::endpoint router); - - // iterates over the router nodes added - typedef std::set::const_iterator router_iterator; - router_iterator router_begin() const { return m_router_nodes.begin(); } - router_iterator router_end() const { return m_router_nodes.end(); } - - // this function is called every time the node sees - // a sign of a node being alive. This node will either - // be inserted in the k-buckets or be moved to the top - // of its bucket. - bool node_seen(node_id const& id, udp::endpoint addr); - - // returns time when the given bucket needs another refresh. - // if the given bucket is empty but there are nodes - // in a bucket closer to us, or if the bucket is non-empty and - // the time from the last activity is more than 15 minutes - ptime next_refresh(int bucket); - - // fills the vector with the count nodes from our buckets that - // are nearest to the given id. - void find_node(node_id const& id, std::vector& l - , bool include_self, int count = 0); - - // returns true if the given node would be placed in a bucket - // that is not full. If the node already exists in the table - // this function returns false - bool need_node(node_id const& id); - - // this will set the given bucket's latest activity - // to the current time - void touch_bucket(int bucket); - - int bucket_size(int bucket) - { - assert(bucket >= 0 && bucket < 160); - return (int)m_buckets[bucket].first.size(); - } - int bucket_size() const { return m_bucket_size; } - - iterator begin() const; - iterator end() const; - - boost::tuple size() const; - size_type num_global_nodes() const; - - // returns true if there are no working nodes - // in the routing table - bool need_bootstrap() const; - int num_active_buckets() const - { return 160 - m_lowest_active_bucket + 1; } - - void replacement_cache(bucket_t& nodes) const; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - // used for debug and monitoring purposes. This will print out - // the state of the routing table to the given stream - void print_state(std::ostream& os) const; -#endif - -private: - - // constant called k in paper - int m_bucket_size; - - dht_settings const& m_settings; - - // 160 (k-bucket, replacement cache) pairs - typedef boost::array, 160> table_t; - table_t m_buckets; - // timestamps of the last activity in each bucket - typedef boost::array table_activity_t; - table_activity_t m_bucket_activity; - node_id m_id; // our own node id - - // this is a set of all the endpoints that have - // been identified as router nodes. They will - // be used in searches, but they will never - // be added to the routing table. - std::set m_router_nodes; - - // this is the lowest bucket index with nodes in it - int m_lowest_active_bucket; -}; - -} } // namespace libtorrent::dht - -#endif // ROUTING_TABLE_HPP - diff --git a/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp b/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp deleted file mode 100644 index a7c47f29a..000000000 --- a/libtorrent/include/libtorrent/kademlia/rpc_manager.hpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - -Copyright (c) 2006, 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 RPC_MANAGER_HPP -#define RPC_MANAGER_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/time.hpp" - -namespace libtorrent { namespace dht -{ - -struct observer; - -using asio::ip::udp; -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(rpc); -#endif - -struct null_observer : public observer -{ - null_observer(boost::pool<>& allocator): observer(allocator) {} - virtual void reply(msg const&) {} - virtual void timeout() {} - virtual void send(msg&) {} - void abort() {} -}; - -class routing_table; - -class rpc_manager -{ -public: - typedef boost::function1 fun; - typedef boost::function1 send_fun; - - rpc_manager(fun const& incoming_fun, node_id const& our_id - , routing_table& table, send_fun const& sf); - ~rpc_manager(); - - // returns true if the node needs a refresh - bool incoming(msg const&); - time_duration tick(); - - void invoke(int message_id, udp::endpoint target - , observer_ptr o); - - void reply(msg& m); - void reply_with_ping(msg& m); - -#ifndef NDEBUG - void check_invariant() const; -#endif - - boost::pool<>& allocator() const - { return m_pool_allocator; } - -private: - - enum { max_transactions = 2048 }; - - unsigned int new_transaction_id(observer_ptr o); - void update_oldest_transaction_id(); - - boost::uint32_t calc_connection_id(udp::endpoint addr); - - mutable boost::pool<> m_pool_allocator; - - typedef boost::array - transactions_t; - transactions_t m_transactions; - std::vector m_aborted_transactions; - - // this is the next transaction id to be used - int m_next_transaction_id; - // this is the oldest transaction id still - // (possibly) in use. This is the transaction - // that will time out first, the one we are - // waiting for to time out - int m_oldest_transaction_id; - - fun m_incoming; - send_fun m_send; - node_id m_our_id; - routing_table& m_table; - ptime m_timer; - node_id m_random_number; - bool m_destructing; -}; - -} } // namespace libtorrent::dht - -#endif - - diff --git a/libtorrent/include/libtorrent/kademlia/traversal_algorithm.hpp b/libtorrent/include/libtorrent/kademlia/traversal_algorithm.hpp deleted file mode 100644 index d51ed5506..000000000 --- a/libtorrent/include/libtorrent/kademlia/traversal_algorithm.hpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -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 TRAVERSAL_ALGORITHM_050324_HPP -#define TRAVERSAL_ALGORITHM_050324_HPP - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -namespace libtorrent { namespace dht -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DECLARE_LOG(traversal); -#endif - -class rpc_manager; - -// this class may not be instantiated as a stack object -class traversal_algorithm : boost::noncopyable -{ -public: - void traverse(node_id const& id, udp::endpoint addr); - void finished(node_id const& id); - void failed(node_id const& id, bool prevent_request = false); - virtual ~traversal_algorithm() {} - boost::pool<>& allocator() const; - -protected: - template - traversal_algorithm( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , InIt start - , InIt end - ); - - void add_requests(); - void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags); - - virtual void done() = 0; - virtual void invoke(node_id const& id, udp::endpoint addr) = 0; - - struct result - { - result(node_id const& id, udp::endpoint addr, unsigned char f = 0) - : id(id), addr(addr), flags(f) - {} - - node_id id; - udp::endpoint addr; - enum { queried = 1, initial = 2 }; - unsigned char flags; - }; - - std::vector::iterator last_iterator(); - - friend void intrusive_ptr_add_ref(traversal_algorithm* p) - { - p->m_ref_count++; - } - - friend void intrusive_ptr_release(traversal_algorithm* p) - { - if (--p->m_ref_count == 0) - delete p; - } - - int m_ref_count; - - node_id m_target; - int m_branch_factor; - int m_max_results; - std::vector m_results; - std::set m_failed; - routing_table& m_table; - rpc_manager& m_rpc; - int m_invoke_count; -}; - -template -traversal_algorithm::traversal_algorithm( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , InIt start // <- nodes to initiate traversal with - , InIt end -) - : m_ref_count(0) - , m_target(target) - , m_branch_factor(branch_factor) - , m_max_results(max_results) - , m_table(table) - , m_rpc(rpc) - , m_invoke_count(0) -{ - using boost::bind; - - for (InIt i = start; i != end; ++i) - { - add_entry(i->id, i->addr, result::initial); - } - - // in case the routing table is empty, use the - // router nodes in the table - if (start == end) - { - for (routing_table::router_iterator i = table.router_begin() - , end(table.router_end()); i != end; ++i) - { - add_entry(node_id(0), *i, result::initial); - } - } - -} - -} } // namespace libtorrent::dht - -#endif // TRAVERSAL_ALGORITHM_050324_HPP - diff --git a/libtorrent/include/libtorrent/lsd.hpp b/libtorrent/include/libtorrent/lsd.hpp deleted file mode 100644 index 9ffbcdfc3..000000000 --- a/libtorrent/include/libtorrent/lsd.hpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - -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_LSD_HPP -#define TORRENT_LSD_HPP - -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" - -#include -#include -#include -#include -#include - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) -#include -#endif - -namespace libtorrent -{ - -typedef boost::function peer_callback_t; - -class lsd : boost::noncopyable -{ -public: - lsd(io_service& ios, address const& listen_interface - , peer_callback_t const& cb); - ~lsd(); - - void rebind(address const& listen_interface); - - void announce(sha1_hash const& ih, int listen_port); - void close(); - -private: - - static address_v4 lsd_multicast_address; - static udp::endpoint lsd_multicast_endpoint; - - void resend_announce(asio::error_code const& e, std::string msg); - void on_announce(asio::error_code const& e - , std::size_t bytes_transferred); - void setup_receive(); - - peer_callback_t m_callback; - - // current retry count - int m_retry_count; - - // used to receive responses in - char m_receive_buffer[1024]; - - // the endpoint we received the message from - udp::endpoint m_remote; - - // the udp socket used to send and receive - // multicast messages on - datagram_socket m_socket; - - // used to resend udp packets in case - // they time out - deadline_timer m_broadcast_timer; - - bool m_disabled; -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - std::ofstream m_log; -#endif -}; - -} - - -#endif - diff --git a/libtorrent/include/libtorrent/natpmp.hpp b/libtorrent/include/libtorrent/natpmp.hpp deleted file mode 100644 index 1c0ffd0be..000000000 --- a/libtorrent/include/libtorrent/natpmp.hpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - -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_NATPMP_HPP -#define TORRENT_NATPMP_HPP - -#include "libtorrent/socket.hpp" - -#include - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) -#include -#endif - -namespace libtorrent -{ - -// int: external tcp port -// int: external udp port -// std::string: error message -typedef boost::function portmap_callback_t; - -class natpmp -{ -public: - natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb); - - void rebind(address const& listen_interface); - - // maps the ports, if a port is set to 0 - // it will not be mapped - void set_mappings(int tcp, int udp); - - void close(); - -private: - - void update_mapping(int i, int port); - void send_map_request(int i); - void resend_request(int i, asio::error_code const& e); - void on_reply(asio::error_code const& e - , std::size_t bytes_transferred); - void try_next_mapping(int i); - void update_expiration_timer(); - void refresh_mapping(int i); - void mapping_expired(asio::error_code const& e, int i); - - struct mapping - { - mapping() - : need_update(false) - , local_port(0) - , external_port(0) - , protocol(1) - {} - - // indicates that the mapping has changed - // and needs an update - bool need_update; - - // the time the port mapping will expire - ptime expires; - - // the local port for this mapping. If this is set - // to 0, the mapping is not in use - int local_port; - - // the external (on the NAT router) port - // for the mapping. This is the port we - // should announce to others - int external_port; - - // 1 = udp, 2 = tcp - int protocol; - }; - - portmap_callback_t m_callback; - - // 0 is tcp and 1 is udp - mapping m_mappings[2]; - - // the endpoint to the nat router - udp::endpoint m_nat_endpoint; - - // this is the mapping that is currently - // being updated. It is -1 in case no - // mapping is being updated at the moment - int m_currently_mapping; - - // current retry count - int m_retry_count; - - // used to receive responses in - char m_response_buffer[16]; - - // the endpoint we received the message from - udp::endpoint m_remote; - - // the udp socket used to communicate - // with the NAT router - datagram_socket m_socket; - - // used to resend udp packets in case - // they time out - deadline_timer m_send_timer; - - // timer used to refresh mappings - deadline_timer m_refresh_timer; - - bool m_disabled; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - std::ofstream m_log; -#endif -}; - -} - - -#endif - diff --git a/libtorrent/include/libtorrent/pch.hpp b/libtorrent/include/libtorrent/pch.hpp deleted file mode 100644 index 735999826..000000000 --- a/libtorrent/include/libtorrent/pch.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#ifdef BOOST_BUILD_PCH_ENABLED - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __OBJC__ -#define Protocol Protocol_ -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef __OBJC__ -#undef Protocol -#endif - -#endif - diff --git a/libtorrent/include/libtorrent/peer.hpp b/libtorrent/include/libtorrent/peer.hpp deleted file mode 100644 index c404a611d..000000000 --- a/libtorrent/include/libtorrent/peer.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - -Copyright (c) 2003, 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_PEER_HPP_INCLUDED -#define TORRENT_PEER_HPP_INCLUDED - -#include - -#include "libtorrent/peer_id.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT peer_entry - { - std::string ip; - int port; - peer_id pid; - - bool operator==(const peer_entry& p) const - { - return pid == p.pid; - } - - bool operator<(const peer_entry& p) const - { - return pid < p.pid; - } - }; - -} - -#endif // TORRENT_PEER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/peer_connection.hpp b/libtorrent/include/libtorrent/peer_connection.hpp deleted file mode 100644 index 9b3de295c..000000000 --- a/libtorrent/include/libtorrent/peer_connection.hpp +++ /dev/null @@ -1,699 +0,0 @@ -/* - -Copyright (c) 2003, 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_PEER_CONNECTION_HPP_INCLUDED -#define TORRENT_PEER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include -#include - -#include "libtorrent/debug.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/buffer.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/allocate_resources.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/bandwidth_manager.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/socket_type.hpp" - -// TODO: each time a block is 'taken over' -// from another peer. That peer must be given -// a chance to become not-interested. - -namespace libtorrent -{ - class torrent; - struct peer_plugin; - - namespace detail - { - struct session_impl; - } - - TORRENT_EXPORT void intrusive_ptr_add_ref(peer_connection const*); - TORRENT_EXPORT void intrusive_ptr_release(peer_connection const*); - - struct TORRENT_EXPORT protocol_error: std::runtime_error - { - protocol_error(const std::string& msg): std::runtime_error(msg) {}; - }; - - class TORRENT_EXPORT peer_connection - : public boost::noncopyable - { - friend class invariant_access; - friend TORRENT_EXPORT void intrusive_ptr_add_ref(peer_connection const*); - friend TORRENT_EXPORT void intrusive_ptr_release(peer_connection const*); - public: - - enum channels - { - upload_channel, - download_channel, - num_channels - }; - - // this is the constructor where the we are the active part. - // The peer_conenction should handshake and verify that the - // other end has the correct id - peer_connection( - aux::session_impl& ses - , boost::weak_ptr t - , boost::shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo); - - // with this constructor we have been contacted and we still don't - // know which torrent the connection belongs to - peer_connection( - aux::session_impl& ses - , boost::shared_ptr s - , policy::peer* peerinfo); - - virtual ~peer_connection(); - - void set_peer_info(policy::peer* pi) - { m_peer_info = pi; } - - policy::peer* peer_info_struct() const - { return m_peer_info; } - - enum peer_speed_t { slow, medium, fast }; - peer_speed_t peer_speed(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::shared_ptr); -#endif - - // this function is called once the torrent associated - // with this peer connection has retrieved the meta- - // data. If the torrent was spawned with metadata - // this is called from the constructor. - void init(); - - // this is called when the metadata is retrieved - // and the files has been checked - virtual void on_metadata() {} - - void set_upload_limit(int limit); - void set_download_limit(int limit); - - int upload_limit() const { return m_upload_limit; } - int download_limit() const { return m_download_limit; } - - bool prefer_whole_pieces() const - { return m_prefer_whole_pieces; } - - void prefer_whole_pieces(bool b) - { m_prefer_whole_pieces = b; } - - bool request_large_blocks() const - { return m_request_large_blocks; } - - void request_large_blocks(bool b) - { m_request_large_blocks = b; } - - void set_non_prioritized(bool b) - { m_non_prioritized = b; } - - bool on_parole() const - { return m_on_parole; } - - // this adds an announcement in the announcement queue - // it will let the peer know that we have the given piece - void announce_piece(int index); - - // tells if this connection has data it want to send - // and has enough upload bandwidth quota left to send it. - bool can_write() const; - bool can_read() const; - - bool is_seed() const; - - bool has_timed_out() const; - - // will send a keep-alive message to the peer - void keep_alive(); - - peer_id const& pid() const { return m_peer_id; } - void set_pid(const peer_id& pid) { m_peer_id = pid; } - bool has_piece(int i) const; - - const std::deque& download_queue() const; - const std::deque& request_queue() const; - const std::deque& upload_queue() const; - - bool is_interesting() const { return m_interesting; } - bool is_choked() const { return m_choked; } - - bool is_peer_interested() const { return m_peer_interested; } - bool has_peer_choked() const { return m_peer_choked; } - - void update_interest(); - - // returns the torrent this connection is a part of - // may be zero if the connection is an incoming connection - // and it hasn't received enough information to determine - // which torrent it should be associated with - boost::weak_ptr associated_torrent() const - { return m_torrent; } - - const stat& statistics() const { return m_statistics; } - void add_stat(size_type downloaded, size_type uploaded); - - // is called once every second by the main loop - void second_tick(float tick_interval); - - boost::shared_ptr get_socket() const { return m_socket; } - tcp::endpoint const& remote() const { return m_remote; } - - std::vector const& get_bitfield() const; - - void timed_out(); - // this will cause this peer_connection to be disconnected. - void disconnect(); - bool is_disconnecting() const { return m_disconnecting; } - - // this is called when the connection attempt has succeeded - // and the peer_connection is supposed to set m_connecting - // to false, and stop monitor writability - void on_connection_complete(asio::error_code const& e); - - // returns true if this connection is still waiting to - // finish the connection attempt - bool is_connecting() const { return m_connecting; } - - // returns true if the socket of this peer hasn't been - // attempted to connect yet (i.e. it's queued for - // connection attempt). - bool is_queued() const { return m_queued; } - - // called when it's time for this peer_conncetion to actually - // initiate the tcp connection. This may be postponed until - // the library isn't using up the limitation of half-open - // tcp connections. - void connect(int ticket); - - // This is called for every peer right after the upload - // bandwidth has been distributed among them - // It will reset the used bandwidth to 0. - void reset_upload_quota(); - - // free upload. - size_type total_free_upload() const; - void add_free_upload(size_type free_upload); - - // trust management. - void received_valid_data(int index); - void received_invalid_data(int index); - int trust_points() const; - - size_type share_diff() const; - - // a connection is local if it was initiated by us. - // if it was an incoming connection, it is remote - bool is_local() const { return m_active; } - - bool on_local_network() const; - bool ignore_bandwidth_limits() const - { return m_ignore_bandwidth_limits; } - - void set_failed() { m_failed = true; } - bool failed() const { return m_failed; } - - int desired_queue_size() const { return m_desired_queue_size; } - -#ifdef TORRENT_VERBOSE_LOGGING - boost::shared_ptr m_logger; -#endif - - // the message handlers are called - // each time a recv() returns some new - // data, the last time it will be called - // is when the entire packet has been - // received, then it will no longer - // be called. i.e. most handlers need - // to check how much of the packet they - // have received before any processing - void incoming_keepalive(); - void incoming_choke(); - void incoming_unchoke(); - void incoming_interested(); - void incoming_not_interested(); - void incoming_have(int piece_index); - void incoming_bitfield(std::vector const& bitfield); - void incoming_request(peer_request const& r); - void incoming_piece(peer_request const& p, char const* data); - void incoming_piece_fragment(); - void incoming_cancel(peer_request const& r); - void incoming_dht_port(int listen_port); - - // the following functions appends messages - // to the send buffer - void send_choke(); - void send_unchoke(); - void send_interested(); - void send_not_interested(); - - // adds a block to the request queue - void add_request(piece_block const& b); - // removes a block from the request queue or download queue - // sends a cancel message if appropriate - // refills the request queue, and possibly ignoring pieces requested - // by peers in the ignore list (to avoid recursion) - void cancel_request(piece_block const& b); - void send_block_requests(); - - int max_assignable_bandwidth(int channel) const - { - return m_bandwidth_limit[channel].max_assignable(); - } - - void assign_bandwidth(int channel, int amount); - void expire_bandwidth(int channel, int amount); - -#ifndef NDEBUG - void check_invariant() const; - ptime m_last_choke; -#endif - - virtual void get_peer_info(peer_info& p) const = 0; - - // is true until we can be sure that the other end - // speaks our protocol (be it bittorrent or http). - virtual bool in_handshake() const = 0; - - // returns the block currently being - // downloaded. And the progress of that - // block. If the peer isn't downloading - // a piece for the moment, the boost::optional - // will be invalid. - virtual boost::optional - downloading_piece_progress() const - { - #ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "downloading_piece_progress() dispatched to the base class!\n"; - #endif - return boost::optional(); - } - - void send_buffer(char const* begin, char const* end); - buffer::interval allocate_send_buffer(int size); - void setup_send(); - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void set_country(char const* c) - { - assert(strlen(c) == 2); - m_country[0] = c[0]; - m_country[1] = c[1]; - } - bool has_country() const { return m_country[0] != 0; } -#endif - - protected: - - virtual void write_choke() = 0; - virtual void write_unchoke() = 0; - virtual void write_interested() = 0; - virtual void write_not_interested() = 0; - virtual void write_request(peer_request const& r) = 0; - virtual void write_cancel(peer_request const& r) = 0; - virtual void write_have(int index) = 0; - virtual void write_keepalive() = 0; - virtual void write_piece(peer_request const& r) = 0; - - virtual void on_connected() = 0; - virtual void on_tick() {} - - virtual void on_receive(asio::error_code const& error - , std::size_t bytes_transferred) = 0; - virtual void on_sent(asio::error_code const& error - , std::size_t bytes_transferred) = 0; - - int send_buffer_size() const - { - return (int)m_send_buffer[0].size() - + (int)m_send_buffer[1].size() - - m_write_pos; - } - - buffer::const_interval receive_buffer() const - { - return buffer::const_interval(&m_recv_buffer[0] - , &m_recv_buffer[0] + m_recv_pos); - } - - void cut_receive_buffer(int size, int packet_size); - - void reset_recv_buffer(int packet_size); - int packet_size() const { return m_packet_size; } - - bool packet_finished() const - { - assert(m_recv_pos <= m_packet_size); - return m_packet_size <= m_recv_pos; - } - - void setup_receive(); - - void attach_to_torrent(sha1_hash const& ih); - - bool verify_piece(peer_request const& p) const; - - // the bandwidth channels, upload and download - // keeps track of the current quotas - bandwidth_limit m_bandwidth_limit[num_channels]; - - // statistics about upload and download speeds - // and total amount of uploads and downloads for - // this peer - stat m_statistics; - - // a back reference to the session - // the peer belongs to. - aux::session_impl& m_ses; - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - // called from the main loop when this connection has any - // work to do. - void on_send_data(asio::error_code const& error - , std::size_t bytes_transferred); - void on_receive_data(asio::error_code const& error - , std::size_t bytes_transferred); - - // this is the limit on the number of outstanding requests - // we have to this peer. This is initialized to the settings - // in the session_settings structure. But it may be lowered - // if the peer is known to require a smaller limit (like BitComet). - // or if the extended handshake sets a limit. - // web seeds also has a limit on the queue size. - int m_max_out_request_queue; - - void set_timeout(int s) { m_timeout = s; } - -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::list > extension_list_t; - extension_list_t m_extensions; -#endif - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - // in case the session settings is set - // to resolve countries, this is set to - // the two character country code this - // peer resides in. - char m_country[2]; -#endif - - private: - - void fill_send_buffer(); - - // the timeout in seconds - int m_timeout; - - // the time when we last got a part of a - // piece packet from this peer - ptime m_last_piece; - - int m_packet_size; - int m_recv_pos; - std::vector m_recv_buffer; - - // this is the buffer where data that is - // to be sent is stored until it gets - // consumed by send(). Since asio requires - // the memory buffer that is given to async. - // operations to remain valid until the operation - // finishes, there has to be two buffers. While - // waiting for a async_write operation on one - // buffer, the other is used to write data to - // be queued up. - std::vector 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; - - // if the sending buffer doesn't finish in one send - // operation, this is the position within that buffer - // where the next operation should continue - int m_write_pos; - - // timeouts - ptime m_last_receive; - ptime m_last_sent; - - boost::shared_ptr m_socket; - // this is the peer we're actually talking to - // it may not necessarily be the peer we're - // connected to, in case we use a proxy - tcp::endpoint m_remote; - - // this is the torrent this connection is - // associated with. If the connection is an - // incoming conncetion, this is set to zero - // until the info_hash is received. Then it's - // set to the torrent it belongs to. - boost::weak_ptr m_torrent; - // is true if it was we that connected to the peer - // and false if we got an incomming connection - // could be considered: true = local, false = remote - bool m_active; - - // remote peer's id - peer_id m_peer_id; - - // other side says that it's interested in downloading - // from us. - bool m_peer_interested; - - // the other side has told us that it won't send anymore - // data to us for a while - bool m_peer_choked; - - // the peer has pieces we are interested in - bool m_interesting; - - // we have choked the upload to the peer - bool m_choked; - - // this is set to true if the connection timed - // out or closed the connection. In that - // case we will not try to reconnect to - // this peer - bool m_failed; - - // if this is set to true, the peer will not - // request bandwidth from the limiter, but instead - // just send and receive as much as possible. - bool m_ignore_bandwidth_limits; - - // the pieces the other end have - std::vector m_have_piece; - - // the number of pieces this peer - // has. Must be the same as - // std::count(m_have_piece.begin(), - // m_have_piece.end(), true) - int m_num_pieces; - - // the queue of requests we have got - // from this peer - std::deque m_requests; - - // the blocks we have reserved in the piece - // picker and will send to this peer. - std::deque m_request_queue; - - // the queue of blocks we have requested - // from this peer - std::deque m_download_queue; - - // the number of request we should queue up - // at the remote end. - int m_desired_queue_size; - - // the amount of data this peer has been given - // as free upload. This is distributed from - // peers from which we get free download - // this will be negative on a peer from which - // we get free download, and positive on peers - // that we give the free upload, to keep the balance. - size_type m_free_upload; - - // for every valid piece we receive where this - // peer was one of the participants, we increase - // this value. For every invalid piece we receive - // where this peer was a participant, we decrease - // this value. If it sinks below a threshold, its - // considered a bad peer and will be banned. - int m_trust_points; - - // if this is true, this peer is assumed to handle all piece - // requests in fifo order. All skipped blocks are re-requested - // immediately instead of having a looser requirement - // where blocks can be sent out of order. The default is to - // allow non-fifo order. - bool m_assume_fifo; - - // the number of invalid piece-requests - // we have got from this peer. If the request - // queue gets empty, and there have been - // invalid requests, we can assume the - // peer is waiting for those pieces. - // we can then clear its download queue - // by sending choke, unchoke. - int m_num_invalid_requests; - - // this is true if this connection has been added - // to the list of connections that will be closed. - bool m_disconnecting; - - // the time when this peer sent us a not_interested message - // the last time. - ptime m_became_uninterested; - - // the time when we sent a not_interested message to - // this peer the last time. - ptime m_became_uninteresting; - - // this is true until this socket has become - // writable for the first time (i.e. the - // connection completed). While connecting - // the timeout will not be triggered. This is - // because windows XP SP2 may delay connection - // attempts, which means that the connection - // may not even have been attempted when the - // time out is reached. - bool m_connecting; - - // This is true until connect is called on the - // peer_connection's socket. It is false on incoming - // connections. - bool m_queued; - - // these are true when there's a asynchronous write - // or read operation running. - bool m_writing; - bool m_reading; - - // if set to true, this peer will always prefer - // to request entire pieces, rather than blocks. - // if it is false, the download rate limit setting - // will be used to determine if whole pieces - // are preferred. - bool m_prefer_whole_pieces; - - // if this is true, the peer has previously participated - // in a piece that failed the piece hash check. This will - // put the peer on parole and only request entire pieces. - // if a piece pass that was partially requested from this - // peer it will leave parole mode and continue download - // pieces as normal peers. - bool m_on_parole; - - // if this is true, the blocks picked by the piece - // picker will be merged before passed to the - // request function. i.e. subsequent blocks are - // merged into larger blocks. This is used by - // the http-downloader, to request whole pieces - // at a time. - bool m_request_large_blocks; - - // if this is true, other (prioritized) peers will - // skip ahead of it in the queue for bandwidth. The - // effect is that non prioritized peers will only use - // the left-over bandwidth (suitable for web seeds). - bool m_non_prioritized; - - // reference counter for intrusive_ptr - mutable boost::detail::atomic_count m_refs; - - int m_upload_limit; - int m_download_limit; - - // this peer's peer info struct. This may - // be 0, in case the connection is incoming - // and hasn't been added to a torrent yet. - policy::peer* m_peer_info; - - // this is a measurement of how fast the peer - // it allows some variance without changing - // back and forth between states - peer_speed_t m_speed; - - // the ticket id from the connection queue. - // This is used to identify the connection - // so that it can be removed from the queue - // once the connection completes - int m_connection_ticket; -#ifndef NDEBUG - public: - bool m_in_constructor; -#endif - }; -} - -#endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/peer_id.hpp b/libtorrent/include/libtorrent/peer_id.hpp deleted file mode 100644 index e5a224bc4..000000000 --- a/libtorrent/include/libtorrent/peer_id.hpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - -Copyright (c) 2003, 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_PEER_ID_HPP_INCLUDED -#define TORRENT_PEER_ID_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - class TORRENT_EXPORT big_number - { - // private type - struct private_pointer {}; - // the number of bytes of the number - enum { number_size = 20 }; - public: - enum { size = number_size }; - - big_number() {} - - big_number(std::string const& s) - { - int sl = int(s.size()) < size ? int(s.size()) : size; - std::memcpy(m_number, &s[0], sl); - } - - // when initialized with 0 - big_number(private_pointer*) { clear(); } - - void clear() - { - std::fill(m_number,m_number+number_size,0); - } - - bool is_all_zeros() const - { - return std::count(m_number,m_number+number_size,0) == number_size; - } - - bool operator==(big_number const& n) const - { - return std::equal(n.m_number, n.m_number+number_size, m_number); - } - - bool operator!=(big_number const& n) const - { - return !std::equal(n.m_number, n.m_number+number_size, m_number); - } - - bool operator<(big_number const& n) const - { - for (int i = 0; i < number_size; ++i) - { - if (m_number[i] < n.m_number[i]) return true; - if (m_number[i] > n.m_number[i]) return false; - } - return false; - } - - big_number operator~() - { - big_number ret; - for (int i = 0; i< number_size; ++i) - ret.m_number[i] = ~m_number[i]; - return ret; - } - - big_number& operator &= (big_number const& n) - { - for (int i = 0; i< number_size; ++i) - m_number[i] &= n.m_number[i]; - return *this; - } - - big_number& operator |= (big_number const& n) - { - for (int i = 0; i< number_size; ++i) - m_number[i] |= n.m_number[i]; - return *this; - } - - unsigned char& operator[](int i) - { assert(i >= 0 && i < number_size); return m_number[i]; } - - unsigned char const& operator[](int i) const - { assert(i >= 0 && i < number_size); return m_number[i]; } - - typedef const unsigned char* const_iterator; - typedef unsigned char* iterator; - - const_iterator begin() const { return m_number; } - const_iterator end() const { return m_number+number_size; } - - iterator begin() { return m_number; } - iterator end() { return m_number+number_size; } - - private: - - unsigned char m_number[number_size]; - - }; - - typedef big_number peer_id; - typedef big_number sha1_hash; - - inline std::ostream& operator<<(std::ostream& os, big_number const& peer) - { - for (big_number::const_iterator i = peer.begin(); - i != peer.end(); ++i) - { - os << std::hex << std::setw(2) << std::setfill('0') - << static_cast(*i); - } - os << std::dec << std::setfill(' '); - return os; - } - - inline std::istream& operator>>(std::istream& is, big_number& peer) - { - using namespace std; - - for (big_number::iterator i = peer.begin(); - i != peer.end(); ++i) - { - char c[2]; - is >> c[0] >> c[1]; - c[0] = tolower(c[0]); - c[1] = tolower(c[1]); - if ( - ((c[0] < '0' || c[0] > '9') && (c[0] < 'a' || c[0] > 'f')) - || ((c[1] < '0' || c[1] > '9') && (c[1] < 'a' || c[1] > 'f')) - || is.fail()) - { - is.setstate(ios_base::failbit); - return is; - } - *i = ((isdigit(c[0])?c[0]-'0':c[0]-'a'+10) << 4) - + (isdigit(c[1])?c[1]-'0':c[1]-'a'+10); - } - return is; - } - -} - -#endif // TORRENT_PEER_ID_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/peer_info.hpp b/libtorrent/include/libtorrent/peer_info.hpp deleted file mode 100644 index 86480ba11..000000000 --- a/libtorrent/include/libtorrent/peer_info.hpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - -Copyright (c) 2003, 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_PEER_INFO_HPP_INCLUDED -#define TORRENT_PEER_INFO_HPP_INCLUDED - -#include - -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - struct TORRENT_EXPORT peer_info - { - enum - { - interesting = 0x1, - choked = 0x2, - remote_interested = 0x4, - remote_choked = 0x8, - supports_extensions = 0x10, - local_connection = 0x20, - handshake = 0x40, - connecting = 0x80, - queued = 0x100 - }; - - unsigned int flags; - - enum peer_source_flags - { - tracker = 0x1, - dht = 0x2, - pex = 0x4, - lsd = 0x8, - resume_data = 0x10 - }; - - int source; - - tcp::endpoint ip; - float up_speed; - float down_speed; - float payload_up_speed; - float payload_down_speed; - size_type total_download; - size_type total_upload; - peer_id pid; - std::vector pieces; - bool seed; // true if this is a seed - int upload_limit; - int download_limit; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - // in case the session settings is set - // to resolve countries, this is set to - // the two character country code this - // peer resides in. - char country[2]; -#endif - - size_type load_balancing; - - // this is the number of requests - // we have sent to this peer - // that we haven't got a response - // for yet - int download_queue_length; - - // this is the number of requests - // the peer has sent to us - // that we haven't sent yet - int upload_queue_length; - - // the number of times this IP - // has failed to connect - int failcount; - - // the currently downloading piece - // if piece index is -1 all associated - // members are just set to 0 - int downloading_piece_index; - int downloading_block_index; - int downloading_progress; - int downloading_total; - - std::string client; - - enum - { - standard_bittorrent = 0, - web_seed = 1 - }; - int connection_type; - }; - -} - -#endif // TORRENT_PEER_INFO_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/peer_request.hpp b/libtorrent/include/libtorrent/peer_request.hpp deleted file mode 100644 index 445ff4d7e..000000000 --- a/libtorrent/include/libtorrent/peer_request.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - -Copyright (c) 2006, 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_PEER_REQUEST_HPP_INCLUDED -#define TORRENT_PEER_REQUEST_HPP_INCLUDED - -namespace libtorrent -{ - struct TORRENT_EXPORT peer_request - { - int piece; - int start; - int length; - bool operator==(peer_request const& r) const - { return piece == r.piece && start == r.start && length == r.length; } - }; -} - -#endif // TORRENT_PEER_REQUEST_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/piece_block_progress.hpp b/libtorrent/include/libtorrent/piece_block_progress.hpp deleted file mode 100644 index 481ffc971..000000000 --- a/libtorrent/include/libtorrent/piece_block_progress.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - -Copyright (c) 2003, 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_PIECE_BLOCK_PROGRESS_HPP_INCLUDED -#define TORRENT_PIECE_BLOCK_PROGRESS_HPP_INCLUDED - -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - struct TORRENT_EXPORT piece_block_progress - { - // the piece and block index - // determines exactly which - // part of the torrent that - // is currently being downloaded - int piece_index; - int block_index; - // the number of bytes we have received - // of this block - int bytes_downloaded; - // the number of bytes in the block - int full_block_bytes; - }; -} - -#endif // TORRENT_PIECE_BLOCK_PROGRESS_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/piece_picker.hpp b/libtorrent/include/libtorrent/piece_picker.hpp deleted file mode 100644 index 7b8612909..000000000 --- a/libtorrent/include/libtorrent/piece_picker.hpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - -Copyright (c) 2003, 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_PIECE_PICKER_HPP_INCLUDED -#define TORRENT_PIECE_PICKER_HPP_INCLUDED - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - class torrent; - class peer_connection; - - struct TORRENT_EXPORT piece_block - { - piece_block(int p_index, int b_index) - : piece_index(p_index) - , block_index(b_index) - {} - int piece_index; - int block_index; - - bool operator<(piece_block const& b) const - { - if (piece_index < b.piece_index) return true; - if (piece_index == b.piece_index) return block_index < b.block_index; - return false; - } - - bool operator==(piece_block const& b) const - { return piece_index == b.piece_index && block_index == b.block_index; } - - bool operator!=(piece_block const& b) const - { return piece_index != b.piece_index || block_index != b.block_index; } - - }; - - class TORRENT_EXPORT piece_picker - { - public: - - struct block_info - { - block_info(): num_downloads(0), requested(0), finished(0) {} - // the peer this block was requested or - // downloaded from - tcp::endpoint peer; - // the number of times this block has been downloaded - unsigned num_downloads:14; - unsigned requested:1; - unsigned finished:1; - }; - - // the peers that are downloading this piece - // are considered fast peers or slow peers. - // none is set if the blocks were downloaded - // in a previous session - enum piece_state_t - { none, slow, medium, fast }; - - struct downloading_piece - { - downloading_piece(): finished(0), requested(0) {} - piece_state_t state; - - // the index of the piece - int index; - // info about each block - // this is a pointer into the m_block_info - // vector owned by the piece_picker - block_info* info; - boost::uint16_t finished; - boost::uint16_t requested; - }; - - piece_picker(int blocks_per_piece - , int total_num_blocks); - - void set_sequenced_download_threshold(int sequenced_download_threshold); - - // the vector tells which pieces we already have - // and which we don't have. - void files_checked( - const std::vector& pieces - , const std::vector& unfinished); - - // increases the peer count for the given piece - // (is used when a HAVE or BITFIELD message is received) - void inc_refcount(int index); - - // decreases the peer count for the given piece - // (used when a peer disconnects) - void dec_refcount(int index); - - // these will increase and decrease the peer count - // of all pieces. They are used when seeds join - // or leave the swarm. - void inc_refcount_all(); - void dec_refcount_all(); - - // This indicates that we just received this piece - // it means that the refcounter will indicate that - // we are not interested in this piece anymore - // (i.e. we don't have to maintain a refcount) - void we_have(int index); - - // sets the priority of a piece. - void set_piece_priority(int index, int prio); - - // returns the priority for the piece at 'index' - int piece_priority(int index) const; - - // returns the current piece priorities for all pieces - void piece_priorities(std::vector& pieces) const; - - // ========== start deprecation ============== - - // fills the bitmask with 1's for pieces that are filtered - void filtered_pieces(std::vector& mask) const; - - // ========== end deprecation ============== - - // pieces should be the vector that represents the pieces a - // client has. It returns a list of all pieces that this client - // has and that are interesting to download. It returns them in - // priority order. It doesn't care about the download flag. - // The user of this function must lookup if any piece is - // marked as being downloaded. If the user of this function - // decides to download a piece, it must mark it as being downloaded - // itself, by using the mark_as_downloading() member function. - // THIS IS DONE BY THE peer_connection::send_request() MEMBER FUNCTION! - // The last argument is the tcp::endpoint of the peer that we'll download - // from. - void pick_pieces(const std::vector& pieces - , std::vector& interesting_blocks - , int num_pieces, bool prefer_whole_pieces - , tcp::endpoint peer, piece_state_t speed) const; - - // returns true if any client is currently downloading this - // piece-block, or if it's queued for downloading by some client - // or if it already has been successfully downloaded - bool is_downloading(piece_block block) const; - bool is_finished(piece_block block) const; - - // marks this piece-block as queued for downloading - void mark_as_downloading(piece_block block, tcp::endpoint const& peer - , piece_state_t s); - void mark_as_finished(piece_block block, tcp::endpoint const& peer); - - // if a piece had a hash-failure, it must be restored and - // made available for redownloading - void restore_piece(int index); - - // clears the given piece's download flag - // this means that this piece-block can be picked again - void abort_download(piece_block block); - - bool is_piece_finished(int index) const; - - // returns the number of blocks there is in the given piece - int blocks_in_piece(int index) const; - - // the number of downloaded blocks that hasn't passed - // the hash-check yet - int unverified_blocks() const; - - void get_downloaders(std::vector& d, int index) const; - - std::vector const& get_download_queue() const - { return m_downloads; } - - boost::optional get_downloader(piece_block block) const; - - // the number of filtered pieces we don't have - int num_filtered() const { return m_num_filtered; } - - // the number of filtered pieces we already have - int num_have_filtered() const { return m_num_have_filtered; } - -#ifndef NDEBUG - // used in debug mode - void check_invariant(const torrent* t = 0) const; -#endif - - // functor that compares indices on downloading_pieces - struct has_index - { - has_index(int i): index(i) { assert(i >= 0); } - bool operator()(const downloading_piece& p) const - { return p.index == index; } - int index; - }; - - int blocks_in_last_piece() const - { return m_blocks_in_last_piece; } - - float distributed_copies() const; - - private: - - struct piece_pos - { - piece_pos() {} - piece_pos(int peer_count_, int index_) - : peer_count(peer_count_) - , downloading(0) - , piece_priority(1) - , index(index_) - { - assert(peer_count_ >= 0); - assert(index_ >= 0); - } - - // selects which vector to look in - unsigned peer_count : 10; - // is 1 if the piece is marked as being downloaded - unsigned downloading : 1; - // is 0 if the piece is filtered (not to be downloaded) - // 1 is normal priority (default) - // 2 is higher priority than pieces at the same availability level - // 3 is same priority as partial pieces - // 4 is higher priority than partial pieces - // 5 and 6 same priority as availability 1 (ignores availability) - // 7 is maximum priority (ignores availability) - unsigned piece_priority : 3; - // index in to the piece_info vector - unsigned index : 18; - - enum - { - // index is set to this to indicate that we have the - // piece. There is no entry for the piece in the - // buckets if this is the case. - we_have_index = 0x3ffff, - // the priority value that means the piece is filtered - filter_priority = 0, - // the max number the peer count can hold - max_peer_count = 0x3ff - }; - - bool have() const { return index == we_have_index; } - void set_have() { index = we_have_index; assert(have()); } - - bool filtered() const { return piece_priority == filter_priority; } - void filtered(bool f) { piece_priority = f ? filter_priority : 0; } - - int priority(int limit) const - { - if (filtered() || have()) return 0; - // pieces we are currently downloading have high priority - int prio = downloading ? (std::min)(1, int(peer_count)) : peer_count * 2; - // if the peer_count is 0 or 1, the priority cannot be higher - if (prio <= 1) return prio; - if (prio >= limit * 2) prio = limit * 2; - // the different priority levels - switch (piece_priority) - { - case 2: return prio - 1; - case 3: return (std::max)(prio / 2, 1); - case 4: return (std::max)(prio / 2 - 1, 1); - case 5: - case 6: return (std::min)(prio / 2 - 1, 2); - case 7: return 1; - } - return prio; - } - - bool operator!=(piece_pos p) const - { return index != p.index || peer_count != p.peer_count; } - - bool operator==(piece_pos p) const - { return index == p.index && peer_count == p.peer_count; } - - }; - - BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 4); - - bool is_ordered(int priority) const - { - return priority >= m_sequenced_download_threshold * 2; - } - - void add(int index); - void move(int vec_index, int elem_index); - - int add_interesting_blocks(const std::vector& piece_list - , const std::vector& pieces - , std::vector& interesting_blocks - , std::vector& backup_blocks - , int num_blocks, bool prefer_whole_pieces - , tcp::endpoint peer, piece_state_t speed) const; - - downloading_piece& add_download_piece(); - void erase_download_piece(std::vector::iterator i); - - // this vector contains all pieces we don't have. - // in the first entry (index 0) is a vector of all pieces - // that no peer have, the vector at index 1 contains - // all pieces that exactly one peer have, index 2 contains - // all pieces exactly two peers have and so on. - // this is not entirely true. The availibility of a piece - // is adjusted depending on its priority. But the principle - // is that the higher index, the lower priority a piece has. - std::vector > m_piece_info; - - // this maps indices to number of peers that has this piece and - // index into the m_piece_info vectors. - // piece_pos::we_have_index means that we have the piece, so it - // doesn't exist in the piece_info buckets - // pieces with the filtered flag set doesn't have entries in - // the m_piece_info buckets either - std::vector m_piece_map; - - // each piece that's currently being downloaded - // has an entry in this list with block allocations. - // i.e. it says wich parts of the piece that - // is being downloaded - std::vector m_downloads; - - // this holds the information of the - // blocks in partially downloaded pieces. - // the first m_blocks_per_piece entries - // in the vector belongs to the first - // entry in m_downloads, the second - // m_blocks_per_piece entries to the - // second entry in m_downloads and so on. - std::vector m_block_info; - - int m_blocks_per_piece; - int m_blocks_in_last_piece; - - // the number of filtered pieces that we don't already - // have. total_number_of_pieces - number_of_pieces_we_have - // - num_filtered is supposed to the number of pieces - // we still want to download - int m_num_filtered; - - // the number of pieces we have that also are filtered - int m_num_have_filtered; - - // the number of pieces we have - int m_num_have; - - // the required popularity of a piece in order to download - // it in sequence instead of random order. - int m_sequenced_download_threshold; -#ifndef NDEBUG - bool m_files_checked_called; -#endif - }; - - inline int piece_picker::blocks_in_piece(int index) const - { - assert(index >= 0); - assert(index < (int)m_piece_map.size()); - if (index+1 == (int)m_piece_map.size()) - return m_blocks_in_last_piece; - else - return m_blocks_per_piece; - } - -} - -#endif // TORRENT_PIECE_PICKER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/policy.hpp b/libtorrent/include/libtorrent/policy.hpp deleted file mode 100644 index 4fa04cb32..000000000 --- a/libtorrent/include/libtorrent/policy.hpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - -Copyright (c) 2003, 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_POLICY_HPP_INCLUDED -#define TORRENT_POLICY_HPP_INCLUDED - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/time.hpp" - -namespace libtorrent -{ - - class torrent; - class peer_connection; - - enum - { - // the limits of the download queue size - min_request_queue = 2, - - // the amount of free upload allowed before - // the peer is choked - free_upload_amount = 4 * 16 * 1024 - }; - - void request_a_block( - torrent& t - , peer_connection& c - , std::vector ignore = std::vector()); - - class TORRENT_EXPORT policy - { - public: - - policy(torrent* t); - - // this is called every 10 seconds to allow - // for peer choking management - void pulse(); - - // this is called once for every peer we get from - // the tracker, pex, lsd or dht. - void peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid - , int source, char flags); - - // called when an incoming connection is accepted - void new_connection(peer_connection& c); - - // the given connection was just closed - void connection_closed(const peer_connection& c); - - // the peer has got at least one interesting piece - void peer_is_interesting(peer_connection& c); - - void piece_finished(int index, bool successfully_verified); - - void block_finished(peer_connection& c, piece_block b); - - // the peer choked us - void choked(peer_connection& c); - - // the peer unchoked us - void unchoked(peer_connection& c); - - // the peer is interested in our pieces - void interested(peer_connection& c); - - // the peer is not interested in our pieces - void not_interested(peer_connection& c); - -#ifndef NDEBUG - bool has_connection(const peer_connection* p); - - void check_invariant() const; -#endif - - struct peer - { - enum connection_type { not_connectable,connectable }; - - peer(const tcp::endpoint& ip, connection_type t, int src); - - size_type total_download() const; - size_type total_upload() const; - - // the ip/port pair this peer is or was connected on - // if it was a remote (incoming) connection, type is - // set thereafter. If it was a peer we got from the - // tracker, type is set to local_connection. - tcp::endpoint ip; - connection_type type; - - // the number of failed connection attempts this peer has - int failcount; - - // this is true if the peer is a seed - bool seed; - - // the time when this peer was optimistically unchoked - // the last time. - libtorrent::ptime last_optimistically_unchoked; - - // the time when the peer connected to us - // or disconnected if it isn't connected right now - libtorrent::ptime connected; - - // this is the accumulated amount of - // uploaded and downloaded data to this - // peer. It only accounts for what was - // shared during the last connection to - // this peer. i.e. These are only updated - // when the connection is closed. For the - // total amount of upload and download - // we'll have to add thes figures with the - // statistics from the peer_connection. - size_type prev_amount_upload; - size_type prev_amount_download; - - // is set to true if this peer has been banned - bool banned; - - // a bitmap combining the peer_source flags - // from peer_info. - int source; - - // if the peer is connected now, this - // will refer to a valid peer_connection - peer_connection* connection; - }; - - int num_peers() const - { - return m_peers.size(); - } - - int num_uploads() const - { - return m_num_unchoked; - } - - typedef std::list::iterator iterator; - typedef std::list::const_iterator const_iterator; - iterator begin_peer() { return m_peers.begin(); } - iterator end_peer() { return m_peers.end(); } - - bool connect_one_peer(); - - private: - - bool unchoke_one_peer(); - void choke_one_peer(); - iterator find_choke_candidate(); - iterator find_unchoke_candidate(); - - // the seed prefix means that the - // function is used while seeding. - bool seed_unchoke_one_peer(); - void seed_choke_one_peer(); - iterator find_seed_choke_candidate(); - iterator find_seed_unchoke_candidate(); - - bool disconnect_one_peer(); - iterator find_disconnect_candidate(); - iterator find_connect_candidate(); - - std::list m_peers; - - torrent* m_torrent; - - // the number of unchoked peers - // at any given time - int m_num_unchoked; - - // free download we have got that hasn't - // been distributed yet. - size_type m_available_free_upload; - - // if there is a connection limit, - // we disconnect one peer every minute in hope of - // establishing a connection with a better peer - ptime m_last_optimistic_disconnect; - }; - -} - -#endif // TORRENT_POLICY_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/random_sample.hpp b/libtorrent/include/libtorrent/random_sample.hpp deleted file mode 100644 index 8d85080df..000000000 --- a/libtorrent/include/libtorrent/random_sample.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -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_RANDOM_SAMPLE_HPP -#define TORRENT_RANDOM_SAMPLE_HPP - -#include -#include - -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - template - inline void random_sample_n(InIter start, InIter end - , OutIter out, Distance n) - { - Distance t = 0; - Distance m = 0; - Distance N = std::distance(start, end); - - assert(N >= n); - - while (m < n) - { - if ((std::rand() / (RAND_MAX + 1.f)) * (N - t) >= n - m) - { - ++start; - ++t; - } - else - { - *out = *start; - ++out; - ++start; - ++t; - ++m; - } - } - } - -} - -#endif diff --git a/libtorrent/include/libtorrent/resource_request.hpp b/libtorrent/include/libtorrent/resource_request.hpp deleted file mode 100644 index 1e41b9cbb..000000000 --- a/libtorrent/include/libtorrent/resource_request.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - -Copyright (c) 2003, Magnus Jonsson, 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_RESOURCE_REQUEST_HPP_INCLUDED -#define TORRENT_RESOURCE_REQUEST_HPP_INCLUDED - -#include - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - struct TORRENT_EXPORT resource_request - { - resource_request() - : used(0) - , min(0) - , max(0) - , given(0) - , leftovers(0) - {} - - resource_request(int used_, int min_, int max_, int given_) - : used(used_) - , min(min_) - , max(max_) - , given(given_) - , leftovers(0) - {} - - int left() const - { - assert(given <= max); - assert(given >= min); - assert(used >= 0); - return (std::max)(given - used, 0); - } - - void reset() { used = leftovers; leftovers = 0; } - - static const int inf = boost::integer_traits::const_max; - - // right now I'm actively using this amount - int used; - - // given cannot be smaller than min - // and not greater than max. - int min; - int max; - - // Reply: Okay, you're allowed to use this amount (a compromise): - int given; - - // this is the amount of resources that exceeded the - // given limit. When the used field is reset (after resources - // have been distributed), it is reset to this number. - int leftovers; - }; -} - - -#endif diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp deleted file mode 100644 index 7cd9961bd..000000000 --- a/libtorrent/include/libtorrent/session.hpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - -Copyright (c) 2006, 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_SESSION_HPP_INCLUDED -#define TORRENT_SESSION_HPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/session_status.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/fingerprint.hpp" - -#include "libtorrent/resource_request.hpp" -#include "libtorrent/storage.hpp" - -#ifdef _MSC_VER -# include -#endif - -namespace libtorrent -{ - struct torrent_plugin; - class torrent; - class ip_filter; - class connection_queue; - - namespace aux - { - // workaround for microsofts - // hardware exceptions that makes - // it hard to debug stuff -#ifdef _MSC_VER - struct eh_initializer - { - eh_initializer() - { - ::_set_se_translator(straight_to_debugger); - } - - static void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*) - { throw; } - }; -#else - struct eh_initializer {}; -#endif - struct session_impl; - - struct filesystem_init - { - filesystem_init(); - }; - - } - - class TORRENT_EXPORT session_proxy - { - friend class session; - public: - session_proxy() {} - private: - session_proxy(boost::shared_ptr impl) - : m_impl(impl) {} - boost::shared_ptr m_impl; - }; - - class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_initializer - { - public: - - session(fingerprint const& print = fingerprint("LT" - , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR, 0, 0)); - session( - fingerprint const& print - , std::pair listen_port_range - , char const* listen_interface = "0.0.0.0"); - - ~session(); - - // returns a list of all torrents in this session - std::vector get_torrents() const; - - // returns an invalid handle in case the torrent doesn't exist - torrent_handle find_torrent(sha1_hash const& info_hash) const; - - // all torrent_handles must be destructed before the session is destructed! - torrent_handle add_torrent( - torrent_info const& ti - , boost::filesystem::path const& save_path - , entry const& resume_data = entry() - , bool compact_mode = true - , int block_size = 16 * 1024 - , storage_constructor_type sc = default_storage_constructor); - - // TODO: deprecated, this is for backwards compatibility only - torrent_handle add_torrent( - entry const& e - , boost::filesystem::path const& save_path - , entry const& resume_data = entry() - , bool compact_mode = true - , int block_size = 16 * 1024 - , storage_constructor_type sc = default_storage_constructor) - { - return add_torrent(torrent_info(e), save_path, resume_data - , compact_mode, block_size, sc); - } - - torrent_handle add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , boost::filesystem::path const& save_path - , entry const& resume_data = entry() - , bool compact_mode = true - , int block_size = 16 * 1024 - , storage_constructor_type sc = default_storage_constructor); - - session_proxy abort() { return session_proxy(m_impl); } - - session_status status() const; - -#ifndef TORRENT_DISABLE_DHT - void start_dht(entry const& startup_state = entry()); - void stop_dht(); - void set_dht_settings(dht_settings const& settings); - entry dht_state() const; - void add_dht_node(std::pair const& node); - void add_dht_router(std::pair const& node); -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::function(torrent*)> ext); -#endif - - void set_ip_filter(ip_filter const& f); - void set_peer_id(peer_id const& pid); - void set_key(int key); - - bool is_listening() const; - - // if the listen port failed in some way - // you can retry to listen on another port- - // range with this function. If the listener - // succeeded and is currently listening, - // a call to this function will shut down the - // listen port and reopen it using these new - // properties (the given interface and port range). - // As usual, if the interface is left as 0 - // this function will return false on failure. - // If it fails, it will also generate alerts describing - // the error. It will return true on success. - bool listen_on( - std::pair const& port_range - , const char* net_interface = 0); - - // returns the port we ended up listening on - unsigned short listen_port() const; - - // Get the number of uploads. - int num_uploads() const; - - // Get the number of connections. This number also contains the - // number of half open connections. - int num_connections() const; - - void remove_torrent(const torrent_handle& h); - - void set_settings(session_settings const& s); - session_settings const& settings(); - - void set_peer_proxy(proxy_settings const& s); - void set_web_seed_proxy(proxy_settings const& s); - void set_tracker_proxy(proxy_settings const& s); - - proxy_settings const& peer_proxy() const; - proxy_settings const& web_seed_proxy() const; - proxy_settings const& tracker_proxy() const; - -#ifndef TORRENT_DISABLE_DHT - void set_dht_proxy(proxy_settings const& s); - proxy_settings const& dht_proxy() const; -#endif - - int upload_rate_limit() const; - int download_rate_limit() const; - - void set_upload_rate_limit(int bytes_per_second); - void set_download_rate_limit(int bytes_per_second); - void set_max_uploads(int limit); - void set_max_connections(int limit); - void set_max_half_open_connections(int limit); - - std::auto_ptr pop_alert(); - void set_severity_level(alert::severity_t s); - - connection_queue& get_connection_queue(); - - // Resource management used for global limits. - resource_request m_ul_bandwidth_quota; - resource_request m_dl_bandwidth_quota; - resource_request m_uploads_quota; - resource_request m_connections_quota; - - private: - - // just a way to initialize boost.filesystem - // before the session_impl is created - aux::filesystem_init m_dummy; - - // data shared between the main thread - // and the working thread - boost::shared_ptr m_impl; - }; - -} - -#endif // TORRENT_SESSION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp deleted file mode 100644 index 363384a70..000000000 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - -Copyright (c) 2003, 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_SESSION_SETTINGS_HPP_INCLUDED -#define TORRENT_SESSION_SETTINGS_HPP_INCLUDED - -#include "libtorrent/version.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - struct TORRENT_EXPORT proxy_settings - { - proxy_settings() : port(0), type(none) {} - - std::string hostname; - int port; - - std::string username; - std::string password; - - enum proxy_type - { - // a plain tcp socket is used, and - // the other settings are ignored. - none, - // the hostname and port settings are - // used to connect to the proxy. No - // username or password is sent. - socks5, - // the hostname and port are used to - // connect to the proxy. the username - // and password are used to authenticate - // with the proxy server. - socks5_pw, - // the http proxy is only available for - // tracker and web seed traffic - // assumes anonymous access to proxy - http, - // http proxy with basic authentication - // uses username and password - http_pw - }; - - proxy_type type; - - }; - - struct TORRENT_EXPORT session_settings - { - session_settings(std::string const& user_agent_ = "libtorrent/" - LIBTORRENT_VERSION) - : user_agent(user_agent_) - , tracker_completion_timeout(60) - , tracker_receive_timeout(20) - , stop_tracker_timeout(10) - , tracker_maximum_response_length(1024*1024) - , piece_timeout(120) - , request_queue_time(3.f) - , max_allowed_in_request_queue(250) - , max_out_request_queue(200) - , whole_pieces_threshold(20) - , peer_timeout(120) - , urlseed_timeout(20) - , urlseed_pipeline_size(5) - , file_pool_size(40) - , allow_multiple_connections_per_ip(false) - , max_failcount(3) - , min_reconnect_time(60) - , peer_connect_timeout(10) - , ignore_limits_on_local_network(true) -#ifndef TORRENT_DISABLE_DHT - , use_dht_as_fallback(true) -#endif - {} - - // this is the user agent that will be sent to the tracker - // when doing requests. It is used to identify the client. - // It cannot contain \r or \n - std::string user_agent; - - // the number of seconds to wait until giving up on a - // tracker request if it hasn't finished - int tracker_completion_timeout; - - // the number of seconds where no data is received - // from the tracker until it should be considered - // as timed out - int tracker_receive_timeout; - - // the time to wait when sending a stopped message - // before considering a tracker to have timed out. - // this is usually shorter, to make the client quit - // faster - int stop_tracker_timeout; - - // if the content-length is greater than this value - // the tracker connection will be aborted - int tracker_maximum_response_length; - - // the number of seconds from a request is sent until - // it times out if no piece response is returned. - int piece_timeout; - - // the length of the request queue given in the number - // of seconds it should take for the other end to send - // all the pieces. i.e. the actual number of requests - // depends on the download rate and this number. - float request_queue_time; - - // the number of outstanding block requests a peer is - // allowed to queue up in the client. If a peer sends - // more requests than this (before the first one has - // been sent) the last request will be dropped. - // the higher this is, the faster upload speeds the - // client can get to a single peer. - int max_allowed_in_request_queue; - - // the maximum number of outstanding requests to - // send to a peer. This limit takes precedence over - // request_queue_time. - int max_out_request_queue; - - // if a whole piece can be downloaded in this number - // of seconds, or less, the peer_connection will prefer - // to request whole pieces at a time from this peer. - // The benefit of this is to better utilize disk caches by - // doing localized accesses and also to make it easier - // to identify bad peers if a piece fails the hash check. - int whole_pieces_threshold; - - // the number of seconds to wait for any activity on - // the peer wire before closing the connectiong due - // to time out. - int peer_timeout; - - // same as peer_timeout, but only applies to url-seeds. - // this is usually set lower, because web servers are - // expected to be more reliable. - int urlseed_timeout; - - // controls the pipelining size of url-seeds - int urlseed_pipeline_size; - - // sets the upper limit on the total number of files this - // session will keep open. The reason why files are - // left open at all is that some anti virus software - // hooks on every file close, and scans the file for - // viruses. deferring the closing of the files will - // be the difference between a usable system and - // a completely hogged down system. Most operating - // systems also has a limit on the total number of - // file descriptors a process may have open. It is - // usually a good idea to find this limit and set the - // number of connections and the number of files - // limits so their sum is slightly below it. - int file_pool_size; - - // false to not allow multiple connections from the same - // IP address. true will allow it. - bool allow_multiple_connections_per_ip; - - // the number of times we can fail to connect to a peer - // before we stop retrying it. - int max_failcount; - - // the number of seconds to wait to reconnect to a peer. - // this time is multiplied with the failcount. - int min_reconnect_time; - - // this is the timeout for a connection attempt. If - // the connect does not succeed within this time, the - // connection is dropped. The time is specified in seconds. - int peer_connect_timeout; - - // if set to true, upload, download and unchoke limits - // are ignored for peers on the local network - bool ignore_limits_on_local_network; - -#ifndef TORRENT_DISABLE_DHT - // while this is true, the dht will note be used unless the - // tracker is online - bool use_dht_as_fallback; -#endif - }; - -#ifndef TORRENT_DISABLE_DHT - struct dht_settings - { - dht_settings() - : max_peers_reply(50) - , search_branching(5) - , service_port(0) - , max_fail_count(20) - {} - - // the maximum number of peers to send in a - // reply to get_peers - int max_peers_reply; - - // the number of simultanous "connections" when - // searching the DHT. - int search_branching; - - // the listen port for the dht. This is a UDP port. - // zero means use the same as the tcp interface - int service_port; - - // the maximum number of times a node can fail - // in a row before it is removed from the table. - int max_fail_count; - }; -#endif - -} - -#endif diff --git a/libtorrent/include/libtorrent/session_status.hpp b/libtorrent/include/libtorrent/session_status.hpp deleted file mode 100644 index adbb1b57d..000000000 --- a/libtorrent/include/libtorrent/session_status.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - -Copyright (c) 2006, 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_SESSION_STATUS_HPP_INCLUDED -#define TORRENT_SESSION_STATUS_HPP_INCLUDED - - -namespace libtorrent -{ - - struct TORRENT_EXPORT session_status - { - bool has_incoming_connections; - - float upload_rate; - float download_rate; - - float payload_upload_rate; - float payload_download_rate; - - size_type total_download; - size_type total_upload; - - size_type total_payload_download; - size_type total_payload_upload; - - int num_peers; - -#ifndef TORRENT_DISABLE_DHT - int dht_nodes; - int dht_node_cache; - int dht_torrents; - size_type dht_global_nodes; -#endif - }; - -} - -#endif // TORRENT_SESSION_STATUS_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/size_type.hpp b/libtorrent/include/libtorrent/size_type.hpp deleted file mode 100644 index 6020a5ac3..000000000 --- a/libtorrent/include/libtorrent/size_type.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - -Copyright (c) 2003, 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_SIZE_TYPE_HPP_INCLUDED -#define TORRENT_SIZE_TYPE_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - typedef boost::int64_t size_type; -} - - -#endif diff --git a/libtorrent/include/libtorrent/socket.hpp b/libtorrent/include/libtorrent/socket.hpp deleted file mode 100644 index c478a92ef..000000000 --- a/libtorrent/include/libtorrent/socket.hpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - -Copyright (c) 2003, 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_SOCKET_HPP_INCLUDED -#define TORRENT_SOCKET_HPP_INCLUDED - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -// if building as Objective C++, asio's template -// parameters Protocol has to be renamed to avoid -// colliding with keywords - -#ifdef __OBJC__ -#define Protocol Protocol_ -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __OBJC__ -#undef Protocol -#endif - -#include "libtorrent/io.hpp" -#include "libtorrent/time.hpp" - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -namespace libtorrent -{ - -/* - namespace asio = boost::asio; - - using boost::asio::ipv4::tcp; - using boost::asio::ipv4::address; - using boost::asio::stream_socket; - using boost::asio::datagram_socket; - using boost::asio::socket_acceptor; - using boost::asio::io_service; - using boost::asio::ipv4::host_resolver; - using boost::asio::async_write; - using boost::asio::ipv4::host; - using boost::asio::deadline_timer; -*/ -// namespace asio = ::asio; - - using asio::ip::tcp; - using asio::ip::udp; - typedef asio::ip::tcp::socket stream_socket; - typedef asio::ip::address address; - typedef asio::ip::address_v4 address_v4; - typedef asio::ip::address_v6 address_v6; - typedef asio::ip::udp::socket datagram_socket; - typedef asio::ip::tcp::acceptor socket_acceptor; - typedef asio::io_service io_service; - - using asio::async_write; - - typedef asio::basic_deadline_timer deadline_timer; - - namespace detail - { - template - void write_address(address const& a, OutIt& out) - { - if (a.is_v4()) - { - write_uint32(a.to_v4().to_ulong(), out); - } - else if (a.is_v6()) - { - asio::ip::address_v6::bytes_type bytes - = a.to_v6().to_bytes(); - std::copy(bytes.begin(), bytes.end(), out); - } - } - - template - address read_v4_address(InIt& in) - { - unsigned long ip = read_uint32(in); - return asio::ip::address_v4(ip); - } - - template - address read_v6_address(InIt& in) - { - typedef asio::ip::address_v6::bytes_type bytes_t; - bytes_t bytes; - for (bytes_t::iterator i = bytes.begin() - , end(bytes.end()); i != end; ++i) - *i = read_uint8(in); - return asio::ip::address_v6(bytes); - } - - template - void write_endpoint(Endpoint const& e, OutIt& out) - { - write_address(e.address(), out); - write_uint16(e.port(), out); - } - - template - Endpoint read_v4_endpoint(InIt& in) - { - address addr = read_v4_address(in); - int port = read_uint16(in); - return Endpoint(addr, port); - } - - template - Endpoint read_v6_endpoint(InIt& in) - { - address addr = read_v6_address(in); - int port = read_uint16(in); - return Endpoint(addr, port); - } - } -} - -#endif // TORRENT_SOCKET_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/socket_type.hpp b/libtorrent/include/libtorrent/socket_type.hpp deleted file mode 100644 index f81d12342..000000000 --- a/libtorrent/include/libtorrent/socket_type.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - -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_SOCKET_TYPE -#define TORRENT_SOCKET_TYPE - -#include "libtorrent/socks5_stream.hpp" -#include "libtorrent/http_stream.hpp" -#include "libtorrent/variant_stream.hpp" - -namespace libtorrent -{ - typedef variant_stream socket_type; -} - -#endif - diff --git a/libtorrent/include/libtorrent/socks5_stream.hpp b/libtorrent/include/libtorrent/socks5_stream.hpp deleted file mode 100644 index 9e8a0d04b..000000000 --- a/libtorrent/include/libtorrent/socks5_stream.hpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "libtorrent/io.hpp" -#include "libtorrent/socket.hpp" -#include -#include -#include -#include -#include - - -namespace libtorrent { - -class socks5_stream : boost::noncopyable -{ -public: - - typedef stream_socket::lowest_layer_type lowest_layer_type; - typedef stream_socket::endpoint_type endpoint_type; - typedef stream_socket::protocol_type protocol_type; - - explicit socks5_stream(asio::io_service& io_service) - : m_sock(io_service) - , m_resolver(io_service) - {} - - void set_proxy(std::string hostname, int port) - { - m_hostname = hostname; - m_port = port; - } - - void set_username(std::string const& user - , std::string const& password) - { - m_user = user; - m_password = password; - } - - template - void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) - { - m_sock.async_read_some(buffers, handler); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec) - { - return m_sock.read_some(buffers, ec); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers) - { - return m_sock.read_some(buffers); - } - - template - void io_control(IO_Control_Command& ioc) - { - m_sock.io_control(ioc); - } - - template - void io_control(IO_Control_Command& ioc, asio::error_code& ec) - { - m_sock.io_control(ioc, ec); - } - - template - void async_write_some(Const_Buffers const& buffers, Handler const& handler) - { - m_sock.async_write_some(buffers, handler); - } - - void bind(endpoint_type const& endpoint) - { - m_sock.bind(endpoint); - } - - template - void bind(endpoint_type const& endpoint, Error_Handler const& error_handler) - { - m_sock.bind(endpoint, error_handler); - } - - void open(protocol_type const& p) - { - m_sock.open(p); - } - - template - void open(protocol_type const& p, Error_Handler const& error_handler) - { - m_sock.open(p, error_handler); - } - - void close() - { - m_remote_endpoint = endpoint_type(); - m_sock.close(); - } - - template - void close(Error_Handler const& error_handler) - { - m_sock.close(error_handler); - } - - endpoint_type remote_endpoint() - { - return m_remote_endpoint; - } - - template - endpoint_type remote_endpoint(Error_Handler const& error_handler) - { - return m_remote_endpoint; - } - - endpoint_type local_endpoint() - { - return m_sock.local_endpoint(); - } - - template - endpoint_type local_endpoint(Error_Handler const& error_handler) - { - return m_sock.local_endpoint(error_handler); - } - - asio::io_service& io_service() - { - return m_sock.io_service(); - } - - lowest_layer_type& lowest_layer() - { - return m_sock.lowest_layer(); - } - - typedef boost::function handler_type; - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - m_remote_endpoint = endpoint; - - // the connect is split up in the following steps: - // 1. resolve name of proxy server - // 2. connect to proxy server - // 3. send SOCKS5 authentication method message - // 4. read SOCKS5 authentication response - // 5. send username+password - // 6. send SOCKS5 CONNECT message - - // to avoid unnecessary copying of the handler, - // store it in a shaed_ptr - boost::shared_ptr h(new handler_type(handler)); - - tcp::resolver::query q(m_hostname - , boost::lexical_cast(m_port)); - m_resolver.async_resolve(q, boost::bind( - &socks5_stream::name_lookup, this, _1, _2, h)); - } - -private: - - void name_lookup(asio::error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h); - void connected(asio::error_code const& e, boost::shared_ptr h); - void handshake1(asio::error_code const& e, boost::shared_ptr h); - void handshake2(asio::error_code const& e, boost::shared_ptr h); - void handshake3(asio::error_code const& e, boost::shared_ptr h); - void handshake4(asio::error_code const& e, boost::shared_ptr h); - void socks_connect(boost::shared_ptr h); - void connect1(asio::error_code const& e, boost::shared_ptr h); - void connect2(asio::error_code const& e, boost::shared_ptr h); - void connect3(asio::error_code const& e, boost::shared_ptr h); - - stream_socket m_sock; - // the socks5 proxy - std::string m_hostname; - int m_port; - // send and receive buffer - std::vector m_buffer; - // proxy authentication - std::string m_user; - std::string m_password; - - endpoint_type m_remote_endpoint; - - tcp::resolver m_resolver; -}; - -} - diff --git a/libtorrent/include/libtorrent/stat.hpp b/libtorrent/include/libtorrent/stat.hpp deleted file mode 100644 index 8e92c12a1..000000000 --- a/libtorrent/include/libtorrent/stat.hpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - -Copyright (c) 2003, 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_STAT_HPP_INCLUDED -#define TORRENT_STAT_HPP_INCLUDED - -#include -#include -#include - -#include "libtorrent/size_type.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - - class TORRENT_EXPORT stat - { - friend class invariant_access; - enum { history = 10 }; - public: - - stat() - : m_downloaded_payload(0) - , m_uploaded_payload(0) - , m_downloaded_protocol(0) - , m_uploaded_protocol(0) - , m_total_download_payload(0) - , m_total_upload_payload(0) - , m_total_download_protocol(0) - , m_total_upload_protocol(0) - , m_mean_download_rate(0) - , m_mean_upload_rate(0) - , m_mean_download_payload_rate(0) - , m_mean_upload_payload_rate(0) - { - std::fill(m_download_rate_history, m_download_rate_history+history, 0.f); - std::fill(m_upload_rate_history, m_upload_rate_history+history, 0.f); - std::fill(m_download_payload_rate_history, m_download_payload_rate_history+history, 0.f); - std::fill(m_upload_payload_rate_history, m_upload_payload_rate_history+history, 0.f); - } - - void operator+=(const stat& s) - { - INVARIANT_CHECK; - - m_downloaded_payload += s.m_downloaded_payload; - m_total_download_payload += s.m_downloaded_payload; - m_downloaded_protocol += s.m_downloaded_protocol; - m_total_download_protocol += s.m_downloaded_protocol; - - m_uploaded_payload += s.m_uploaded_payload; - m_total_upload_payload += s.m_uploaded_payload; - m_uploaded_protocol += s.m_uploaded_protocol; - m_total_upload_protocol += s.m_uploaded_protocol; - } - - void received_bytes(int bytes_payload, int bytes_protocol) - { - INVARIANT_CHECK; - - assert(bytes_payload >= 0); - assert(bytes_protocol >= 0); - - m_downloaded_payload += bytes_payload; - m_total_download_payload += bytes_payload; - m_downloaded_protocol += bytes_protocol; - m_total_download_protocol += bytes_protocol; - } - - void sent_bytes(int bytes_payload, int bytes_protocol) - { - INVARIANT_CHECK; - - assert(bytes_payload >= 0); - assert(bytes_protocol >= 0); - - m_uploaded_payload += bytes_payload; - m_total_upload_payload += bytes_payload; - m_uploaded_protocol += bytes_protocol; - m_total_upload_protocol += bytes_protocol; - } - - // should be called once every second - void second_tick(float tick_interval); - - float upload_rate() const { return m_mean_upload_rate; } - float download_rate() const { return m_mean_download_rate; } - - float upload_payload_rate() const { return m_mean_upload_payload_rate; } - float download_payload_rate() const { return m_mean_download_payload_rate; } - - size_type total_payload_upload() const { return m_total_upload_payload; } - size_type total_payload_download() const { return m_total_download_payload; } - - size_type total_protocol_upload() const { return m_total_upload_protocol; } - size_type total_protocol_download() const { return m_total_download_protocol; } - - // this is used to offset the statistics when a - // peer_connection is opened and have some previous - // transfers from earlier connections. - void add_stat(size_type downloaded, size_type uploaded) - { - m_total_download_payload += downloaded; - m_total_upload_payload += uploaded; - } - - private: - -#ifndef NDEBUG - void check_invariant() const - { - assert(m_mean_upload_rate >= 0); - assert(m_mean_download_rate >= 0); - assert(m_mean_upload_payload_rate >= 0); - assert(m_mean_download_payload_rate >= 0); - assert(m_total_upload_payload >= 0); - assert(m_total_download_payload >= 0); - assert(m_total_upload_protocol >= 0); - assert(m_total_download_protocol >= 0); - } -#endif - - // history of download/upload speeds a few seconds back - float m_download_rate_history[history]; - float m_upload_rate_history[history]; - - float m_download_payload_rate_history[history]; - float m_upload_payload_rate_history[history]; - - // the accumulators we are adding the downloads/uploads - // to this second. This only counts the actual payload - // and ignores the bytes sent as protocol chatter. - int m_downloaded_payload; - int m_uploaded_payload; - - // the accumulators we are adding the downloads/uploads - // to this second. This only counts the protocol - // chatter and ignores the actual payload - int m_downloaded_protocol; - int m_uploaded_protocol; - - // total download/upload counters - // only counting payload data - size_type m_total_download_payload; - size_type m_total_upload_payload; - - // total download/upload counters - // only counting protocol chatter - size_type m_total_download_protocol; - size_type m_total_upload_protocol; - - // current mean download/upload rates - float m_mean_download_rate; - float m_mean_upload_rate; - - float m_mean_download_payload_rate; - float m_mean_upload_payload_rate; - }; - -} - -#endif // TORRENT_STAT_HPP_INCLUDED diff --git a/libtorrent/include/libtorrent/storage.hpp b/libtorrent/include/libtorrent/storage.hpp deleted file mode 100644 index ccb17cb71..000000000 --- a/libtorrent/include/libtorrent/storage.hpp +++ /dev/null @@ -1,205 +0,0 @@ -/* - -Copyright (c) 2003, 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_STORAGE_HPP_INCLUDE -#define TORRENT_STORAGE_HPP_INCLUDE - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - namespace aux - { - struct piece_checker_data; - } - - class session; - struct file_pool; - -#if defined(_WIN32) && defined(UNICODE) - - TORRENT_EXPORT std::wstring safe_convert(std::string const& s); - -#endif - - TORRENT_EXPORT std::vector > get_filesizes( - torrent_info const& t - , boost::filesystem::path p); - - TORRENT_EXPORT bool match_filesizes( - torrent_info const& t - , boost::filesystem::path p - , std::vector > const& sizes - , bool compact_mode - , std::string* error = 0); - - struct TORRENT_EXPORT file_allocation_failed: std::exception - { - file_allocation_failed(const char* error_msg): m_msg(error_msg) {} - virtual const char* what() const throw() { return m_msg.c_str(); } - virtual ~file_allocation_failed() throw() {} - std::string m_msg; - }; - - struct TORRENT_EXPORT storage_interface - { - // create directories and set file sizes - // if allocate_files is true. - // allocate_files is true if allocation mode - // is set to full and sparse files are supported - virtual void initialize(bool allocate_files) = 0; - - // may throw file_error if storage for slot does not exist - virtual size_type read(char* buf, int slot, int offset, int size) = 0; - - // may throw file_error if storage for slot hasn't been allocated - virtual void write(const char* buf, int slot, int offset, int size) = 0; - - virtual bool move_storage(boost::filesystem::path save_path) = 0; - - // verify storage dependent fast resume entries - virtual bool verify_resume_data(entry& rd, std::string& error) = 0; - - // write storage dependent fast resume entries - virtual void write_resume_data(entry& rd) const = 0; - - // moves (or copies) the content in src_slot to dst_slot - virtual void move_slot(int src_slot, int dst_slot) = 0; - - // swaps the data in slot1 and slot2 - virtual void swap_slots(int slot1, int slot2) = 0; - - // swaps the puts the data in slot1 in slot2, the data in slot2 - // in slot3 and the data in slot3 in slot1 - virtual void swap_slots3(int slot1, int slot2, int slot3) = 0; - - // this will close all open files that are opened for - // writing. This is called when a torrent has finished - // downloading. - virtual void release_files() = 0; - virtual ~storage_interface() {} - }; - - typedef storage_interface* (&storage_constructor_type)( - torrent_info const&, boost::filesystem::path const& - , file_pool&); - - TORRENT_EXPORT storage_interface* default_storage_constructor(torrent_info const& ti - , boost::filesystem::path const& path, file_pool& fp); - - // returns true if the filesystem the path relies on supports - // sparse files or automatic zero filling of files. - TORRENT_EXPORT bool supports_sparse_files(boost::filesystem::path const& p); - - class TORRENT_EXPORT piece_manager : boost::noncopyable - { - public: - - piece_manager( - const torrent_info& info - , const boost::filesystem::path& path - , file_pool& fp - , storage_constructor_type sc); - - ~piece_manager(); - - bool check_fastresume(aux::piece_checker_data& d - , std::vector& pieces, int& num_pieces, bool compact_mode); - std::pair check_files(std::vector& pieces - , int& num_pieces, boost::recursive_mutex& mutex); - - void release_files(); - - void write_resume_data(entry& rd) const; - bool verify_resume_data(entry& rd, std::string& error); - - bool is_allocating() const; - bool allocate_slots(int num_slots, bool abort_on_disk = false); - void mark_failed(int index); - - unsigned long piece_crc( - int slot_index - , int block_size - , piece_picker::block_info const* bi); - int slot_for_piece(int piece_index) const; - - size_type read( - char* buf - , int piece_index - , int offset - , int size); - - void write( - const char* buf - , int piece_index - , int offset - , int size); - - boost::filesystem::path const& save_path() const; - bool move_storage(boost::filesystem::path const&); - - // fills the vector that maps all allocated - // slots to the piece that is stored (or - // partially stored) there. -2 is the index - // of unassigned pieces and -1 is unallocated - void export_piece_map(std::vector& pieces) const; - - bool compact_allocation() const; - - private: - class impl; - std::auto_ptr m_pimpl; - }; - -} - -#endif // TORRENT_STORAGE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/time.hpp b/libtorrent/include/libtorrent/time.hpp deleted file mode 100644 index 2470522c0..000000000 --- a/libtorrent/include/libtorrent/time.hpp +++ /dev/null @@ -1,383 +0,0 @@ -/* - -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_TIME_HPP_INCLUDED -#define TORRENT_TIME_HPP_INCLUDED - -#include - -#ifndef _WIN32 -#include -#endif - -namespace libtorrent -{ - inline char const* time_now_string() - { - time_t t = std::time(0); - tm* timeinfo = std::localtime(&t); - static char str[200]; - std::strftime(str, 200, "%b %d %X", timeinfo); - return str; - } -} - -#if (!defined (__MACH__) && !defined (_WIN32) && !defined(_POSIX_MONOTONIC_CLOCK) || _POSIX_MONOTONIC_CLOCK < 0) || defined (TORRENT_USE_BOOST_DATE_TIME) - -#include - -namespace libtorrent -{ - typedef boost::posix_time::ptime ptime; - typedef boost::posix_time::time_duration time_duration; - inline ptime time_now() - { return boost::posix_time::microsec_clock::universal_time(); } - inline ptime min_time() - { return boost::posix_time::ptime(boost::posix_time::min_date_time); } - inline ptime max_time() - { return boost::posix_time::ptime(boost::posix_time::max_date_time); } - inline time_duration seconds(int s) { return boost::posix_time::seconds(s); } - inline time_duration milliseconds(int s) { return boost::posix_time::milliseconds(s); } - inline time_duration microsec(int s) { return boost::posix_time::microsec(s); } - inline time_duration minutes(int s) { return boost::posix_time::minutes(s); } - inline time_duration hours(int s) { return boost::posix_time::hours(s); } - - inline int total_seconds(time_duration td) - { return td.total_seconds(); } - inline int total_milliseconds(time_duration td) - { return td.total_milliseconds(); } - inline boost::int64_t total_microseconds(time_duration td) - { return td.total_microseconds(); } - -} - -#else - -#include -#include - -namespace libtorrent -{ - // libtorrent time_duration type - struct time_duration - { - time_duration() {} - time_duration operator/(int rhs) const { return time_duration(diff / rhs); } - explicit time_duration(boost::int64_t d) : diff(d) {} - boost::int64_t diff; - }; - - inline bool is_negative(time_duration dt) { return dt.diff < 0; } - inline bool operator<(time_duration lhs, time_duration rhs) - { return lhs.diff < rhs.diff; } - inline bool operator>(time_duration lhs, time_duration rhs) - { return lhs.diff > rhs.diff; } - - // libtorrent time type - struct ptime - { - ptime() {} - explicit ptime(boost::int64_t t): time(t) {} - boost::int64_t time; - }; - - inline bool operator>(ptime lhs, ptime rhs) - { return lhs.time > rhs.time; } - inline bool operator>=(ptime lhs, ptime rhs) - { return lhs.time >= rhs.time; } - inline bool operator<=(ptime lhs, ptime rhs) - { return lhs.time <= rhs.time; } - inline bool operator<(ptime lhs, ptime rhs) - { return lhs.time < rhs.time; } - inline bool operator!=(ptime lhs, ptime rhs) - { return lhs.time != rhs.time;} - inline bool operator==(ptime lhs, ptime rhs) - { return lhs.time == rhs.time;} - inline time_duration operator-(ptime lhs, ptime rhs) - { return time_duration(lhs.time - rhs.time); } - inline ptime operator+(ptime lhs, time_duration rhs) - { return ptime(lhs.time + rhs.diff); } - inline ptime operator+(time_duration lhs, ptime rhs) - { return ptime(rhs.time + lhs.diff); } - inline ptime operator-(ptime lhs, time_duration rhs) - { return ptime(lhs.time - rhs.diff); } - - ptime time_now(); - inline ptime min_time() { return ptime(0); } - inline ptime max_time() { return ptime((std::numeric_limits::max)()); } - int total_seconds(time_duration td); - int total_milliseconds(time_duration td); - boost::int64_t total_microseconds(time_duration td); -} - -// asio time_traits -namespace asio -{ - template<> - struct time_traits - { - typedef libtorrent::ptime time_type; - typedef libtorrent::time_duration duration_type; - static time_type now() - { return time_type(libtorrent::time_now()); } - static time_type add(time_type t, duration_type d) - { return time_type(t.time + d.diff);} - static duration_type subtract(time_type t1, time_type t2) - { return duration_type(t1 - t2); } - static bool less_than(time_type t1, time_type t2) - { return t1 < t2; } - static boost::posix_time::time_duration to_posix_duration( - duration_type d) - { return boost::posix_time::microseconds(libtorrent::total_microseconds(d)); } - }; -} - -#if defined(__MACH__) - -#include -#include - -// high precision timer for darwin intel and ppc - -namespace libtorrent -{ - namespace aux - { - inline boost::int64_t absolutetime_to_microseconds(boost::int64_t at) - { - static mach_timebase_info_data_t timebase_info = {0,0}; - if (timebase_info.denom == 0) - mach_timebase_info(&timebase_info); - // make sure we don't overflow - assert((at >= 0 && at >= at / 1000 * timebase_info.numer / timebase_info.denom) - || (at < 0 && at < at / 1000 * timebase_info.numer / timebase_info.denom)); - return at / 1000 * timebase_info.numer / timebase_info.denom; - } - - inline boost::int64_t microseconds_to_absolutetime(boost::int64_t ms) - { - static mach_timebase_info_data_t timebase_info = {0,0}; - if (timebase_info.denom == 0) - { - mach_timebase_info(&timebase_info); - assert(timebase_info.numer > 0); - assert(timebase_info.denom > 0); - } - // make sure we don't overflow - assert((ms >= 0 && ms <= ms * timebase_info.denom / timebase_info.numer * 1000) - || (ms < 0 && ms > ms * timebase_info.denom / timebase_info.numer * 1000)); - return ms * timebase_info.denom / timebase_info.numer * 1000; - } - } - - inline int total_seconds(time_duration td) - { - return aux::absolutetime_to_microseconds(td.diff) - / 1000000; - } - inline int total_milliseconds(time_duration td) - { - return aux::absolutetime_to_microseconds(td.diff) - / 1000; - } - inline boost::int64_t total_microseconds(time_duration td) - { - return aux::absolutetime_to_microseconds(td.diff); - } - - inline ptime time_now() { return ptime(mach_absolute_time()); } - - inline time_duration microsec(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s)); - } - inline time_duration milliseconds(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s * 1000)); - } - inline time_duration seconds(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s * 1000000)); - } - inline time_duration minutes(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60)); - } - inline time_duration hours(boost::int64_t s) - { - return time_duration(aux::microseconds_to_absolutetime(s * 1000000 * 60 * 60)); - } - -} -#elif defined(_WIN32) - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include - -namespace libtorrent -{ - namespace aux - { - inline boost::int64_t performance_counter_to_microseconds(boost::int64_t pc) - { - static LARGE_INTEGER performace_counter_frequency = {0,0}; - if (performace_counter_frequency.QuadPart == 0) - QueryPerformanceFrequency(&performace_counter_frequency); - -#ifndef NDEBUG - // make sure we don't overflow - boost::int64_t ret = (pc * 1000 / performace_counter_frequency.QuadPart) * 1000; - assert((pc >= 0 && pc >= ret) || (pc < 0 && pc < ret)); -#endif - return (pc * 1000 / performace_counter_frequency.QuadPart) * 1000; - } - - inline boost::int64_t microseconds_to_performance_counter(boost::int64_t ms) - { - static LARGE_INTEGER performace_counter_frequency = {0,0}; - if (performace_counter_frequency.QuadPart == 0) - QueryPerformanceFrequency(&performace_counter_frequency); -#ifndef NDEBUG - // make sure we don't overflow - boost::int64_t ret = (ms / 1000) * performace_counter_frequency.QuadPart / 1000; - assert((ms >= 0 && ms <= ret) - || (ms < 0 && ms > ret)); -#endif - return (ms / 1000) * performace_counter_frequency.QuadPart / 1000; - } - } - - inline int total_seconds(time_duration td) - { - return aux::performance_counter_to_microseconds(td.diff) - / 1000000; - } - inline int total_milliseconds(time_duration td) - { - return aux::performance_counter_to_microseconds(td.diff) - / 1000; - } - inline boost::int64_t total_microseconds(time_duration td) - { - return aux::performance_counter_to_microseconds(td.diff); - } - - inline ptime time_now() - { - LARGE_INTEGER now; - QueryPerformanceCounter(&now); - return ptime(now.QuadPart); - } - - inline time_duration microsec(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter(s)); - } - inline time_duration milliseconds(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter( - s * 1000)); - } - inline time_duration seconds(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter( - s * 1000000)); - } - inline time_duration minutes(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter( - s * 1000000 * 60)); - } - inline time_duration hours(boost::int64_t s) - { - return time_duration(aux::microseconds_to_performance_counter( - s * 1000000 * 60 * 60)); - } - -} - -#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 - -#include - -namespace libtorrent -{ - inline int total_seconds(time_duration td) - { - return td.diff / 1000000; - } - inline int total_milliseconds(time_duration td) - { - return td.diff / 1000; - } - inline boost::int64_t total_microseconds(time_duration td) - { - return td.diff; - } - - inline ptime time_now() - { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ptime(boost::int64_t(ts.tv_sec) * 1000000 + ts.tv_nsec / 1000); - } - - inline time_duration microsec(boost::int64_t s) - { - return time_duration(s); - } - inline time_duration milliseconds(boost::int64_t s) - { - return time_duration(s * 1000); - } - inline time_duration seconds(boost::int64_t s) - { - return time_duration(s * 1000000); - } - inline time_duration minutes(boost::int64_t s) - { - return time_duration(s * 1000000 * 60); - } - inline time_duration hours(boost::int64_t s) - { - return time_duration(s * 1000000 * 60 * 60); - } - -} - -#endif - -#endif -#endif - diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp deleted file mode 100644 index 7194463e9..000000000 --- a/libtorrent/include/libtorrent/torrent.hpp +++ /dev/null @@ -1,771 +0,0 @@ -/* - -Copyright (c) 2003, 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_TORRENT_HPP_INCLUDE -#define TORRENT_TORRENT_HPP_INCLUDE - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/resource_request.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/escape_string.hpp" -#include "libtorrent/bandwidth_manager.hpp" -#include "libtorrent/storage.hpp" - -namespace libtorrent -{ -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - struct logger; -#endif - - class piece_manager; - struct torrent_plugin; - - namespace aux - { - struct session_impl; - struct piece_checker_data; - } - - // a torrent is a class that holds information - // for a specific download. It updates itself against - // the tracker - class TORRENT_EXPORT torrent: public request_callback - , public boost::enable_shared_from_this - { - public: - - torrent( - aux::session_impl& ses - , aux::checker_impl& checker - , torrent_info const& tf - , boost::filesystem::path const& save_path - , tcp::endpoint const& net_interface - , bool compact_mode - , int block_size - , session_settings const& s - , storage_constructor_type sc); - - // used with metadata-less torrents - // (the metadata is downloaded from the peers) - torrent( - aux::session_impl& ses - , aux::checker_impl& checker - , char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , boost::filesystem::path const& save_path - , tcp::endpoint const& net_interface - , bool compact_mode - , int block_size - , session_settings const& s - , storage_constructor_type sc); - - ~torrent(); - - // starts the announce timer - void start(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - void add_extension(boost::shared_ptr); -#endif - - // this is called when the torrent has metadata. - // it will initialize the storage and the piece-picker - void init(); - - // this will flag the torrent as aborted. The main - // loop in session_impl will check for this state - // on all torrents once every second, and take - // the necessary actions then. - void abort(); - bool is_aborted() const { return m_abort; } - - // returns true if this torrent is being allocated - // by the checker thread. - bool is_allocating() const; - - session_settings const& settings() const; - - aux::session_impl& session() { return m_ses; } - - void set_sequenced_download_threshold(int threshold); - - bool verify_resume_data(entry& rd, std::string& error) - { assert(m_storage); return m_storage->verify_resume_data(rd, error); } - - // is called every second by session. This will - // caclulate the upload/download and number - // of connections this torrent needs. And prepare - // it for being used by allocate_resources. - void second_tick(stat& accumulator, float tick_interval); - - // debug purpose only - void print(std::ostream& os) const; - - std::string name() const; - - bool check_fastresume(aux::piece_checker_data&); - std::pair check_files(); - void files_checked(std::vector const& - unfinished_pieces); - - stat statistics() const { return m_stat; } - size_type bytes_left() const; - boost::tuples::tuple bytes_done() const; - size_type quantized_bytes_done() const; - - void pause(); - void resume(); - bool is_paused() const { return m_paused; } - - // ============ start deprecation ============= - void filter_piece(int index, bool filter); - void filter_pieces(std::vector const& bitmask); - bool is_piece_filtered(int index) const; - void filtered_pieces(std::vector& bitmask) const; - void filter_files(std::vector const& files); - // ============ end deprecation ============= - - void set_piece_priority(int index, int priority); - int piece_priority(int index) const; - - void prioritize_pieces(std::vector const& pieces); - void piece_priorities(std::vector&) const; - - void prioritize_files(std::vector const& files); - - torrent_status status() const; - void file_progress(std::vector& fp) const; - - void use_interface(const char* net_interface); - tcp::endpoint const& get_interface() const { return m_net_interface; } - - void connect_to_url_seed(std::string const& url); - peer_connection* connect_to_peer(policy::peer* peerinfo); - - void set_ratio(float ratio) - { assert(ratio >= 0.0f); m_ratio = ratio; } - - float ratio() const - { return m_ratio; } - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void resolve_countries(bool r) - { m_resolve_countries = r; } - - bool resolving_countries() const { return m_resolve_countries; } -#endif - -// -------------------------------------------- - // BANDWIDTH MANAGEMENT - - bandwidth_limit m_bandwidth_limit[2]; - - void request_bandwidth(int channel - , boost::intrusive_ptr p - , bool non_prioritized); - - void expire_bandwidth(int channel, int amount); - void assign_bandwidth(int channel, int amount); - - int bandwidth_throttle(int channel) const; - -// -------------------------------------------- - // PEER MANAGEMENT - - // add or remove a url that will be attempted for - // finding the file(s) in this torrent. - void add_url_seed(std::string const& url) - { m_web_seeds.insert(url); } - - void remove_url_seed(std::string const& url) - { m_web_seeds.erase(url); } - - // used by peer_connection to attach itself to a torrent - // since incoming connections don't know what torrent - // they're a part of until they have received an info_hash. - void attach_peer(peer_connection* p); - - // this will remove the peer and make sure all - // the pieces it had have their reference counter - // decreased in the piece_picker - void remove_peer(peer_connection* p); - - bool want_more_peers() const; - void try_connect_peer(); - - peer_connection* connection_for(tcp::endpoint const& a) - { - peer_iterator i = m_connections.find(a); - if (i == m_connections.end()) return 0; - return i->second; - } - - // the number of peers that belong to this torrent - int num_peers() const { return (int)m_connections.size(); } - int num_seeds() const; - - typedef std::map::iterator peer_iterator; - typedef std::map::const_iterator const_peer_iterator; - - const_peer_iterator begin() const { return m_connections.begin(); } - const_peer_iterator end() const { return m_connections.end(); } - - peer_iterator begin() { return m_connections.begin(); } - peer_iterator end() { return m_connections.end(); } - - void resolve_peer_country(boost::intrusive_ptr const& p) const; - -// -------------------------------------------- - // TRACKER MANAGEMENT - - // these are callbacks called by the tracker_connection instance - // (either http_tracker_connection or udp_tracker_connection) - // when this torrent got a response from its tracker request - // or when a failure occured - virtual void tracker_response( - tracker_request const& r - , std::vector& e, int interval - , int complete, int incomplete); - virtual void tracker_request_timed_out( - tracker_request const& r); - virtual void tracker_request_error(tracker_request const& r - , int response_code, const std::string& str); - virtual void tracker_warning(std::string const& msg); - - // generates a request string for sending - // to the tracker - tracker_request generate_tracker_request(); - - // if no password and username is set - // this will return an empty string, otherwise - // it will concatenate the login and password - // ready to be sent over http (but without - // base64 encoding). - std::string tracker_login() const; - - // returns the absolute time when the next tracker - // announce will take place. - ptime next_announce() const; - - // returns true if it is time for this torrent to make another - // tracker request - bool should_request(); - - // forcefully sets next_announce to the current time - void force_tracker_request(); - void force_tracker_request(ptime); - - // sets the username and password that will be sent to - // the tracker - void set_tracker_login(std::string const& name, std::string const& pw); - - // the tcp::endpoint of the tracker that we managed to - // announce ourself at the last time we tried to announce - const tcp::endpoint& current_tracker() const; - -// -------------------------------------------- - // PIECE MANAGEMENT - - // returns true if we have downloaded the given piece - bool have_piece(int index) const - { - assert(index >= 0 && index < (signed)m_have_pieces.size()); - return m_have_pieces[index]; - } - - const std::vector& pieces() const - { return m_have_pieces; } - - int num_pieces() const { return m_num_pieces; } - - // when we get a have- or bitfield- messages, this is called for every - // piece a peer has gained. - void peer_has(int index) - { - if (m_picker.get()) - { - assert(!is_seed()); - assert(index >= 0 && index < (signed)m_have_pieces.size()); - m_picker->inc_refcount(index); - } -#ifndef NDEBUG - else - { - assert(is_seed()); - } -#endif - } - - void peer_has_all() - { - if (m_picker.get()) - { - assert(!is_seed()); - m_picker->inc_refcount_all(); - } -#ifndef NDEBUG - else - { - assert(is_seed()); - } -#endif - } - - // when peer disconnects, this is called for every piece it had - void peer_lost(int index) - { - if (m_picker.get()) - { - assert(!is_seed()); - assert(index >= 0 && index < (signed)m_have_pieces.size()); - m_picker->dec_refcount(index); - } -#ifndef NDEBUG - else - { - assert(is_seed()); - } -#endif - } - - int block_size() const { assert(m_block_size > 0); return m_block_size; } - - // this will tell all peers that we just got his piece - // and also let the piece picker know that we have this piece - // so it wont pick it for download - void announce_piece(int index); - - void disconnect_all(); - - // this is called wheh the torrent has completed - // the download. It will post an event, disconnect - // all seeds and let the tracker know we're finished. - void completed(); - - // this is the asio callback that is called when a name - // lookup for a PEER is completed. - void on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator i - , peer_id pid); - - // this is the asio callback that is called when a name - // lookup for a WEB SEED is completed. - void on_name_lookup(asio::error_code const& e, tcp::resolver::iterator i - , std::string url, tcp::endpoint proxy); - - // this is the asio callback that is called when a name - // lookup for a proxy for a web seed is completed. - void on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator i - , std::string url); - - // this is called when the torrent has finished. i.e. - // all the pieces we have not filtered have been downloaded. - // If no pieces are filtered, this is called first and then - // completed() is called immediately after it. - void finished(); - - bool verify_piece(int piece_index); - - // this is called from the peer_connection - // each time a piece has failed the hash - // test - void piece_failed(int index); - void received_redundant_data(int num_bytes) - { assert(num_bytes > 0); m_total_redundant_bytes += num_bytes; } - - // this is true if we have all the pieces - bool is_seed() const - { - return valid_metadata() - && m_num_pieces == m_torrent_file.num_pieces(); - } - - // this is true if we have all the pieces that we want - bool is_finished() const - { - if (is_seed()) return true; - return valid_metadata() && m_torrent_file.num_pieces() - - m_num_pieces - m_picker->num_filtered() == 0; - } - - boost::filesystem::path save_path() const; - alert_manager& alerts() const; - piece_picker& picker() - { - assert(!is_seed()); - assert(m_picker.get()); - return *m_picker; - } - bool has_picker() const - { - assert((valid_metadata() && !is_seed()) == bool(m_picker.get() != 0)); - return m_picker.get() != 0; - } - policy& get_policy() - { - assert(m_policy); - return *m_policy; - } - piece_manager& filesystem(); - torrent_info const& torrent_file() const - { return m_torrent_file; } - - std::vector const& trackers() const - { return m_trackers; } - - void replace_trackers(std::vector const& urls); - - torrent_handle get_handle() const; - - // LOGGING -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - virtual void debug_log(const std::string& line); -#endif - - // DEBUG -#ifndef NDEBUG - void check_invariant() const; -#endif - -// -------------------------------------------- - // RESOURCE MANAGEMENT - - void distribute_resources(float tick_interval); - - resource_request m_uploads_quota; - resource_request m_connections_quota; - - void set_peer_upload_limit(tcp::endpoint ip, int limit); - void set_peer_download_limit(tcp::endpoint ip, int limit); - - void set_upload_limit(int limit); - int upload_limit() const; - void set_download_limit(int limit); - int download_limit() const; - - void set_max_uploads(int limit); - void set_max_connections(int limit); - bool move_storage(boost::filesystem::path const& save_path); - - // unless this returns true, new connections must wait - // with their initialization. - bool ready_for_connections() const - { return m_connections_initialized; } - bool valid_metadata() const - { return m_storage.get() != 0; } - - // parses the info section from the given - // bencoded tree and moves the torrent - // to the checker thread for initial checking - // of the storage. - void set_metadata(entry const&); - - private: - - void try_next_tracker(); - int prioritize_tracker(int tracker_index); - void on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i - , boost::intrusive_ptr p) const; - bool request_bandwidth_from_session(int channel) const; - - void update_peer_interest(); - - torrent_info m_torrent_file; - - // is set to true when the torrent has - // been aborted. - bool m_abort; - - // is true if this torrent has been paused - bool m_paused; - // this is true from the time when the torrent was - // paused to the time should_request() is called - bool m_just_paused; - - tracker_request::event_t m_event; - - void parse_response(const entry& e, std::vector& peer_list); - - // the size of a request block - // each piece is divided into these - // blocks when requested - int m_block_size; - - // if this pointer is 0, the torrent is in - // a state where the metadata hasn't been - // received yet. - boost::scoped_ptr m_storage; - - // the time of next tracker request - ptime m_next_request; - - // ----------------------------- - // DATA FROM TRACKER RESPONSE - - // the number number of seconds between requests - // from the tracker - int m_duration; - - // the scrape data from the tracker response, this - // is optional and may be -1. - int m_complete; - int m_incomplete; - -#ifndef NDEBUG - public: -#endif - std::map m_connections; -#ifndef NDEBUG - private: -#endif - - // The list of web seeds in this torrent. Seeds - // with fatal errors are removed from the set - std::set m_web_seeds; - - // urls of the web seeds that we are currently - // resolving the address for - std::set m_resolving_web_seeds; - - // used to resolve the names of web seeds - mutable tcp::resolver m_host_resolver; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - // this is true while there is a country - // resolution in progress. To avoid flodding - // the DNS request queue, only one ip is resolved - // at a time. - mutable bool m_resolving_country; - - // this is true if the user has enabled - // country resolution in this torrent - bool m_resolve_countries; -#endif - - // this announce timer is used both - // by Local service discovery and - // by the DHT. - deadline_timer m_announce_timer; - - static void on_announce_disp(boost::weak_ptr p - , asio::error_code const& e); - - // this is called once per announce interval - void on_announce(); - -#ifndef TORRENT_DISABLE_DHT - static void on_dht_announce_response_disp(boost::weak_ptr t - , std::vector const& peers); - void on_dht_announce_response(std::vector const& peers); - bool should_announce_dht() const; - - // the time when the DHT was last announced of our - // presence on this torrent - ptime m_last_dht_announce; -#endif - - // this is the upload and download statistics for the whole torrent. - // it's updated from all its peers once every second. - libtorrent::stat m_stat; - - // ----------------------------- - - boost::shared_ptr m_policy; - - // a back reference to the session - // this torrent belongs to. - aux::session_impl& m_ses; - aux::checker_impl& m_checker; - - boost::scoped_ptr m_picker; - - // the queue of peer_connections that want more bandwidth - std::deque m_bandwidth_queue[2]; - - std::vector m_trackers; - // this is an index into m_torrent_file.trackers() - int m_last_working_tracker; - int m_currently_trying_tracker; - // the number of connection attempts that has - // failed in a row, this is currently used to - // determine the timeout until next try. - int m_failed_trackers; - - // this is a counter that is increased every - // second, and when it reaches 10, the policy::pulse() - // is called and the time scaler is reset to 0. - int m_time_scaler; - - // the bitmask that says which pieces we have - std::vector m_have_pieces; - - // the number of pieces we have. The same as - // std::accumulate(m_have_pieces.begin(), - // m_have_pieces.end(), 0) - int m_num_pieces; - - // in case the piece picker hasn't been constructed - // when this settings is set, this variable will keep - // its value until the piece picker is created - int m_sequenced_download_threshold; - - // is false by default and set to - // true when the first tracker reponse - // is received - bool m_got_tracker_response; - - // the upload/download ratio that each peer - // tries to maintain. - // 0 is infinite - float m_ratio; - - // the number of bytes that has been - // downloaded that failed the hash-test - size_type m_total_failed_bytes; - size_type m_total_redundant_bytes; - - std::string m_username; - std::string m_password; - - // the network interface all outgoing connections - // are opened through - tcp::endpoint m_net_interface; - - boost::filesystem::path m_save_path; - - // determines the storage state for this torrent. - const bool m_compact_mode; - - // defaults to 16 kiB, but can be set by the user - // when creating the torrent - const int m_default_block_size; - - // this is set to false as long as the connections - // of this torrent hasn't been initialized. If we - // have metadata from the start, connections are - // initialized immediately, if we didn't have metadata, - // they are initialized right after files_checked(). - // valid_resume_data() will return false as long as - // the connections aren't initialized, to avoid - // them from altering the piece-picker before it - // has been initialized with files_checked(). - bool m_connections_initialized; - - // if the torrent is started without metadata, it may - // still be given a name until the metadata is received - // once the metadata is received this field will no - // longer be used and will be reset - boost::scoped_ptr m_name; - - session_settings const& m_settings; - - storage_constructor_type m_storage_constructor; - -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::list > extension_list_t; - extension_list_t m_extensions; -#endif - -#ifndef NDEBUG - // this is the amount downloaded when this torrent - // is started. i.e. - // total_done - m_initial_done <= total_payload_download - size_type m_initial_done; -#endif - -#ifdef TORRENT_LOGGING - boost::shared_ptr m_log; - boost::shared_ptr m_peer_log; - int m_second_count; - - enum { debug_bw_history_size = 10 }; - int m_ul_history[debug_bw_history_size]; - int m_dl_history[debug_bw_history_size]; -#endif - }; - - inline ptime torrent::next_announce() const - { - return m_next_request; - } - - inline void torrent::force_tracker_request() - { - m_next_request = time_now(); - } - - inline void torrent::force_tracker_request(ptime t) - { - m_next_request = t; - } - - inline void torrent::set_tracker_login( - std::string const& name - , std::string const& pw) - { - m_username = name; - m_password = pw; - } - -} - -#endif // TORRENT_TORRENT_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/torrent_handle.hpp b/libtorrent/include/libtorrent/torrent_handle.hpp deleted file mode 100644 index cb4b892d2..000000000 --- a/libtorrent/include/libtorrent/torrent_handle.hpp +++ /dev/null @@ -1,376 +0,0 @@ -/* - -Copyright (c) 2003, 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_TORRENT_HANDLE_HPP_INCLUDED -#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED - -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/peer_info.hpp" -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - namespace aux - { - struct session_impl; - struct checker_impl; - } - - struct TORRENT_EXPORT duplicate_torrent: std::exception - { - virtual const char* what() const throw() - { return "torrent already exists in session"; } - }; - - struct TORRENT_EXPORT invalid_handle: std::exception - { - virtual const char* what() const throw() - { return "invalid torrent handle used"; } - }; - - struct TORRENT_EXPORT torrent_status - { - torrent_status() - : state(queued_for_checking) - , paused(false) - , progress(0.f) - , total_download(0) - , total_upload(0) - , total_payload_download(0) - , total_payload_upload(0) - , total_failed_bytes(0) - , total_redundant_bytes(0) - , download_rate(0) - , upload_rate(0) - , download_payload_rate(0) - , upload_payload_rate(0) - , num_peers(0) - , num_complete(-1) - , num_incomplete(-1) - , pieces(0) - , num_pieces(0) - , total_done(0) - , total_wanted_done(0) - , total_wanted(0) - , num_seeds(0) - , distributed_copies(0.f) - , block_size(0) - {} - - enum state_t - { - queued_for_checking, - checking_files, - connecting_to_tracker, - downloading_metadata, - downloading, - finished, - seeding, - allocating - }; - - state_t state; - bool paused; - float progress; - boost::posix_time::time_duration next_announce; - boost::posix_time::time_duration announce_interval; - - std::string current_tracker; - - // transferred this session! - // total, payload plus protocol - size_type total_download; - size_type total_upload; - - // payload only - size_type total_payload_download; - size_type total_payload_upload; - - // the amount of payload bytes that - // has failed their hash test - size_type total_failed_bytes; - - // the number of payload bytes that - // has been received redundantly. - size_type total_redundant_bytes; - - // current transfer rate - // payload plus protocol - float download_rate; - float upload_rate; - - // the rate of payload that is - // sent and received - float download_payload_rate; - float upload_payload_rate; - - // the number of peers this torrent - // is connected to. - int num_peers; - - // if the tracker sends scrape info in its - // announce reply, these fields will be - // set to the total number of peers that - // have the whole file and the total number - // of peers that are still downloading - int num_complete; - int num_incomplete; - - const std::vector* pieces; - - // this is the number of pieces the client has - // downloaded. it is equal to: - // std::accumulate(pieces->begin(), pieces->end()); - int num_pieces; - - // the number of bytes of the file we have - // including pieces that may have been filtered - // after we downloaded them - size_type total_done; - - // the number of bytes we have of those that we - // want. i.e. not counting bytes from pieces that - // are filtered as not wanted. - size_type total_wanted_done; - - // the total number of bytes we want to download - // this may be smaller than the total torrent size - // in case any pieces are filtered as not wanted - size_type total_wanted; - - // the number of peers this torrent is connected to - // that are seeding. - int num_seeds; - - // the number of distributed copies of the file. - // note that one copy may be spread out among many peers. - // - // the integer part tells how many copies - // there are of the rarest piece(s) - // - // the fractional part tells the fraction of pieces that - // have more copies than the rarest piece(s). - float distributed_copies; - - // the block size that is used in this torrent. i.e. - // the number of bytes each piece request asks for - // and each bit in the download queue bitfield represents - int block_size; - }; - - struct TORRENT_EXPORT partial_piece_info - { - enum { max_blocks_per_piece = 256 }; - int piece_index; - int blocks_in_piece; - std::bitset requested_blocks; - std::bitset finished_blocks; - tcp::endpoint peer[max_blocks_per_piece]; - int num_downloads[max_blocks_per_piece]; - enum state_t { none, slow, medium, fast }; - state_t piece_state; - }; - - struct TORRENT_EXPORT torrent_handle - { - friend class invariant_access; - friend struct aux::session_impl; - friend class torrent; - - torrent_handle(): m_ses(0), m_chk(0), m_info_hash(0) {} - - void get_peer_info(std::vector& v) const; - bool send_chat_message(tcp::endpoint ip, std::string message) const; - torrent_status status() const; - void get_download_queue(std::vector& queue) const; - - // fills the specified vector with the download progress [0, 1] - // of each file in the torrent. The files are ordered as in - // the torrent_info. - void file_progress(std::vector& progress); - - std::vector const& trackers() const; - void replace_trackers(std::vector const&) const; - - void add_url_seed(std::string const& url); - - bool has_metadata() const; - const torrent_info& get_torrent_info() const; - bool is_valid() const; - - bool is_seed() const; - bool is_paused() const; - void pause() const; - void resume() const; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void resolve_countries(bool r); - bool resolve_countries() const; -#endif - - // all these are deprecated, use piece - // priority functions instead - - // ================ start deprecation ============ - - // marks the piece with the given index as filtered - // it will not be downloaded - void filter_piece(int index, bool filter) const; - void filter_pieces(std::vector const& pieces) const; - bool is_piece_filtered(int index) const; - std::vector filtered_pieces() const; - // marks the file with the given index as filtered - // it will not be downloaded - void filter_files(std::vector const& files) const; - - // ================ end deprecation ============ - - // priority must be within the range [0, 7] - void piece_priority(int index, int priority) const; - int piece_priority(int index) const; - - void prioritize_pieces(std::vector const& pieces) const; - std::vector piece_priorities() const; - - void prioritize_files(std::vector const& files) const; - - - // set the interface to bind outgoing connections - // to. - void use_interface(const char* net_interface) const; - - entry write_resume_data() const; - - // forces this torrent to reannounce - // (make a rerequest from the tracker) - void force_reannounce() const; - - // forces a reannounce in the specified amount of time. - // This overrides the default announce interval, and no - // announce will take place until the given time has - // timed out. - void force_reannounce(boost::posix_time::time_duration) const; - - // returns the name of this torrent, in case it doesn't - // have metadata it returns the name assigned to it - // when it was added. - std::string name() const; - - // TODO: add a feature where the user can tell the torrent - // to finish all pieces currently in the pipeline, and then - // abort the torrent. - - void set_upload_limit(int limit) const; - int upload_limit() const; - void set_download_limit(int limit) const; - int download_limit() const; - - void set_sequenced_download_threshold(int threshold) const; - - void set_peer_upload_limit(tcp::endpoint ip, int limit) const; - void set_peer_download_limit(tcp::endpoint ip, int limit) const; - - // manually connect a peer - void connect_peer(tcp::endpoint const& adr, int source = 0) const; - - // valid ratios are 0 (infinite ratio) or [ 1.0 , inf ) - // the ratio is uploaded / downloaded. less than 1 is not allowed - void set_ratio(float up_down_ratio) const; - - boost::filesystem::path save_path() const; - - // -1 means unlimited unchokes - void set_max_uploads(int max_uploads) const; - - // -1 means unlimited connections - void set_max_connections(int max_connections) const; - - void set_tracker_login(std::string const& name - , std::string const& password) const; - - // post condition: save_path() == save_path if true is returned - bool move_storage(boost::filesystem::path const& save_path) const; - - const sha1_hash& info_hash() const - { return m_info_hash; } - - bool operator==(const torrent_handle& h) const - { return m_info_hash == h.m_info_hash; } - - bool operator!=(const torrent_handle& h) const - { return m_info_hash != h.m_info_hash; } - - bool operator<(const torrent_handle& h) const - { return m_info_hash < h.m_info_hash; } - - private: - - torrent_handle(aux::session_impl* s, - aux::checker_impl* c, - const sha1_hash& h) - : m_ses(s) - , m_chk(c) - , m_info_hash(h) - { - assert(m_ses != 0); - } - -#ifndef NDEBUG - void check_invariant() const; -#endif - - aux::session_impl* m_ses; - aux::checker_impl* m_chk; - sha1_hash m_info_hash; - - }; - - -} - -#endif // TORRENT_TORRENT_HANDLE_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/torrent_info.hpp b/libtorrent/include/libtorrent/torrent_info.hpp deleted file mode 100644 index d26f9f1f2..000000000 --- a/libtorrent/include/libtorrent/torrent_info.hpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - -Copyright (c) 2003, 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_TORRENT_INFO_HPP_INCLUDE -#define TORRENT_TORRENT_INFO_HPP_INCLUDE - - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/entry.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/time.hpp" - -namespace libtorrent -{ - namespace pt = boost::posix_time; - namespace gr = boost::gregorian; - - struct TORRENT_EXPORT file_entry - { - boost::filesystem::path path; - size_type offset; // the offset of this file inside the torrent - size_type size; // the size of this file - // if the path was incorrectly encoded, this is - // the origianal corrupt encoded string. It is - // preserved in order to be able to reproduce - // the correct info-hash - boost::shared_ptr orig_path; - }; - - struct TORRENT_EXPORT file_slice - { - int file_index; - size_type offset; - size_type size; - }; - - struct TORRENT_EXPORT announce_entry - { - announce_entry(std::string const& u): url(u), tier(0) {} - std::string url; - int tier; - }; - - struct TORRENT_EXPORT invalid_torrent_file: std::exception - { - virtual const char* what() const throw() { return "invalid torrent file"; } - }; - - class TORRENT_EXPORT torrent_info - { - public: - - torrent_info(); - torrent_info(sha1_hash const& info_hash); - torrent_info(entry const& torrent_file); - ~torrent_info(); - - entry create_torrent() const; - entry create_info_metadata() const; - void set_comment(char const* str); - void set_creator(char const* str); - void set_piece_size(int size); - void set_hash(int index, sha1_hash const& h); - void add_tracker(std::string const& url, int tier = 0); - void add_file(boost::filesystem::path file, size_type size); - void add_url_seed(std::string const& url); - - std::vector map_block(int piece, size_type offset, int size) const; - peer_request map_file(int file, size_type offset, int size) const; - - std::vector const& url_seeds() const - { - assert(!m_half_metadata); - return m_url_seeds; - } - - typedef std::vector::const_iterator file_iterator; - typedef std::vector::const_reverse_iterator reverse_file_iterator; - - // list the files in the torrent file - file_iterator begin_files() const { return m_files.begin(); } - file_iterator end_files() const { return m_files.end(); } - reverse_file_iterator rbegin_files() const { return m_files.rbegin(); } - reverse_file_iterator rend_files() const { return m_files.rend(); } - - int num_files() const - { assert(m_piece_length > 0); return (int)m_files.size(); } - const file_entry& file_at(int index) const - { assert(index >= 0 && index < (int)m_files.size()); return m_files[index]; } - - const std::vector& trackers() const { return m_urls; } - - size_type total_size() const { assert(m_piece_length > 0); return m_total_size; } - size_type piece_length() const { assert(m_piece_length > 0); return m_piece_length; } - int num_pieces() const { assert(m_piece_length > 0); return m_num_pieces; } - const sha1_hash& info_hash() const { return m_info_hash; } - const std::string& name() const { assert(m_piece_length > 0); return m_name; } - -// ------- start deprecation ------- - void print(std::ostream& os) const; -// ------- end deprecation ------- - - bool is_valid() const { return m_piece_length > 0; } - - bool priv() const { return m_private; } - void set_priv(bool v) { m_private = v; } - - void convert_file_names(); - - size_type piece_size(int index) const; - - const sha1_hash& hash_for_piece(int index) const - { - assert(index >= 0); - assert(index < (int)m_piece_hash.size()); - assert(!m_half_metadata); - return m_piece_hash[index]; - } - - boost::optional creation_date() const; - - const std::string& creator() const - { return m_created_by; } - - const std::string& comment() const - { return m_comment; } - - // dht nodes to add to the routing table/bootstrap from - typedef std::vector > nodes_t; - - nodes_t const& nodes() const - { - assert(!m_half_metadata); - return m_nodes; - } - - void add_node(std::pair const& node); - - void parse_info_section(entry const& e); - - entry extra(char const* key) const - { return m_extra_info[key]; } - - // frees parts of the metadata that isn't - // used by seeds - void seed_free(); - - private: - - void read_torrent_info(const entry& libtorrent); - - // the urls to the trackers - std::vector m_urls; - - std::vector m_url_seeds; - - // the length of one piece - // if this is 0, the torrent_info is - // in an uninitialized state - size_type m_piece_length; - - // the sha-1 hashes of each piece - std::vector m_piece_hash; - - // the list of files that this torrent consists of - std::vector m_files; - - nodes_t m_nodes; - - // the sum of all filesizes - size_type m_total_size; - - // the number of pieces in the torrent - int m_num_pieces; - - // the hash that identifies this torrent - // is mutable because it's calculated - // lazily - mutable sha1_hash m_info_hash; - - std::string m_name; - - // if a creation date is found in the torrent file - // this will be set to that, otherwise it'll be - // 1970, Jan 1 - pt::ptime m_creation_date; - - // if a comment is found in the torrent file - // this will be set to that comment - std::string m_comment; - - // an optional string naming the software used - // to create the torrent file - std::string m_created_by; - - // this is used when creating a torrent. If there's - // only one file there are cases where it's impossible - // to know if it should be written as a multifile torrent - // or not. e.g. test/test there's one file and one directory - // and they have the same name. - bool m_multifile; - - // this is true if the torrent is private. i.e., is should not - // be announced on the dht - bool m_private; - - // contains any non-parsed entries from the info-section - // these are kept in order to be able to accurately - // reproduce the info-section when sending the metadata - // to peers. - entry m_extra_info; - -#ifndef NDEBUG - // this is set to true when seed_free() is called - bool m_half_metadata; -#endif - }; - -} - -#endif // TORRENT_TORRENT_INFO_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/tracker_manager.hpp b/libtorrent/include/libtorrent/tracker_manager.hpp deleted file mode 100644 index a4d24f751..000000000 --- a/libtorrent/include/libtorrent/tracker_manager.hpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - -Copyright (c) 2003, 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_TRACKER_MANAGER_HPP_INCLUDED -#define TORRENT_TRACKER_MANAGER_HPP_INCLUDED - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/socket.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/peer.hpp" -#include "libtorrent/config.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/connection_queue.hpp" - -namespace libtorrent -{ - struct request_callback; - class tracker_manager; - struct timeout_handler; - struct tracker_connection; - - // encodes a string using the base64 scheme - TORRENT_EXPORT std::string base64encode(const std::string& s); - - // returns -1 if gzip header is invalid or the header size in bytes - TORRENT_EXPORT int gzip_header(const char* buf, int size); - - TORRENT_EXPORT boost::tuple - parse_url_components(std::string url); - - struct TORRENT_EXPORT tracker_request - { - tracker_request() - : kind(announce_request) - , event(none) - , key(0) - , num_want(0) - {} - - enum - { - announce_request, - scrape_request - } kind; - - enum event_t - { - none, - completed, - started, - stopped - }; - - sha1_hash info_hash; - peer_id pid; - size_type downloaded; - size_type uploaded; - size_type left; - unsigned short listen_port; - event_t event; - std::string url; - int key; - int num_want; - }; - - struct TORRENT_EXPORT request_callback - { - friend class tracker_manager; - request_callback(): m_manager(0) {} - virtual ~request_callback() {} - virtual void tracker_warning(std::string const& msg) = 0; - virtual void tracker_response( - tracker_request const& - , std::vector& peers - , int interval - , int complete - , int incomplete) = 0; - virtual void tracker_request_timed_out( - tracker_request const&) = 0; - virtual void tracker_request_error( - tracker_request const& - , int response_code - , const std::string& description) = 0; - - tcp::endpoint m_tracker_address; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - virtual void debug_log(const std::string& line) = 0; -#endif - private: - tracker_manager* m_manager; - }; - - TORRENT_EXPORT bool inflate_gzip( - std::vector& buffer - , tracker_request const& req - , request_callback* requester - , int maximum_tracker_response_length); - - TORRENT_EXPORT void intrusive_ptr_add_ref(timeout_handler const*); - TORRENT_EXPORT void intrusive_ptr_release(timeout_handler const*); - - struct TORRENT_EXPORT timeout_handler - : boost::noncopyable - { - friend TORRENT_EXPORT void intrusive_ptr_add_ref(timeout_handler const*); - friend TORRENT_EXPORT void intrusive_ptr_release(timeout_handler const*); - - timeout_handler(asio::strand& str); - - void set_timeout(int completion_timeout, int read_timeout); - void restart_read_timeout(); - void cancel(); - - virtual void on_timeout() = 0; - virtual ~timeout_handler() {} - - private: - - void timeout_callback(asio::error_code const&); - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - asio::strand& m_strand; - // used for timeouts - // this is set when the request has been sent - ptime m_start_time; - // this is set every time something is received - ptime m_read_time; - // the asio async operation - deadline_timer m_timeout; - - int m_completion_timeout; - int m_read_timeout; - - typedef boost::mutex mutex_t; - mutable mutex_t m_mutex; - mutable int m_refs; - }; - - struct TORRENT_EXPORT tracker_connection - : timeout_handler - { - tracker_connection(tracker_manager& man - , tracker_request req - , asio::strand& str - , address bind_interface - , boost::weak_ptr r); - - request_callback& requester(); - virtual ~tracker_connection() {} - - tracker_request const& tracker_req() const { return m_req; } - bool has_requester() const { return !m_requester.expired(); } - - void fail(int code, char const* msg); - void fail_timeout(); - void close(); - address const& bind_interface() const { return m_bind_interface; } - - protected: - boost::weak_ptr m_requester; - private: - address m_bind_interface; - tracker_manager& m_man; - const tracker_request m_req; - }; - - class TORRENT_EXPORT tracker_manager: boost::noncopyable - { - public: - - tracker_manager(session_settings const& s, proxy_settings const& ps) - : m_settings(s) - , m_proxy(ps) - , m_abort(false) {} - - void queue_request( - asio::strand& str - , connection_queue& cc - , tracker_request r - , std::string const& auth - , address bind_infc - , boost::weak_ptr c - = boost::weak_ptr()); - void abort_all_requests(); - - void remove_request(tracker_connection const*); - bool empty() const; - - private: - - typedef boost::recursive_mutex mutex_t; - mutable mutex_t m_mutex; - - typedef std::list > - tracker_connections_t; - tracker_connections_t m_connections; - session_settings const& m_settings; - proxy_settings const& m_proxy; - bool m_abort; - }; -} - -#endif // TORRENT_TRACKER_MANAGER_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/udp_tracker_connection.hpp b/libtorrent/include/libtorrent/udp_tracker_connection.hpp deleted file mode 100644 index c0e6853b9..000000000 --- a/libtorrent/include/libtorrent/udp_tracker_connection.hpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - -Copyright (c) 2003, 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_UDP_TRACKER_CONNECTION_HPP_INCLUDED -#define TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/socket.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/peer.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/config.hpp" - -namespace libtorrent -{ - class TORRENT_EXPORT udp_tracker_connection: public tracker_connection - { - friend class tracker_manager; - public: - - udp_tracker_connection( - asio::strand& str - , tracker_manager& man - , tracker_request const& req - , std::string const& hostname - , unsigned short port - , address bind_infc - , boost::weak_ptr c - , session_settings const& stn); - - private: - - enum action_t - { - action_connect, - action_announce, - action_scrape, - action_error - }; - - boost::intrusive_ptr self() - { return boost::intrusive_ptr(this); } - - void name_lookup(asio::error_code const& error, udp::resolver::iterator i); - void timeout(asio::error_code const& error); - - void send_udp_connect(); - void connect_response(asio::error_code const& error, std::size_t bytes_transferred); - - void send_udp_announce(); - void announce_response(asio::error_code const& error, std::size_t bytes_transferred); - - void send_udp_scrape(); - void scrape_response(asio::error_code const& error, std::size_t bytes_transferred); - - virtual void on_timeout(); - - tracker_manager& m_man; - - asio::strand& m_strand; - udp::resolver m_name_lookup; - boost::shared_ptr m_socket; - udp::endpoint m_target; - udp::endpoint m_sender; - - int m_transaction_id; - boost::int64_t m_connection_id; - session_settings const& m_settings; - int m_attempts; - std::vector m_buffer; - }; - -} - -#endif // TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/upnp.hpp b/libtorrent/include/libtorrent/upnp.hpp deleted file mode 100644 index d4b701aad..000000000 --- a/libtorrent/include/libtorrent/upnp.hpp +++ /dev/null @@ -1,237 +0,0 @@ -/* - -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_UPNP_HPP -#define TORRENT_UPNP_HPP - -#include "libtorrent/socket.hpp" -#include "libtorrent/http_connection.hpp" -#include "libtorrent/connection_queue.hpp" - -#include -#include -#include -#include -#include -#include - - -#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defined (TORRENT_UPNP_LOGGING) -#define TORRENT_UPNP_LOGGING -#endif - -#if defined(TORRENT_UPNP_LOGGING) -#include -#endif - -namespace libtorrent -{ - -bool is_local(address const& a); -address_v4 guess_local_address(asio::io_service&); - -// int: external tcp port -// int: external udp port -// std::string: error message -typedef boost::function portmap_callback_t; - -class upnp : boost::noncopyable -{ -public: - upnp(io_service& ios, connection_queue& cc - , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb); - ~upnp(); - - void rebind(address const& listen_interface); - - // maps the ports, if a port is set to 0 - // it will not be mapped - void set_mappings(int tcp, int udp); - - void close(); - -private: - - static address_v4 upnp_multicast_address; - static udp::endpoint upnp_multicast_endpoint; - - enum { num_mappings = 2 }; - enum { default_lease_time = 3600 }; - - void update_mapping(int i, int port); - void resend_request(asio::error_code const& e); - void on_reply(asio::error_code const& e - , std::size_t bytes_transferred); - void discover_device(); - - struct rootdevice; - - void on_upnp_xml(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d); - void on_upnp_map_response(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d - , int mapping); - void on_upnp_unmap_response(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d - , int mapping); - void on_expire(asio::error_code const& e); - - void post(rootdevice& d, std::stringstream const& s - , std::string const& soap_action); - void map_port(rootdevice& d, int i); - void unmap_port(rootdevice& d, int i); - void disable(); - - struct mapping_t - { - mapping_t() - : need_update(false) - , local_port(0) - , external_port(0) - , protocol(1) - {} - - // the time the port mapping will expire - ptime expires; - - bool need_update; - - // the local port for this mapping. If this is set - // to 0, the mapping is not in use - int local_port; - - // the external (on the NAT router) port - // for the mapping. This is the port we - // should announce to others - int external_port; - - // 1 = udp, 0 = tcp - int protocol; - }; - - struct rootdevice - { - rootdevice(): service_namespace(0) - , lease_duration(default_lease_time) - , supports_specific_external(true) - , disabled(false) - { - mapping[0].protocol = 0; - mapping[1].protocol = 1; - } - - // the interface url, through which the list of - // supported interfaces are fetched - std::string url; - - // the url to the WANIP or WANPPP interface - std::string control_url; - // either the WANIP namespace or the WANPPP namespace - char const* service_namespace; - - mapping_t mapping[num_mappings]; - - std::string hostname; - int port; - std::string path; - - int lease_duration; - // true if the device supports specifying a - // specific external port, false if it doesn't - bool supports_specific_external; - - bool disabled; - - mutable boost::shared_ptr upnp_connection; - - void close() const - { - if (!upnp_connection) return; - upnp_connection->close(); - upnp_connection.reset(); - } - - bool operator<(rootdevice const& rhs) const - { return url < rhs.url; } - }; - - int m_udp_local_port; - int m_tcp_local_port; - - std::string const& m_user_agent; - - // the set of devices we've found - std::set m_devices; - - portmap_callback_t m_callback; - - // current retry count - int m_retry_count; - - // used to receive responses in - char m_receive_buffer[1024]; - - // the endpoint we received the message from - udp::endpoint m_remote; - - // the local address we're listening on - address_v4 m_local_ip; - - // the udp socket used to send and receive - // multicast messages on the network - datagram_socket m_socket; - - // used to resend udp packets in case - // they time out - deadline_timer m_broadcast_timer; - - // timer used to refresh mappings - deadline_timer m_refresh_timer; - - asio::strand m_strand; - - bool m_disabled; - bool m_closing; - - connection_queue& m_cc; - -#ifdef TORRENT_UPNP_LOGGING - std::ofstream m_log; -#endif -}; - -} - - -#endif - diff --git a/libtorrent/include/libtorrent/utf8.hpp b/libtorrent/include/libtorrent/utf8.hpp deleted file mode 100644 index 157a7fdba..000000000 --- a/libtorrent/include/libtorrent/utf8.hpp +++ /dev/null @@ -1,161 +0,0 @@ -/* - Copyright (C) 2004-2005 Cory Nelson - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. -*/ - -// namespaces added by Arvid Norberg - -#ifndef __UTF8_H__ -#define __UTF8_H__ - -#include -#include -#include -#include - -namespace libtorrent { -namespace detail { - -template -wchar_t decode_utf8_mb(InputIterator &iter, InputIterator last) -{ - if (iter == last) throw std::runtime_error("incomplete UTF-8 sequence"); - if (((*iter) & 0xc0) != 0x80) throw std::runtime_error("invalid UTF-8 sequence"); - - return (wchar_t)((*iter++) & 0x3f); -} - -template -wchar_t decode_utf8(InputIterator &iter, InputIterator last) -{ - wchar_t ret; - - if (((*iter) & 0x80) == 0) // one byte - { - ret = *iter++; - } - else if (((*iter) & 0xe0) == 0xc0) // two bytes - { - wchar_t byte1 = (*iter++) & 0x1f; - wchar_t byte2 = decode_utf8_mb(iter, last); - ret = (byte1 << 6) | byte2; - } - else if (((*iter) & 0xf0) == 0xe0) // three bytes - { - wchar_t byte1 = (*iter++) & 0x0f; - wchar_t byte2 = decode_utf8_mb(iter, last); - wchar_t byte3 = decode_utf8_mb(iter, last); - ret = (byte1 << 12) | (byte2 << 6) | byte3; - } - // TODO: support surrogate pairs - else throw std::runtime_error("UTF-8 not convertable to UTF-16"); - - return ret; -} - -template -OutputIterator utf8_wchar(InputIterator first, InputIterator last, OutputIterator dest) -{ - for(; first!=last; ++dest) - *dest = decode_utf8(first, last); - return dest; -} - -template -void encode_wchar(InputIterator iter, OutputIterator &dest) -{ - if(*iter <= 0x007F) - { - *dest=(char)*iter; - ++dest; - } - else if(*iter <= 0x07FF) - { - *dest = (char)( - 0xC0 | - ((*iter & 0x07C0) >> 6) - ); - ++dest; - - *dest = (char)( - 0x80 | - (*iter & 0x003F) - ); - ++dest; - } - else if(*iter <= 0xFFFF) - { - *dest = (char)( - 0xE0 | - ((*iter & 0xF000) >> 12) - ); - ++dest; - - *dest = (char)( - 0x80 | - ((*iter & 0x0FC0) >> 6) - ); - ++dest; - - *dest = (char)( - 0x80 | - (*iter & 0x003F) - ); - ++dest; - } -} - -template -OutputIterator wchar_utf8(InputIterator first, InputIterator last, OutputIterator dest) -{ - for(; first!=last; ++first) - encode_wchar(first, dest); - return dest; -} - -} - -inline void utf8_wchar(const std::string &utf8, std::wstring &wide) -{ - wide.clear(); - detail::utf8_wchar(utf8.begin(), utf8.end(), std::back_inserter(wide)); -} - -inline std::wstring utf8_wchar(const std::string &str) -{ - std::wstring ret; - utf8_wchar(str, ret); - return ret; -} - -inline void wchar_utf8(const std::wstring &wide, std::string &utf8) -{ - utf8.clear(); - detail::wchar_utf8(wide.begin(), wide.end(), std::back_inserter(utf8)); -} - -inline std::string wchar_utf8(const std::wstring &str) -{ - std::string ret; - wchar_utf8(str, ret); - return ret; -} - -} - -#endif diff --git a/libtorrent/include/libtorrent/variant_stream.hpp b/libtorrent/include/libtorrent/variant_stream.hpp deleted file mode 100644 index 8f9888519..000000000 --- a/libtorrent/include/libtorrent/variant_stream.hpp +++ /dev/null @@ -1,716 +0,0 @@ -// Copyright Daniel Wallin and Arvid Norberg 2007. -// Use, modification and distribution is -// subject to 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 VARIANT_STREAM_070211_HPP -# define VARIANT_STREAM_070211_HPP - -# include - -# include -# include -# include -# include -# include - -# include -# include -# include - -# include -# include - -#include - -# define NETWORK_VARIANT_STREAM_LIMIT 5 - -namespace libtorrent { - -namespace aux -{ - - struct delete_visitor - : boost::static_visitor<> - { - template - void operator()(T* p) const - { - delete p; - } - - void operator()(boost::blank) const - {} - }; - -// -------------- io_control ----------- - - template - struct io_control_visitor_ec: boost::static_visitor<> - { - io_control_visitor_ec(IO_Control_Command& ioc, asio::error_code& ec) - : ioc(ioc), ec(ec) {} - - template - void operator()(T* p) const - { - p->io_control(ioc, ec); - } - - void operator()(boost::blank) const - {} - - IO_Control_Command& ioc; - asio::error_code& ec; - }; - - template - struct io_control_visitor - : boost::static_visitor<> - { - io_control_visitor(IO_Control_Command& ioc) - : ioc(ioc) {} - - template - void operator()(T* p) const - { - p->io_control(ioc); - } - - void operator()(boost::blank) const - {} - - IO_Control_Command& ioc; - }; -// -------------- async_connect ----------- - - template - struct async_connect_visitor - : boost::static_visitor<> - { - async_connect_visitor(EndpointType const& endpoint, Handler const& handler) - : endpoint(endpoint) - , handler(handler) - {} - - template - void operator()(T* p) const - { - p->async_connect(endpoint, handler); - } - - void operator()(boost::blank) const - {} - - EndpointType const& endpoint; - Handler const& handler; - }; - -// -------------- bind ----------- - - template - struct bind_visitor - : boost::static_visitor<> - { - bind_visitor(EndpointType const& ep, Error_Handler const& error_handler) - : endpoint(ep) - , error_handler(error_handler) - {} - - template - void operator()(T* p) const - { - p->bind(endpoint, error_handler); - } - - void operator()(boost::blank) const - {} - - EndpointType const& endpoint; - Error_Handler const& error_handler; - }; - - template - struct bind_visitor - : boost::static_visitor<> - { - bind_visitor(EndpointType const& ep) - : endpoint(ep) - {} - - template - void operator()(T* p) const - { - p->bind(endpoint); - } - - void operator()(boost::blank) const - {} - - EndpointType const& endpoint; - }; - -// -------------- open ----------- - - template - struct open_visitor - : boost::static_visitor<> - { - open_visitor(Protocol const& p, Error_Handler const& error_handler) - : proto(p) - , error_handler(error_handler) - {} - - template - void operator()(T* p) const - { - p->open(proto, error_handler); - } - - void operator()(boost::blank) const - {} - - Protocol const& proto; - Error_Handler const& error_handler; - }; - - template - struct open_visitor - : boost::static_visitor<> - { - open_visitor(Protocol const& p) - : proto(p) - {} - - template - void operator()(T* p) const - { - p->open(proto); - } - - void operator()(boost::blank) const - {} - - Protocol const& proto; - }; - -// -------------- close ----------- - - template - struct close_visitor - : boost::static_visitor<> - { - close_visitor(Error_Handler const& error_handler) - : error_handler(error_handler) - {} - - template - void operator()(T* p) const - { - p->close(error_handler); - } - - void operator()(boost::blank) const - {} - - Error_Handler const& error_handler; - }; - - template <> - struct close_visitor - : boost::static_visitor<> - { - template - void operator()(T* p) const - { - p->close(); - } - - void operator()(boost::blank) const - {} - }; - -// -------------- remote_endpoint ----------- - - template - struct remote_endpoint_visitor - : boost::static_visitor - { - remote_endpoint_visitor(Error_Handler const& error_handler) - : error_handler(error_handler) - {} - - template - EndpointType operator()(T* p) const - { - return p->remote_endpoint(error_handler); - } - - EndpointType operator()(boost::blank) const - { - return EndpointType(); - } - - Error_Handler const& error_handler; - }; - - template - struct remote_endpoint_visitor - : boost::static_visitor - { - template - EndpointType operator()(T* p) const - { - return p->remote_endpoint(); - } - - EndpointType operator()(boost::blank) const - { - return EndpointType(); - } - }; - -// -------------- local_endpoint ----------- - - template - struct local_endpoint_visitor - : boost::static_visitor - { - local_endpoint_visitor(Error_Handler const& error_handler) - : error_handler(error_handler) - {} - - template - EndpointType operator()(T* p) const - { - return p->local_endpoint(error_handler); - } - - EndpointType operator()(boost::blank) const - { - return EndpointType(); - } - - Error_Handler const& error_handler; - }; - - template - struct local_endpoint_visitor - : boost::static_visitor - { - template - EndpointType operator()(T* p) const - { - return p->local_endpoint(); - } - - EndpointType operator()(boost::blank) const - { - return EndpointType(); - } - }; - -// -------------- async_read_some ----------- - - template - struct async_read_some_visitor - : boost::static_visitor<> - { - async_read_some_visitor(Mutable_Buffers const& buffers, Handler const& handler) - : buffers(buffers) - , handler(handler) - {} - - template - void operator()(T* p) const - { - p->async_read_some(buffers, handler); - } - void operator()(boost::blank) const - {} - - Mutable_Buffers const& buffers; - Handler const& handler; - }; - -// -------------- read_some ----------- - - template - struct read_some_visitor - : boost::static_visitor - { - read_some_visitor(Mutable_Buffers const& buffers) - : buffers(buffers) - {} - - template - std::size_t operator()(T* p) const - { return p->read_some(buffers); } - - std::size_t operator()(boost::blank) const - { return 0; } - - Mutable_Buffers const& buffers; - }; - - template - struct read_some_visitor_ec - : boost::static_visitor - { - read_some_visitor_ec(Mutable_Buffers const& buffers, asio::error_code& ec) - : buffers(buffers) - , ec(ec) - {} - - template - std::size_t operator()(T* p) const - { return p->read_some(buffers, ec); } - - std::size_t operator()(boost::blank) const - { return 0; } - - Mutable_Buffers const& buffers; - asio::error_code& ec; - }; - -// -------------- async_write_some ----------- - - template - struct async_write_some_visitor - : boost::static_visitor<> - { - async_write_some_visitor(Const_Buffers const& buffers, Handler const& handler) - : buffers(buffers) - , handler(handler) - {} - - template - void operator()(T* p) const - { - p->async_write_some(buffers, handler); - } - - void operator()(boost::blank) const - {} - - Const_Buffers const& buffers; - Handler const& handler; - }; - -// -------------- in_avail ----------- - - template - struct in_avail_visitor - : boost::static_visitor - { - in_avail_visitor(Error_Handler const& error_handler) - : error_handler(error_handler) - {} - - template - std::size_t operator()(T* p) const - { - return p->in_avail(error_handler); - } - - std::size_t operator()(boost::blank) const - { - return 0; - } - - Error_Handler const& error_handler; - }; - - template <> - struct in_avail_visitor - : boost::static_visitor - { - template - std::size_t operator()(T* p) const - { - return p->in_avail(); - } - - void operator()(boost::blank) const - {} - }; - -// -------------- io_service ----------- - - template - struct io_service_visitor - : boost::static_visitor - { - template - IOService& operator()(T* p) const - { - return p->io_service(); - } - - IOService& operator()(boost::blank) const - { - return *(IOService*)0; - } - }; - -// -------------- lowest_layer ----------- - - template - struct lowest_layer_visitor - : boost::static_visitor - { - template - LowestLayer& operator()(T* p) const - { - return p->lowest_layer(); - } - - LowestLayer& operator()(boost::blank) const - { - return *(LowestLayer*)0; - } - }; - -} // namespace aux - -template < - BOOST_PP_ENUM_BINARY_PARAMS( - NETWORK_VARIANT_STREAM_LIMIT, class S, = boost::mpl::void_ BOOST_PP_INTERCEPT - ) -> -class variant_stream : boost::noncopyable -{ -public: - typedef BOOST_PP_CAT(boost::mpl::vector, NETWORK_VARIANT_STREAM_LIMIT)< - BOOST_PP_ENUM_PARAMS(NETWORK_VARIANT_STREAM_LIMIT, S) - > types0; - - typedef typename boost::mpl::remove::type types; - - typedef typename boost::make_variant_over< - typename boost::mpl::push_back< - typename boost::mpl::transform< - types - , boost::add_pointer - >::type - , boost::blank - >::type - >::type variant_type; - - typedef typename S0::lowest_layer_type lowest_layer_type; - typedef typename S0::endpoint_type endpoint_type; - typedef typename S0::protocol_type protocol_type; - - explicit variant_stream(asio::io_service& io_service) - : m_io_service(io_service) - , m_variant(boost::blank()) - {} - - template - void instantiate() - { - std::auto_ptr owned(new S(m_io_service)); - boost::apply_visitor(aux::delete_visitor(), m_variant); - m_variant = owned.get(); - owned.release(); - } - - template - S& get() - { - return *boost::get(m_variant); - } - - bool instantiated() const - { - return m_variant.which() != boost::mpl::size::value; - } - - ~variant_stream() - { - boost::apply_visitor(aux::delete_visitor(), m_variant); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers, asio::error_code& ec) - { - assert(instantiated()); - return boost::apply_visitor( - aux::read_some_visitor_ec(buffers, ec) - , m_variant - ); - } - - template - std::size_t read_some(Mutable_Buffers const& buffers) - { - assert(instantiated()); - return boost::apply_visitor( - aux::read_some_visitor(buffers) - , m_variant - ); - } - - template - void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) - { - assert(instantiated()); - boost::apply_visitor( - aux::async_read_some_visitor(buffers, handler) - , m_variant - ); - } - - template - void async_write_some(Const_Buffers const& buffers, Handler const& handler) - { - assert(instantiated()); - boost::apply_visitor( - aux::async_write_some_visitor(buffers, handler) - , m_variant - ); - } - - template - void async_connect(endpoint_type const& endpoint, Handler const& handler) - { - assert(instantiated()); - boost::apply_visitor( - aux::async_connect_visitor(endpoint, handler), m_variant - ); - } - - template - void io_control(IO_Control_Command& ioc) - { - assert(instantiated()); - boost::apply_visitor( - aux::io_control_visitor(ioc), m_variant - ); - } - - template - void io_control(IO_Control_Command& ioc, asio::error_code& ec) - { - assert(instantiated()); - boost::apply_visitor( - aux::io_control_visitor_ec(ioc, ec) - , m_variant - ); - } - - void bind(endpoint_type const& endpoint) - { - assert(instantiated()); - boost::apply_visitor(aux::bind_visitor(endpoint), m_variant); - } - - template - void bind(endpoint_type const& endpoint, Error_Handler const& error_handler) - { - assert(instantiated()); - boost::apply_visitor( - aux::bind_visitor(endpoint, error_handler), m_variant - ); - } - - void open(protocol_type const& p) - { - assert(instantiated()); - boost::apply_visitor(aux::open_visitor(p), m_variant); - } - - template - void open(protocol_type const& p, Error_Handler const& error_handler) - { - assert(instantiated()); - boost::apply_visitor( - aux::open_visitor(p, error_handler), m_variant - ); - } - - void close() - { - assert(instantiated()); - boost::apply_visitor(aux::close_visitor<>(), m_variant); - } - - template - void close(Error_Handler const& error_handler) - { - assert(instantiated()); - boost::apply_visitor( - aux::close_visitor(error_handler), m_variant - ); - } - - std::size_t in_avail() - { - assert(instantiated()); - return boost::apply_visitor(aux::in_avail_visitor<>(), m_variant); - } - - template - std::size_t in_avail(Error_Handler const& error_handler) - { - assert(instantiated()); - return boost::apply_visitor( - aux::in_avail_visitor(error_handler), m_variant - ); - } - - endpoint_type remote_endpoint() - { - assert(instantiated()); - return boost::apply_visitor(aux::remote_endpoint_visitor(), m_variant); - } - - template - endpoint_type remote_endpoint(Error_Handler const& error_handler) - { - assert(instantiated()); - return boost::apply_visitor( - aux::remote_endpoint_visitor(error_handler), m_variant - ); - } - - endpoint_type local_endpoint() - { - assert(instantiated()); - return boost::apply_visitor(aux::local_endpoint_visitor(), m_variant); - } - - template - endpoint_type local_endpoint(Error_Handler const& error_handler) - { - assert(instantiated()); - return boost::apply_visitor( - aux::local_endpoint_visitor(error_handler), m_variant - ); - } - - asio::io_service& io_service() - { - assert(instantiated()); - return boost::apply_visitor( - aux::io_service_visitor(), m_variant - ); - } - - lowest_layer_type& lowest_layer() - { - assert(instantiated()); - return boost::apply_visitor( - aux::lowest_layer_visitor(), m_variant - ); - } - -private: - asio::io_service& m_io_service; - variant_type m_variant; -}; - -} // namespace libtorrent - -#endif // VARIANT_STREAM_070211_HPP - diff --git a/libtorrent/include/libtorrent/version.hpp b/libtorrent/include/libtorrent/version.hpp deleted file mode 100644 index de1b8bcc8..000000000 --- a/libtorrent/include/libtorrent/version.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - -Copyright (c) 2003, 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_VERSION_HPP_INCLUDED -#define TORRENT_VERSION_HPP_INCLUDED - -#define LIBTORRENT_VERSION_MAJOR 0 -#define LIBTORRENT_VERSION_MINOR 13 - -#define LIBTORRENT_VERSION "0.13.0.0" - -#endif diff --git a/libtorrent/include/libtorrent/web_peer_connection.hpp b/libtorrent/include/libtorrent/web_peer_connection.hpp deleted file mode 100644 index 690066fb2..000000000 --- a/libtorrent/include/libtorrent/web_peer_connection.hpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - -Copyright (c) 2003, 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_WEB_PEER_CONNECTION_HPP_INCLUDED -#define TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED - -#include -#include -#include -#include -#include - -#include "libtorrent/debug.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/buffer.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/storage.hpp" -#include "libtorrent/stat.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/allocate_resources.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/piece_block_progress.hpp" -#include "libtorrent/config.hpp" -// parse_url -#include "libtorrent/tracker_manager.hpp" -// http_parser -#include "libtorrent/http_tracker_connection.hpp" - -namespace libtorrent -{ - class torrent; - - namespace detail - { - struct session_impl; - } - - class TORRENT_EXPORT web_peer_connection - : public peer_connection - { - friend class invariant_access; - public: - - // this is the constructor where the we are the active part. - // The peer_conenction should handshake and verify that the - // other end has the correct id - web_peer_connection( - aux::session_impl& ses - , boost::weak_ptr t - , boost::shared_ptr s - , tcp::endpoint const& remote - , std::string const& url - , policy::peer* peerinfo); - - ~web_peer_connection(); - - // called from the main loop when this connection has any - // work to do. - void on_sent(asio::error_code const& error - , std::size_t bytes_transferred); - void on_receive(asio::error_code const& error - , std::size_t bytes_transferred); - - std::string const& url() const { return m_url; } - - virtual void get_peer_info(peer_info& p) const; - virtual bool in_handshake() const; - - // the following functions appends messages - // to the send buffer - void write_choke() {} - void write_unchoke() {} - void write_interested() {} - void write_not_interested() {} - void write_request(peer_request const& r); - void write_cancel(peer_request const& r) {} - void write_have(int index) {} - void write_piece(peer_request const& r) {} - void write_keepalive() {} - void on_connected(); - -#ifndef NDEBUG - void check_invariant() const; -#endif - - private: - - // returns the block currently being - // downloaded. And the progress of that - // block. If the peer isn't downloading - // a piece for the moment, the boost::optional - // will be invalid. - boost::optional downloading_piece_progress() const; - - // this has one entry per bittorrent request - std::deque m_requests; - // this has one entry per http-request - // (might be more than the bt requests) - std::deque m_file_requests; - - std::string m_server_string; - http_parser m_parser; - std::string m_auth; - std::string m_host; - int m_port; - std::string m_path; - std::string m_url; - - // the first request will contain a little bit more data - // than subsequent ones, things that aren't critical are left - // out to save bandwidth. - bool m_first_request; - - // this is used for intermediate storage of pieces - // that is received in more than on HTTP responses - std::vector m_piece; - // the mapping of the data in the m_piece buffer - peer_request m_intermediate_piece; - - // the number of bytes into the receive buffer where - // current read cursor is. - int m_body_start; - // the number of bytes received in the current HTTP - // response. used to know where in the buffer the - // next response starts - int m_received_body; - }; -} - -#endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/xml_parse.hpp b/libtorrent/include/libtorrent/xml_parse.hpp deleted file mode 100644 index c3aeddad7..000000000 --- a/libtorrent/include/libtorrent/xml_parse.hpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - -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_XML_PARSE_HPP -#define TORRENT_XML_PARSE_HPP - -namespace libtorrent -{ - const int xml_start_tag = 0; - const int xml_end_tag = 1; - const int xml_string = 2; - - template - void xml_parse(char* p, char* end, CallbackType callback) - { - for(;p != end; ++p) - { - char const* start = p; - // look for tag start - for(; *p != '<' && p != end; ++p); - - if (p != start) - { - if (p != end) - { - assert(*p == '<'); - *p = 0; - } - callback(xml_string, start); - if (p != end) *p = '<'; - } - - if (p == end) break; - - // skip '<' - ++p; - - // parse the name of the tag. Ignore attributes - for (start = p; p != end && *p != '>'; ++p) - { - // terminate the string at the first space - // to ignore tag attributes - if (*p == ' ') *p = 0; - } - - // parse error - if (p == end) break; - - assert(*p == '>'); - *p = 0; - - if (*start == '/') - { - ++start; - callback(xml_end_tag, start); - } - else - { - callback(xml_start_tag, start); - } - *p = '>'; - } - - } - -} - - -#endif - diff --git a/libtorrent/src/Makefile.am b/libtorrent/src/Makefile.am deleted file mode 100644 index 5df13cde7..000000000 --- a/libtorrent/src/Makefile.am +++ /dev/null @@ -1,94 +0,0 @@ -lib_LTLIBRARIES = libtorrent.la - -if USE_DHT -kademlia_sources = kademlia/closest_nodes.cpp \ -kademlia/dht_tracker.cpp \ -kademlia/find_data.cpp \ -kademlia/node.cpp \ -kademlia/node_id.cpp \ -kademlia/refresh.cpp \ -kademlia/routing_table.cpp \ -kademlia/rpc_manager.cpp \ -kademlia/traversal_algorithm.cpp -endif - -libtorrent_la_SOURCES = allocate_resources.cpp \ -bandwidth_manager.cpp entry.cpp escape_string.cpp \ -peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \ -natpmp.cpp piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp \ -stat.cpp storage.cpp torrent.cpp torrent_handle.cpp \ -torrent_info.cpp tracker_manager.cpp http_connection.cpp \ -http_tracker_connection.cpp udp_tracker_connection.cpp \ -alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \ -logger.cpp file_pool.cpp ut_pex.cpp lsd.cpp upnp.cpp instantiate_connection.cpp \ -socks5_stream.cpp http_stream.cpp connection_queue.cpp $(kademlia_sources) - -noinst_HEADERS = \ -$(top_srcdir)/include/libtorrent/alert.hpp \ -$(top_srcdir)/include/libtorrent/alert_types.hpp \ -$(top_srcdir)/include/libtorrent/allocate_resources.hpp \ -$(top_srcdir)/include/libtorrent/aux_/allocate_resources_impl.hpp \ -$(top_srcdir)/include/libtorrent/aux_/session_impl.hpp \ -$(top_srcdir)/include/libtorrent/bandwidth_manager.hpp \ -$(top_srcdir)/include/libtorrent/bencode.hpp \ -$(top_srcdir)/include/libtorrent/buffer.hpp \ -$(top_srcdir)/include/libtorrent/connection_queue.hpp \ -$(top_srcdir)/include/libtorrent/debug.hpp \ -$(top_srcdir)/include/libtorrent/entry.hpp \ -$(top_srcdir)/include/libtorrent/escape_string.hpp \ -$(top_srcdir)/include/libtorrent/extensions.hpp \ -$(top_srcdir)/include/libtorrent/extensions/metadata_transfer.hpp \ -$(top_srcdir)/include/libtorrent/extensions/logger.hpp \ -$(top_srcdir)/include/libtorrent/extensions/ut_pex.hpp \ -$(top_srcdir)/include/libtorrent/file.hpp \ -$(top_srcdir)/include/libtorrent/file_pool.hpp \ -$(top_srcdir)/include/libtorrent/fingerprint.hpp \ -$(top_srcdir)/include/libtorrent/hasher.hpp \ -$(top_srcdir)/include/libtorrent/http_connection.hpp \ -$(top_srcdir)/include/libtorrent/http_stream.hpp \ -$(top_srcdir)/include/libtorrent/session_settings.hpp \ -$(top_srcdir)/include/libtorrent/http_tracker_connection.hpp \ -$(top_srcdir)/include/libtorrent/identify_client.hpp \ -$(top_srcdir)/include/libtorrent/instantiate_connection.hpp \ -$(top_srcdir)/include/libtorrent/invariant_check.hpp \ -$(top_srcdir)/include/libtorrent/io.hpp \ -$(top_srcdir)/include/libtorrent/ip_filter.hpp \ -$(top_srcdir)/include/libtorrent/lsd.hpp \ -$(top_srcdir)/include/libtorrent/peer.hpp \ -$(top_srcdir)/include/libtorrent/peer_connection.hpp \ -$(top_srcdir)/include/libtorrent/bt_peer_connection.hpp \ -$(top_srcdir)/include/libtorrent/web_peer_connection.hpp \ -$(top_srcdir)/include/libtorrent/natpmp.hpp \ -$(top_srcdir)/include/libtorrent/pch.hpp \ -$(top_srcdir)/include/libtorrent/peer_id.hpp \ -$(top_srcdir)/include/libtorrent/peer_info.hpp \ -$(top_srcdir)/include/libtorrent/peer_request.hpp \ -$(top_srcdir)/include/libtorrent/piece_block_progress.hpp \ -$(top_srcdir)/include/libtorrent/piece_picker.hpp \ -$(top_srcdir)/include/libtorrent/policy.hpp \ -$(top_srcdir)/include/libtorrent/resource_request.hpp \ -$(top_srcdir)/include/libtorrent/session.hpp \ -$(top_srcdir)/include/libtorrent/size_type.hpp \ -$(top_srcdir)/include/libtorrent/socket.hpp \ -$(top_srcdir)/include/libtorrent/socket_type.hpp \ -$(top_srcdir)/include/libtorrent/socks5_stream.hpp \ -$(top_srcdir)/include/libtorrent/stat.hpp \ -$(top_srcdir)/include/libtorrent/storage.hpp \ -$(top_srcdir)/include/libtorrent/time.hpp \ -$(top_srcdir)/include/libtorrent/torrent.hpp \ -$(top_srcdir)/include/libtorrent/torrent_handle.hpp \ -$(top_srcdir)/include/libtorrent/torrent_info.hpp \ -$(top_srcdir)/include/libtorrent/tracker_manager.hpp \ -$(top_srcdir)/include/libtorrent/udp_tracker_connection.hpp \ -$(top_srcdir)/include/libtorrent/utf8.hpp \ -$(top_srcdir)/include/libtorrent/xml_parse.hpp \ -$(top_srcdir)/include/libtorrent/variant_stream.hpp \ -$(top_srcdir)/include/libtorrent/version.hpp - - -libtorrent_la_LDFLAGS = $(LDFLAGS) -release @VERSION@ -libtorrent_la_LIBADD = @ZLIB@ -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ - -AM_CXXFLAGS= -ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @ZLIBINCL@ @DEBUGFLAGS@ @PTHREAD_CFLAGS@ -AM_LDFLAGS= $(LDFLAGS) -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ - diff --git a/libtorrent/src/Makefile.in b/libtorrent/src/Makefile.in deleted file mode 100644 index aa318eddc..000000000 --- a/libtorrent/src/Makefile.in +++ /dev/null @@ -1,672 +0,0 @@ -# Makefile.in generated by automake 1.9.6 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ - - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -top_builddir = .. -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -INSTALL = @INSTALL@ -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -build_triplet = @build@ -host_triplet = @host@ -subdir = src -DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/ac_cxx_namespaces.m4 \ - $(top_srcdir)/m4/acx_pthread.m4 \ - $(top_srcdir)/m4/ax_boost_date-time.m4 \ - $(top_srcdir)/m4/ax_boost_filesystem.m4 \ - $(top_srcdir)/m4/ax_boost_program_options.m4 \ - $(top_srcdir)/m4/ax_boost_regex.m4 \ - $(top_srcdir)/m4/ax_boost_thread.m4 $(top_srcdir)/configure.in -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(libdir)" -libLTLIBRARIES_INSTALL = $(INSTALL) -LTLIBRARIES = $(lib_LTLIBRARIES) -libtorrent_la_DEPENDENCIES = -am__libtorrent_la_SOURCES_DIST = allocate_resources.cpp \ - bandwidth_manager.cpp entry.cpp escape_string.cpp \ - peer_connection.cpp bt_peer_connection.cpp \ - web_peer_connection.cpp piece_picker.cpp policy.cpp \ - session.cpp session_impl.cpp sha1.cpp stat.cpp storage.cpp \ - torrent.cpp torrent_handle.cpp torrent_info.cpp \ - tracker_manager.cpp http_tracker_connection.cpp \ - udp_tracker_connection.cpp alert.cpp identify_client.cpp \ - ip_filter.cpp file.cpp metadata_transfer.cpp logger.cpp \ - file_pool.cpp ut_pex.cpp kademlia/closest_nodes.cpp \ - kademlia/dht_tracker.cpp kademlia/find_data.cpp \ - kademlia/node.cpp kademlia/node_id.cpp kademlia/refresh.cpp \ - kademlia/routing_table.cpp kademlia/rpc_manager.cpp \ - kademlia/traversal_algorithm.cpp -@USE_DHT_TRUE@am__objects_1 = closest_nodes.lo dht_tracker.lo \ -@USE_DHT_TRUE@ find_data.lo node.lo node_id.lo refresh.lo \ -@USE_DHT_TRUE@ routing_table.lo rpc_manager.lo \ -@USE_DHT_TRUE@ traversal_algorithm.lo -am_libtorrent_la_OBJECTS = allocate_resources.lo bandwidth_manager.lo \ - entry.lo escape_string.lo peer_connection.lo \ - bt_peer_connection.lo web_peer_connection.lo piece_picker.lo \ - policy.lo session.lo session_impl.lo sha1.lo stat.lo \ - storage.lo torrent.lo torrent_handle.lo torrent_info.lo \ - tracker_manager.lo http_tracker_connection.lo \ - udp_tracker_connection.lo alert.lo identify_client.lo \ - ip_filter.lo file.lo metadata_transfer.lo logger.lo \ - file_pool.lo ut_pex.lo $(am__objects_1) -libtorrent_la_OBJECTS = $(am_libtorrent_la_OBJECTS) -DEFAULT_INCLUDES = -I. -I$(srcdir) -depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles -CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CXXFLAGS) $(CXXFLAGS) -CXXLD = $(CXX) -CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ - $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(libtorrent_la_SOURCES) -DIST_SOURCES = $(am__libtorrent_la_SOURCES_DIST) -HEADERS = $(noinst_HEADERS) -ETAGS = etags -CTAGS = ctags -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -AMDEP_FALSE = @AMDEP_FALSE@ -AMDEP_TRUE = @AMDEP_TRUE@ -AMTAR = @AMTAR@ -AR = @AR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -BOOST_DATE_TIME_LIB = @BOOST_DATE_TIME_LIB@ -BOOST_FILESYSTEM_LIB = @BOOST_FILESYSTEM_LIB@ -BOOST_PROGRAM_OPTIONS_LIB = @BOOST_PROGRAM_OPTIONS_LIB@ -BOOST_REGEX_LIB = @BOOST_REGEX_LIB@ -BOOST_THREAD_LIB = @BOOST_THREAD_LIB@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CLIENT_TEST_BIN = @CLIENT_TEST_BIN@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CXX = @CXX@ -CXXCPP = @CXXCPP@ -CXXDEPMODE = @CXXDEPMODE@ -CXXFLAGS = @CXXFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DEBUGFLAGS = @DEBUGFLAGS@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO = @ECHO@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXAMPLESDIR = @EXAMPLESDIR@ -EXEEXT = @EXEEXT@ -F77 = @F77@ -FFLAGS = @FFLAGS@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LIBTOOL = @LIBTOOL@ -LN_S = @LN_S@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PTHREAD_CC = @PTHREAD_CC@ -PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ -PTHREAD_LIBS = @PTHREAD_LIBS@ -RANLIB = @RANLIB@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -STRIP = @STRIP@ -USE_DHT_FALSE = @USE_DHT_FALSE@ -USE_DHT_TRUE = @USE_DHT_TRUE@ -VERSION = @VERSION@ -ZLIB = @ZLIB@ -ZLIBDIR = @ZLIBDIR@ -ZLIBINCL = @ZLIBINCL@ -ac_ct_AR = @ac_ct_AR@ -ac_ct_CC = @ac_ct_CC@ -ac_ct_CXX = @ac_ct_CXX@ -ac_ct_F77 = @ac_ct_F77@ -ac_ct_RANLIB = @ac_ct_RANLIB@ -ac_ct_STRIP = @ac_ct_STRIP@ -acx_pthread_config = @acx_pthread_config@ -am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ -am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ -am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ -am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build = @build@ -build_alias = @build_alias@ -build_cpu = @build_cpu@ -build_os = @build_os@ -build_vendor = @build_vendor@ -datadir = @datadir@ -exec_prefix = @exec_prefix@ -host = @host@ -host_alias = @host_alias@ -host_cpu = @host_cpu@ -host_os = @host_os@ -host_vendor = @host_vendor@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -lib_LTLIBRARIES = libtorrent.la -@USE_DHT_TRUE@kademlia_sources = kademlia/closest_nodes.cpp \ -@USE_DHT_TRUE@kademlia/dht_tracker.cpp \ -@USE_DHT_TRUE@kademlia/find_data.cpp \ -@USE_DHT_TRUE@kademlia/node.cpp \ -@USE_DHT_TRUE@kademlia/node_id.cpp \ -@USE_DHT_TRUE@kademlia/refresh.cpp \ -@USE_DHT_TRUE@kademlia/routing_table.cpp \ -@USE_DHT_TRUE@kademlia/rpc_manager.cpp \ -@USE_DHT_TRUE@kademlia/traversal_algorithm.cpp - -libtorrent_la_SOURCES = allocate_resources.cpp \ -bandwidth_manager.cpp entry.cpp escape_string.cpp \ -peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \ -piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp stat.cpp \ -storage.cpp torrent.cpp torrent_handle.cpp \ -torrent_info.cpp tracker_manager.cpp \ -http_tracker_connection.cpp udp_tracker_connection.cpp \ -alert.cpp identify_client.cpp ip_filter.cpp file.cpp metadata_transfer.cpp \ -logger.cpp file_pool.cpp ut_pex.cpp $(kademlia_sources) - -noinst_HEADERS = \ -$(top_srcdir)/include/libtorrent/alert.hpp \ -$(top_srcdir)/include/libtorrent/alert_types.hpp \ -$(top_srcdir)/include/libtorrent/allocate_resources.hpp \ -$(top_srcdir)/include/libtorrent/aux_/allocate_resources_impl.hpp \ -$(top_srcdir)/include/libtorrent/aux_/session_impl.hpp \ -$(top_srcdir)/include/libtorrent/bandwidth_manager.hpp \ -$(top_srcdir)/include/libtorrent/bencode.hpp \ -$(top_srcdir)/include/libtorrent/buffer.hpp \ -$(top_srcdir)/include/libtorrent/debug.hpp \ -$(top_srcdir)/include/libtorrent/entry.hpp \ -$(top_srcdir)/include/libtorrent/escape_string.hpp \ -$(top_srcdir)/include/libtorrent/extensions.hpp \ -$(top_srcdir)/include/libtorrent/extensions/metadata_transfer.hpp \ -$(top_srcdir)/include/libtorrent/extensions/logger.hpp \ -$(top_srcdir)/include/libtorrent/extensions/ut_pex.hpp \ -$(top_srcdir)/include/libtorrent/file.hpp \ -$(top_srcdir)/include/libtorrent/file_pool.hpp \ -$(top_srcdir)/include/libtorrent/fingerprint.hpp \ -$(top_srcdir)/include/libtorrent/hasher.hpp \ -$(top_srcdir)/include/libtorrent/session_settings.hpp \ -$(top_srcdir)/include/libtorrent/http_tracker_connection.hpp \ -$(top_srcdir)/include/libtorrent/identify_client.hpp \ -$(top_srcdir)/include/libtorrent/invariant_check.hpp \ -$(top_srcdir)/include/libtorrent/io.hpp \ -$(top_srcdir)/include/libtorrent/ip_filter.hpp \ -$(top_srcdir)/include/libtorrent/peer.hpp \ -$(top_srcdir)/include/libtorrent/peer_connection.hpp \ -$(top_srcdir)/include/libtorrent/bt_peer_connection.hpp \ -$(top_srcdir)/include/libtorrent/web_peer_connection.hpp \ -$(top_srcdir)/include/libtorrent/peer_id.hpp \ -$(top_srcdir)/include/libtorrent/peer_info.hpp \ -$(top_srcdir)/include/libtorrent/peer_request.hpp \ -$(top_srcdir)/include/libtorrent/piece_block_progress.hpp \ -$(top_srcdir)/include/libtorrent/piece_picker.hpp \ -$(top_srcdir)/include/libtorrent/policy.hpp \ -$(top_srcdir)/include/libtorrent/resource_request.hpp \ -$(top_srcdir)/include/libtorrent/session.hpp \ -$(top_srcdir)/include/libtorrent/size_type.hpp \ -$(top_srcdir)/include/libtorrent/socket.hpp \ -$(top_srcdir)/include/libtorrent/stat.hpp \ -$(top_srcdir)/include/libtorrent/storage.hpp \ -$(top_srcdir)/include/libtorrent/torrent.hpp \ -$(top_srcdir)/include/libtorrent/torrent_handle.hpp \ -$(top_srcdir)/include/libtorrent/torrent_info.hpp \ -$(top_srcdir)/include/libtorrent/tracker_manager.hpp \ -$(top_srcdir)/include/libtorrent/udp_tracker_connection.hpp \ -$(top_srcdir)/include/libtorrent/utf8.hpp \ -$(top_srcdir)/include/libtorrent/version.hpp - -libtorrent_la_LDFLAGS = $(LDFLAGS) -version-info 1:0:1 -libtorrent_la_LIBADD = @ZLIB@ -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ -AM_CXXFLAGS = -ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @ZLIBINCL@ @DEBUGFLAGS@ @PTHREAD_CFLAGS@ -AM_LDFLAGS = $(LDFLAGS) -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@ -all: all-am - -.SUFFIXES: -.SUFFIXES: .cpp .lo .o .obj -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-libLTLIBRARIES: $(lib_LTLIBRARIES) - @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - if test -f $$p; then \ - f=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ - $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ - else :; fi; \ - done - -uninstall-libLTLIBRARIES: - @$(NORMAL_UNINSTALL) - @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - p=$(am__strip_dir) \ - echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ - $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ - done - -clean-libLTLIBRARIES: - -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -libtorrent.la: $(libtorrent_la_OBJECTS) $(libtorrent_la_DEPENDENCIES) - $(CXXLINK) -rpath $(libdir) $(libtorrent_la_LDFLAGS) $(libtorrent_la_OBJECTS) $(libtorrent_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alert.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/allocate_resources.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bandwidth_manager.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bt_peer_connection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/closest_nodes.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dht_tracker.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entry.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/escape_string.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file_pool.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/find_data.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http_tracker_connection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/identify_client.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_filter.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logger.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/metadata_transfer.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_id.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/peer_connection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/piece_picker.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/policy.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refresh.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/routing_table.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpc_manager.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session_impl.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha1.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stat.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/storage.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torrent.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torrent_handle.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/torrent_info.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tracker_manager.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traversal_algorithm.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udp_tracker_connection.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ut_pex.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/web_peer_connection.Plo@am__quote@ - -.cpp.o: -@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< - -.cpp.obj: -@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.cpp.lo: -@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< - -closest_nodes.lo: kademlia/closest_nodes.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT closest_nodes.lo -MD -MP -MF "$(DEPDIR)/closest_nodes.Tpo" -c -o closest_nodes.lo `test -f 'kademlia/closest_nodes.cpp' || echo '$(srcdir)/'`kademlia/closest_nodes.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/closest_nodes.Tpo" "$(DEPDIR)/closest_nodes.Plo"; else rm -f "$(DEPDIR)/closest_nodes.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/closest_nodes.cpp' object='closest_nodes.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o closest_nodes.lo `test -f 'kademlia/closest_nodes.cpp' || echo '$(srcdir)/'`kademlia/closest_nodes.cpp - -dht_tracker.lo: kademlia/dht_tracker.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT dht_tracker.lo -MD -MP -MF "$(DEPDIR)/dht_tracker.Tpo" -c -o dht_tracker.lo `test -f 'kademlia/dht_tracker.cpp' || echo '$(srcdir)/'`kademlia/dht_tracker.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/dht_tracker.Tpo" "$(DEPDIR)/dht_tracker.Plo"; else rm -f "$(DEPDIR)/dht_tracker.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/dht_tracker.cpp' object='dht_tracker.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o dht_tracker.lo `test -f 'kademlia/dht_tracker.cpp' || echo '$(srcdir)/'`kademlia/dht_tracker.cpp - -find_data.lo: kademlia/find_data.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT find_data.lo -MD -MP -MF "$(DEPDIR)/find_data.Tpo" -c -o find_data.lo `test -f 'kademlia/find_data.cpp' || echo '$(srcdir)/'`kademlia/find_data.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/find_data.Tpo" "$(DEPDIR)/find_data.Plo"; else rm -f "$(DEPDIR)/find_data.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/find_data.cpp' object='find_data.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o find_data.lo `test -f 'kademlia/find_data.cpp' || echo '$(srcdir)/'`kademlia/find_data.cpp - -node.lo: kademlia/node.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT node.lo -MD -MP -MF "$(DEPDIR)/node.Tpo" -c -o node.lo `test -f 'kademlia/node.cpp' || echo '$(srcdir)/'`kademlia/node.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/node.Tpo" "$(DEPDIR)/node.Plo"; else rm -f "$(DEPDIR)/node.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/node.cpp' object='node.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o node.lo `test -f 'kademlia/node.cpp' || echo '$(srcdir)/'`kademlia/node.cpp - -node_id.lo: kademlia/node_id.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT node_id.lo -MD -MP -MF "$(DEPDIR)/node_id.Tpo" -c -o node_id.lo `test -f 'kademlia/node_id.cpp' || echo '$(srcdir)/'`kademlia/node_id.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/node_id.Tpo" "$(DEPDIR)/node_id.Plo"; else rm -f "$(DEPDIR)/node_id.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/node_id.cpp' object='node_id.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o node_id.lo `test -f 'kademlia/node_id.cpp' || echo '$(srcdir)/'`kademlia/node_id.cpp - -refresh.lo: kademlia/refresh.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT refresh.lo -MD -MP -MF "$(DEPDIR)/refresh.Tpo" -c -o refresh.lo `test -f 'kademlia/refresh.cpp' || echo '$(srcdir)/'`kademlia/refresh.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/refresh.Tpo" "$(DEPDIR)/refresh.Plo"; else rm -f "$(DEPDIR)/refresh.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/refresh.cpp' object='refresh.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o refresh.lo `test -f 'kademlia/refresh.cpp' || echo '$(srcdir)/'`kademlia/refresh.cpp - -routing_table.lo: kademlia/routing_table.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT routing_table.lo -MD -MP -MF "$(DEPDIR)/routing_table.Tpo" -c -o routing_table.lo `test -f 'kademlia/routing_table.cpp' || echo '$(srcdir)/'`kademlia/routing_table.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/routing_table.Tpo" "$(DEPDIR)/routing_table.Plo"; else rm -f "$(DEPDIR)/routing_table.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/routing_table.cpp' object='routing_table.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o routing_table.lo `test -f 'kademlia/routing_table.cpp' || echo '$(srcdir)/'`kademlia/routing_table.cpp - -rpc_manager.lo: kademlia/rpc_manager.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT rpc_manager.lo -MD -MP -MF "$(DEPDIR)/rpc_manager.Tpo" -c -o rpc_manager.lo `test -f 'kademlia/rpc_manager.cpp' || echo '$(srcdir)/'`kademlia/rpc_manager.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/rpc_manager.Tpo" "$(DEPDIR)/rpc_manager.Plo"; else rm -f "$(DEPDIR)/rpc_manager.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/rpc_manager.cpp' object='rpc_manager.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o rpc_manager.lo `test -f 'kademlia/rpc_manager.cpp' || echo '$(srcdir)/'`kademlia/rpc_manager.cpp - -traversal_algorithm.lo: kademlia/traversal_algorithm.cpp -@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT traversal_algorithm.lo -MD -MP -MF "$(DEPDIR)/traversal_algorithm.Tpo" -c -o traversal_algorithm.lo `test -f 'kademlia/traversal_algorithm.cpp' || echo '$(srcdir)/'`kademlia/traversal_algorithm.cpp; \ -@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/traversal_algorithm.Tpo" "$(DEPDIR)/traversal_algorithm.Plo"; else rm -f "$(DEPDIR)/traversal_algorithm.Tpo"; exit 1; fi -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='kademlia/traversal_algorithm.cpp' object='traversal_algorithm.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o traversal_algorithm.lo `test -f 'kademlia/traversal_algorithm.cpp' || echo '$(srcdir)/'`kademlia/traversal_algorithm.cpp - -mostlyclean-libtool: - -rm -f *.lo - -clean-libtool: - -rm -rf .libs _libs - -distclean-libtool: - -rm -f libtool -uninstall-info-am: - -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - mkid -fID $$unique -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ - test -n "$$unique" || unique=$$empty_fix; \ - $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ - $$tags $$unique; \ - fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - tags=; \ - here=`pwd`; \ - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) ' { files[$$0] = 1; } \ - END { for (i in files) print i; }'`; \ - test -z "$(CTAGS_ARGS)$$tags$$unique" \ - || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ - $$tags $$unique - -GTAGS: - here=`$(am__cd) $(top_builddir) && pwd` \ - && cd $(top_srcdir) \ - && gtags -i $(GTAGS_ARGS) $$here - -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - -distdir: $(DISTFILES) - $(mkdir_p) $(distdir)/../include/libtorrent $(distdir)/../include/libtorrent/aux_ $(distdir)/../include/libtorrent/extensions - @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ - list='$(DISTFILES)'; for file in $$list; do \ - case $$file in \ - $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ - $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ - esac; \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test "$$dir" != "$$file" && test "$$dir" != "."; then \ - dir="/$$dir"; \ - $(mkdir_p) "$(distdir)$$dir"; \ - else \ - dir=''; \ - fi; \ - if test -d $$d/$$file; then \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile $(LTLIBRARIES) $(HEADERS) -installdirs: - for dir in "$(DESTDIR)$(libdir)"; do \ - test -z "$$dir" || $(mkdir_p) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ - mostlyclean-am - -distclean: distclean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-libtool distclean-tags - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: - -install-exec-am: install-libLTLIBRARIES - -install-info: install-info-am - -install-man: - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES - -.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libLTLIBRARIES clean-libtool ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-exec \ - install-exec-am install-info install-info-am \ - install-libLTLIBRARIES install-man install-strip installcheck \ - installcheck-am installdirs maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-compile \ - mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags uninstall uninstall-am uninstall-info-am \ - uninstall-libLTLIBRARIES - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/libtorrent/src/alert.cpp b/libtorrent/src/alert.cpp deleted file mode 100644 index b990db7e1..000000000 --- a/libtorrent/src/alert.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg, Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/alert.hpp" - -namespace libtorrent { - - alert::alert(severity_t severity, const std::string& msg) - : m_msg(msg) - , m_severity(severity) - , m_timestamp(time_now()) - { - } - - alert::~alert() - { - } - - ptime alert::timestamp() const - { - return m_timestamp; - } - - const std::string& alert::msg() const - { - return m_msg; - } - - alert::severity_t alert::severity() const - { - return m_severity; - } - - - - alert_manager::alert_manager() - : m_severity(alert::none) - {} - - alert_manager::~alert_manager() - { - while (!m_alerts.empty()) - { - delete m_alerts.front(); - m_alerts.pop(); - } - } - - void alert_manager::post_alert(const alert& alert_) - { - boost::mutex::scoped_lock lock(m_mutex); - if (m_severity > alert_.severity()) return; - - // the internal limit is 100 alerts - if (m_alerts.size() == 100) - { - alert* result = m_alerts.front(); - m_alerts.pop(); - delete result; - } - m_alerts.push(alert_.clone().release()); - } - - std::auto_ptr alert_manager::get() - { - boost::mutex::scoped_lock lock(m_mutex); - - assert(!m_alerts.empty()); - - alert* result = m_alerts.front(); - m_alerts.pop(); - return std::auto_ptr(result); - } - - bool alert_manager::pending() const - { - boost::mutex::scoped_lock lock(m_mutex); - - return !m_alerts.empty(); - } - - void alert_manager::set_severity(alert::severity_t severity) - { - boost::mutex::scoped_lock lock(m_mutex); - - m_severity = severity; - } - - bool alert_manager::should_post(alert::severity_t severity) const - { - return severity >= m_severity; - } - -} // namespace libtorrent - diff --git a/libtorrent/src/allocate_resources.cpp b/libtorrent/src/allocate_resources.cpp deleted file mode 100644 index deef06dc4..000000000 --- a/libtorrent/src/allocate_resources.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - -Copyright (c) 2006, Magnus Jonsson, 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. - -*/ - -//The Standard Library defines the two template functions std::min() -//and std::max() in the header. In general, you should -//use these template functions for calculating the min and max values -//of a pair. Unfortunately, Visual C++ does not define these function -// templates. This is because the names min and max clash with -//the traditional min and max macros defined in . -//As a workaround, Visual C++ defines two alternative templates with -//identical functionality called _cpp_min() and _cpp_max(). You can -//use them instead of std::min() and std::max().To disable the -//generation of the min and max macros in Visual C++, #define -//NOMINMAX before #including . - -#include "libtorrent/pch.hpp" - -#ifdef _WIN32 - //support boost1.32.0(2004-11-19 18:47) - //now all libs can be compiled and linked with static module - #define NOMINMAX -#endif - -#include "libtorrent/allocate_resources.hpp" -#include "libtorrent/size_type.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/aux_/allocate_resources_impl.hpp" - -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1310 -#define for if (false) {} else for -#else -#include -#endif - -namespace libtorrent -{ - int saturated_add(int a, int b) - { - assert(a >= 0); - assert(b >= 0); - assert(a <= resource_request::inf); - assert(b <= resource_request::inf); - assert(resource_request::inf + resource_request::inf < 0); - - unsigned int sum = unsigned(a) + unsigned(b); - if (sum > unsigned(resource_request::inf)) - sum = resource_request::inf; - - assert(sum >= unsigned(a) && sum >= unsigned(b)); - return int(sum); - } - -#if defined(_MSC_VER) && _MSC_VER < 1310 - - namespace detail - { - struct iterator_wrapper - { - typedef std::map >::iterator orig_iter; - - orig_iter iter; - - iterator_wrapper(orig_iter i): iter(i) {} - void operator++() { ++iter; } - torrent& operator*() { return *(iter->second); } - bool operator==(const iterator_wrapper& i) const - { return iter == i.iter; } - bool operator!=(const iterator_wrapper& i) const - { return iter != i.iter; } - }; - - struct iterator_wrapper2 - { - typedef std::map::iterator orig_iter; - - orig_iter iter; - - iterator_wrapper2(orig_iter i): iter(i) {} - void operator++() { ++iter; } - peer_connection& operator*() { return *(iter->second); } - bool operator==(const iterator_wrapper2& i) const - { return iter == i.iter; } - bool operator!=(const iterator_wrapper2& i) const - { return iter != i.iter; } - }; - - } - - void allocate_resources( - int resources - , std::map >& c - , resource_request torrent::* res) - { - aux::allocate_resources_impl( - resources - , detail::iterator_wrapper(c.begin()) - , detail::iterator_wrapper(c.end()) - , res); - } - - void allocate_resources( - int resources - , std::map& c - , resource_request peer_connection::* res) - { - aux::allocate_resources_impl( - resources - , detail::iterator_wrapper2(c.begin()) - , detail::iterator_wrapper2(c.end()) - , res); - } - -#else - - namespace aux - { - peer_connection& pick_peer( - std::pair - , boost::intrusive_ptr > const& p) - { - return *p.second; - } - - peer_connection& pick_peer2( - std::pair const& p) - { - return *p.second; - } - - torrent& deref(std::pair > const& p) - { - return *p.second; - } - - session& deref(session* p) - { - return *p; - } - } - - void allocate_resources( - int resources - , std::map >& c - , resource_request torrent::* res) - { - typedef std::map >::iterator orig_iter; - typedef std::pair > in_param; - typedef boost::transform_iterator new_iter; - - aux::allocate_resources_impl( - resources - , new_iter(c.begin(), &aux::deref) - , new_iter(c.end(), &aux::deref) - , res); - } - - void allocate_resources( - int resources - , std::map& c - , resource_request peer_connection::* res) - { - typedef std::map::iterator orig_iter; - typedef std::pair in_param; - typedef boost::transform_iterator new_iter; - - aux::allocate_resources_impl( - resources - , new_iter(c.begin(), &aux::pick_peer2) - , new_iter(c.end(), &aux::pick_peer2) - , res); - } - - void allocate_resources( - int resources - , std::vector& _sessions - , resource_request session::* res) - { - typedef std::vector::iterator orig_iter; - typedef session* in_param; - typedef boost::transform_iterator new_iter; - - aux::allocate_resources_impl( - resources - , new_iter(_sessions.begin(), &aux::deref) - , new_iter(_sessions.end(), &aux::deref) - , res); - } - -#endif - -} // namespace libtorrent diff --git a/libtorrent/src/bandwidth_manager.cpp b/libtorrent/src/bandwidth_manager.cpp deleted file mode 100644 index 19dc6fcf7..000000000 --- a/libtorrent/src/bandwidth_manager.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/bandwidth_manager.hpp" -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/time.hpp" - -#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING -#include "libtorrent/aux_/session_impl.hpp" -#endif - -namespace libtorrent -{ - namespace - { - const time_duration window_size = seconds(1); - } - - history_entry::history_entry(intrusive_ptr p - , weak_ptr t, int a, ptime exp) - : expires_at(exp), amount(a), peer(p), tor(t) - {} - - bw_queue_entry::bw_queue_entry(intrusive_ptr const& pe - , bool no_prio) - : peer(pe), non_prioritized(no_prio) - {} - - bandwidth_manager::bandwidth_manager(io_service& ios, int channel) - : m_ios(ios) - , m_history_timer(m_ios) - , m_limit(bandwidth_limit::inf) - , m_current_quota(0) - , m_channel(channel) - {} - - void bandwidth_manager::request_bandwidth(intrusive_ptr peer - , bool non_prioritized) - { - INVARIANT_CHECK; - - assert(!peer->ignore_bandwidth_limits()); - - // make sure this peer isn't already in line - // waiting for bandwidth -#ifndef NDEBUG - for (std::deque::iterator i = m_queue.begin() - , end(m_queue.end()); i != end; ++i) - { - assert(i->peer < peer || peer < i->peer); - } -#endif - - assert(peer->max_assignable_bandwidth(m_channel) > 0); - - // if the queue is empty, we have to push the new - // peer at the back of it. If the peer is non-prioritized - // it is not supposed to cut in fron of anybody, so then - // we also just add it at the end - if (m_queue.empty() || non_prioritized) - { - m_queue.push_back(bw_queue_entry(peer, non_prioritized)); - } - else - { - // skip forward in the queue until we find a prioritized peer - // or hit the front of it. - std::deque::reverse_iterator i = m_queue.rbegin(); - while (i != m_queue.rend() && i->non_prioritized) ++i; - m_queue.insert(i.base(), bw_queue_entry(peer, non_prioritized)); - } - if (m_queue.size() == 1) hand_out_bandwidth(); - } - - -#ifndef NDEBUG - void bandwidth_manager::check_invariant() const - { - int current_quota = 0; - for (std::deque::const_iterator i - = m_history.begin(), end(m_history.end()); i != end; ++i) - { - current_quota += i->amount; - } - - assert(current_quota == m_current_quota); - } -#endif - - void bandwidth_manager::add_history_entry(history_entry const& e) try - { - INVARIANT_CHECK; -#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING -// (*m_ses->m_logger) << "bw history [" << m_channel << "]\n"; -#endif - - m_history.push_front(e); - m_current_quota += e.amount; - // in case the size > 1 there is already a timer - // active that will be invoked, no need to set one up - if (m_history.size() > 1) return; - - m_history_timer.expires_at(e.expires_at); - m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1)); - } - catch (std::exception&) { assert(false); } - - void bandwidth_manager::on_history_expire(asio::error_code const& e) try - { - INVARIANT_CHECK; - - if (e) return; - -#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING -// (*m_ses->m_logger) << "bw expire [" << m_channel << "]\n"; -#endif - - assert(!m_history.empty()); - - ptime now(time_now()); - while (!m_history.empty() && m_history.back().expires_at <= now) - { - history_entry e = m_history.back(); - m_history.pop_back(); - m_current_quota -= e.amount; - assert(m_current_quota >= 0); - intrusive_ptr c = e.peer; - shared_ptr t = e.tor.lock(); - if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount); - if (t) t->expire_bandwidth(m_channel, e.amount); - } - - // now, wait for the next chunk to expire - if (!m_history.empty()) - { - m_history_timer.expires_at(m_history.back().expires_at); - m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1)); - } - - // since some bandwidth just expired, it - // means we can hand out more (in case there - // are still consumers in line) - if (!m_queue.empty()) hand_out_bandwidth(); - } - catch (std::exception&) - { - assert(false); - }; - - void bandwidth_manager::hand_out_bandwidth() try - { - INVARIANT_CHECK; -#if defined TORRENT_LOGGING || defined TORRENT_VERBOSE_LOGGING -// (*m_ses->m_logger) << "hand out bw [" << m_channel << "]\n"; -#endif - - ptime now(time_now()); - - mutex_t::scoped_lock l(m_mutex); - int limit = m_limit; - l.unlock(); - - // available bandwidth to hand out - int amount = limit - m_current_quota; - - int bandwidth_block_size_limit = max_bandwidth_block_size; - if (m_queue.size() > 3 && bandwidth_block_size_limit > limit / int(m_queue.size())) - bandwidth_block_size_limit = std::max(max_bandwidth_block_size / int(m_queue.size() - 3) - , min_bandwidth_block_size); - - while (!m_queue.empty() && amount > 0) - { - assert(amount == limit - m_current_quota); - bw_queue_entry qe = m_queue.front(); - m_queue.pop_front(); - - shared_ptr t = qe.peer->associated_torrent().lock(); - if (!t) continue; - if (qe.peer->is_disconnecting()) - { - t->expire_bandwidth(m_channel, -1); - continue; - } - - // at this point, max_assignable may actually be zero. Since - // the bandwidth quota is subtracted once the data has been - // send. If the peer was added to the queue while the data was - // still being sent, max_assignable may have been > 0 at that time. - int max_assignable = qe.peer->max_assignable_bandwidth(m_channel); - if (max_assignable == 0) - { - t->expire_bandwidth(m_channel, -1); - continue; - } - // don't hand out chunks larger than the throttle - // per second on the torrent - if (max_assignable > t->bandwidth_throttle(m_channel)) - max_assignable = t->bandwidth_throttle(m_channel); - - // so, hand out max_assignable, but no more than - // the available bandwidth (amount) and no more - // than the max_bandwidth_block_size - int single_amount = std::min(amount - , std::min(bandwidth_block_size_limit - , max_assignable)); - assert(single_amount > 0); - amount -= single_amount; - qe.peer->assign_bandwidth(m_channel, single_amount); - t->assign_bandwidth(m_channel, single_amount); - add_history_entry(history_entry(qe.peer, t, single_amount, now + window_size)); - } - } - catch (std::exception& e) - { assert(false); }; - -} - diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp deleted file mode 100644 index 082d856aa..000000000 --- a/libtorrent/src/bt_peer_connection.cpp +++ /dev/null @@ -1,1378 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/aux_/session_impl.hpp" - -using boost::bind; -using boost::shared_ptr; -using libtorrent::aux::session_impl; - -namespace libtorrent -{ - - const bt_peer_connection::message_handler - bt_peer_connection::m_message_handler[] = - { - &bt_peer_connection::on_choke, - &bt_peer_connection::on_unchoke, - &bt_peer_connection::on_interested, - &bt_peer_connection::on_not_interested, - &bt_peer_connection::on_have, - &bt_peer_connection::on_bitfield, - &bt_peer_connection::on_request, - &bt_peer_connection::on_piece, - &bt_peer_connection::on_cancel, - &bt_peer_connection::on_dht_port, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - &bt_peer_connection::on_extended - }; - - - bt_peer_connection::bt_peer_connection( - session_impl& ses - , boost::weak_ptr tor - , shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo) - : peer_connection(ses, tor, s, remote - , peerinfo) - , m_state(read_protocol_length) -#ifndef TORRENT_DISABLE_EXTENSIONS - , m_supports_extensions(false) -#endif - , m_supports_dht_port(false) -#ifndef NDEBUG - , m_sent_bitfield(false) - , m_in_constructor(true) -#endif - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "*** bt_peer_connection\n"; -#endif - - write_handshake(); - - // start in the state where we are trying to read the - // handshake from the other side - reset_recv_buffer(1); - - // assume the other end has no pieces - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - if (t->ready_for_connections()) - write_bitfield(t->pieces()); - - setup_send(); - setup_receive(); -#ifndef NDEBUG - m_in_constructor = false; -#endif - } - - bt_peer_connection::bt_peer_connection( - session_impl& ses - , boost::shared_ptr s - , policy::peer* peerinfo) - : peer_connection(ses, s, peerinfo) - , m_state(read_protocol_length) -#ifndef TORRENT_DISABLE_EXTENSIONS - , m_supports_extensions(false) -#endif - , m_supports_dht_port(false) -#ifndef NDEBUG - , m_sent_bitfield(false) - , m_in_constructor(true) -#endif - { - // we are not attached to any torrent yet. - // we have to wait for the handshake to see - // which torrent the connector want's to connect to - - - // upload bandwidth will only be given to connections - // that are part of a torrent. Since this is an incoming - // connection, we have to give it some initial bandwidth - // to send the handshake. - m_bandwidth_limit[download_channel].assign(80); - m_bandwidth_limit[upload_channel].assign(80); - - // start in the state where we are trying to read the - // handshake from the other side - reset_recv_buffer(1); - setup_receive(); -#ifndef NDEBUG - m_in_constructor = false; -#endif - } - - bt_peer_connection::~bt_peer_connection() - { - } - - void bt_peer_connection::on_metadata() - { - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - write_bitfield(t->pieces()); - } - - void bt_peer_connection::write_dht_port(int listen_port) - { - INVARIANT_CHECK; -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> DHT_PORT [ " << listen_port << " ]\n"; -#endif - buffer::interval packet = allocate_send_buffer(7); - detail::write_uint32(3, packet.begin); - detail::write_uint8(msg_dht_port, packet.begin); - detail::write_uint16(listen_port, packet.begin); - assert(packet.begin == packet.end); - setup_send(); - } - - void bt_peer_connection::get_peer_info(peer_info& p) const - { - assert(!associated_torrent().expired()); - - p.down_speed = statistics().download_rate(); - p.up_speed = statistics().upload_rate(); - p.payload_down_speed = statistics().download_payload_rate(); - p.payload_up_speed = statistics().upload_payload_rate(); - p.pid = pid(); - p.ip = remote(); - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - p.country[0] = m_country[0]; - p.country[1] = m_country[1]; -#endif - - p.total_download = statistics().total_payload_download(); - p.total_upload = statistics().total_payload_upload(); - - if (m_bandwidth_limit[upload_channel].throttle() == bandwidth_limit::inf) - p.upload_limit = -1; - else - p.upload_limit = m_bandwidth_limit[upload_channel].throttle(); - - if (m_bandwidth_limit[download_channel].throttle() == bandwidth_limit::inf) - p.download_limit = -1; - else - p.download_limit = m_bandwidth_limit[download_channel].throttle(); - - p.load_balancing = total_free_upload(); - - p.download_queue_length = (int)download_queue().size(); - p.upload_queue_length = (int)upload_queue().size(); - - if (boost::optional ret = downloading_piece_progress()) - { - p.downloading_piece_index = ret->piece_index; - p.downloading_block_index = ret->block_index; - p.downloading_progress = ret->bytes_downloaded; - p.downloading_total = ret->full_block_bytes; - } - else - { - p.downloading_piece_index = -1; - p.downloading_block_index = -1; - p.downloading_progress = 0; - p.downloading_total = 0; - } - - p.flags = 0; - if (is_interesting()) p.flags |= peer_info::interesting; - if (is_choked()) p.flags |= peer_info::choked; - if (is_peer_interested()) p.flags |= peer_info::remote_interested; - if (has_peer_choked()) p.flags |= peer_info::remote_choked; - if (support_extensions()) p.flags |= peer_info::supports_extensions; - if (is_local()) p.flags |= peer_info::local_connection; - if (!is_connecting() && m_state < read_packet_size) - p.flags |= peer_info::handshake; - if (is_connecting() && !is_queued()) p.flags |= peer_info::connecting; - if (is_queued()) p.flags |= peer_info::queued; - - p.pieces = get_bitfield(); - p.seed = is_seed(); - - p.client = m_client_version; - p.connection_type = peer_info::standard_bittorrent; - - if (peer_info_struct()) - { - p.source = peer_info_struct()->source; - p.failcount = peer_info_struct()->failcount; - } - else - { - assert(!is_local()); - p.source = 0; - p.failcount = 0; - } - } - - bool bt_peer_connection::in_handshake() const - { - return m_state < read_packet_size; - } - - void bt_peer_connection::write_handshake() - { - INVARIANT_CHECK; - - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - // add handshake to the send buffer - const char version_string[] = "BitTorrent protocol"; - const int string_len = sizeof(version_string)-1; - - buffer::interval i = allocate_send_buffer(1 + string_len + 8 + 20 + 20); - // length of version string - *i.begin = string_len; - ++i.begin; - - // version string itself - std::copy( - version_string - , version_string + string_len - , i.begin); - i.begin += string_len; - - // 8 zeroes - std::fill(i.begin, i.begin + 8, 0); - -#ifndef TORRENT_DISABLE_DHT - // indicate that we support the DHT messages - *(i.begin + 7) = 0x01; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - // we support extensions - *(i.begin + 5) = 0x10; -#endif - - i.begin += 8; - - // info hash - sha1_hash const& ih = t->torrent_file().info_hash(); - std::copy(ih.begin(), ih.end(), i.begin); - i.begin += 20; - - // peer id - std::copy( - m_ses.get_peer_id().begin() - , m_ses.get_peer_id().end() - , i.begin); - i.begin += 20; - assert(i.begin == i.end); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> HANDSHAKE\n"; -#endif - setup_send(); - } - - boost::optional bt_peer_connection::downloading_piece_progress() const - { - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - buffer::const_interval recv_buffer = receive_buffer(); - // are we currently receiving a 'piece' message? - if (m_state != read_packet - || recv_buffer.left() < 9 - || recv_buffer[0] != msg_piece) - return boost::optional(); - - const char* ptr = recv_buffer.begin + 1; - peer_request r; - r.piece = detail::read_int32(ptr); - r.start = detail::read_int32(ptr); - r.length = packet_size() - 9; - - // is any of the piece message header data invalid? - if (!verify_piece(r)) - return boost::optional(); - - piece_block_progress p; - - p.piece_index = r.piece; - p.block_index = r.start / t->block_size(); - p.bytes_downloaded = recv_buffer.left() - 9; - p.full_block_bytes = r.length; - - return boost::optional(p); - } - - - // message handlers - - // ----------------------------- - // --------- KEEPALIVE --------- - // ----------------------------- - - void bt_peer_connection::on_keepalive() - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== KEEPALIVE\n"; -#endif - incoming_keepalive(); - } - - // ----------------------------- - // ----------- CHOKE ----------- - // ----------------------------- - - void bt_peer_connection::on_choke(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - if (packet_size() != 1) - throw protocol_error("'choke' message size != 1"); - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - incoming_choke(); - } - - // ----------------------------- - // ---------- UNCHOKE ---------- - // ----------------------------- - - void bt_peer_connection::on_unchoke(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - if (packet_size() != 1) - throw protocol_error("'unchoke' message size != 1"); - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - incoming_unchoke(); - } - - // ----------------------------- - // -------- INTERESTED --------- - // ----------------------------- - - void bt_peer_connection::on_interested(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - if (packet_size() != 1) - throw protocol_error("'interested' message size != 1"); - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - incoming_interested(); - } - - // ----------------------------- - // ------ NOT INTERESTED ------- - // ----------------------------- - - void bt_peer_connection::on_not_interested(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - if (packet_size() != 1) - throw protocol_error("'not interested' message size != 1"); - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - incoming_not_interested(); - } - - // ----------------------------- - // ----------- HAVE ------------ - // ----------------------------- - - void bt_peer_connection::on_have(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - if (packet_size() != 5) - throw protocol_error("'have' message size != 5"); - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - const char* ptr = recv_buffer.begin + 1; - int index = detail::read_int32(ptr); - - incoming_have(index); - } - - // ----------------------------- - // --------- BITFIELD ---------- - // ----------------------------- - - void bt_peer_connection::on_bitfield(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - // if we don't have the metedata, we cannot - // verify the bitfield size - if (t->valid_metadata() - && packet_size() - 1 != ((int)get_bitfield().size() + 7) / 8) - throw protocol_error("bitfield with invalid size"); - - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - std::vector bitfield; - - if (!t->valid_metadata()) - bitfield.resize((packet_size() - 1) * 8); - else - bitfield.resize(get_bitfield().size()); - - // if we don't have metadata yet - // just remember the bitmask - // don't update the piecepicker - // (since it doesn't exist yet) - for (int i = 0; i < (int)bitfield.size(); ++i) - bitfield[i] = (recv_buffer[1 + (i>>3)] & (1 << (7 - (i&7)))) != 0; - - incoming_bitfield(bitfield); - } - - // ----------------------------- - // ---------- REQUEST ---------- - // ----------------------------- - - void bt_peer_connection::on_request(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - if (packet_size() != 13) - throw protocol_error("'request' message size != 13"); - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - peer_request r; - const char* ptr = recv_buffer.begin + 1; - r.piece = detail::read_int32(ptr); - r.start = detail::read_int32(ptr); - r.length = detail::read_int32(ptr); - - incoming_request(r); - } - - // ----------------------------- - // ----------- PIECE ----------- - // ----------------------------- - - void bt_peer_connection::on_piece(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - - buffer::const_interval recv_buffer = receive_buffer(); - int recv_pos = recv_buffer.end - recv_buffer.begin; - - // classify the received data as protocol chatter - // or data payload for the statistics - if (recv_pos <= 9) - // only received protocol data - m_statistics.received_bytes(0, received); - else if (recv_pos - received >= 9) - // only received payload data - m_statistics.received_bytes(received, 0); - else - { - // received a bit of both - assert(recv_pos - received < 9); - assert(recv_pos > 9); - assert(9 - (recv_pos - received) <= 9); - m_statistics.received_bytes( - recv_pos - 9 - , 9 - (recv_pos - received)); - } - - incoming_piece_fragment(); - if (!packet_finished()) return; - - const char* ptr = recv_buffer.begin + 1; - peer_request p; - p.piece = detail::read_int32(ptr); - p.start = detail::read_int32(ptr); - p.length = packet_size() - 9; - - incoming_piece(p, recv_buffer.begin + 9); - } - - // ----------------------------- - // ---------- CANCEL ----------- - // ----------------------------- - - void bt_peer_connection::on_cancel(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - if (packet_size() != 13) - throw protocol_error("'cancel' message size != 13"); - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - peer_request r; - const char* ptr = recv_buffer.begin + 1; - r.piece = detail::read_int32(ptr); - r.start = detail::read_int32(ptr); - r.length = detail::read_int32(ptr); - - incoming_cancel(r); - } - - // ----------------------------- - // --------- DHT PORT ---------- - // ----------------------------- - - void bt_peer_connection::on_dht_port(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - if (packet_size() != 3) - throw protocol_error("'dht_port' message size != 3"); - m_statistics.received_bytes(0, received); - if (!packet_finished()) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - const char* ptr = recv_buffer.begin + 1; - int listen_port = detail::read_uint16(ptr); - - incoming_dht_port(listen_port); - } - - // ----------------------------- - // --------- EXTENDED ---------- - // ----------------------------- - - void bt_peer_connection::on_extended(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - m_statistics.received_bytes(0, received); - if (packet_size() < 2) - throw protocol_error("'extended' message smaller than 2 bytes"); - - if (associated_torrent().expired()) - throw protocol_error("'extended' message sent before proper handshake"); - - buffer::const_interval recv_buffer = receive_buffer(); - if (recv_buffer.left() < 2) return; - - assert(*recv_buffer.begin == msg_extended); - ++recv_buffer.begin; - - int extended_id = detail::read_uint8(recv_buffer.begin); - - if (extended_id == 0) - { - on_extended_handshake(); - return; - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_extended(packet_size() - 2, extended_id - , recv_buffer)) - return; - } -#endif - - throw protocol_error("unknown extended message id: " - + boost::lexical_cast(extended_id)); - } - - void bt_peer_connection::on_extended_handshake() - { - if (!packet_finished()) return; - - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - buffer::const_interval recv_buffer = receive_buffer(); - - entry root; - try - { - root = bdecode(recv_buffer.begin + 2, recv_buffer.end); - } - catch (std::exception& exc) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "invalid extended handshake: " << exc.what() << "\n"; -#endif - return; - } - -#ifdef TORRENT_VERBOSE_LOGGING - std::stringstream ext; - root.print(ext); - (*m_logger) << "<== EXTENDED HANDSHAKE: \n" << ext.str(); -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end;) - { - // a false return value means that the extension - // isn't supported by the other end. So, it is removed. - if (!(*i)->on_extension_handshake(root)) - i = m_extensions.erase(i); - else - ++i; - } -#endif - - // there is supposed to be a remote listen port - if (entry* listen_port = root.find_key("p")) - { - if (listen_port->type() == entry::int_t) - { - tcp::endpoint adr(remote().address() - , (unsigned short)listen_port->integer()); - t->get_policy().peer_from_tracker(adr, pid(), 0, 0); - } - } - // there should be a version too - // but where do we put that info? - - if (entry* client_info = root.find_key("v")) - { - if (client_info->type() == entry::string_t) - m_client_version = client_info->string(); - } - - if (entry* reqq = root.find_key("reqq")) - { - if (reqq->type() == entry::int_t) - m_max_out_request_queue = reqq->integer(); - if (m_max_out_request_queue < 1) - m_max_out_request_queue = 1; - } - } - - bool bt_peer_connection::dispatch_message(int received) - { - INVARIANT_CHECK; - - assert(received > 0); - - // this means the connection has been closed already - if (associated_torrent().expired()) return false; - - buffer::const_interval recv_buffer = receive_buffer(); - - int packet_type = recv_buffer[0]; - if (packet_type < 0 - || packet_type >= num_supported_messages - || m_message_handler[packet_type] == 0) - { -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_unknown_message(packet_size(), packet_type - , buffer::const_interval(recv_buffer.begin+1 - , recv_buffer.end))) - return packet_finished(); - } -#endif - - throw protocol_error("unknown message id: " - + boost::lexical_cast(packet_type) - + " size: " + boost::lexical_cast(packet_size())); - } - - assert(m_message_handler[packet_type] != 0); - - // call the correct handler for this packet type - (this->*m_message_handler[packet_type])(received); - - return packet_finished(); - } - - void bt_peer_connection::write_keepalive() - { - INVARIANT_CHECK; - - char buf[] = {0,0,0,0}; - send_buffer(buf, buf + sizeof(buf)); - } - - void bt_peer_connection::write_cancel(peer_request const& r) - { - INVARIANT_CHECK; - - assert(associated_torrent().lock()->valid_metadata()); - - char buf[] = {0,0,0,13, msg_cancel}; - - buffer::interval i = allocate_send_buffer(17); - - std::copy(buf, buf + 5, i.begin); - i.begin += 5; - - // index - detail::write_int32(r.piece, i.begin); - // begin - detail::write_int32(r.start, i.begin); - // length - detail::write_int32(r.length, i.begin); - assert(i.begin == i.end); - - setup_send(); - } - - void bt_peer_connection::write_request(peer_request const& r) - { - INVARIANT_CHECK; - - assert(associated_torrent().lock()->valid_metadata()); - - char buf[] = {0,0,0,13, msg_request}; - - buffer::interval i = allocate_send_buffer(17); - - std::copy(buf, buf + 5, i.begin); - i.begin += 5; - - // index - detail::write_int32(r.piece, i.begin); - // begin - detail::write_int32(r.start, i.begin); - // length - detail::write_int32(r.length, i.begin); - assert(i.begin == i.end); - - setup_send(); - } - - void bt_peer_connection::write_bitfield(std::vector const& bitfield) - { - INVARIANT_CHECK; - - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - assert(m_sent_bitfield == false); - assert(t->valid_metadata()); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> BITFIELD "; - - std::stringstream bitfield_string; - for (int i = 0; i < (int)get_bitfield().size(); ++i) - { - if (bitfield[i]) bitfield_string << "1"; - else bitfield_string << "0"; - } - bitfield_string << "\n"; - (*m_logger) << bitfield_string.str(); -#endif - const int packet_size = ((int)bitfield.size() + 7) / 8 + 5; - - buffer::interval i = allocate_send_buffer(packet_size); - - detail::write_int32(packet_size - 4, i.begin); - detail::write_uint8(msg_bitfield, i.begin); - - std::fill(i.begin, i.end, 0); - for (int c = 0; c < (int)bitfield.size(); ++c) - { - if (bitfield[c]) - i.begin[c >> 3] |= 1 << (7 - (c & 7)); - } - assert(i.end - i.begin == ((int)bitfield.size() + 7) / 8); -#ifndef NDEBUG - m_sent_bitfield = true; -#endif - setup_send(); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - void bt_peer_connection::write_extensions() - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> EXTENSIONS\n"; -#endif - assert(m_supports_extensions); - - entry handshake(entry::dictionary_t); - entry extension_list(entry::dictionary_t); - - handshake["m"] = extension_list; - - // only send the port in case we bade the connection - // on incoming connections the other end already knows - // our listen port - if (is_local()) handshake["p"] = m_ses.listen_port(); - handshake["v"] = m_ses.settings().user_agent; - std::string remote_address; - std::back_insert_iterator out(remote_address); - detail::write_address(remote().address(), out); - handshake["ip"] = remote_address; - handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue; - - // loop backwards, to make the first extension be the last - // to fill in the handshake (i.e. give the first extensions priority) - for (extension_list_t::reverse_iterator i = m_extensions.rbegin() - , end(m_extensions.rend()); i != end; ++i) - { - (*i)->add_handshake(handshake); - } - - std::vector msg; - bencode(std::back_inserter(msg), handshake); - - // make room for message - buffer::interval i = allocate_send_buffer(6 + msg.size()); - - // write the length of the message - detail::write_int32((int)msg.size() + 2, i.begin); - detail::write_uint8(msg_extended, i.begin); - // signal handshake message - detail::write_uint8(0, i.begin); - - std::copy(msg.begin(), msg.end(), i.begin); - i.begin += msg.size(); - assert(i.begin == i.end); - -#ifdef TORRENT_VERBOSE_LOGGING - std::stringstream ext; - handshake.print(ext); - (*m_logger) << "==> EXTENDED HANDSHAKE: \n" << ext.str(); -#endif - - setup_send(); - } -#endif - - void bt_peer_connection::write_choke() - { - INVARIANT_CHECK; - - if (is_choked()) return; - char msg[] = {0,0,0,1,msg_choke}; - send_buffer(msg, msg + sizeof(msg)); - } - - void bt_peer_connection::write_unchoke() - { - INVARIANT_CHECK; - - char msg[] = {0,0,0,1,msg_unchoke}; - send_buffer(msg, msg + sizeof(msg)); - } - - void bt_peer_connection::write_interested() - { - INVARIANT_CHECK; - - char msg[] = {0,0,0,1,msg_interested}; - send_buffer(msg, msg + sizeof(msg)); - } - - void bt_peer_connection::write_not_interested() - { - INVARIANT_CHECK; - - char msg[] = {0,0,0,1,msg_not_interested}; - send_buffer(msg, msg + sizeof(msg)); - } - - void bt_peer_connection::write_have(int index) - { - assert(associated_torrent().lock()->valid_metadata()); - assert(index >= 0); - assert(index < associated_torrent().lock()->torrent_file().num_pieces()); - INVARIANT_CHECK; - - const int packet_size = 9; - char msg[packet_size] = {0,0,0,5,msg_have}; - char* ptr = msg + 5; - detail::write_int32(index, ptr); - send_buffer(msg, msg + packet_size); - } - - void bt_peer_connection::write_piece(peer_request const& r) - { - INVARIANT_CHECK; - - const int packet_size = 4 + 5 + 4 + r.length; - - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - buffer::interval i = allocate_send_buffer(packet_size); - - detail::write_int32(packet_size-4, i.begin); - detail::write_uint8(msg_piece, i.begin); - detail::write_int32(r.piece, i.begin); - detail::write_int32(r.start, i.begin); - - t->filesystem().read( - i.begin, r.piece, r.start, r.length); - - assert(i.begin + r.length == i.end); - - m_payloads.push_back(range(send_buffer_size() - r.length, r.length)); - setup_send(); - } - - namespace - { - struct match_peer_id - { - match_peer_id(peer_id const& id, peer_connection const* pc) - : m_id(id), m_pc(pc) - { assert(pc); } - - bool operator()(policy::peer const& p) const - { - return p.connection != m_pc - && p.connection - && p.connection->pid() == m_id - && !p.connection->pid().is_all_zeros(); - } - - peer_id m_id; - peer_connection const* m_pc; - }; - } - - // -------------------------- - // RECEIVE DATA - // -------------------------- - - // throws exception when the client should be disconnected - void bt_peer_connection::on_receive(asio::error_code const& error - , std::size_t bytes_transferred) - { - INVARIANT_CHECK; - - if (error) return; - - buffer::const_interval recv_buffer = receive_buffer(); - - boost::shared_ptr t = associated_torrent().lock(); - - switch(m_state) - { - case read_protocol_length: - { - m_statistics.received_bytes(0, bytes_transferred); - if (!packet_finished()) break; - - int packet_size = recv_buffer[0]; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " protocol length: " << packet_size << "\n"; -#endif - if (packet_size > 100 || packet_size <= 0) - { - std::stringstream s; - s << "incorrect protocol length (" - << packet_size - << ") should be 19."; - throw std::runtime_error(s.str()); - } - m_state = read_protocol_string; - reset_recv_buffer(packet_size); - } - break; - - case read_protocol_string: - { - m_statistics.received_bytes(0, bytes_transferred); - if (!packet_finished()) break; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " protocol: '" << std::string(recv_buffer.begin - , recv_buffer.end) << "'\n"; -#endif - const char protocol_string[] = "BitTorrent protocol"; - if (recv_buffer.end - recv_buffer.begin != 19 - || !std::equal(recv_buffer.begin, recv_buffer.end - , protocol_string)) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "incorrect protocol name\n"; -#endif - std::stringstream s; - s << "got invalid protocol name: '" - << std::string(recv_buffer.begin, recv_buffer.end) - << "'"; - throw std::runtime_error(s.str()); - } - - m_state = read_info_hash; - reset_recv_buffer(28); - } - break; - - case read_info_hash: - { - m_statistics.received_bytes(0, bytes_transferred); - if (!packet_finished()) break; - -#ifdef TORRENT_VERBOSE_LOGGING - for (int i=0; i < 8; ++i) - { - for (int j=0; j < 8; ++j) - { - if (recv_buffer[i] & (0x80 >> j)) (*m_logger) << "1"; - else (*m_logger) << "0"; - } - } - (*m_logger) << "\n"; - if (recv_buffer[7] & 0x01) - (*m_logger) << "supports DHT port message\n"; - if (recv_buffer[7] & 0x02) - (*m_logger) << "supports FAST extensions\n"; - if (recv_buffer[5] & 0x10) - (*m_logger) << "supports extensions protocol\n"; -#endif - -#ifndef DISABLE_EXTENSIONS - if ((recv_buffer[5] & 0x10)) - m_supports_extensions = true; -#endif - if (recv_buffer[7] & 0x01) - m_supports_dht_port = true; - - // ok, now we have got enough of the handshake. Is this connection - // attached to a torrent? - if (!t) - { - // now, we have to see if there's a torrent with the - // info_hash we got from the peer - sha1_hash info_hash; - std::copy(recv_buffer.begin + 8, recv_buffer.begin + 28 - , (char*)info_hash.begin()); - - attach_to_torrent(info_hash); - t = associated_torrent().lock(); - assert(t); - - // yes, we found the torrent - // reply with our handshake - write_handshake(); - if (t->valid_metadata()) - write_bitfield(t->pieces()); - } - else - { - // verify info hash - if (!std::equal(recv_buffer.begin + 8, recv_buffer.begin + 28 - , (const char*)t->torrent_file().info_hash().begin())) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " received invalid info_hash\n"; -#endif - throw protocol_error("invalid info-hash in handshake"); - } - } - - assert(t->get_policy().has_connection(this)); - - m_state = read_peer_id; - reset_recv_buffer(20); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " info_hash received\n"; -#endif - } - break; - - case read_peer_id: - { - if (!t) return; - m_statistics.received_bytes(0, bytes_transferred); - if (!packet_finished()) break; - assert(packet_size() == 20); - -#ifdef TORRENT_VERBOSE_LOGGING - { - peer_id tmp; - std::copy(recv_buffer.begin, recv_buffer.begin + 20, (char*)tmp.begin()); - std::stringstream s; - s << "received peer_id: " << tmp << " client: " << identify_client(tmp) << "\n"; - s << "as ascii: "; - for (peer_id::iterator i = tmp.begin(); i != tmp.end(); ++i) - { - if (std::isprint(*i)) s << *i; - else s << "."; - } - s << "\n"; - (*m_logger) << s.str(); - } -#endif - peer_id pid; - std::copy(recv_buffer.begin, recv_buffer.begin + 20, (char*)pid.begin()); - set_pid(pid); - - if (t->settings().allow_multiple_connections_per_ip) - { - // now, let's see if this connection should be closed - policy& p = t->get_policy(); - policy::iterator i = std::find_if(p.begin_peer(), p.end_peer() - , match_peer_id(pid, this)); - if (i != p.end_peer()) - { - assert(i->connection->pid() == pid); - // we found another connection with the same peer-id - // which connection should be closed in order to be - // sure that the other end closes the same connection? - // the peer with greatest peer-id is the one allowed to - // initiate connections. So, if our peer-id is greater than - // the others, we should close the incoming connection, - // if not, we should close the outgoing one. - if (pid < m_ses.get_peer_id() && is_local()) - { - i->connection->disconnect(); - } - else - { - throw protocol_error("duplicate peer-id, connection closed"); - } - } - } - - if (pid == m_ses.get_peer_id()) - { - throw protocol_error("closing connection to ourself"); - } - -#ifndef TORRENT_DISABLE_DHT - if (m_supports_dht_port && m_ses.m_dht) - write_dht_port(m_ses.get_dht_settings().service_port); -#endif - - m_client_version = identify_client(pid); - boost::optional f = client_fingerprint(pid); - if (f && std::equal(f->name, f->name + 2, "BC")) - { - // if this is a bitcomet client, lower the request queue size limit - if (m_max_out_request_queue > 50) m_max_out_request_queue = 50; - } - - // disconnect if the peer has the same peer-id as ourself - // since it most likely is ourself then - if (pid == m_ses.get_peer_id()) - throw std::runtime_error("closing connection to ourself"); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end;) - { - if (!(*i)->on_handshake()) - { - i = m_extensions.erase(i); - } - else - { - ++i; - } - } - - if (m_supports_extensions) write_extensions(); -#endif - - // consider this a successful connection, reset the failcount - if (peer_info_struct()) peer_info_struct()->failcount = 0; - m_state = read_packet_size; - reset_recv_buffer(4); - } - break; - - case read_packet_size: - { - if (!t) return; - m_statistics.received_bytes(0, bytes_transferred); - if (!packet_finished()) break; - - const char* ptr = recv_buffer.begin; - int packet_size = detail::read_int32(ptr); - - // don't accept packets larger than 1 MB - if (packet_size > 1024*1024 || packet_size < 0) - { - // packet too large - throw std::runtime_error("packet > 1 MB (" - + boost::lexical_cast( - (unsigned int)packet_size) + " bytes)"); - } - - if (packet_size == 0) - { - incoming_keepalive(); - // keepalive message - m_state = read_packet_size; - reset_recv_buffer(4); - } - else - { - m_state = read_packet; - reset_recv_buffer(packet_size); - } - } - break; - - case read_packet: - { - if (!t) return; - if (dispatch_message(bytes_transferred)) - { - m_state = read_packet_size; - reset_recv_buffer(4); - } - } - break; - - } - } - - // -------------------------- - // SEND DATA - // -------------------------- - - // throws exception when the client should be disconnected - void bt_peer_connection::on_sent(asio::error_code const& error - , std::size_t bytes_transferred) - { - INVARIANT_CHECK; - - if (error) return; - - // manage the payload markers - int amount_payload = 0; - if (!m_payloads.empty()) - { - for (std::deque::iterator i = m_payloads.begin(); - i != m_payloads.end(); ++i) - { - i->start -= bytes_transferred; - if (i->start < 0) - { - if (i->start + i->length <= 0) - { - amount_payload += i->length; - } - else - { - amount_payload += -i->start; - i->length -= -i->start; - i->start = 0; - } - } - } - } - - // TODO: move the erasing into the loop above - // remove all payload ranges that has been sent - m_payloads.erase( - std::remove_if(m_payloads.begin(), m_payloads.end(), range_below_zero) - , m_payloads.end()); - - assert(amount_payload <= (int)bytes_transferred); - m_statistics.sent_bytes(amount_payload, bytes_transferred - amount_payload); - } - -#ifndef NDEBUG - void bt_peer_connection::check_invariant() const - { - if (!m_in_constructor) - peer_connection::check_invariant(); - - if (!m_payloads.empty()) - { - for (std::deque::const_iterator i = m_payloads.begin(); - i != m_payloads.end() - 1; ++i) - { - assert(i->start + i->length <= (i+1)->start); - } - } - } -#endif - -} - diff --git a/libtorrent/src/connection_queue.cpp b/libtorrent/src/connection_queue.cpp deleted file mode 100644 index f83baa196..000000000 --- a/libtorrent/src/connection_queue.cpp +++ /dev/null @@ -1,169 +0,0 @@ - -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/connection_queue.hpp" - -namespace libtorrent -{ - - connection_queue::connection_queue(io_service& ios): m_next_ticket(0) - , m_num_connecting(0) - , m_half_open_limit(0) - , m_timer(ios) - {} - - bool connection_queue::free_slots() const - { return m_num_connecting < m_half_open_limit || m_half_open_limit <= 0; } - - void connection_queue::enqueue(boost::function const& on_connect - , boost::function const& on_timeout - , time_duration timeout) - { - INVARIANT_CHECK; - - m_queue.push_back(entry()); - entry& e = m_queue.back(); - e.on_connect = on_connect; - e.on_timeout = on_timeout; - e.ticket = m_next_ticket; - e.timeout = timeout; - ++m_next_ticket; - try_connect(); - } - - void connection_queue::done(int ticket) - { - INVARIANT_CHECK; - - std::list::iterator i = std::find_if(m_queue.begin() - , m_queue.end(), boost::bind(&entry::ticket, _1) == ticket); - if (i == m_queue.end()) - { - // this might not be here in case on_timeout calls remove - return; - } - if (i->connecting) --m_num_connecting; - m_queue.erase(i); - try_connect(); - } - - void connection_queue::limit(int limit) - { m_half_open_limit = limit; } - - int connection_queue::limit() const - { return m_half_open_limit; } - -#ifndef NDEBUG - - void connection_queue::check_invariant() const - { - int num_connecting = 0; - for (std::list::const_iterator i = m_queue.begin(); - i != m_queue.end(); ++i) - { - if (i->connecting) ++num_connecting; - } - assert(num_connecting == m_num_connecting); - } - -#endif - - void connection_queue::try_connect() - { - INVARIANT_CHECK; - - if (!free_slots() || m_queue.empty()) - return; - - std::list::iterator i = std::find_if(m_queue.begin() - , m_queue.end(), boost::bind(&entry::connecting, _1) == false); - while (i != m_queue.end()) - { - assert(i->connecting == false); - ptime expire = time_now() + i->timeout; - if (m_num_connecting == 0) - { - m_timer.expires_at(expire); - m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1)); - } - i->connecting = true; - ++m_num_connecting; - i->expires = expire; - - INVARIANT_CHECK; - - entry& ent = *i; - ++i; - try { ent.on_connect(ent.ticket); } catch (std::exception&) {} - - if (!free_slots()) break; - i = std::find_if(i, m_queue.end(), boost::bind(&entry::connecting, _1) == false); - } - } - - void connection_queue::on_timeout(asio::error_code const& e) - { - INVARIANT_CHECK; - - assert(!e || e == asio::error::operation_aborted); - if (e) return; - - ptime next_expire = max_time(); - ptime now = time_now(); - for (std::list::iterator i = m_queue.begin(); - i != m_queue.end();) - { - if (i->connecting && i->expires < now) - { - boost::function on_timeout = i->on_timeout; - m_queue.erase(i++); - --m_num_connecting; - try { on_timeout(); } catch (std::exception&) {} - continue; - } - if (i->expires < next_expire) - next_expire = i->expires; - ++i; - } - if (next_expire < max_time()) - { - m_timer.expires_at(next_expire); - m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1)); - } - try_connect(); - } - -} - diff --git a/libtorrent/src/entry.cpp b/libtorrent/src/entry.cpp deleted file mode 100644 index 6506ed4c2..000000000 --- a/libtorrent/src/entry.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include "libtorrent/entry.hpp" -#include "libtorrent/config.hpp" - -#if defined(_MSC_VER) -namespace std -{ - using ::isprint; -} -#define for if (false) {} else for -#endif - -namespace -{ - template - void call_destructor(T* o) - { - assert(o); - o->~T(); - } - - struct compare_string - { - compare_string(char const* s): m_str(s) {} - - bool operator()( - std::pair const& e) const - { - return m_str && e.first == m_str; - } - char const* m_str; - }; -} - -namespace libtorrent -{ - namespace detail - { - TORRENT_EXPORT char const* integer_to_str(char* buf, int size, entry::integer_type val) - { - int sign = 0; - if (val < 0) - { - sign = 1; - val = -val; - } - buf[--size] = '\0'; - if (val == 0) buf[--size] = '0'; - for (; size > sign && val != 0;) - { - buf[--size] = '0' + char(val % 10); - val /= 10; - } - if (sign) buf[--size] = '-'; - return buf + size; - } - } - - entry& entry::operator[](char const* key) - { - dictionary_type::iterator i = dict().find(key); - if (i != dict().end()) return i->second; - dictionary_type::iterator ret = dict().insert( - dict().begin() - , std::make_pair(std::string(key), entry())); - return ret->second; - } - - - entry& entry::operator[](std::string const& key) - { - return (*this)[key.c_str()]; - } - - entry* entry::find_key(char const* key) - { - dictionary_type::iterator i = std::find_if( - dict().begin() - , dict().end() - , compare_string(key)); - if (i == dict().end()) return 0; - return &i->second; - - } - - entry const* entry::find_key(char const* key) const - { - dictionary_type::const_iterator i = dict().find(key); - if (i == dict().end()) return 0; - return &i->second; - } - - const entry& entry::operator[](char const* key) const - { - dictionary_type::const_iterator i = dict().find(key); - if (i == dict().end()) throw type_error( - (std::string("key not found: ") + key).c_str()); - return i->second; - } - - const entry& entry::operator[](std::string const& key) const - { - return (*this)[key.c_str()]; - } - - entry::entry(dictionary_type const& v) - { - new(data) dictionary_type(v); - m_type = dictionary_t; - } - - entry::entry(string_type const& v) - { - new(data) string_type(v); - m_type = string_t; - } - - entry::entry(list_type const& v) - { - new(data) list_type(v); - m_type = list_t; - } - - entry::entry(integer_type const& v) - { - new(data) integer_type(v); - m_type = int_t; - } - - void entry::operator=(dictionary_type const& v) - { - destruct(); - new(data) dictionary_type(v); - m_type = dictionary_t; - } - - void entry::operator=(string_type const& v) - { - destruct(); - new(data) string_type(v); - m_type = string_t; - } - - void entry::operator=(list_type const& v) - { - destruct(); - new(data) list_type(v); - m_type = list_t; - } - - void entry::operator=(integer_type const& v) - { - destruct(); - new(data) integer_type(v); - m_type = int_t; - } - - bool entry::operator==(entry const& e) const - { - if (m_type != e.m_type) return false; - - switch(m_type) - { - case int_t: - return integer() == e.integer(); - case string_t: - return string() == e.string(); - case list_t: - return list() == e.list(); - case dictionary_t: - return dict() == e.dict(); - default: - assert(m_type == undefined_t); - return true; - } - } - - void entry::construct(data_type t) - { - m_type = t; - switch(m_type) - { - case int_t: - new(data) integer_type; - break; - case string_t: - new(data) string_type; - break; - case list_t: - new(data) list_type; - break; - case dictionary_t: - new (data) dictionary_type; - break; - default: - assert(m_type == undefined_t); - m_type = undefined_t; - } - } - - void entry::copy(entry const& e) - { - m_type = e.m_type; - switch(m_type) - { - case int_t: - new(data) integer_type(e.integer()); - break; - case string_t: - new(data) string_type(e.string()); - break; - case list_t: - new(data) list_type(e.list()); - break; - case dictionary_t: - new (data) dictionary_type(e.dict()); - break; - default: - m_type = undefined_t; - } - } - - void entry::destruct() - { - switch(m_type) - { - case int_t: - call_destructor(reinterpret_cast(data)); - break; - case string_t: - call_destructor(reinterpret_cast(data)); - break; - case list_t: - call_destructor(reinterpret_cast(data)); - break; - case dictionary_t: - call_destructor(reinterpret_cast(data)); - break; - default: - assert(m_type == undefined_t); - break; - } - } - - void entry::print(std::ostream& os, int indent) const - { - assert(indent >= 0); - for (int i = 0; i < indent; ++i) os << " "; - switch (m_type) - { - case int_t: - os << integer() << "\n"; - break; - case string_t: - { - bool binary_string = false; - for (std::string::const_iterator i = string().begin(); i != string().end(); ++i) - { - if (!std::isprint(static_cast(*i))) - { - binary_string = true; - break; - } - } - if (binary_string) - { - os.unsetf(std::ios_base::dec); - os.setf(std::ios_base::hex); - for (std::string::const_iterator i = string().begin(); i != string().end(); ++i) - os << std::setfill('0') << std::setw(2) - << static_cast((unsigned char)*i); - os.unsetf(std::ios_base::hex); - os.setf(std::ios_base::dec); - os << "\n"; - } - else - { - os << string() << "\n"; - } - } break; - case list_t: - { - os << "list\n"; - for (list_type::const_iterator i = list().begin(); i != list().end(); ++i) - { - i->print(os, indent+1); - } - } break; - case dictionary_t: - { - os << "dictionary\n"; - for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i) - { - for (int j = 0; j < indent+1; ++j) os << " "; - os << "[" << i->first << "]"; - if (i->second.type() != entry::string_t - && i->second.type() != entry::int_t) - os << "\n"; - else os << " "; - i->second.print(os, indent+2); - } - } break; - default: - os << "\n"; - } - } -} - diff --git a/libtorrent/src/escape_string.cpp b/libtorrent/src/escape_string.cpp deleted file mode 100644 index 02a4fa085..000000000 --- a/libtorrent/src/escape_string.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include - -namespace libtorrent -{ - std::string unescape_string(std::string const& s) - { - std::string ret; - for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) - { - if(*i == '+') - { - ret += ' '; - } - else if (*i != '%') - { - ret += *i; - } - else - { - ++i; - if (i == s.end()) - throw std::runtime_error("invalid escaped string"); - - int high; - if(*i >= '0' && *i <= '9') high = *i - '0'; - else if(*i >= 'A' && *i <= 'F') high = *i + 10 - 'A'; - else if(*i >= 'a' && *i <= 'f') high = *i + 10 - 'a'; - else throw std::runtime_error("invalid escaped string"); - - ++i; - if (i == s.end()) - throw std::runtime_error("invalid escaped string"); - - int low; - if(*i >= '0' && *i <= '9') low = *i - '0'; - else if(*i >= 'A' && *i <= 'F') low = *i + 10 - 'A'; - else if(*i >= 'a' && *i <= 'f') low = *i + 10 - 'a'; - else throw std::runtime_error("invalid escaped string"); - - ret += char(high * 16 + low); - } - } - return ret; - } - - - std::string escape_string(const char* str, int len) - { - assert(str != 0); - assert(len >= 0); - // http://www.ietf.org/rfc/rfc2396.txt - // section 2.3 - // some trackers seems to require that ' is escaped -// static const char unreserved_chars[] = "-_.!~*'()"; - static const char unreserved_chars[] = "-_.!~*()" - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - "0123456789"; - - std::stringstream ret; - ret << std::hex << std::setfill('0'); - for (int i = 0; i < len; ++i) - { - if (std::count( - unreserved_chars - , unreserved_chars+sizeof(unreserved_chars)-1 - , *str)) - { - ret << *str; - } - else - { - ret << '%' - << std::setw(2) - << (int)static_cast(*str); - } - ++str; - } - return ret.str(); - } - - std::string escape_path(const char* str, int len) - { - assert(str != 0); - assert(len >= 0); - static const char unreserved_chars[] = "/-_.!~*()" - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - "0123456789"; - - std::stringstream ret; - ret << std::hex << std::setfill('0'); - for (int i = 0; i < len; ++i) - { - if (std::count( - unreserved_chars - , unreserved_chars+sizeof(unreserved_chars)-1 - , *str)) - { - ret << *str; - } - else - { - ret << '%' - << std::setw(2) - << (int)static_cast(*str); - } - ++str; - } - return ret.str(); - } -} diff --git a/libtorrent/src/file.cpp b/libtorrent/src/file.cpp deleted file mode 100644 index 71bc795a4..000000000 --- a/libtorrent/src/file.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _WIN32 -// windows part -#include "libtorrent/utf8.hpp" - -#include -#include -#include -#include - -#ifndef _MODE_T_ -typedef int mode_t; -#endif - -#ifdef UNICODE -#include "libtorrent/storage.hpp" -#endif - -#else -// unix part -#define _FILE_OFFSET_BITS 64 -#include -#include -#include -#include -#include - -#include -// make sure the _FILE_OFFSET_BITS define worked -// on this platform -BOOST_STATIC_ASSERT(sizeof(lseek(0, 0, 0)) >= 8); - -#endif - -#include -#include "libtorrent/file.hpp" -#include - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -#ifndef O_RANDOM -#define O_RANDOM 0 -#endif - -#ifdef UNICODE -#include "libtorrent/storage.hpp" -#endif - - -namespace fs = boost::filesystem; - -namespace -{ - enum { mode_in = 1, mode_out = 2 }; - - mode_t map_open_mode(int m) - { - if (m == (mode_in | mode_out)) return O_RDWR | O_CREAT | O_BINARY | O_RANDOM; - if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM; - if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM; - assert(false); - return 0; - } - -#ifdef WIN32 - std::string utf8_native(std::string const& s) - { - try - { - std::wstring ws; - libtorrent::utf8_wchar(s, ws); - std::size_t size = wcstombs(0, ws.c_str(), 0); - if (size == std::size_t(-1)) return s; - std::string ret; - ret.resize(size); - size = wcstombs(&ret[0], ws.c_str(), size + 1); - if (size == wchar_t(-1)) return s; - ret.resize(size); - return ret; - } - catch(std::exception) - { - return s; - } - } -#else - std::string utf8_native(std::string const& s) - { - return s; - } -#endif - -} - -namespace libtorrent -{ - - const file::open_mode file::in(mode_in); - const file::open_mode file::out(mode_out); - - const file::seek_mode file::begin(1); - const file::seek_mode file::end(2); - - struct file::impl - { - impl() - : m_fd(-1) - , m_open_mode(0) - {} - - impl(fs::path const& path, int mode) - : m_fd(-1) - , m_open_mode(0) - { - open(path, mode); - } - - ~impl() - { - close(); - } - - void open(fs::path const& path, int mode) - { - assert(path.is_complete()); - close(); -#if defined(_WIN32) && defined(UNICODE) - std::wstring wpath(safe_convert(path.native_file_string())); - m_fd = ::_wopen( - wpath.c_str() - , map_open_mode(mode) - , S_IREAD | S_IWRITE); -#else -#ifdef _WIN32 - m_fd = ::_open( -#else - m_fd = ::open( -#endif - utf8_native(path.native_file_string()).c_str() - , map_open_mode(mode) -#ifdef _WIN32 - , S_IREAD | S_IWRITE); -#else - , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -#endif -#endif - if (m_fd == -1) - { - std::stringstream msg; - msg << "open failed: '" << path.native_file_string() << "'. " - << strerror(errno); - throw file_error(msg.str()); - } - m_open_mode = mode; - } - - void close() - { - if (m_fd == -1) return; - -#ifdef _WIN32 - ::_close(m_fd); -#else - ::close(m_fd); -#endif - m_fd = -1; - m_open_mode = 0; - } - - size_type read(char* buf, size_type num_bytes) - { - assert(m_open_mode & mode_in); - assert(m_fd != -1); - -#ifdef _WIN32 - size_type ret = ::_read(m_fd, buf, num_bytes); -#else - size_type ret = ::read(m_fd, buf, num_bytes); -#endif - if (ret == -1) - { - std::stringstream msg; - msg << "read failed: " << strerror(errno); - throw file_error(msg.str()); - } - return ret; - } - - size_type write(const char* buf, size_type num_bytes) - { - assert(m_open_mode & mode_out); - assert(m_fd != -1); - - // TODO: Test this a bit more, what happens with random failures in - // the files? -// if ((rand() % 100) > 80) -// throw file_error("debug"); - -#ifdef _WIN32 - size_type ret = ::_write(m_fd, buf, num_bytes); -#else - size_type ret = ::write(m_fd, buf, num_bytes); -#endif - if (ret == -1) - { - std::stringstream msg; - msg << "write failed: " << strerror(errno); - throw file_error(msg.str()); - } - return ret; - } - - void set_size(size_type s) - { - size_type pos = tell(); - seek(1, 0); - char dummy = 0; - read(&dummy, 1); - seek(1, 0); - write(&dummy, 1); - seek(pos, 1); - } - - size_type seek(size_type offset, int m) - { - assert(m_open_mode); - assert(m_fd != -1); - - int seekdir = (m == 1)?SEEK_SET:SEEK_END; -#ifdef _WIN32 - size_type ret = _lseeki64(m_fd, offset, seekdir); -#else - size_type ret = lseek(m_fd, offset, seekdir); -#endif - - // For some strange reason this fails - // on win32. Use windows specific file - // wrapper instead. - if (ret == -1) - { - std::stringstream msg; - msg << "seek failed: '" << strerror(errno) - << "' fd: " << m_fd - << " offset: " << offset - << " seekdir: " << seekdir; - throw file_error(msg.str()); - } - return ret; - } - - size_type tell() - { - assert(m_open_mode); - assert(m_fd != -1); - -#ifdef _WIN32 - return _telli64(m_fd); -#else - return lseek(m_fd, 0, SEEK_CUR); -#endif - } - - int m_fd; - int m_open_mode; - }; - - // pimpl forwardings - - file::file() : m_impl(new impl()) {} - - file::file(boost::filesystem::path const& p, file::open_mode m) - : m_impl(new impl(p, m.m_mask)) - {} - - file::~file() {} - - void file::open(boost::filesystem::path const& p, file::open_mode m) - { - m_impl->open(p, m.m_mask); - } - - void file::close() - { - m_impl->close(); - } - - size_type file::write(const char* buf, size_type num_bytes) - { - return m_impl->write(buf, num_bytes); - } - - size_type file::read(char* buf, size_type num_bytes) - { - return m_impl->read(buf, num_bytes); - } - - void file::set_size(size_type s) - { - m_impl->set_size(s); - } - - size_type file::seek(size_type pos, file::seek_mode m) - { - return m_impl->seek(pos, m.m_val); - } - - size_type file::tell() - { - return m_impl->tell(); - } - -} diff --git a/libtorrent/src/file_pool.cpp b/libtorrent/src/file_pool.cpp deleted file mode 100644 index ab4ea8d6c..000000000 --- a/libtorrent/src/file_pool.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/file_pool.hpp" - -#include - -namespace libtorrent -{ - using boost::multi_index::nth_index; - using boost::multi_index::get; - - boost::shared_ptr file_pool::open_file(void* st, fs::path const& p, file::open_mode m) - { - assert(st != 0); - assert(p.is_complete()); - assert(m == file::in || m == (file::in | file::out)); - boost::mutex::scoped_lock l(m_mutex); - typedef nth_index::type path_view; - path_view& pt = get<0>(m_files); - path_view::iterator i = pt.find(p); - if (i != pt.end()) - { - lru_file_entry e = *i; - e.last_use = time_now(); - - if (e.key != st) - { - // this means that another instance of the storage - // is using the exact same file. - throw file_error("torrent uses the same file as another torrent " - "(" + p.string() + ")"); - } - - e.key = st; - if ((e.mode & m) != m) - { - // close the file before we open it with - // the new read/write privilages - i->file_ptr.reset(); - assert(e.file_ptr.unique()); - e.file_ptr.reset(); - e.file_ptr.reset(new file(p, m)); - e.mode = m; - } - pt.replace(i, e); - return e.file_ptr; - } - // the file is not in our cache - if ((int)m_files.size() >= m_size) - { - // the file cache is at its maximum size, close - // the least recently used (lru) file from it - typedef nth_index::type lru_view; - lru_view& lt = get<1>(m_files); - lru_view::iterator i = lt.begin(); - // the first entry in this view is the least recently used - assert(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use)); - lt.erase(i); - } - lru_file_entry e(boost::shared_ptr(new file(p, m))); - e.mode = m; - e.key = st; - e.file_path = p; - pt.insert(e); - return e.file_ptr; - } - - void file_pool::release(void* st) - { - boost::mutex::scoped_lock l(m_mutex); - assert(st != 0); - using boost::tie; - - typedef nth_index::type key_view; - key_view& kt = get<2>(m_files); - - key_view::iterator start, end; - tie(start, end) = kt.equal_range(st); - kt.erase(start, end); - } - - void file_pool::resize(int size) - { - assert(size > 0); - if (size == m_size) return; - boost::mutex::scoped_lock l(m_mutex); - m_size = size; - if (int(m_files.size()) <= m_size) return; - - // close the least recently used files - typedef nth_index::type lru_view; - lru_view& lt = get<1>(m_files); - lru_view::iterator i = lt.begin(); - while (int(m_files.size()) > m_size) - { - // the first entry in this view is the least recently used - assert(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use)); - lt.erase(i++); - } - } - -} diff --git a/libtorrent/src/file_win.cpp b/libtorrent/src/file_win.cpp deleted file mode 100644 index 9d2c2f4bf..000000000 --- a/libtorrent/src/file_win.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* - -Copyright (c) 2003, Magnus Jonsson & Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/file.hpp" -#include "libtorrent/utf8.hpp" - -#ifdef UNICODE -#include "libtorrent/storage.hpp" -#endif - -#include -#include -#include - -namespace -{ - // must be used to not leak memory in case something would throw - class auto_localfree - { - public: - auto_localfree(HLOCAL memory) - : m_memory(memory) - { - } - ~auto_localfree() - { - if (m_memory) - LocalFree(m_memory); - } - private: - HLOCAL m_memory; - }; - - std::string utf8_native(std::string const& s) - { - try - { - std::wstring ws; - libtorrent::utf8_wchar(s, ws); - std::size_t size = wcstombs(0, ws.c_str(), 0); - if (size == std::size_t(-1)) return s; - std::string ret; - ret.resize(size); - size = wcstombs(&ret[0], ws.c_str(), size + 1); - if (size == wchar_t(-1)) return s; - ret.resize(size); - return ret; - } - catch(std::exception) - { - return s; - } - } - - void throw_exception(const char* thrower) - { - DWORD err = GetLastError(); - -#ifdef UNICODE - wchar_t *wbuffer = 0; - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM - |FORMAT_MESSAGE_ALLOCATE_BUFFER - , 0, err, 0, (LPWSTR)&wbuffer, 0, 0); - auto_localfree auto_free(wbuffer); - std::string tmp_utf8; - libtorrent::wchar_utf8(wbuffer, tmp_utf8); - char const* buffer = tmp_utf8.c_str(); -#else - char* buffer = 0; - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM - |FORMAT_MESSAGE_ALLOCATE_BUFFER - , 0, err, 0, (LPSTR)&buffer, 0, 0); - auto_localfree auto_free(buffer); -#endif - - std::stringstream s; - s << (thrower ? thrower : "NULL") << ": " << (buffer ? buffer : "NULL"); - - throw libtorrent::file_error(s.str()); - } -} - -namespace libtorrent -{ - - struct file::impl : boost::noncopyable - { - enum open_flags - { - read_flag = 1, - write_flag = 2 - }; - - enum seek_mode - { - seek_begin = FILE_BEGIN, - seek_from_here = FILE_CURRENT, - seek_end = FILE_END - }; - - impl() - { - m_file_handle = INVALID_HANDLE_VALUE; - } - - void open(const char *file_name, open_flags flags) - { - assert(file_name); - assert(flags & (read_flag | write_flag)); - - DWORD access_mask = 0; - if (flags & read_flag) - access_mask |= GENERIC_READ; - if (flags & write_flag) - access_mask |= GENERIC_WRITE; - - assert(access_mask & (GENERIC_READ | GENERIC_WRITE)); - - #ifdef UNICODE - std::wstring wfile_name(safe_convert(file_name)); - HANDLE new_handle = CreateFile( - wfile_name.c_str() - , access_mask - , FILE_SHARE_READ - , 0 - , (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING - , FILE_ATTRIBUTE_NORMAL - , 0); - #else - HANDLE new_handle = CreateFile( - utf8_native(file_name).c_str() - , access_mask - , FILE_SHARE_READ - , 0 - , (flags & write_flag)?OPEN_ALWAYS:OPEN_EXISTING - , FILE_ATTRIBUTE_NORMAL - , 0); - #endif - - if (new_handle == INVALID_HANDLE_VALUE) - throw_exception(file_name); - // try to make the file sparse if supported - if (access_mask & GENERIC_WRITE) - { - DWORD temp; - ::DeviceIoControl(new_handle, FSCTL_SET_SPARSE, 0, 0 - , 0, 0, &temp, 0); - } - // will only close old file if the open succeeded - close(); - m_file_handle = new_handle; - } - - void close() - { - if (m_file_handle != INVALID_HANDLE_VALUE) - { - CloseHandle(m_file_handle); - m_file_handle = INVALID_HANDLE_VALUE; - } - } - - ~impl() - { - close(); - } - - size_type write(const char* buffer, size_type num_bytes) - { - assert(buffer); - assert((DWORD)num_bytes == num_bytes); - DWORD bytes_written = 0; - if (num_bytes != 0) - { - if (FALSE == WriteFile( - m_file_handle - , buffer - , (DWORD)num_bytes - , &bytes_written - , 0)) - { - throw_exception("file::write"); - } - } - return bytes_written; - } - - size_type read(char* buffer, size_type num_bytes) - { - assert(buffer); - assert(num_bytes >= 0); - assert((DWORD)num_bytes == num_bytes); - - DWORD bytes_read = 0; - if (num_bytes != 0) - { - if (FALSE == ReadFile( - m_file_handle - , buffer - , (DWORD)num_bytes - , &bytes_read - , 0)) - { - throw_exception("file::read"); - } - } - return bytes_read; - } - - void set_size(size_type s) - { - size_type pos = tell(); - seek(s, seek_begin); - if (FALSE == ::SetEndOfFile(m_file_handle)) - throw_exception("file::set_size"); - - seek(pos, seek_begin); - } - - size_type seek(size_type pos, seek_mode from_where) - { - assert(pos >= 0 || from_where != seek_begin); - assert(pos <= 0 || from_where != seek_end); - LARGE_INTEGER offs; - offs.QuadPart = pos; - if (FALSE == SetFilePointerEx( - m_file_handle - , offs - , &offs - , from_where)) - { - throw_exception("file::seek"); - } - return offs.QuadPart; - } - - size_type tell() - { - LARGE_INTEGER offs; - offs.QuadPart = 0; - - // is there any other way to get offset? - if (FALSE == SetFilePointerEx( - m_file_handle - , offs - , &offs - , FILE_CURRENT)) - { - throw_exception("file::tell"); - } - - size_type pos = offs.QuadPart; - assert(pos >= 0); - return pos; - } -/* - size_type size() - { - LARGE_INTEGER s; - if (FALSE == GetFileSizeEx(m_file_handle, &s)) - { - throw_exception("file::size"); - } - - size_type size = s.QuadPart; - assert(size >= 0); - return size; - } -*/ - private: - - HANDLE m_file_handle; - - }; -} - -namespace libtorrent -{ - - const file::seek_mode file::begin(file::impl::seek_begin); - const file::seek_mode file::end(file::impl::seek_end); - - const file::open_mode file::in(file::impl::read_flag); - const file::open_mode file::out(file::impl::write_flag); - - file::file() - : m_impl(new libtorrent::file::impl()) - { - } - file::file(boost::filesystem::path const& p, open_mode m) - : m_impl(new libtorrent::file::impl()) - { - open(p,m); - } - - file::~file() - { - } - - void file::open(boost::filesystem::path const& p, open_mode m) - { - assert(p.is_complete()); - m_impl->open(p.native_file_string().c_str(), impl::open_flags(m.m_mask)); - } - - void file::close() - { - m_impl->close(); - } - - size_type file::write(const char* buffer, size_type num_bytes) - { - return m_impl->write(buffer, num_bytes); - } - - size_type file::read(char* buffer, size_type num_bytes) - { - return m_impl->read(buffer, num_bytes); - } - - void file::set_size(size_type s) - { - m_impl->set_size(s); - } - - size_type file::seek(size_type pos, seek_mode m) - { - return m_impl->seek(pos,impl::seek_mode(m.m_val)); - } - - size_type file::tell() - { - return m_impl->tell(); - } -} diff --git a/libtorrent/src/http_connection.cpp b/libtorrent/src/http_connection.cpp deleted file mode 100644 index ba1592898..000000000 --- a/libtorrent/src/http_connection.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/http_connection.hpp" - -#include -#include -#include -#include - -using boost::bind; - -namespace libtorrent -{ - -void http_connection::get(std::string const& url, time_duration timeout - , bool handle_redirect) -{ - m_redirect = handle_redirect; - std::string protocol; - std::string auth; - std::string hostname; - std::string path; - int port; - boost::tie(protocol, auth, hostname, port, path) = parse_url_components(url); - std::stringstream headers; - headers << "GET " << path << " HTTP/1.0\r\n" - "Host:" << hostname << - "\r\nConnection: close\r\n"; - if (!auth.empty()) - headers << "Authorization: Basic " << base64encode(auth) << "\r\n"; - headers << "\r\n"; - sendbuffer = headers.str(); - start(hostname, boost::lexical_cast(port), timeout); -} - -void http_connection::start(std::string const& hostname, std::string const& port - , time_duration timeout, bool handle_redirect) -{ - m_redirect = handle_redirect; - m_timeout = timeout; - m_timer.expires_from_now(m_timeout); - m_timer.async_wait(bind(&http_connection::on_timeout - , boost::weak_ptr(shared_from_this()), _1)); - m_called = false; - if (m_sock.is_open() && m_hostname == hostname && m_port == port) - { - m_parser.reset(); - asio::async_write(m_sock, asio::buffer(sendbuffer) - , bind(&http_connection::on_write, shared_from_this(), _1)); - } - else - { - m_sock.close(); - tcp::resolver::query query(hostname, port); - m_resolver.async_resolve(query, bind(&http_connection::on_resolve - , shared_from_this(), _1, _2)); - m_hostname = hostname; - m_port = port; - } -} - -void http_connection::on_connect_timeout() -{ - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - - if (m_bottled && m_called) return; - m_called = true; - m_handler(asio::error::timed_out, m_parser, 0, 0); - close(); -} - -void http_connection::on_timeout(boost::weak_ptr p - , asio::error_code const& e) -{ - boost::shared_ptr c = p.lock(); - if (!c) return; - if (c->m_connection_ticket > -1) c->m_cc.done(c->m_connection_ticket); - c->m_connection_ticket = -1; - - if (e == asio::error::operation_aborted) return; - - if (c->m_bottled && c->m_called) return; - - if (c->m_last_receive + c->m_timeout < time_now()) - { - c->m_called = true; - c->m_handler(asio::error::timed_out, c->m_parser, 0, 0); - return; - } - - c->m_timer.expires_at(c->m_last_receive + c->m_timeout); - c->m_timer.async_wait(bind(&http_connection::on_timeout, p, _1)); -} - -void http_connection::close() -{ - m_timer.cancel(); - m_limiter_timer.cancel(); - m_sock.close(); - m_hostname.clear(); - m_port.clear(); - - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; -} - -void http_connection::on_resolve(asio::error_code const& e - , tcp::resolver::iterator i) -{ - if (e) - { - close(); - if (m_bottled && m_called) return; - m_called = true; - m_handler(e, m_parser, 0, 0); - return; - } - assert(i != tcp::resolver::iterator()); - m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i) - , bind(&http_connection::on_connect_timeout, shared_from_this()) - , m_timeout); -} - -void http_connection::connect(int ticket, tcp::endpoint target_address) -{ - m_connection_ticket = ticket; - m_sock.async_connect(target_address, boost::bind(&http_connection::on_connect - , shared_from_this(), _1/*, ++i*/)); -} - -void http_connection::on_connect(asio::error_code const& e - /*, tcp::resolver::iterator i*/) -{ - if (!e) - { - m_last_receive = time_now(); - asio::async_write(m_sock, asio::buffer(sendbuffer) - , bind(&http_connection::on_write, shared_from_this(), _1)); - } -/* else if (i != tcp::resolver::iterator()) - { - // The connection failed. Try the next endpoint in the list. - m_sock.close(); - m_cc.enqueue(bind(&http_connection::connect, shared_from_this(), _1, *i) - , bind(&http_connection::on_connect_timeout, shared_from_this()) - , m_timeout); - } -*/ else - { - close(); - if (m_bottled && m_called) return; - m_called = true; - m_handler(e, m_parser, 0, 0); - } -} - -void http_connection::on_write(asio::error_code const& e) -{ - if (e) - { - close(); - if (m_bottled && m_called) return; - m_called = true; - m_handler(e, m_parser, 0, 0); - return; - } - - std::string().swap(sendbuffer); - m_recvbuffer.resize(4096); - - int amount_to_read = m_recvbuffer.size() - m_read_pos; - if (m_rate_limit > 0 && amount_to_read > m_download_quota) - { - amount_to_read = m_download_quota; - if (m_download_quota == 0) - { - if (!m_limiter_timer_active) - on_assign_bandwidth(asio::error_code()); - return; - } - } - m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos - , amount_to_read) - , bind(&http_connection::on_read - , shared_from_this(), _1, _2)); -} - -void http_connection::on_read(asio::error_code const& e - , std::size_t bytes_transferred) -{ - if (m_rate_limit) - { - m_download_quota -= bytes_transferred; - assert(m_download_quota >= 0); - } - - if (e == asio::error::eof) - { - close(); - if (m_bottled && m_called) return; - m_called = true; - char const* data = 0; - std::size_t size = 0; - if (m_bottled) - { - data = m_parser.get_body().begin; - size = m_parser.get_body().left(); - } - m_handler(asio::error_code(), m_parser, data, size); - return; - } - - if (e) - { - close(); - if (m_bottled && m_called) return; - m_called = true; - m_handler(e, m_parser, 0, 0); - return; - } - - m_read_pos += bytes_transferred; - assert(m_read_pos <= int(m_recvbuffer.size())); - - // having a nonempty path means we should handle redirects - if (m_redirect && m_parser.header_finished()) - { - int code = m_parser.status_code(); - if (code >= 300 && code < 400) - { - // attempt a redirect - std::string url = m_parser.header("location"); - if (url.empty()) - { - // missing location header - if (m_bottled && m_called) return; - m_called = true; - m_handler(e, m_parser, 0, 0); - return; - } - - m_limiter_timer_active = false; - close(); - - get(url, m_timeout); - return; - } - - m_redirect = false; - } - - if (m_bottled || !m_parser.header_finished()) - { - libtorrent::buffer::const_interval rcv_buf(&m_recvbuffer[0] - , &m_recvbuffer[0] + m_read_pos); - m_parser.incoming(rcv_buf); - if (!m_bottled && m_parser.header_finished()) - { - if (m_read_pos > m_parser.body_start()) - m_handler(e, m_parser, &m_recvbuffer[0] + m_parser.body_start() - , m_read_pos - m_parser.body_start()); - m_read_pos = 0; - m_last_receive = time_now(); - } - else if (m_bottled && m_parser.finished()) - { - m_timer.cancel(); - if (m_bottled && m_called) return; - m_called = true; - m_handler(e, m_parser, m_parser.get_body().begin, m_parser.get_body().left()); - } - } - else - { - assert(!m_bottled); - m_handler(e, m_parser, &m_recvbuffer[0], m_read_pos); - m_read_pos = 0; - m_last_receive = time_now(); - } - - if (int(m_recvbuffer.size()) == m_read_pos) - m_recvbuffer.resize((std::min)(m_read_pos + 2048, 1024*500)); - if (m_read_pos == 1024 * 500) - { - close(); - if (m_bottled && m_called) return; - m_called = true; - m_handler(asio::error::eof, m_parser, 0, 0); - return; - } - int amount_to_read = m_recvbuffer.size() - m_read_pos; - if (m_rate_limit > 0 && amount_to_read > m_download_quota) - { - amount_to_read = m_download_quota; - if (m_download_quota == 0) - { - if (!m_limiter_timer_active) - on_assign_bandwidth(asio::error_code()); - return; - } - } - m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos - , amount_to_read) - , bind(&http_connection::on_read - , shared_from_this(), _1, _2)); -} - -void http_connection::on_assign_bandwidth(asio::error_code const& e) -{ - if ((e == asio::error::operation_aborted - && m_limiter_timer_active) - || !m_sock.is_open()) - { - if (!m_bottled || !m_called) - m_handler(e, m_parser, 0, 0); - return; - } - m_limiter_timer_active = false; - if (e) return; - - if (m_download_quota > 0) return; - - m_download_quota = m_rate_limit / 4; - - int amount_to_read = m_recvbuffer.size() - m_read_pos; - if (amount_to_read > m_download_quota) - amount_to_read = m_download_quota; - - m_sock.async_read_some(asio::buffer(&m_recvbuffer[0] + m_read_pos - , amount_to_read) - , bind(&http_connection::on_read - , shared_from_this(), _1, _2)); - - m_limiter_timer_active = true; - m_limiter_timer.expires_from_now(milliseconds(250)); - m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth - , shared_from_this(), _1)); -} - -void http_connection::rate_limit(int limit) -{ - if (!m_limiter_timer_active) - { - m_limiter_timer_active = true; - m_limiter_timer.expires_from_now(milliseconds(250)); - m_limiter_timer.async_wait(bind(&http_connection::on_assign_bandwidth - , shared_from_this(), _1)); - } - m_rate_limit = limit; -} - -} - diff --git a/libtorrent/src/http_stream.cpp b/libtorrent/src/http_stream.cpp deleted file mode 100644 index 0973af798..000000000 --- a/libtorrent/src/http_stream.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/http_stream.hpp" -#include "libtorrent/tracker_manager.hpp" // for base64encode - -namespace libtorrent -{ - - void http_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h) - { - if (e || i == tcp::resolver::iterator()) - { - (*h)(e); - close(); - return; - } - - m_sock.async_connect(i->endpoint(), boost::bind( - &http_stream::connected, this, _1, h)); - } - - void http_stream::connected(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - using namespace libtorrent::detail; - - if (m_no_connect) - { - std::vector().swap(m_buffer); - (*h)(e); - return; - } - - // send CONNECT - std::back_insert_iterator > p(m_buffer); - write_string("CONNECT " + boost::lexical_cast(m_remote_endpoint) - + " HTTP/1.0\r\n", p); - if (!m_user.empty()) - { - write_string("Proxy-Authorization: Basic " + base64encode( - m_user + ":" + m_password) + "\r\n", p); - } - write_string("\r\n", p); - asio::async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&http_stream::handshake1, this, _1, h)); - } - - void http_stream::handshake1(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - // read one byte from the socket - m_buffer.resize(1); - asio::async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&http_stream::handshake2, this, _1, h)); - } - - void http_stream::handshake2(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - int read_pos = m_buffer.size(); - // look for \n\n and \r\n\r\n - // both of which means end of http response header - bool found_end = false; - if (m_buffer[read_pos - 1] == '\n' && read_pos > 2) - { - if (m_buffer[read_pos - 2] == '\n') - { - found_end = true; - } - else if (read_pos > 4 - && m_buffer[read_pos - 2] == '\r' - && m_buffer[read_pos - 3] == '\n' - && m_buffer[read_pos - 4] == '\r') - { - found_end = true; - } - } - - if (found_end) - { - m_buffer.push_back(0); - char* status = strchr(&m_buffer[0], ' '); - if (status == 0) - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - - status++; - int code = atoi(status); - if (code != 200) - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - - (*h)(e); - std::vector().swap(m_buffer); - return; - } - - // read another byte from the socket - m_buffer.resize(read_pos + 1); - asio::async_read(m_sock, asio::buffer(&m_buffer[0] + read_pos, 1) - , boost::bind(&http_stream::handshake2, this, _1, h)); - } - -} - diff --git a/libtorrent/src/http_tracker_connection.cpp b/libtorrent/src/http_tracker_connection.cpp deleted file mode 100644 index 94b1e422a..000000000 --- a/libtorrent/src/http_tracker_connection.cpp +++ /dev/null @@ -1,921 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include - -#include "libtorrent/config.hpp" -#include "zlib.h" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/instantiate_connection.hpp" - -using namespace libtorrent; -using boost::bind; - -namespace -{ - enum - { - minimum_tracker_response_length = 3, - http_buffer_size = 2048 - }; - - - enum - { - FTEXT = 0x01, - FHCRC = 0x02, - FEXTRA = 0x04, - FNAME = 0x08, - FCOMMENT = 0x10, - FRESERVED = 0xe0, - - GZIP_MAGIC0 = 0x1f, - GZIP_MAGIC1 = 0x8b - }; - -} - -namespace -{ - bool url_has_argument(std::string const& url, std::string argument) - { - size_t i = url.find('?'); - if (i == std::string::npos) return false; - - argument += '='; - - if (url.compare(i + 1, argument.size(), argument) == 0) return true; - argument.insert(0, "&"); - return url.find(argument, i) - != std::string::npos; - } - - char to_lower(char c) { return std::tolower(c); } -} - -namespace libtorrent -{ - http_parser::http_parser() - : m_recv_pos(0) - , m_status_code(-1) - , m_content_length(-1) - , m_state(read_status) - , m_recv_buffer(0, 0) - , m_body_start_pos(0) - , m_finished(false) - {} - - boost::tuple http_parser::incoming(buffer::const_interval recv_buffer) - { - assert(recv_buffer.left() >= m_recv_buffer.left()); - boost::tuple ret(0, 0); - - // early exit if there's nothing new in the receive buffer - if (recv_buffer.left() == m_recv_buffer.left()) return ret; - m_recv_buffer = recv_buffer; - - char const* pos = recv_buffer.begin + m_recv_pos; - if (m_state == read_status) - { - assert(!m_finished); - char const* newline = std::find(pos, recv_buffer.end, '\n'); - // if we don't have a full line yet, wait. - if (newline == recv_buffer.end) return ret; - - if (newline == pos) - throw std::runtime_error("unexpected newline in HTTP response"); - - char const* line_end = newline; - if (pos != line_end && *(line_end - 1) == '\r') --line_end; - - std::istringstream line(std::string(pos, line_end)); - ++newline; - int incoming = (int)std::distance(pos, newline); - m_recv_pos += incoming; - boost::get<1>(ret) += incoming; - pos = newline; - - line >> m_protocol; - if (m_protocol.substr(0, 5) != "HTTP/") - { - throw std::runtime_error("unknown protocol in HTTP response: " - + m_protocol + " line: " + std::string(pos, newline)); - } - line >> m_status_code; - std::getline(line, m_server_message); - m_state = read_header; - } - - if (m_state == read_header) - { - assert(!m_finished); - char const* newline = std::find(pos, recv_buffer.end, '\n'); - std::string line; - - while (newline != recv_buffer.end && m_state == read_header) - { - // if the LF character is preceeded by a CR - // charachter, don't copy it into the line string. - char const* line_end = newline; - if (pos != line_end && *(line_end - 1) == '\r') --line_end; - line.assign(pos, line_end); - ++newline; - m_recv_pos += newline - pos; - boost::get<1>(ret) += newline - pos; - pos = newline; - - std::string::size_type separator = line.find(':'); - if (separator == std::string::npos) - { - // this means we got a blank line, - // the header is finished and the body - // starts. - m_state = read_body; - m_body_start_pos = m_recv_pos; - break; - } - - std::string name = line.substr(0, separator); - std::transform(name.begin(), name.end(), name.begin(), &to_lower); - ++separator; - // skip whitespace - while (separator < line.size() - && (line[separator] == ' ' || line[separator] == '\t')) - ++separator; - std::string value = line.substr(separator, std::string::npos); - m_header.insert(std::make_pair(name, value)); - - if (name == "content-length") - { - try - { - m_content_length = boost::lexical_cast(value); - } - catch(boost::bad_lexical_cast&) {} - } - else if (name == "content-range") - { - std::stringstream range_str(value); - char dummy; - std::string bytes; - size_type range_start, range_end; - range_str >> bytes >> range_start >> dummy >> range_end; - if (!range_str || range_end < range_start) - { - throw std::runtime_error("invalid content-range in HTTP response: " + range_str.str()); - } - // the http range is inclusive - m_content_length = range_end - range_start + 1; - } - - assert(m_recv_pos <= (int)recv_buffer.left()); - newline = std::find(pos, recv_buffer.end, '\n'); - } - } - - if (m_state == read_body) - { - int incoming = recv_buffer.end - pos; - if (m_recv_pos - m_body_start_pos + incoming > m_content_length - && m_content_length >= 0) - incoming = m_content_length - m_recv_pos + m_body_start_pos; - - assert(incoming >= 0); - m_recv_pos += incoming; - boost::get<0>(ret) += incoming; - - if (m_content_length >= 0 - && m_recv_pos - m_body_start_pos >= m_content_length) - { - m_finished = true; - } - } - return ret; - } - - buffer::const_interval http_parser::get_body() const - { - assert(m_state == read_body); - if (m_content_length >= 0) - return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos - , m_recv_buffer.begin + std::min(m_recv_pos - , m_body_start_pos + m_content_length)); - else - return buffer::const_interval(m_recv_buffer.begin + m_body_start_pos - , m_recv_buffer.begin + m_recv_pos); - } - - void http_parser::reset() - { - m_recv_pos = 0; - m_body_start_pos = 0; - m_status_code = -1; - m_content_length = -1; - m_finished = false; - m_state = read_status; - m_recv_buffer.begin = 0; - m_recv_buffer.end = 0; - m_header.clear(); - } - - http_tracker_connection::http_tracker_connection( - asio::strand& str - , connection_queue& cc - , tracker_manager& man - , tracker_request const& req - , std::string const& hostname - , unsigned short port - , std::string request - , address bind_infc - , boost::weak_ptr c - , session_settings const& stn - , proxy_settings const& ps - , std::string const& auth) - : tracker_connection(man, req, str, bind_infc, c) - , m_man(man) - , m_strand(str) - , m_name_lookup(m_strand.io_service()) - , m_port(port) - , m_recv_pos(0) - , m_buffer(http_buffer_size) - , m_settings(stn) - , m_proxy(ps) - , m_password(auth) - , m_timed_out(false) - , m_connection_ticket(-1) - , m_cc(cc) - { - m_send_buffer.assign("GET "); - - // should we use the proxy? - if (m_proxy.type == proxy_settings::http - || m_proxy.type == proxy_settings::http_pw) - { - m_send_buffer += "http://"; - m_send_buffer += hostname; - if (port != 80) - { - m_send_buffer += ":"; - m_send_buffer += boost::lexical_cast(port); - } - } - - if (tracker_req().kind == tracker_request::scrape_request) - { - // find and replace "announce" with "scrape" - // in request - - std::size_t pos = request.find("announce"); - if (pos == std::string::npos) - throw std::runtime_error("scrape is not available on url: '" - + tracker_req().url +"'"); - request.replace(pos, 8, "scrape"); - } - - m_send_buffer += request; - - // if request-string already contains - // some parameters, append an ampersand instead - // of a question mark - size_t arguments_start = request.find('?'); - if (arguments_start != std::string::npos) - m_send_buffer += "&"; - else - m_send_buffer += "?"; - - if (!url_has_argument(request, "info_hash")) - { - m_send_buffer += "info_hash="; - m_send_buffer += escape_string( - reinterpret_cast(req.info_hash.begin()), 20); - m_send_buffer += '&'; - } - - if (tracker_req().kind == tracker_request::announce_request) - { - if (!url_has_argument(request, "peer_id")) - { - m_send_buffer += "peer_id="; - m_send_buffer += escape_string( - reinterpret_cast(req.pid.begin()), 20); - m_send_buffer += '&'; - } - - if (!url_has_argument(request, "port")) - { - m_send_buffer += "port="; - m_send_buffer += boost::lexical_cast(req.listen_port); - m_send_buffer += '&'; - } - - if (!url_has_argument(request, "uploaded")) - { - m_send_buffer += "uploaded="; - m_send_buffer += boost::lexical_cast(req.uploaded); - m_send_buffer += '&'; - } - - if (!url_has_argument(request, "downloaded")) - { - m_send_buffer += "downloaded="; - m_send_buffer += boost::lexical_cast(req.downloaded); - m_send_buffer += '&'; - } - - if (!url_has_argument(request, "left")) - { - m_send_buffer += "left="; - m_send_buffer += boost::lexical_cast(req.left); - m_send_buffer += '&'; - } - - if (req.event != tracker_request::none) - { - if (!url_has_argument(request, "event")) - { - const char* event_string[] = {"completed", "started", "stopped"}; - m_send_buffer += "event="; - m_send_buffer += event_string[req.event - 1]; - m_send_buffer += '&'; - } - } - if (!url_has_argument(request, "key")) - { - m_send_buffer += "key="; - std::stringstream key_string; - key_string << std::hex << req.key; - m_send_buffer += key_string.str(); - m_send_buffer += '&'; - } - - if (!url_has_argument(request, "compact")) - { - m_send_buffer += "compact=1&"; - } - if (!url_has_argument(request, "numwant")) - { - m_send_buffer += "numwant="; - m_send_buffer += boost::lexical_cast( - std::min(req.num_want, 999)); - m_send_buffer += '&'; - } - - // extension that tells the tracker that - // we don't need any peer_id's in the response - if (!url_has_argument(request, "no_peer_id")) - { - m_send_buffer += "no_peer_id=1"; - } - else - { - // remove the trailing '&' - m_send_buffer.resize(m_send_buffer.size() - 1); - } - } - - m_send_buffer += " HTTP/1.0\r\nAccept-Encoding: gzip\r\n" - "User-Agent: "; - m_send_buffer += m_settings.user_agent; - m_send_buffer += "\r\n" - "Host: "; - m_send_buffer += hostname; - if (port != 80) - { - m_send_buffer += ':'; - m_send_buffer += boost::lexical_cast(port); - } - if (m_proxy.type == proxy_settings::http_pw) - { - m_send_buffer += "\r\nProxy-Authorization: Basic "; - m_send_buffer += base64encode(m_proxy.username + ":" + m_proxy.password); - } - if (!auth.empty()) - { - m_send_buffer += "\r\nAuthorization: Basic "; - m_send_buffer += base64encode(auth); - } - m_send_buffer += "\r\n\r\n"; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) - { - requester().debug_log("==> TRACKER_REQUEST [ str: " + m_send_buffer + " ]"); - std::stringstream info_hash_str; - info_hash_str << req.info_hash; - requester().debug_log("info_hash: " - + boost::lexical_cast(req.info_hash)); - requester().debug_log("name lookup: " + hostname); - } -#endif - - tcp::resolver::query q(hostname - , boost::lexical_cast(m_port)); - m_name_lookup.async_resolve(q, m_strand.wrap( - boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2))); - set_timeout(m_settings.tracker_completion_timeout - , m_settings.tracker_receive_timeout); - } - - void http_tracker_connection::on_timeout() - { - m_timed_out = true; - m_socket.reset(); - m_name_lookup.cancel(); - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - fail_timeout(); - } - - void http_tracker_connection::name_lookup(asio::error_code const& error - , tcp::resolver::iterator i) try - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) requester().debug_log("tracker name lookup handler called"); -#endif - if (error == asio::error::operation_aborted) return; - if (m_timed_out) return; - - if (error || i == tcp::resolver::iterator()) - { - fail(-1, error.message().c_str()); - return; - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) requester().debug_log("tracker name lookup successful"); -#endif - restart_read_timeout(); - - // look for an address that has the same kind as the one - // we're listening on. To make sure the tracker get our - // correct listening address. - tcp::resolver::iterator target = i; - tcp::resolver::iterator end; - tcp::endpoint target_address = *i; - for (; target != end && target->endpoint().address().is_v4() - != bind_interface().is_v4(); ++target); - if (target == end) - { - assert(target_address.address().is_v4() != bind_interface().is_v4()); - if (has_requester()) - { - std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6"; - std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; - requester().tracker_warning("the tracker only resolves to an " - + tracker_address_type + " address, and you're listening on an " - + bind_address_type + " socket. This may prevent you from receiving incoming connections."); - } - } - else - { - target_address = *target; - } - - if (has_requester()) requester().m_tracker_address = target_address; - m_socket = instantiate_connection(m_name_lookup.io_service(), m_proxy); - - if (m_proxy.type == proxy_settings::http - || m_proxy.type == proxy_settings::http_pw) - { - // the tracker connection will talk immediately to - // the proxy, without requiring CONNECT support - m_socket->get().set_no_connect(true); - } - - m_socket->open(target_address.protocol()); - m_socket->bind(tcp::endpoint(bind_interface(), 0)); - m_cc.enqueue(bind(&http_tracker_connection::connect, self(), _1, target_address) - , bind(&http_tracker_connection::on_timeout, self()) - , seconds(m_settings.tracker_receive_timeout)); - } - catch (std::exception& e) - { - fail(-1, e.what()); - }; - - void http_tracker_connection::connect(int ticket, tcp::endpoint target_address) - { - m_connection_ticket = ticket; - m_socket->async_connect(target_address, bind(&http_tracker_connection::connected, self(), _1)); - } - - void http_tracker_connection::connected(asio::error_code const& error) try - { - if (m_connection_ticket > -1) m_cc.done(m_connection_ticket); - m_connection_ticket = -1; - if (error == asio::error::operation_aborted) return; - if (m_timed_out) return; - if (error) - { - fail(-1, error.message().c_str()); - return; - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) requester().debug_log("tracker connection successful"); -#endif - - restart_read_timeout(); - async_write(*m_socket, asio::buffer(m_send_buffer.c_str() - , m_send_buffer.size()), bind(&http_tracker_connection::sent - , self(), _1)); - } - catch (std::exception& e) - { - fail(-1, e.what()); - } - - void http_tracker_connection::sent(asio::error_code const& error) try - { - if (error == asio::error::operation_aborted) return; - if (m_timed_out) return; - if (error) - { - fail(-1, error.message().c_str()); - return; - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) requester().debug_log("tracker send data completed"); -#endif - restart_read_timeout(); - assert(m_buffer.size() - m_recv_pos > 0); - m_socket->async_read_some(asio::buffer(&m_buffer[m_recv_pos] - , m_buffer.size() - m_recv_pos), bind(&http_tracker_connection::receive - , self(), _1, _2)); - } - catch (std::exception& e) - { - fail(-1, e.what()); - }; // msvc 7.1 seems to require this semi-colon - - - void http_tracker_connection::receive(asio::error_code const& error - , std::size_t bytes_transferred) try - { - if (error == asio::error::operation_aborted) return; - if (m_timed_out) return; - - if (error) - { - if (error == asio::error::eof) - { - on_response(); - close(); - return; - } - - fail(-1, error.message().c_str()); - return; - } - - restart_read_timeout(); - assert(bytes_transferred > 0); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) requester().debug_log("tracker connection reading " - + boost::lexical_cast(bytes_transferred)); -#endif - - m_recv_pos += bytes_transferred; - m_parser.incoming(buffer::const_interval(&m_buffer[0] - , &m_buffer[0] + m_recv_pos)); - - // if the receive buffer is full, expand it with http_buffer_size - if ((int)m_buffer.size() == m_recv_pos) - { - if ((int)m_buffer.size() >= m_settings.tracker_maximum_response_length) - { - fail(200, "too large tracker response"); - return; - } - assert(http_buffer_size > 0); - if ((int)m_buffer.size() + http_buffer_size - > m_settings.tracker_maximum_response_length) - m_buffer.resize(m_settings.tracker_maximum_response_length); - else - m_buffer.resize(m_buffer.size() + http_buffer_size); - } - - if (m_parser.header_finished()) - { - int cl = m_parser.header("content-length"); - if (cl > m_settings.tracker_maximum_response_length) - { - fail(-1, "content-length is greater than maximum response length"); - return; - } - - if (cl > 0 && cl < minimum_tracker_response_length && m_parser.status_code() == 200) - { - fail(-1, "content-length is smaller than minimum response length"); - return; - } - } - - if (m_parser.finished()) - { - on_response(); - close(); - return; - } - - assert(m_buffer.size() - m_recv_pos > 0); - m_socket->async_read_some(asio::buffer(&m_buffer[m_recv_pos] - , m_buffer.size() - m_recv_pos), bind(&http_tracker_connection::receive - , self(), _1, _2)); - } - catch (std::exception& e) - { - fail(-1, e.what()); - }; - - void http_tracker_connection::on_response() - { - if (!m_parser.header_finished()) - { - fail(-1, "premature end of file"); - return; - } - - std::string location = m_parser.header("location"); - - if (m_parser.status_code() >= 300 && m_parser.status_code() < 400) - { - if (location.empty()) - { - std::string error_str = "got redirection response ("; - error_str += boost::lexical_cast(m_parser.status_code()); - error_str += ") without 'Location' header"; - fail(-1, error_str.c_str()); - return; - } - - // if the protocol isn't specified, assume http - if (location.compare(0, 7, "http://") != 0 - && location.compare(0, 6, "udp://") != 0) - { - location.insert(0, "http://"); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) requester().debug_log("Redirecting to \"" + location + "\""); -#endif - if (has_requester()) requester().tracker_warning("Redirecting to \"" + location + "\""); - tracker_request req = tracker_req(); - - req.url = location; - - m_man.queue_request(m_strand, m_cc, req - , m_password, bind_interface(), m_requester); - close(); - return; - } - - if (m_parser.status_code() != 200) - { - fail(m_parser.status_code(), m_parser.message().c_str()); - close(); - return; - } - - buffer::const_interval buf(&m_buffer[0] + m_parser.body_start(), &m_buffer[0] + m_recv_pos); - - std::string content_encoding = m_parser.header("content-encoding"); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) requester().debug_log("content-encoding: \"" + content_encoding + "\""); -#endif - - if (content_encoding == "gzip" || content_encoding == "x-gzip") - { - boost::shared_ptr r = m_requester.lock(); - - if (!r) - { - close(); - return; - } - m_buffer.erase(m_buffer.begin(), m_buffer.begin() + m_parser.body_start()); - if (inflate_gzip(m_buffer, tracker_request(), r.get(), - m_settings.tracker_maximum_response_length)) - { - close(); - return; - } - buf.begin = &m_buffer[0]; - buf.end = &m_buffer[0] + m_buffer.size(); - } - else if (!content_encoding.empty()) - { - std::string error_str = "unknown content encoding in response: \""; - error_str += content_encoding; - error_str += "\""; - fail(-1, error_str.c_str()); - return; - } - - // handle tracker response - try - { - entry e = bdecode(buf.begin, buf.end); - parse(e); - } - catch (std::exception& e) - { - std::string error_str(e.what()); - error_str += ": \""; - for (char const* i = buf.begin, *end(buf.end); i != end; ++i) - { - if (std::isprint(*i)) error_str += *i; - else error_str += "0x" + boost::lexical_cast((unsigned int)*i) + " "; - } - error_str += "\""; - fail(m_parser.status_code(), error_str.c_str()); - } - #ifndef NDEBUG - catch (...) - { - assert(false); - } - #endif - } - - peer_entry http_tracker_connection::extract_peer_info(const entry& info) - { - peer_entry ret; - - // extract peer id (if any) - entry const* i = info.find_key("peer id"); - if (i != 0) - { - if (i->string().length() != 20) - throw std::runtime_error("invalid response from tracker"); - std::copy(i->string().begin(), i->string().end(), ret.pid.begin()); - } - else - { - // if there's no peer_id, just initialize it to a bunch of zeroes - std::fill_n(ret.pid.begin(), 20, 0); - } - - // extract ip - i = info.find_key("ip"); - if (i == 0) throw std::runtime_error("invalid response from tracker"); - ret.ip = i->string(); - - // extract port - i = info.find_key("port"); - if (i == 0) throw std::runtime_error("invalid response from tracker"); - ret.port = (unsigned short)i->integer(); - - return ret; - } - - void http_tracker_connection::parse(entry const& e) - { - if (!has_requester()) return; - - try - { - // parse the response - try - { - entry const& failure = e["failure reason"]; - - fail(m_parser.status_code(), failure.string().c_str()); - return; - } - catch (type_error const&) {} - - try - { - entry const& warning = e["warning message"]; - if (has_requester()) - requester().tracker_warning(warning.string()); - } - catch(type_error const&) {} - - std::vector peer_list; - - if (tracker_req().kind == tracker_request::scrape_request) - { - std::string ih; - std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end() - , std::back_inserter(ih)); - entry scrape_data = e["files"][ih]; - int complete = scrape_data["complete"].integer(); - int incomplete = scrape_data["incomplete"].integer(); - requester().tracker_response(tracker_request(), peer_list, 0, complete - , incomplete); - return; - } - - int interval = (int)e["interval"].integer(); - - if (e["peers"].type() == entry::string_t) - { - std::string const& peers = e["peers"].string(); - for (std::string::const_iterator i = peers.begin(); - i != peers.end();) - { - if (std::distance(i, peers.end()) < 6) break; - - peer_entry p; - p.pid.clear(); - std::stringstream ip_str; - ip_str << (int)detail::read_uint8(i) << "."; - ip_str << (int)detail::read_uint8(i) << "."; - ip_str << (int)detail::read_uint8(i) << "."; - ip_str << (int)detail::read_uint8(i); - p.ip = ip_str.str(); - p.port = detail::read_uint16(i); - peer_list.push_back(p); - } - } - else - { - entry::list_type const& l = e["peers"].list(); - for(entry::list_type::const_iterator i = l.begin(); i != l.end(); ++i) - { - peer_entry p = extract_peer_info(*i); - peer_list.push_back(p); - } - } - - // look for optional scrape info - int complete = -1; - int incomplete = -1; - - try { complete = e["complete"].integer(); } - catch(type_error&) {} - - try { incomplete = e["incomplete"].integer(); } - catch(type_error&) {} - - requester().tracker_response(tracker_request(), peer_list, interval, complete - , incomplete); - } - catch(type_error& e) - { - requester().tracker_request_error(tracker_request(), m_parser.status_code(), e.what()); - } - catch(std::runtime_error& e) - { - requester().tracker_request_error(tracker_request(), m_parser.status_code(), e.what()); - } - } - -} - diff --git a/libtorrent/src/identify_client.cpp b/libtorrent/src/identify_client.cpp deleted file mode 100644 index cf837a05b..000000000 --- a/libtorrent/src/identify_client.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/identify_client.hpp" -#include "libtorrent/fingerprint.hpp" - -namespace -{ - - using namespace libtorrent; - - int decode_digit(char c) - { - if (std::isdigit(c)) return c - '0'; - return unsigned(c) - 'A' + 10; - } - - // takes a peer id and returns a valid boost::optional - // object if the peer id matched the azureus style encoding - // the returned fingerprint contains information about the - // client's id - boost::optional parse_az_style(const peer_id& id) - { - fingerprint ret("..", 0, 0, 0, 0); - - if (id[0] != '-' || !std::isprint(id[1]) || (id[2] < '0') - || (id[3] < '0') || (id[4] < '0') - || (id[5] < '0') || (id[6] < '0') - || id[7] != '-') - return boost::optional(); - - ret.name[0] = id[1]; - ret.name[1] = id[2]; - ret.major_version = decode_digit(id[3]); - ret.minor_version = decode_digit(id[4]); - ret.revision_version = decode_digit(id[5]); - ret.tag_version = decode_digit(id[6]); - - return boost::optional(ret); - } - - // checks if a peer id can possibly contain a shadow-style - // identification - boost::optional parse_shadow_style(const peer_id& id) - { - fingerprint ret("..", 0, 0, 0, 0); - - if (!std::isalnum(id[0])) - return boost::optional(); - - if (std::equal(id.begin()+4, id.begin()+6, "--")) - { - if ((id[1] < '0') || (id[2] < '0') - || (id[3] < '0')) - return boost::optional(); - ret.major_version = decode_digit(id[1]); - ret.minor_version = decode_digit(id[2]); - ret.revision_version = decode_digit(id[3]); - } - else - { - if (id[8] != 0 || id[1] > 127 || id[2] > 127 || id[3] > 127) - return boost::optional(); - ret.major_version = id[1]; - ret.minor_version = id[2]; - ret.revision_version = id[3]; - } - - ret.name[0] = id[0]; - ret.name[1] = 0; - - ret.tag_version = 0; - return boost::optional(ret); - } - - // checks if a peer id can possibly contain a mainline-style - // identification - boost::optional parse_mainline_style(const peer_id& id) - { - char ids[21]; - std::copy(id.begin(), id.end(), ids); - ids[20] = 0; - fingerprint ret("..", 0, 0, 0, 0); - ret.name[1] = 0; - ret.tag_version = 0; - if (sscanf(ids, "%c%d-%d-%d--", &ret.name[0], &ret.major_version, &ret.minor_version - , &ret.revision_version) != 4 - || !std::isprint(ret.name[0])) - return boost::optional(); - - return boost::optional(ret); - } - - struct map_entry - { - char const* id; - char const* name; - }; - - // only support BitTorrentSpecification - // must be ordered alphabetically - map_entry name_map[] = - { - {"A", "ABC"} - , {"AG", "Ares"} - , {"AR", "Arctic Torrent"} - , {"AV", "Avicora"} - , {"AX", "BitPump"} - , {"AZ", "Azureus"} - , {"A~", "Ares"} - , {"BB", "BitBuddy"} - , {"BC", "BitComet"} - , {"BF", "Bitflu"} - , {"BG", "BTG"} - , {"BR", "BitRocket"} - , {"BS", "BTSlave"} - , {"BX", "BittorrentX"} - , {"CD", "Enhanced CTorrent"} - , {"CT", "CTorrent"} - , {"DE", "Deluge Torrent"} - , {"EB", "EBit"} - , {"ES", "electric sheep"} - , {"HL", "Halite"} - , {"HN", "Hydranode"} - , {"KT", "KTorrent"} - , {"LK", "Linkage"} - , {"LP", "lphant"} - , {"LT", "libtorrent"} - , {"M", "Mainline"} - , {"ML", "MLDonkey"} - , {"MO", "Mono Torrent"} - , {"MP", "MooPolice"} - , {"MT", "Moonlight Torrent"} - , {"O", "Osprey Permaseed"} - , {"PD", "Pando"} - , {"Q", "BTQueue"} - , {"QT", "Qt 4"} - , {"R", "Tribler"} - , {"S", "Shadow"} - , {"SB", "Swiftbit"} - , {"SN", "ShareNet"} - , {"SS", "SwarmScope"} - , {"SZ", "Shareaza"} - , {"S~", "Shareaza (beta)"} - , {"T", "BitTornado"} - , {"TN", "Torrent.NET"} - , {"TR", "Transmission"} - , {"TS", "TorrentStorm"} - , {"TT", "TuoTu"} - , {"U", "UPnP"} - , {"UL", "uLeecher"} - , {"UT", "MicroTorrent"} - , {"XT", "XanTorrent"} - , {"XX", "Xtorrent"} - , {"ZT", "ZipTorrent"} - , {"lt", "libTorrent (libtorrent.rakshasa.no/}"} - , {"pX", "pHoeniX"} - , {"qB", "qBittorrent"} - }; - - bool compare_id(map_entry const& lhs, map_entry const& rhs) - { - return lhs.id[0] < rhs.id[0] - || ((lhs.id[0] == rhs.id[0]) && (lhs.id[1] < rhs.id[1])); - } - - std::string lookup(fingerprint const& f) - { - std::stringstream identity; - - const int size = sizeof(name_map)/sizeof(name_map[0]); - map_entry tmp = {f.name, ""}; - map_entry* i = - std::lower_bound(name_map, name_map + size - , tmp, &compare_id); - -#ifndef NDEBUG - for (int i = 1; i < size; ++i) - { - assert(compare_id(name_map[i-1] - , name_map[i])); - } -#endif - - if (i < name_map + size && std::equal(f.name, f.name + 2, i->id)) - identity << i->name; - else - { - identity << f.name[0]; - if (f.name[1] != 0) identity << f.name[1]; - } - - identity << " " << (int)f.major_version - << "." << (int)f.minor_version - << "." << (int)f.revision_version; - - if (f.name[1] != 0) - identity << "." << (int)f.tag_version; - - return identity.str(); - } - - bool find_string(unsigned char const* id, char const* search) - { - return std::equal(search, search + std::strlen(search), id); - } -} - -namespace libtorrent -{ - - boost::optional client_fingerprint(peer_id const& p) - { - // look for azureus style id - boost::optional f; - f = parse_az_style(p); - if (f) return f; - - // look for shadow style id - f = parse_shadow_style(p); - if (f) return f; - - // look for mainline style id - f = parse_mainline_style(p); - if (f) return f; - return f; - } - - std::string identify_client(peer_id const& p) - { - peer_id::const_iterator PID = p.begin(); - boost::optional f; - - if (p.is_all_zeros()) return "Unknown"; - - // ---------------------- - // non standard encodings - // ---------------------- - - if (find_string(PID, "Deadman Walking-")) return "Deadman"; - if (find_string(PID + 5, "Azureus")) return "Azureus 2.0.3.2"; - if (find_string(PID, "DansClient")) return "XanTorrent"; - if (find_string(PID + 4, "btfans")) return "SimpleBT"; - if (find_string(PID, "PRC.P---")) return "Bittorrent Plus! II"; - if (find_string(PID, "P87.P---")) return "Bittorrent Plus!"; - if (find_string(PID, "S587Plus")) return "Bittorrent Plus!"; - if (find_string(PID, "martini")) return "Martini Man"; - if (find_string(PID, "Plus---")) return "Bittorrent Plus"; - if (find_string(PID, "turbobt")) return "TurboBT"; - if (find_string(PID, "a00---0")) return "Swarmy"; - if (find_string(PID, "a02---0")) return "Swarmy"; - if (find_string(PID, "T00---0")) return "Teeweety"; - if (find_string(PID, "BTDWV-")) return "Deadman Walking"; - if (find_string(PID + 2, "BS")) return "BitSpirit"; - if (find_string(PID, "btuga")) return "BTugaXP"; - if (find_string(PID, "oernu")) return "BTugaXP"; - if (find_string(PID, "Mbrst")) return "Burst!"; - if (find_string(PID, "Plus")) return "Plus!"; - if (find_string(PID, "-Qt-")) return "Qt"; - if (find_string(PID, "exbc")) return "BitComet"; - if (find_string(PID, "-G3")) return "G3 Torrent"; - if (find_string(PID, "XBT")) return "XBT"; - if (find_string(PID, "OP")) return "Opera"; - - if (find_string(PID, "-BOW") && PID[7] == '-') - return "Bits on Wheels " + std::string(PID + 4, PID + 7); - - - if (find_string(PID, "eX")) - { - std::string user(PID + 2, PID + 14); - return std::string("eXeem ('") + user.c_str() + "')"; - } - - if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\x97")) - return "Experimental 3.2.1b2"; - - if (std::equal(PID, PID + 13, "\0\0\0\0\0\0\0\0\0\0\0\0\0")) - return "Experimental 3.1"; - - - // look for azureus style id - f = parse_az_style(p); - if (f) return lookup(*f); - - // look for shadow style id - f = parse_shadow_style(p); - if (f) return lookup(*f); - - // look for mainline style id - f = parse_mainline_style(p); - if (f) return lookup(*f); - - - if (std::equal(PID, PID + 12, "\0\0\0\0\0\0\0\0\0\0\0\0")) - return "Generic"; - - std::string unknown("Unknown ["); - for (peer_id::const_iterator i = p.begin(); i != p.end(); ++i) - { - unknown += std::isprint(*i)?*i:'.'; - } - unknown += "]"; - return unknown; - } - -} diff --git a/libtorrent/src/instantiate_connection.cpp b/libtorrent/src/instantiate_connection.cpp deleted file mode 100644 index ff4efbc59..000000000 --- a/libtorrent/src/instantiate_connection.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/socket.hpp" -#include "libtorrent/session_settings.hpp" -#include "libtorrent/socket_type.hpp" -#include -#include -#include - -namespace libtorrent -{ - - boost::shared_ptr instantiate_connection( - asio::io_service& ios, proxy_settings const& ps) - { - boost::shared_ptr s(new socket_type(ios)); - - if (ps.type == proxy_settings::none) - { - s->instantiate(); - } - else if (ps.type == proxy_settings::http - || ps.type == proxy_settings::http_pw) - { - s->instantiate(); - s->get().set_proxy(ps.hostname, ps.port); - if (ps.type == proxy_settings::socks5_pw) - s->get().set_username(ps.username, ps.password); - } - else if (ps.type == proxy_settings::socks5 - || ps.type == proxy_settings::socks5_pw) - { - s->instantiate(); - s->get().set_proxy(ps.hostname, ps.port); - if (ps.type == proxy_settings::socks5_pw) - s->get().set_username(ps.username, ps.password); - } - else - { - throw std::runtime_error("unsupported proxy type"); - } - return s; - } - -} - diff --git a/libtorrent/src/ip_filter.cpp b/libtorrent/src/ip_filter.cpp deleted file mode 100644 index 92ea711c7..000000000 --- a/libtorrent/src/ip_filter.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - -Copyright (c) 2005, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/ip_filter.hpp" -#include -//#include - - -namespace libtorrent -{ - void ip_filter::add_rule(address first, address last, int flags) - { - if (first.is_v4()) - { - assert(last.is_v4()); - m_filter4.add_rule(first.to_v4(), last.to_v4(), flags); - } - else if (first.is_v6()) - { - assert(last.is_v6()); - m_filter6.add_rule(first.to_v6(), last.to_v6(), flags); - } - else - assert(false); - } - - int ip_filter::access(address const& addr) const - { - if (addr.is_v4()) - return m_filter4.access(addr.to_v4()); - assert(addr.is_v6()); - return m_filter6.access(addr.to_v6()); - } - - ip_filter::filter_tuple_t ip_filter::export_filter() const - { - return boost::make_tuple(m_filter4.export_filter() - , m_filter6.export_filter()); - } - -/* - void ip_filter::print() const - { - for (range_t::iterator i = m_access_list.begin(); i != m_access_list.end(); ++i) - { - std::cout << i->start.as_string() << " " << i->access << "\n"; - } - } -*/ -} - diff --git a/libtorrent/src/kademlia/closest_nodes.cpp b/libtorrent/src/kademlia/closest_nodes.cpp deleted file mode 100644 index 0c7d9d276..000000000 --- a/libtorrent/src/kademlia/closest_nodes.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include - -namespace libtorrent { namespace dht -{ - -using asio::ip::udp; - -closest_nodes_observer::~closest_nodes_observer() -{ - if (m_algorithm) m_algorithm->failed(m_self, true); -} - -void closest_nodes_observer::reply(msg const& in) -{ - if (!m_algorithm) - { - assert(false); - return; - } - - if (!in.nodes.empty()) - { - for (msg::nodes_t::const_iterator i = in.nodes.begin() - , end(in.nodes.end()); i != end; ++i) - { - m_algorithm->traverse(i->id, i->addr); - } - } - m_algorithm->finished(m_self); - m_algorithm = 0; -} - -void closest_nodes_observer::timeout() -{ - if (!m_algorithm) return; - m_algorithm->failed(m_self); - m_algorithm = 0; -} - - -closest_nodes::closest_nodes( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback -) - : traversal_algorithm( - target - , branch_factor - , max_results - , table - , rpc - , table.begin() - , table.end() - ) - , m_done_callback(callback) -{ - boost::intrusive_ptr self(this); - add_requests(); -} - -void closest_nodes::invoke(node_id const& id, udp::endpoint addr) -{ - observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target)); - m_rpc.invoke(messages::find_node, addr, o); -} - -void closest_nodes::done() -{ - std::vector results; - int result_size = m_table.bucket_size(); - if (result_size > (int)m_results.size()) result_size = (int)m_results.size(); - for (std::vector::iterator i = m_results.begin() - , end(m_results.begin() + result_size); i != end; ++i) - { - results.push_back(node_entry(i->id, i->addr)); - } - m_done_callback(results); -} - -void closest_nodes::initiate( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback -) -{ - new closest_nodes(target, branch_factor, max_results, table, rpc, callback); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/dht_tracker.cpp b/libtorrent/src/kademlia/dht_tracker.cpp deleted file mode 100644 index eda6cd864..000000000 --- a/libtorrent/src/kademlia/dht_tracker.cpp +++ /dev/null @@ -1,974 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/kademlia/node.hpp" -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/kademlia/traversal_algorithm.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" - -#include "libtorrent/socket.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/version.hpp" - -using boost::ref; -using boost::lexical_cast; -using libtorrent::dht::node_impl; -using libtorrent::dht::node_id; -using libtorrent::dht::packet_t; -using libtorrent::dht::msg; -using libtorrent::dht::packet_iterator; -namespace messages = libtorrent::dht::messages; -using namespace libtorrent::detail; - -enum -{ - key_refresh = 5 // generate a new write token key every 5 minutes -}; - -using asio::ip::udp; -typedef asio::ip::address_v4 address; - -namespace -{ - const int tick_period = 1; // minutes - - struct count_peers - { - int& count; - count_peers(int& c): count(c) {} - void operator()(std::pair const& t) - { - count += std::distance(t.second.peers.begin() - , t.second.peers.end()); - } - }; - - boost::optional read_id(libtorrent::entry const& d) - { - using namespace libtorrent; - using libtorrent::dht::node_id; - - if (d.type() != entry::dictionary_t) return boost::optional(); - entry const* nid = d.find_key("node-id"); - if (!nid - || nid->type() != entry::string_t - || nid->string().length() != 40) - return boost::optional(); - return boost::optional( - boost::lexical_cast(nid->string())); - } - - template - void read_endpoint_list(libtorrent::entry const* n, std::vector& epl) - { - using namespace libtorrent; - entry::list_type const& contacts = n->list(); - for (entry::list_type::const_iterator i = contacts.begin() - , end(contacts.end()); i != end; ++i) - { - std::string const& p = i->string(); - if (p.size() < 6) continue; - std::string::const_iterator in = p.begin(); - if (p.size() == 6) - epl.push_back(read_v4_endpoint(in)); - else if (p.size() == 18) - epl.push_back(read_v6_endpoint(in)); - } - } - -} - -namespace libtorrent { namespace dht -{ - - void intrusive_ptr_add_ref(dht_tracker const* c) - { - assert(c != 0); - assert(c->m_refs >= 0); - ++c->m_refs; - } - - void intrusive_ptr_release(dht_tracker const* c) - { - assert(c != 0); - assert(c->m_refs > 0); - if (--c->m_refs == 0) - delete c; - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_DEFINE_LOG(dht_tracker) -#endif - - // class that puts the networking and the kademlia node in a single - // unit and connecting them together. - dht_tracker::dht_tracker(asio::io_service& ios, dht_settings const& settings - , asio::ip::address listen_interface, entry const& bootstrap) - : m_strand(ios) - , m_socket(ios, udp::endpoint(listen_interface, settings.service_port)) - , m_dht(bind(&dht_tracker::send_packet, this, _1), settings - , read_id(bootstrap)) - , m_buffer(0) - , m_last_new_key(time_now() - minutes(key_refresh)) - , m_timer(ios) - , m_connection_timer(ios) - , m_refresh_timer(ios) - , m_settings(settings) - , m_refresh_bucket(160) - , m_host_resolver(ios) - , m_refs(0) - { - using boost::bind; - - m_in_buf[0].resize(1000); - m_in_buf[1].resize(1000); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - m_counter = 0; - std::fill_n(m_replies_bytes_sent, 5, 0); - std::fill_n(m_queries_bytes_received, 5, 0); - std::fill_n(m_replies_sent, 5, 0); - std::fill_n(m_queries_received, 5, 0); - m_announces = 0; - m_failed_announces = 0; - m_total_message_input = 0; - m_ut_message_input = 0; - m_lt_message_input = 0; - m_mp_message_input = 0; - m_gr_message_input = 0; - m_mo_message_input = 0; - m_total_in_bytes = 0; - m_total_out_bytes = 0; - m_queries_out_bytes = 0; - - // turns on and off individual components' logging - -// rpc_log().enable(false); -// node_log().enable(false); -// traversal_log().enable(false); -// dht_tracker_log.enable(false); - -#endif - std::vector initial_nodes; - - if (bootstrap.type() == entry::dictionary_t) - { - try - { - if (entry const* nodes = bootstrap.find_key("nodes")) - read_endpoint_list(nodes, initial_nodes); - } catch (std::exception&) {} - } - - m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0] - , m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer] - , m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2))); - m_timer.expires_from_now(seconds(1)); - m_timer.async_wait(m_strand.wrap(bind(&dht_tracker::tick, self(), _1))); - - m_connection_timer.expires_from_now(seconds(10)); - m_connection_timer.async_wait(m_strand.wrap( - bind(&dht_tracker::connection_timeout, self(), _1))); - - m_refresh_timer.expires_from_now(seconds(5)); - m_refresh_timer.async_wait(m_strand.wrap(bind(&dht_tracker::refresh_timeout, self(), _1))); - - m_dht.bootstrap(initial_nodes, bind(&dht_tracker::on_bootstrap, self())); - } - - void dht_tracker::stop() - { - m_timer.cancel(); - m_connection_timer.cancel(); - m_refresh_timer.cancel(); - m_socket.close(); - } - - void dht_tracker::dht_status(session_status& s) - { - boost::tie(s.dht_nodes, s.dht_node_cache) = m_dht.size(); - s.dht_torrents = m_dht.data_size(); - s.dht_global_nodes = m_dht.num_global_nodes(); - } - - void dht_tracker::connection_timeout(asio::error_code const& e) - try - { - if (e) return; - time_duration d = m_dht.connection_timeout(); - m_connection_timer.expires_from_now(d); - m_connection_timer.async_wait(m_strand.wrap(bind(&dht_tracker::connection_timeout, self(), _1))); - } - catch (std::exception& exc) - { -#ifndef NDEBUG - std::cerr << "exception-type: " << typeid(exc).name() << std::endl; - std::cerr << "what: " << exc.what() << std::endl; - assert(false); -#endif - }; - - void dht_tracker::refresh_timeout(asio::error_code const& e) - try - { - if (e) return; - time_duration d = m_dht.refresh_timeout(); - m_refresh_timer.expires_from_now(d); - m_refresh_timer.async_wait(m_strand.wrap( - bind(&dht_tracker::refresh_timeout, self(), _1))); - } - catch (std::exception&) - { - assert(false); - }; - - void dht_tracker::rebind(asio::ip::address listen_interface, int listen_port) - { - m_socket.close(); - udp::endpoint ep(listen_interface, listen_port); - m_socket.open(ep.protocol()); - m_socket.bind(ep); - } - - void dht_tracker::tick(asio::error_code const& e) - try - { - if (e) return; - m_timer.expires_from_now(minutes(tick_period)); - m_timer.async_wait(m_strand.wrap(bind(&dht_tracker::tick, this, _1))); - - ptime now = time_now(); - if (now - m_last_new_key > minutes(key_refresh)) - { - m_last_new_key = now; - m_dht.new_write_key(); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() << " new write key"; -#endif - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - static bool first = true; - if (first) - { - boost::filesystem::create_directory("libtorrent_logs"); - } - - std::ofstream st("libtorrent_logs/routing_table_state.txt", std::ios_base::trunc); - m_dht.print_state(st); - - // count torrents - int torrents = std::distance(m_dht.begin_data(), m_dht.end_data()); - - // count peers - int peers = 0; - std::for_each(m_dht.begin_data(), m_dht.end_data(), count_peers(peers)); - - std::ofstream pc("libtorrent_logs/dht_stats.log", std::ios_base::app); - if (first) - { - first = false; - pc << "\n\n ***** starting log at " << time_now_string() << " *****\n\n" - << "minute:active nodes:passive nodes" - ":ping replies sent:ping queries recvd:ping" - ":ping replies sent:ping queries recvd:ping" - ":find_node replies bytes sent:find_node queries bytes recv" - ":find_node replies bytes sent:find_node queries bytes recv" - ":get_peers replies sent:get_peers queries recvd:get_peers" - ":get_peers replies bytes sent:get_peers queries bytes recv" - ":announce_peer replies sent:announce_peer queries recvd:announce_peer" - ":announce_peer replies bytes sent:announce_peer queries bytes recv" - ":error replies sent:error queries recvd:error" - ":error replies bytes sent:error queries bytes recv" - ":num torrents:num peers:announces per min" - ":failed announces per min:total msgs per min" - ":ut msgs per min:lt msgs per min:mp msgs per min" - ":gr msgs per min:bytes in per sec:bytes out per sec" - ":queries out bytes per sec\n\n"; - } - - int active; - int passive; - boost::tie(active, passive) = m_dht.size(); - pc << (m_counter * tick_period) - << "\t" << active - << "\t" << passive; - for (int i = 0; i < 5; ++i) - pc << "\t" << (m_replies_sent[i] / float(tick_period)) - << "\t" << (m_queries_received[i] / float(tick_period)) - << "\t" << (m_replies_bytes_sent[i] / float(tick_period*60)) - << "\t" << (m_queries_bytes_received[i] / float(tick_period*60)); - - pc << "\t" << torrents - << "\t" << peers - << "\t" << m_announces / float(tick_period) - << "\t" << m_failed_announces / float(tick_period) - << "\t" << (m_total_message_input / float(tick_period)) - << "\t" << (m_ut_message_input / float(tick_period)) - << "\t" << (m_lt_message_input / float(tick_period)) - << "\t" << (m_mp_message_input / float(tick_period)) - << "\t" << (m_gr_message_input / float(tick_period)) - << "\t" << (m_mo_message_input / float(tick_period)) - << "\t" << (m_total_in_bytes / float(tick_period*60)) - << "\t" << (m_total_out_bytes / float(tick_period*60)) - << "\t" << (m_queries_out_bytes / float(tick_period*60)) - << std::endl; - ++m_counter; - std::fill_n(m_replies_bytes_sent, 5, 0); - std::fill_n(m_queries_bytes_received, 5, 0); - std::fill_n(m_replies_sent, 5, 0); - std::fill_n(m_queries_received, 5, 0); - m_announces = 0; - m_failed_announces = 0; - m_total_message_input = 0; - m_ut_message_input = 0; - m_lt_message_input = 0; - m_total_in_bytes = 0; - m_total_out_bytes = 0; - m_queries_out_bytes = 0; -#endif - } - catch (std::exception&) - { - assert(false); - }; - - void dht_tracker::announce(sha1_hash const& ih, int listen_port - , boost::function const& - , sha1_hash const&)> f) - { - m_dht.announce(ih, listen_port, f); - } - - // translate bittorrent kademlia message into the generice kademlia message - // used by the library - void dht_tracker::on_receive(asio::error_code const& error, size_t bytes_transferred) - try - { - if (error == asio::error::operation_aborted) return; - - int current_buffer = m_buffer; - m_buffer = (m_buffer + 1) & 1; - m_socket.async_receive_from(asio::buffer(&m_in_buf[m_buffer][0] - , m_in_buf[m_buffer].size()), m_remote_endpoint[m_buffer] - , m_strand.wrap(bind(&dht_tracker::on_receive, self(), _1, _2))); - - if (error) return; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - ++m_total_message_input; - m_total_in_bytes += bytes_transferred; -#endif - - try - { - using libtorrent::entry; - using libtorrent::bdecode; - - assert(bytes_transferred > 0); - - entry e = bdecode(m_in_buf[current_buffer].begin() - , m_in_buf[current_buffer].end()); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() << " RECEIVED [" - << m_remote_endpoint[current_buffer] << "]:"; -#endif - - libtorrent::dht::msg m; - m.message_id = 0; - m.addr = m_remote_endpoint[current_buffer]; - m.transaction_id = e["t"].string(); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - try - { - entry const* ver = e.find_key("v"); - if (!ver) throw std::exception(); - - std::string const& client = ver->string(); - if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "UT")) - { - ++m_ut_message_input; - TORRENT_LOG(dht_tracker) << " client: uTorrent"; - } - else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "LT")) - { - ++m_lt_message_input; - TORRENT_LOG(dht_tracker) << " client: libtorrent"; - } - else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MP")) - { - ++m_mp_message_input; - TORRENT_LOG(dht_tracker) << " client: MooPolice"; - } - else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "GR")) - { - ++m_gr_message_input; - TORRENT_LOG(dht_tracker) << " client: GetRight"; - } - else if (client.size() > 1 && std::equal(client.begin(), client.begin() + 2, "MO")) - { - ++m_mo_message_input; - TORRENT_LOG(dht_tracker) << " client: Mono Torrent"; - } - else - { - TORRENT_LOG(dht_tracker) << " client: " << client; - } - } - catch (std::exception&) - { - TORRENT_LOG(dht_tracker) << " client: generic"; - }; -#endif - - std::string const& msg_type = e["y"].string(); - - if (msg_type == "r") - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " reply: transaction: " - << m.transaction_id; -#endif - - m.reply = true; - entry const& r = e["r"]; - std::string const& id = r["id"].string(); - if (id.size() != 20) throw std::runtime_error("invalid size of id"); - std::copy(id.begin(), id.end(), m.id.begin()); - - if (entry const* n = r.find_key("values")) - { - m.peers.clear(); - if (n->list().size() == 1) - { - // assume it's mainline format - std::string const& peers = n->list().front().string(); - std::string::const_iterator i = peers.begin(); - std::string::const_iterator end = peers.end(); - - while (std::distance(i, end) >= 6) - m.peers.push_back(read_v4_endpoint(i)); - } - else - { - // assume it's uTorrent/libtorrent format - read_endpoint_list(n, m.peers); - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size(); -#endif - } - - m.nodes.clear(); - if (entry const* n = r.find_key("nodes")) - { - std::string const& nodes = n->string(); - std::string::const_iterator i = nodes.begin(); - std::string::const_iterator end = nodes.end(); - - while (std::distance(i, end) >= 26) - { - node_id id; - std::copy(i, i + 20, id.begin()); - i += 20; - m.nodes.push_back(libtorrent::dht::node_entry( - id, read_v4_endpoint(i))); - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size(); -#endif - } - - if (entry const* n = r.find_key("nodes2")) - { - entry::list_type const& contacts = n->list(); - for (entry::list_type::const_iterator i = contacts.begin() - , end(contacts.end()); i != end; ++i) - { - std::string const& p = i->string(); - if (p.size() < 6 + 20) continue; - std::string::const_iterator in = p.begin(); - - node_id id; - std::copy(in, in + 20, id.begin()); - in += 20; - if (p.size() == 6 + 20) - m.nodes.push_back(libtorrent::dht::node_entry( - id, read_v4_endpoint(in))); - else if (p.size() == 18 + 20) - m.nodes.push_back(libtorrent::dht::node_entry( - id, read_v6_endpoint(in))); - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " nodes2 + nodes: " << m.nodes.size(); -#endif - } - - entry const* token = r.find_key("token"); - if (token) m.write_token = *token; - } - else if (msg_type == "q") - { - m.reply = false; - entry const& a = e["a"]; - std::string const& id = a["id"].string(); - if (id.size() != 20) throw std::runtime_error("invalid size of id"); - std::copy(id.begin(), id.end(), m.id.begin()); - - std::string request_kind(e["q"].string()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " query: " << request_kind; -#endif - - if (request_kind == "ping") - { - m.message_id = libtorrent::dht::messages::ping; - } - else if (request_kind == "find_node") - { - std::string const& target = a["target"].string(); - if (target.size() != 20) throw std::runtime_error("invalid size of target id"); - std::copy(target.begin(), target.end(), m.info_hash.begin()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " target: " - << boost::lexical_cast(m.info_hash); -#endif - - m.message_id = libtorrent::dht::messages::find_node; - } - else if (request_kind == "get_peers") - { - std::string const& info_hash = a["info_hash"].string(); - if (info_hash.size() != 20) throw std::runtime_error("invalid size of info-hash"); - std::copy(info_hash.begin(), info_hash.end(), m.info_hash.begin()); - m.message_id = libtorrent::dht::messages::get_peers; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " info_hash: " - << boost::lexical_cast(m.info_hash); -#endif - } - else if (request_kind == "announce_peer") - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - ++m_announces; -#endif - std::string const& info_hash = a["info_hash"].string(); - if (info_hash.size() != 20) - throw std::runtime_error("invalid size of info-hash"); - std::copy(info_hash.begin(), info_hash.end(), m.info_hash.begin()); - m.port = a["port"].integer(); - m.write_token = a["token"]; - m.message_id = libtorrent::dht::messages::announce_peer; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " info_hash: " - << boost::lexical_cast(m.info_hash); - TORRENT_LOG(dht_tracker) << " port: " << m.port; - - if (!m_dht.verify_token(m)) - ++m_failed_announces; -#endif - } - else - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " *** UNSUPPORTED REQUEST *** : " - << request_kind; -#endif - throw std::runtime_error("unsupported request: " + request_kind); - } - } - else if (msg_type == "e") - { - entry::list_type const& list = e["e"].list(); - m.message_id = messages::error; - m.error_msg = list.back().string(); - m.error_code = list.front().integer(); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " incoming error: " << m.error_code << " " - << m.error_msg; -#endif - throw std::runtime_error("DHT error message"); - } - else - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " *** UNSUPPORTED MESSAGE TYPE *** : " - << msg_type; -#endif - throw std::runtime_error("unsupported message type: " + msg_type); - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - if (!m.reply) - { - ++m_queries_received[m.message_id]; - m_queries_bytes_received[m.message_id] += int(bytes_transferred); - } - TORRENT_LOG(dht_tracker) << e; -#endif - assert(m.message_id != messages::error); - m_dht.incoming(m); - } - catch (std::exception& e) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - int current_buffer = (m_buffer + 1) & 1; - std::string msg(m_in_buf[current_buffer].begin() - , m_in_buf[current_buffer].begin() + bytes_transferred); - TORRENT_LOG(dht_tracker) << "invalid incoming packet: " - << e.what() << "\n" << msg << "\n"; -#endif - } - } - catch (std::exception& e) - { - assert(false); - }; - - entry dht_tracker::state() const - { - entry ret(entry::dictionary_t); - { - entry nodes(entry::list_t); - for (node_impl::iterator i(m_dht.begin()) - , end(m_dht.end()); i != end; ++i) - { - std::string node; - std::back_insert_iterator out(node); - write_endpoint(i->addr, out); - nodes.list().push_back(entry(node)); - } - bucket_t cache; - m_dht.replacement_cache(cache); - for (bucket_t::iterator i(cache.begin()) - , end(cache.end()); i != end; ++i) - { - std::string node; - std::back_insert_iterator out(node); - write_endpoint(i->addr, out); - nodes.list().push_back(entry(node)); - } - if (!nodes.list().empty()) - ret["nodes"] = nodes; - } - - ret["node-id"] = boost::lexical_cast(m_dht.nid()); - return ret; - } - - void dht_tracker::add_node(udp::endpoint node) - { - m_dht.add_node(node); - } - - void dht_tracker::add_node(std::pair const& node) - { - udp::resolver::query q(node.first, lexical_cast(node.second)); - m_host_resolver.async_resolve(q, m_strand.wrap( - bind(&dht_tracker::on_name_lookup, self(), _1, _2))); - } - - void dht_tracker::on_name_lookup(asio::error_code const& e - , udp::resolver::iterator host) try - { - if (e || host == udp::resolver::iterator()) return; - add_node(host->endpoint()); - } - catch (std::exception&) - { - assert(false); - }; - - void dht_tracker::add_router_node(std::pair const& node) - { - udp::resolver::query q(node.first, lexical_cast(node.second)); - m_host_resolver.async_resolve(q, m_strand.wrap( - bind(&dht_tracker::on_router_name_lookup, self(), _1, _2))); - } - - void dht_tracker::on_router_name_lookup(asio::error_code const& e - , udp::resolver::iterator host) try - { - if (e || host == udp::resolver::iterator()) return; - m_dht.add_router_node(host->endpoint()); - } - catch (std::exception&) - { - assert(false); - }; - - void dht_tracker::on_bootstrap() - {} - - namespace - { - void write_nodes_entry(entry& r, libtorrent::dht::msg const& m) - { - bool ipv6_nodes = false; - r["nodes"] = entry(entry::string_t); - entry& n = r["nodes"]; - std::back_insert_iterator out(n.string()); - for (msg::nodes_t::const_iterator i = m.nodes.begin() - , end(m.nodes.end()); i != end; ++i) - { - if (!i->addr.address().is_v4()) - { - ipv6_nodes = true; - continue; - } - std::copy(i->id.begin(), i->id.end(), out); - write_endpoint(i->addr, out); - } - - if (ipv6_nodes) - { - r["nodes2"] = entry(entry::list_t); - entry& p = r["nodes2"]; - std::string endpoint; - for (msg::nodes_t::const_iterator i = m.nodes.begin() - , end(m.nodes.end()); i != end; ++i) - { - if (!i->addr.address().is_v6()) continue; - endpoint.resize(18 + 20); - std::string::iterator out = endpoint.begin(); - std::copy(i->id.begin(), i->id.end(), out); - out += 20; - write_endpoint(i->addr, out); - endpoint.resize(out - endpoint.begin()); - p.list().push_back(entry(endpoint)); - } - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " nodes: " << m.nodes.size(); -#endif - } - } - - void dht_tracker::send_packet(msg const& m) - try - { - using libtorrent::bencode; - using libtorrent::entry; - entry e(entry::dictionary_t); - assert(!m.transaction_id.empty() || m.message_id == messages::error); - e["t"] = m.transaction_id; - static char const version_str[] = {'L', 'T' - , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR}; - e["v"] = std::string(version_str, version_str + 4); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() - << " SENDING [" << m.addr << "]:"; - TORRENT_LOG(dht_tracker) << " transaction: " << m.transaction_id; -#endif - - if (m.message_id == messages::error) - { - assert(m.reply); - e["y"] = "e"; - entry error_list(entry::list_t); - assert(m.error_code > 200 && m.error_code <= 204); - error_list.list().push_back(entry(m.error_code)); - error_list.list().push_back(entry(m.error_msg)); - e["e"] = error_list; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() - << " outgoing error: " << m.error_code << " " << m.error_msg; -#endif - } - else if (m.reply) - { - e["y"] = "r"; - e["r"] = entry(entry::dictionary_t); - entry& r = e["r"]; - r["id"] = std::string(m.id.begin(), m.id.end()); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << time_now_string() - << " reply: " << messages::ids[m.message_id]; -#endif - - if (m.write_token.type() != entry::undefined_t) - r["token"] = m.write_token; - - switch (m.message_id) - { - case messages::ping: - break; - case messages::find_node: - { - write_nodes_entry(r, m); - break; - } - case messages::get_peers: - { - if (m.peers.empty()) - { - write_nodes_entry(r, m); - } - else - { - r["values"] = entry(entry::list_t); - entry& p = r["values"]; - std::string endpoint; - for (msg::peers_t::const_iterator i = m.peers.begin() - , end(m.peers.end()); i != end; ++i) - { - endpoint.resize(18); - std::string::iterator out = endpoint.begin(); - write_endpoint(*i, out); - endpoint.resize(out - endpoint.begin()); - p.list().push_back(entry(endpoint)); - } -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " peers: " << m.peers.size(); -#endif - } - break; - } - - case messages::announce_peer: - break; - break; - } - } - else - { - e["y"] = "q"; - e["a"] = entry(entry::dictionary_t); - entry& a = e["a"]; - a["id"] = std::string(m.id.begin(), m.id.end()); - - if (m.write_token.type() != entry::undefined_t) - a["token"] = m.write_token; - assert(m.message_id <= messages::error); - e["q"] = messages::ids[m.message_id]; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " query: " - << messages::ids[m.message_id]; -#endif - - switch (m.message_id) - { - case messages::find_node: - { - a["target"] = std::string(m.info_hash.begin(), m.info_hash.end()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " target: " - << boost::lexical_cast(m.info_hash); -#endif - break; - } - case messages::get_peers: - { - a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " info_hash: " - << boost::lexical_cast(m.info_hash); -#endif - break; - } - case messages::announce_peer: - a["port"] = m_settings.service_port; - a["info_hash"] = std::string(m.info_hash.begin(), m.info_hash.end()); - a["token"] = m.write_token; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(dht_tracker) << " port: " - << m_settings.service_port - << " info_hash: " << boost::lexical_cast(m.info_hash); -#endif - break; - default: break; - } - - } - - m_send_buf.clear(); - bencode(std::back_inserter(m_send_buf), e); - asio::error_code ec; - m_socket.send_to(asio::buffer(&m_send_buf[0] - , (int)m_send_buf.size()), m.addr, 0, ec); - if (ec) return; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - m_total_out_bytes += m_send_buf.size(); - - if (m.reply) - { - ++m_replies_sent[m.message_id]; - m_replies_bytes_sent[m.message_id] += int(m_send_buf.size()); - } - else - { - m_queries_out_bytes += m_send_buf.size(); - } - TORRENT_LOG(dht_tracker) << e; -#endif - - if (!m.piggy_backed_ping) return; - - msg pm; - pm.reply = false; - pm.piggy_backed_ping = false; - pm.message_id = messages::ping; - pm.transaction_id = m.ping_transaction_id; - pm.id = m.id; - pm.addr = m.addr; - - send_packet(pm); - } - catch (std::exception&) - { - // m_send may fail with "no route to host" - // but it shouldn't throw since an error code - // is passed in instead - assert(false); - } - -}} - diff --git a/libtorrent/src/kademlia/find_data.cpp b/libtorrent/src/kademlia/find_data.cpp deleted file mode 100644 index 4ada42fb3..000000000 --- a/libtorrent/src/kademlia/find_data.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include - -namespace libtorrent { namespace dht -{ - -find_data_observer::~find_data_observer() -{ - if (m_algorithm) m_algorithm->failed(m_self); -} - -void find_data_observer::reply(msg const& m) -{ - if (!m_algorithm) - { - assert(false); - return; - } - - if (!m.peers.empty()) - { - m_algorithm->got_data(&m); - } - else - { - for (msg::nodes_t::const_iterator i = m.nodes.begin() - , end(m.nodes.end()); i != end; ++i) - { - m_algorithm->traverse(i->id, i->addr); - } - } - m_algorithm->finished(m_self); - m_algorithm = 0; -} - -void find_data_observer::timeout() -{ - if (!m_algorithm) return; - m_algorithm->failed(m_self); - m_algorithm = 0; -} - - -find_data::find_data( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback -) - : traversal_algorithm( - target - , branch_factor - , max_results - , table - , rpc - , table.begin() - , table.end() - ) - , m_done_callback(callback) - , m_done(false) -{ - boost::intrusive_ptr self(this); - add_requests(); -} - -void find_data::invoke(node_id const& id, asio::ip::udp::endpoint addr) -{ - if (m_done) - { - m_invoke_count = -1; - return; - } - - observer_ptr o(new (m_rpc.allocator().malloc()) find_data_observer(this, id, m_target)); - m_rpc.invoke(messages::get_peers, addr, o); -} - -void find_data::got_data(msg const* m) -{ - m_done = true; - m_done_callback(m); -} - -void find_data::done() -{ - if (m_invoke_count != 0) return; - if (!m_done) m_done_callback(0); -} - -void find_data::initiate( - node_id target - , int branch_factor - , int max_results - , routing_table& table - , rpc_manager& rpc - , done_callback const& callback -) -{ - std::cerr << "find_data::initiate, key: " << target << "\n"; - new find_data(target, branch_factor, max_results, table, rpc, callback); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/node.cpp b/libtorrent/src/kademlia/node.cpp deleted file mode 100644 index 74641ec43..000000000 --- a/libtorrent/src/kademlia/node.cpp +++ /dev/null @@ -1,497 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "libtorrent/io.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/random_sample.hpp" -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/kademlia/rpc_manager.hpp" -#include "libtorrent/kademlia/packet_iterator.hpp" -#include "libtorrent/kademlia/routing_table.hpp" -#include "libtorrent/kademlia/node.hpp" - -#include "libtorrent/kademlia/refresh.hpp" -#include "libtorrent/kademlia/closest_nodes.hpp" -#include "libtorrent/kademlia/find_data.hpp" - -using boost::bind; - -namespace libtorrent { namespace dht -{ - -#ifdef _MSC_VER -namespace -{ - char rand() { return (char)std::rand(); } -} -#endif - -// TODO: configurable? -enum { announce_interval = 30 }; - -using asio::ip::udp; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(node) -#endif - -node_id generate_id() -{ - char random[20]; - std::srand(std::time(0)); -#ifdef _MSC_VER - std::generate(random, random + 20, &rand); -#else - std::generate(random, random + 20, &std::rand); -#endif - - hasher h; - h.update(random, 20); - return h.final(); -} - -// remove peers that have timed out -void purge_peers(std::set& peers) -{ - for (std::set::iterator i = peers.begin() - , end(peers.end()); i != end;) - { - // the peer has timed out - if (i->added + minutes(int(announce_interval * 1.5f)) < time_now()) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "peer timed out at: " << i->addr.address(); -#endif - peers.erase(i++); - } - else - ++i; - } -} - -void nop() {} - -node_impl::node_impl(boost::function const& f - , dht_settings const& settings, boost::optional node_id) - : m_settings(settings) - , m_id(node_id ? *node_id : generate_id()) - , m_table(m_id, 8, settings) - , m_rpc(bind(&node_impl::incoming_request, this, _1) - , m_id, m_table, f) - , m_last_tracker_tick(time_now()) -{ - m_secret[0] = std::rand(); - m_secret[1] = std::rand(); -} - -bool node_impl::verify_token(msg const& m) -{ - if (m.write_token.type() != entry::string_t) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "token of incorrect type " << m.write_token.type(); -#endif - return false; - } - std::string const& token = m.write_token.string(); - if (token.length() != 4) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "token of incorrect length: " << token.length(); -#endif - return false; - } - - hasher h1; - std::string address = m.addr.address().to_string(); - h1.update(&address[0], address.length()); - h1.update((char*)&m_secret[0], sizeof(m_secret[0])); - h1.update((char*)&m.info_hash[0], sha1_hash::size); - - sha1_hash h = h1.final(); - if (std::equal(token.begin(), token.end(), (signed char*)&h[0])) - return true; - - hasher h2; - h2.update(&address[0], address.length()); - h2.update((char*)&m_secret[1], sizeof(m_secret[1])); - h2.update((char*)&m.info_hash[0], sha1_hash::size); - h = h2.final(); - if (std::equal(token.begin(), token.end(), (signed char*)&h[0])) - return true; - return false; -} - -entry node_impl::generate_token(msg const& m) -{ - std::string token; - token.resize(4); - hasher h; - std::string address = m.addr.address().to_string(); - h.update(&address[0], address.length()); - h.update((char*)&m_secret[0], sizeof(m_secret[0])); - h.update((char*)&m.info_hash[0], sha1_hash::size); - - sha1_hash hash = h.final(); - std::copy(hash.begin(), hash.begin() + 4, (signed char*)&token[0]); - return entry(token); -} - -void node_impl::refresh(node_id const& id - , boost::function0 f) -{ - // use the 'bucket size' closest nodes - // to start the refresh with - std::vector start; - start.reserve(m_table.bucket_size()); - m_table.find_node(id, start, false); - refresh::initiate(id, m_settings.search_branching, 10, m_table.bucket_size() - , m_table, start.begin(), start.end(), m_rpc, f); -} - -void node_impl::bootstrap(std::vector const& nodes - , boost::function0 f) -{ - std::vector start; - start.reserve(nodes.size()); - std::copy(nodes.begin(), nodes.end(), std::back_inserter(start)); - refresh::initiate(m_id, m_settings.search_branching, 10, m_table.bucket_size() - , m_table, start.begin(), start.end(), m_rpc, f); -} - -void node_impl::refresh() -{ - std::vector start; - start.reserve(m_table.size().get<0>()); - std::copy(m_table.begin(), m_table.end(), std::back_inserter(start)); - - refresh::initiate(m_id, m_settings.search_branching, 10, m_table.bucket_size() - , m_table, start.begin(), start.end(), m_rpc, bind(&nop)); -} - -int node_impl::bucket_size(int bucket) -{ - return m_table.bucket_size(bucket); -} - -void node_impl::new_write_key() -{ - m_secret[1] = m_secret[0]; - m_secret[0] = std::rand(); -} - -void node_impl::refresh_bucket(int bucket) try -{ - assert(bucket >= 0 && bucket < 160); - - // generate a random node_id within the given bucket - node_id target = generate_id(); - int num_bits = 160 - bucket; - node_id mask(0); - for (int i = 0; i < num_bits; ++i) - { - int byte = i / 8; - mask[byte] |= 0x80 >> (i % 8); - } - - node_id root = m_id; - root &= mask; - target &= ~mask; - target |= root; - - // make sure this is in another subtree than m_id - // clear the (num_bits - 1) bit and then set it to the - // inverse of m_id's corresponding bit. - target[(num_bits - 1) / 8] &= ~(0x80 >> ((num_bits - 1) % 8)); - target[(num_bits - 1) / 8] |= - (~(m_id[(num_bits - 1) / 8])) & (0x80 >> ((num_bits - 1) % 8)); - - assert(distance_exp(m_id, target) == bucket); - - std::vector start; - start.reserve(m_table.bucket_size()); - m_table.find_node(target, start, false, m_table.bucket_size()); - - refresh::initiate(target, m_settings.search_branching, 10, m_table.bucket_size() - , m_table, start.begin(), start.end(), m_rpc, bind(&nop)); - m_table.touch_bucket(bucket); -} -catch (std::exception&) {} - -void node_impl::incoming(msg const& m) -{ - if (m_rpc.incoming(m)) - { - refresh(); - } -} - -namespace -{ - void announce_fun(std::vector const& v, rpc_manager& rpc - , int listen_port, sha1_hash const& ih - , boost::function const&, sha1_hash const&)> f) - { - bool nodes = false; - // only store on the first k nodes - for (std::vector::const_iterator i = v.begin() - , end(v.end()); i != end; ++i) - { - rpc.invoke(messages::get_peers, i->addr, observer_ptr( - new (rpc.allocator().malloc()) get_peers_observer(ih, listen_port, rpc, f))); - nodes = true; - } - } -} - -void node_impl::add_router_node(udp::endpoint router) -{ - m_table.add_router_node(router); -} - -void node_impl::add_node(udp::endpoint node) -{ - // ping the node, and if we get a reply, it - // will be added to the routing table - observer_ptr o(new (m_rpc.allocator().malloc()) null_observer(m_rpc.allocator())); - m_rpc.invoke(messages::ping, node, o); -} - -void node_impl::announce(sha1_hash const& info_hash, int listen_port - , boost::function const&, sha1_hash const&)> f) -{ - // search for nodes with ids close to id, and then invoke the - // get_peers and then announce_peer rpc on them. - closest_nodes::initiate(info_hash, m_settings.search_branching - , m_table.bucket_size(), m_table, m_rpc - , boost::bind(&announce_fun, _1, boost::ref(m_rpc), listen_port - , info_hash, f)); -} - -time_duration node_impl::refresh_timeout() -{ - int refresh = -1; - ptime now = time_now(); - ptime next = now + minutes(15); - try - { - for (int i = 0; i < 160; ++i) - { - ptime r = m_table.next_refresh(i); - if (r <= next) - { - refresh = i; - next = r; - } - } - if (next < now) - { - assert(refresh > -1); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "refreshing bucket: " << refresh; -#endif - refresh_bucket(refresh); - } - } - catch (std::exception&) {} - - time_duration next_refresh = next - now; - time_duration min_next_refresh - = minutes(15) / (m_table.num_active_buckets()); - if (min_next_refresh > seconds(40)) - min_next_refresh = seconds(40); - - if (next_refresh < min_next_refresh) - next_refresh = min_next_refresh; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(node) << "next refresh: " << total_seconds(next_refresh) << " seconds"; -#endif - - return next_refresh; -} - -time_duration node_impl::connection_timeout() -{ - time_duration d = m_rpc.tick(); - try - { - ptime now(time_now()); - if (now - m_last_tracker_tick < minutes(10)) return d; - m_last_tracker_tick = now; - - // look through all peers and see if any have timed out - for (data_iterator i = begin_data(), end(end_data()); i != end;) - { - torrent_entry& t = i->second; - node_id const& key = i->first; - ++i; - purge_peers(t.peers); - - // if there are no more peers, remove the entry altogether - if (t.peers.empty()) - { - table_t::iterator i = m_map.find(key); - if (i != m_map.end()) m_map.erase(i); - } - } - } - catch (std::exception&) {} - - return d; -} - -void node_impl::on_announce(msg const& m, msg& reply) -{ - if (!verify_token(m)) - { - reply.message_id = messages::error; - reply.error_code = 203; - reply.error_msg = "Incorrect token in announce_peer"; - return; - } - - // the token was correct. That means this - // node is not spoofing its address. So, let - // the table get a chance to add it. - m_table.node_seen(m.id, m.addr); - - torrent_entry& v = m_map[m.info_hash]; - peer_entry e; - e.addr = tcp::endpoint(m.addr.address(), m.addr.port()); - e.added = time_now(); - std::set::iterator i = v.peers.find(e); - if (i != v.peers.end()) v.peers.erase(i++); - v.peers.insert(i, e); -} - -namespace -{ - tcp::endpoint get_endpoint(peer_entry const& p) - { - return p.addr; - } -} - -bool node_impl::on_find(msg const& m, std::vector& peers) const -{ - table_t::const_iterator i = m_map.find(m.info_hash); - if (i == m_map.end()) return false; - - torrent_entry const& v = i->second; - - int num = (std::min)((int)v.peers.size(), m_settings.max_peers_reply); - peers.clear(); - peers.reserve(num); - random_sample_n(boost::make_transform_iterator(v.peers.begin(), &get_endpoint) - , boost::make_transform_iterator(v.peers.end(), &get_endpoint) - , std::back_inserter(peers), num); - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - for (std::vector::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - TORRENT_LOG(node) << " " << *i; - } -#endif - return true; -} - -void node_impl::incoming_request(msg const& m) -{ - msg reply; - reply.message_id = m.message_id; - reply.addr = m.addr; - reply.reply = true; - reply.transaction_id = m.transaction_id; - - switch (m.message_id) - { - case messages::ping: - break; - case messages::get_peers: - { - reply.info_hash = m.info_hash; - reply.write_token = generate_token(m); - - if (!on_find(m, reply.peers)) - { - // we don't have any peers for this info_hash, - // return nodes instead - m_table.find_node(m.info_hash, reply.nodes, false); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - for (std::vector::iterator i = reply.nodes.begin() - , end(reply.nodes.end()); i != end; ++i) - { - TORRENT_LOG(node) << " " << i->id << " " << i->addr; - } -#endif - } - } - break; - case messages::find_node: - { - reply.info_hash = m.info_hash; - - m_table.find_node(m.info_hash, reply.nodes, false); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - for (std::vector::iterator i = reply.nodes.begin() - , end(reply.nodes.end()); i != end; ++i) - { - TORRENT_LOG(node) << " " << i->id << " " << i->addr; - } -#endif - } - break; - case messages::announce_peer: - on_announce(m, reply); - break; - default: - assert(false); - }; - - if (m_table.need_node(m.id)) - m_rpc.reply_with_ping(reply); - else - m_rpc.reply(reply); -} - - -} } // namespace libtorrent::dht diff --git a/libtorrent/src/kademlia/node_id.cpp b/libtorrent/src/kademlia/node_id.cpp deleted file mode 100644 index 4ed413714..000000000 --- a/libtorrent/src/kademlia/node_id.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include - -#include "libtorrent/kademlia/node_id.hpp" - -using boost::bind; - -namespace libtorrent { namespace dht -{ - -// returns the distance between the two nodes -// using the kademlia XOR-metric -node_id distance(node_id const& n1, node_id const& n2) -{ - node_id ret; - node_id::iterator k = ret.begin(); - for (node_id::const_iterator i = n1.begin(), j = n2.begin() - , end(n1.end()); i != end; ++i, ++j, ++k) - { - *k = *i ^ *j; - } - return ret; -} - -// returns true if: distance(n1, ref) < distance(n2, ref) -bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref) -{ - for (node_id::const_iterator i = n1.begin(), j = n2.begin() - , k = ref.begin(), end(n1.end()); i != end; ++i, ++j, ++k) - { - boost::uint8_t lhs = (*i ^ *k); - boost::uint8_t rhs = (*j ^ *k); - if (lhs < rhs) return true; - if (lhs > rhs) return false; - } - return false; -} - -// returns n in: 2^n <= distance(n1, n2) < 2^(n+1) -// useful for finding out which bucket a node belongs to -int distance_exp(node_id const& n1, node_id const& n2) -{ - int byte = node_id::size - 1; - for (node_id::const_iterator i = n1.begin(), j = n2.begin() - , end(n1.end()); i != end; ++i, ++j, --byte) - { - assert(byte >= 0); - boost::uint8_t t = *i ^ *j; - if (t == 0) continue; - // we have found the first non-zero byte - // return the bit-number of the first bit - // that differs - int bit = byte * 8; - for (int b = 7; b > 0; --b) - if (t >= (1 << b)) return bit + b; - return bit; - } - - return 0; -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/refresh.cpp b/libtorrent/src/kademlia/refresh.cpp deleted file mode 100644 index ce94ca93b..000000000 --- a/libtorrent/src/kademlia/refresh.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include - -#include - -using boost::bind; - -namespace libtorrent { namespace dht -{ - -using asio::ip::udp; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(refresh) -#endif - -refresh_observer::~refresh_observer() -{ - if (m_algorithm) m_algorithm->failed(m_self, true); -} - -void refresh_observer::reply(msg const& in) -{ - if (!m_algorithm) return; - - if (!in.nodes.empty()) - { - for (msg::nodes_t::const_iterator i = in.nodes.begin() - , end(in.nodes.end()); i != end; ++i) - { - m_algorithm->traverse(i->id, i->addr); - } - } - m_algorithm->finished(m_self); - m_algorithm = 0; -} - -void refresh_observer::timeout() -{ - if (!m_algorithm) return; - m_algorithm->failed(m_self); - m_algorithm = 0; -} - -ping_observer::~ping_observer() -{ - if (m_algorithm) m_algorithm->ping_timeout(m_self, true); -} - -void ping_observer::reply(msg const& m) -{ - if (!m_algorithm) return; - - m_algorithm->ping_reply(m_self); - m_algorithm = 0; -} - -void ping_observer::timeout() -{ - if (!m_algorithm) return; - m_algorithm->ping_timeout(m_self); - m_algorithm = 0; -} - -void refresh::invoke(node_id const& nid, udp::endpoint addr) -{ - observer_ptr o(new (m_rpc.allocator().malloc()) refresh_observer( - this, nid, m_target)); - - m_rpc.invoke(messages::find_node, addr, o); -} - -void refresh::done() -{ - m_leftover_nodes_iterator = (int)m_results.size() > m_max_results ? - m_results.begin() + m_max_results : m_results.end(); - - invoke_pings_or_finish(); -} - -void refresh::ping_reply(node_id nid) -{ - m_active_pings--; - invoke_pings_or_finish(); -} - -void refresh::ping_timeout(node_id nid, bool prevent_request) -{ - m_active_pings--; - invoke_pings_or_finish(prevent_request); -} - -void refresh::invoke_pings_or_finish(bool prevent_request) -{ - if (prevent_request) - { - --m_max_active_pings; - if (m_max_active_pings <= 0) - m_max_active_pings = 1; - } - else - { - while (m_active_pings < m_max_active_pings) - { - if (m_leftover_nodes_iterator == m_results.end()) break; - - result const& node = *m_leftover_nodes_iterator; - - // Skip initial nodes - if (node.flags & result::initial) - { - ++m_leftover_nodes_iterator; - continue; - } - - try - { - observer_ptr o(new (m_rpc.allocator().malloc()) ping_observer( - this, node.id)); - m_rpc.invoke(messages::ping, node.addr, o); - ++m_active_pings; - ++m_leftover_nodes_iterator; - } - catch (std::exception& e) {} - } - } - - if (m_active_pings == 0) - { - m_done_callback(); - } -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/routing_table.cpp b/libtorrent/src/kademlia/routing_table.cpp deleted file mode 100644 index 45091481c..000000000 --- a/libtorrent/src/kademlia/routing_table.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include "libtorrent/kademlia/routing_table.hpp" -#include "libtorrent/kademlia/node_id.hpp" -#include "libtorrent/session_settings.hpp" - -using boost::bind; -using boost::uint8_t; - -namespace libtorrent { namespace dht -{ - -using asio::ip::udp; -typedef asio::ip::address_v4 address; - -routing_table::routing_table(node_id const& id, int bucket_size - , dht_settings const& settings) - : m_bucket_size(bucket_size) - , m_settings(settings) - , m_id(id) - , m_lowest_active_bucket(160) -{ - // distribute the refresh times for the buckets in an - // attempt do even out the network load - for (int i = 0; i < 160; ++i) - m_bucket_activity[i] = time_now() - milliseconds(i*5625); - m_bucket_activity[0] = time_now() - minutes(15); -} - -boost::tuple routing_table::size() const -{ - int nodes = 0; - int replacements = 0; - for (table_t::const_iterator i = m_buckets.begin() - , end(m_buckets.end()); i != end; ++i) - { - nodes += i->first.size(); - replacements += i->second.size(); - } - return boost::make_tuple(nodes, replacements); -} - -size_type routing_table::num_global_nodes() const -{ - int first_full = m_lowest_active_bucket; - int num_nodes = 1; // we are one of the nodes - for (; first_full < 160 - && int(m_buckets[first_full].first.size()) < m_bucket_size; - ++first_full) - { - num_nodes += m_buckets[first_full].first.size(); - } - - return (2 << (160 - first_full)) * num_nodes; -} - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - -void routing_table::print_state(std::ostream& os) const -{ - os << "kademlia routing table state\n" - << "bucket_size: " << m_bucket_size << "\n" - << "global node count: " << num_global_nodes() << "\n" - << "node_id: " << m_id << "\n\n"; - - os << "number of nodes per bucket:\n-- live "; - for (int i = 8; i < 160; ++i) - os << "-"; - os << "\n"; - - for (int k = 0; k < 8; ++k) - { - for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end()); - i != end; ++i) - { - os << (int(i->first.size()) > (7 - k) ? "|" : " "); - } - os << "\n"; - } - for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end()); - i != end; ++i) - { - os << "+"; - } - os << "\n"; - for (int k = 0; k < 8; ++k) - { - for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end()); - i != end; ++i) - { - os << (int(i->second.size()) > k ? "|" : " "); - } - os << "\n"; - } - os << "-- cached "; - for (int i = 10; i < 160; ++i) - os << "-"; - os << "\n\n"; - - os << "nodes:\n"; - for (table_t::const_iterator i = m_buckets.begin(), end(m_buckets.end()); - i != end; ++i) - { - int bucket_index = int(i - m_buckets.begin()); - os << "=== BUCKET = " << bucket_index - << " = " << (bucket_index >= m_lowest_active_bucket?"active":"inactive") - << " = " << total_seconds(time_now() - m_bucket_activity[bucket_index]) - << " s ago ===== \n"; - for (bucket_t::const_iterator j = i->first.begin() - , end(i->first.end()); j != end; ++j) - { - os << "ip: " << j->addr << " fails: " << j->fail_count - << " id: " << j->id << "\n"; - } - } -} - -#endif - -void routing_table::touch_bucket(int bucket) -{ - m_bucket_activity[bucket] = time_now(); -} - -ptime routing_table::next_refresh(int bucket) -{ - assert(bucket < 160); - assert(bucket >= 0); - // lower than or equal to since a refresh of bucket 0 will - // effectively refresh the lowest active bucket as well - if (bucket < m_lowest_active_bucket && bucket > 0) - return time_now() + minutes(15); - return m_bucket_activity[bucket] + minutes(15); -} - -void routing_table::replacement_cache(bucket_t& nodes) const -{ - for (table_t::const_iterator i = m_buckets.begin() - , end(m_buckets.end()); i != end; ++i) - { - std::copy(i->second.begin(), i->second.end() - , std::back_inserter(nodes)); - } -} - -bool routing_table::need_node(node_id const& id) -{ - int bucket_index = distance_exp(m_id, id); - assert(bucket_index < (int)m_buckets.size()); - assert(bucket_index >= 0); - bucket_t& b = m_buckets[bucket_index].first; - bucket_t& rb = m_buckets[bucket_index].second; - - // if the replacement cache is full, we don't - // need another node. The table is fine the - // way it is. - if ((int)rb.size() >= m_bucket_size) return false; - - // if the node already exists, we don't need it - if (std::find_if(b.begin(), b.end(), bind(&node_entry::id, _1) == id) - != b.end()) return false; - - if (std::find_if(rb.begin(), rb.end(), bind(&node_entry::id, _1) == id) - != rb.end()) return false; - - return true; -} - -void routing_table::node_failed(node_id const& id) -{ - int bucket_index = distance_exp(m_id, id); - assert(bucket_index < (int)m_buckets.size()); - assert(bucket_index >= 0); - bucket_t& b = m_buckets[bucket_index].first; - bucket_t& rb = m_buckets[bucket_index].second; - - bucket_t::iterator i = std::find_if(b.begin(), b.end() - , bind(&node_entry::id, _1) == id); - - if (i == b.end()) return; - - // if messages to ourself fails, ignore it - if (bucket_index == 0) return; - - if (rb.empty()) - { - ++i->fail_count; - if (i->fail_count >= m_settings.max_fail_count) - { - b.erase(i); - assert(m_lowest_active_bucket <= bucket_index); - while (m_buckets[m_lowest_active_bucket].first.empty() - && m_lowest_active_bucket < 160) - { - ++m_lowest_active_bucket; - } - } - return; - } - - b.erase(i); - b.push_back(rb.back()); - rb.erase(rb.end() - 1); -} - -void routing_table::add_router_node(udp::endpoint router) -{ - m_router_nodes.insert(router); -} - -// this function is called every time the node sees -// a sign of a node being alive. This node will either -// be inserted in the k-buckets or be moved to the top -// of its bucket. -// the return value indicates if the table needs a refresh. -// if true, the node should refresh the table (i.e. do a find_node -// on its own id) -bool routing_table::node_seen(node_id const& id, udp::endpoint addr) -{ - if (m_router_nodes.find(addr) != m_router_nodes.end()) return false; - int bucket_index = distance_exp(m_id, id); - assert(bucket_index < (int)m_buckets.size()); - assert(bucket_index >= 0); - bucket_t& b = m_buckets[bucket_index].first; - - bucket_t::iterator i = std::find_if(b.begin(), b.end() - , bind(&node_entry::id, _1) == id); - - bool ret = need_bootstrap(); - - //m_bucket_activity[bucket_index] = time_now(); - - if (i != b.end()) - { - // TODO: what do we do if we see a node with - // the same id as a node at a different address? -// assert(i->addr == addr); - - // we already have the node in our bucket - // just move it to the back since it was - // the last node we had any contact with - // in this bucket - b.erase(i); - b.push_back(node_entry(id, addr)); -// TORRENT_LOG(table) << "replacing node: " << id << " " << addr; - return ret; - } - - // if the node was not present in our list - // we will only insert it if there is room - // for it, or if some of our nodes have gone - // offline - if ((int)b.size() < m_bucket_size) - { - if (b.empty()) b.reserve(m_bucket_size); - b.push_back(node_entry(id, addr)); - // if bucket index is 0, the node is ourselves - // don't updated m_lowest_active_bucket - if (bucket_index < m_lowest_active_bucket - && bucket_index > 0) - m_lowest_active_bucket = bucket_index; -// TORRENT_LOG(table) << "inserting node: " << id << " " << addr; - return ret; - } - - // if there is no room, we look for nodes marked as stale - // in the k-bucket. If we find one, we can replace it. - // A node is considered stale if it has failed at least one - // time. Here we choose the node that has failed most times. - // If we don't find one, place this node in the replacement- - // cache and replace any nodes that will fail in the future - // with nodes from that cache. - - i = std::max_element(b.begin(), b.end() - , bind(&node_entry::fail_count, _1) - < bind(&node_entry::fail_count, _2)); - - if (i != b.end() && i->fail_count > 0) - { - // i points to a node that has been marked - // as stale. Replace it with this new one - b.erase(i); - b.push_back(node_entry(id, addr)); -// TORRENT_LOG(table) << "replacing stale node: " << id << " " << addr; - return ret; - } - - // if we don't have any identified stale nodes in - // the bucket, and the bucket is full, we have to - // cache this node and wait until some node fails - // and then replace it. - - bucket_t& rb = m_buckets[bucket_index].second; - - i = std::find_if(rb.begin(), rb.end() - , bind(&node_entry::id, _1) == id); - - // if the node is already in the replacement bucket - // just return. - if (i != rb.end()) return ret; - - if ((int)rb.size() > m_bucket_size) rb.erase(rb.begin()); - if (rb.empty()) rb.reserve(m_bucket_size); - rb.push_back(node_entry(id, addr)); -// TORRENT_LOG(table) << "inserting node in replacement cache: " << id << " " << addr; - return ret; -} - -bool routing_table::need_bootstrap() const -{ - for (const_iterator i = begin(); i != end(); ++i) - { - if (i->fail_count == 0) return false; - } - return true; -} - -// fills the vector with the k nodes from our buckets that -// are nearest to the given id. -void routing_table::find_node(node_id const& target - , std::vector& l, bool include_self, int count) -{ - l.clear(); - if (count == 0) count = m_bucket_size; - l.reserve(count); - - int bucket_index = distance_exp(m_id, target); - bucket_t& b = m_buckets[bucket_index].first; - - // copy all nodes that hasn't failed into the target - // vector. - std::remove_copy_if(b.begin(), b.end(), std::back_inserter(l) - , bind(&node_entry::fail_count, _1)); - assert((int)l.size() <= count); - - if ((int)l.size() == count) - { - assert(std::count_if(l.begin(), l.end() - , boost::bind(&node_entry::fail_count, _1) != 0) == 0); - return; - } - - // if we didn't have enough nodes in that bucket - // we have to reply with nodes from buckets closer - // to us. i.e. all the buckets in the range - // [0, bucket_index) if we are to include ourself - // or [1, bucket_index) if not. - bucket_t tmpb; - for (int i = include_self?0:1; i < count; ++i) - { - bucket_t& b = m_buckets[i].first; - std::remove_copy_if(b.begin(), b.end(), std::back_inserter(tmpb) - , bind(&node_entry::fail_count, _1)); - } - - std::random_shuffle(tmpb.begin(), tmpb.end()); - size_t to_copy = (std::min)(m_bucket_size - l.size() - , tmpb.size()); - std::copy(tmpb.begin(), tmpb.begin() + to_copy - , std::back_inserter(l)); - - assert((int)l.size() <= m_bucket_size); - - // return if we have enough nodes or if the bucket index - // is the biggest index available (there are no more buckets) - // to look in. - if ((int)l.size() == count - || bucket_index == (int)m_buckets.size() - 1) - { - assert(std::count_if(l.begin(), l.end() - , boost::bind(&node_entry::fail_count, _1) != 0) == 0); - return; - } - - for (size_t i = bucket_index + 1; i < m_buckets.size(); ++i) - { - bucket_t& b = m_buckets[i].first; - - std::remove_copy_if(b.begin(), b.end(), std::back_inserter(l) - , bind(&node_entry::fail_count, _1)); - if ((int)l.size() >= count) - { - l.erase(l.begin() + count, l.end()); - assert(std::count_if(l.begin(), l.end() - , boost::bind(&node_entry::fail_count, _1) != 0) == 0); - return; - } - } - assert((int)l.size() == count - || std::distance(l.begin(), l.end()) < m_bucket_size); - assert((int)l.size() <= count); - - assert(std::count_if(l.begin(), l.end() - , boost::bind(&node_entry::fail_count, _1) != 0) == 0); -} - -routing_table::iterator routing_table::begin() const -{ - return iterator(m_buckets.begin(), m_buckets.end()); -} - -routing_table::iterator routing_table::end() const -{ - return iterator(m_buckets.end(), m_buckets.end()); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/rpc_manager.cpp b/libtorrent/src/kademlia/rpc_manager.cpp deleted file mode 100644 index 93eac8565..000000000 --- a/libtorrent/src/kademlia/rpc_manager.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" -#include "libtorrent/socket.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using boost::shared_ptr; -using boost::bind; - -namespace libtorrent { namespace dht -{ - -namespace io = libtorrent::detail; -namespace mpl = boost::mpl; - -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(rpc) -#endif - -void intrusive_ptr_add_ref(observer const* o) -{ - assert(o->m_refs >= 0); - assert(o != 0); - ++o->m_refs; -} - -void intrusive_ptr_release(observer const* o) -{ - assert(o->m_refs > 0); - assert(o != 0); - if (--o->m_refs == 0) - { - boost::pool<>& p = o->pool_allocator; - o->~observer(); - p.ordered_free(const_cast(o)); - } -} - -node_id generate_id(); - -typedef mpl::vector< - closest_nodes_observer - , find_data_observer - , announce_observer - , get_peers_observer - , refresh_observer - , ping_observer - , null_observer - > observer_types; - -typedef mpl::max_element< - mpl::transform_view > - >::type max_observer_type_iter; - -rpc_manager::rpc_manager(fun const& f, node_id const& our_id - , routing_table& table, send_fun const& sf) - : m_pool_allocator(sizeof(mpl::deref::type)) - , m_next_transaction_id(rand() % max_transactions) - , m_oldest_transaction_id(m_next_transaction_id) - , m_incoming(f) - , m_send(sf) - , m_our_id(our_id) - , m_table(table) - , m_timer(time_now()) - , m_random_number(generate_id()) - , m_destructing(false) -{ - std::srand(time(0)); -} - -rpc_manager::~rpc_manager() -{ - m_destructing = true; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Destructing"; -#endif - std::for_each(m_aborted_transactions.begin(), m_aborted_transactions.end() - , bind(&observer::abort, _1)); - - for (transactions_t::iterator i = m_transactions.begin() - , end(m_transactions.end()); i != end; ++i) - { - if (*i) (*i)->abort(); - } -} - -#ifndef NDEBUG -void rpc_manager::check_invariant() const -{ - assert(m_oldest_transaction_id >= 0); - assert(m_oldest_transaction_id < max_transactions); - assert(m_next_transaction_id >= 0); - assert(m_next_transaction_id < max_transactions); - assert(!m_transactions[m_next_transaction_id]); - - for (int i = (m_next_transaction_id + 1) % max_transactions; - i != m_oldest_transaction_id; i = (i + 1) % max_transactions) - { - assert(!m_transactions[i]); - } -} -#endif - -bool rpc_manager::incoming(msg const& m) -{ - INVARIANT_CHECK; - - if (m_destructing) return false; - - if (m.reply) - { - // if we don't have the transaction id in our - // request list, ignore the packet - - if (m.transaction_id.size() < 2) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with invalid transaction id size: " - << m.transaction_id.size() << " from " << m.addr; -#endif - msg reply; - reply.reply = true; - reply.message_id = messages::error; - reply.error_code = 203; // Protocol error - reply.error_msg = "reply with invalid transaction id, size " - + boost::lexical_cast(m.transaction_id.size()); - reply.addr = m.addr; - reply.transaction_id = ""; - m_send(reply); - return false; - } - - std::string::const_iterator i = m.transaction_id.begin(); - int tid = io::read_uint16(i); - - if (tid >= (int)m_transactions.size() - || tid < 0) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with invalid transaction id: " - << tid << " from " << m.addr; -#endif - msg reply; - reply.reply = true; - reply.message_id = messages::error; - reply.error_code = 203; // Protocol error - reply.error_msg = "reply with invalid transaction id"; - reply.addr = m.addr; - reply.transaction_id = ""; - m_send(reply); - return false; - } - - observer_ptr o = m_transactions[tid]; - - if (!o) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with unknown transaction id: " - << tid << " from " << m.addr << " (possibly timed out)"; -#endif - return false; - } - - if (m.addr != o->target_addr) - { -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Reply with incorrect address and valid transaction id: " - << tid << " from " << m.addr; -#endif - return false; - } - -#ifdef TORRENT_DHT_VERBOSE_LOGGING - std::ofstream reply_stats("libtorrent_logs/round_trip_ms.log", std::ios::app); - reply_stats << m.addr << "\t" << total_milliseconds(time_now() - o->sent) - << std::endl; -#endif - o->reply(m); - m_transactions[tid] = 0; - - if (m.piggy_backed_ping) - { - // there is a ping request piggy - // backed in this reply - msg ph; - ph.message_id = messages::ping; - ph.transaction_id = m.ping_transaction_id; - ph.addr = m.addr; - ph.reply = true; - - reply(ph); - } - return m_table.node_seen(m.id, m.addr); - } - else - { - assert(m.message_id != messages::error); - // this is an incoming request - m_incoming(m); - } - return false; -} - -time_duration rpc_manager::tick() -{ - INVARIANT_CHECK; - - const int timeout_ms = 10 * 1000; - - // look for observers that has timed out - - if (m_next_transaction_id == m_oldest_transaction_id) return milliseconds(timeout_ms); - - std::vector timeouts; - - for (;m_next_transaction_id != m_oldest_transaction_id; - m_oldest_transaction_id = (m_oldest_transaction_id + 1) % max_transactions) - { - assert(m_oldest_transaction_id >= 0); - assert(m_oldest_transaction_id < max_transactions); - - observer_ptr o = m_transactions[m_oldest_transaction_id]; - if (!o) continue; - - time_duration diff = o->sent + milliseconds(timeout_ms) - time_now(); - if (diff > seconds(0)) - { - if (diff < seconds(1)) return seconds(1); - return diff; - } - - try - { - m_transactions[m_oldest_transaction_id] = 0; - timeouts.push_back(o); - } catch (std::exception) {} - } - - std::for_each(timeouts.begin(), timeouts.end(), bind(&observer::timeout, _1)); - timeouts.clear(); - - // clear the aborted transactions, will likely - // generate new requests. We need to swap, since the - // destrutors may add more observers to the m_aborted_transactions - std::vector().swap(m_aborted_transactions); - return milliseconds(timeout_ms); -} - -unsigned int rpc_manager::new_transaction_id(observer_ptr o) -{ - INVARIANT_CHECK; - - unsigned int tid = m_next_transaction_id; - m_next_transaction_id = (m_next_transaction_id + 1) % max_transactions; - if (m_transactions[m_next_transaction_id]) - { - // moving the observer into the set of aborted transactions - // it will prevent it from spawning new requests right now, - // since that would break the invariant - m_aborted_transactions.push_back(m_transactions[m_next_transaction_id]); - m_transactions[m_next_transaction_id] = 0; - assert(m_oldest_transaction_id == m_next_transaction_id); - } - assert(!m_transactions[tid]); - m_transactions[tid] = o; - if (m_oldest_transaction_id == m_next_transaction_id) - { - m_oldest_transaction_id = (m_oldest_transaction_id + 1) % max_transactions; -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "WARNING: transaction limit reached! Too many concurrent" - " messages! limit: " << (int)max_transactions; -#endif - update_oldest_transaction_id(); - } - - return tid; -} - -void rpc_manager::update_oldest_transaction_id() -{ - INVARIANT_CHECK; - - assert(m_oldest_transaction_id != m_next_transaction_id); - while (!m_transactions[m_oldest_transaction_id]) - { - m_oldest_transaction_id = (m_oldest_transaction_id + 1) - % max_transactions; - if (m_oldest_transaction_id == m_next_transaction_id) - break; - } -} - -void rpc_manager::invoke(int message_id, udp::endpoint target_addr - , observer_ptr o) -{ - INVARIANT_CHECK; - - if (m_destructing) - { - o->abort(); - return; - } - - msg m; - m.message_id = message_id; - m.reply = false; - m.id = m_our_id; - m.addr = target_addr; - assert(!m_transactions[m_next_transaction_id]); -#ifndef NDEBUG - int potential_new_id = m_next_transaction_id; -#endif - try - { - m.transaction_id.clear(); - std::back_insert_iterator out(m.transaction_id); - io::write_uint16(m_next_transaction_id, out); - - o->send(m); - - o->sent = time_now(); - o->target_addr = target_addr; - - #ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(rpc) << "Invoking " << messages::ids[message_id] - << " -> " << target_addr; - #endif - m_send(m); - new_transaction_id(o); - } - catch (std::exception& e) - { - // m_send may fail with "no route to host" - assert(potential_new_id == m_next_transaction_id); - o->abort(); - } -} - -void rpc_manager::reply(msg& m) -{ - INVARIANT_CHECK; - - if (m_destructing) return; - - assert(m.reply); - m.piggy_backed_ping = false; - m.id = m_our_id; - - m_send(m); -} - -void rpc_manager::reply_with_ping(msg& m) -{ - INVARIANT_CHECK; - - if (m_destructing) return; - assert(m.reply); - - m.piggy_backed_ping = true; - m.id = m_our_id; - - m.ping_transaction_id.clear(); - std::back_insert_iterator out(m.ping_transaction_id); - io::write_uint16(m_next_transaction_id, out); - - observer_ptr o(new (allocator().malloc()) null_observer(allocator())); - assert(!m_transactions[m_next_transaction_id]); - o->sent = time_now(); - o->target_addr = m.addr; - - m_send(m); - new_transaction_id(o); -} - - - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/kademlia/traversal_algorithm.cpp b/libtorrent/src/kademlia/traversal_algorithm.cpp deleted file mode 100644 index ceb977f19..000000000 --- a/libtorrent/src/kademlia/traversal_algorithm.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg & Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include - -#include - -using boost::bind; -using asio::ip::udp; - -namespace libtorrent { namespace dht -{ -#ifdef TORRENT_DHT_VERBOSE_LOGGING -TORRENT_DEFINE_LOG(traversal) -#endif - -void traversal_algorithm::add_entry(node_id const& id, udp::endpoint addr, unsigned char flags) -{ - if (m_failed.find(addr) != m_failed.end()) return; - - result const entry(id, addr, flags); - - std::vector::iterator i = std::lower_bound( - m_results.begin() - , m_results.end() - , entry - , bind( - compare_ref - , bind(&result::id, _1) - , bind(&result::id, _2) - , m_target - ) - ); - - if (i == m_results.end() || i->id != id) - { - assert(std::find_if(m_results.begin(), m_results.end() - , bind(&result::id, _1) == id) == m_results.end()); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(traversal) << "adding result: " << id << " " << addr; -#endif - m_results.insert(i, entry); - } -} - -boost::pool<>& traversal_algorithm::allocator() const -{ - return m_rpc.allocator(); -} - -void traversal_algorithm::traverse(node_id const& id, udp::endpoint addr) -{ - add_entry(id, addr, 0); -} - -void traversal_algorithm::finished(node_id const& id) -{ - --m_invoke_count; - add_requests(); - if (m_invoke_count == 0) done(); -} - -// prevent request means that the total number of requests has -// overflown. This query failed because it was the oldest one. -// So, if this is true, don't make another request -void traversal_algorithm::failed(node_id const& id, bool prevent_request) -{ - m_invoke_count--; - - std::vector::iterator i = std::find_if( - m_results.begin() - , m_results.end() - , bind( - std::equal_to() - , bind(&result::id, _1) - , id - ) - ); - - assert(i != m_results.end()); - - if (i != m_results.end()) - { - assert(i->flags & result::queried); - m_failed.insert(i->addr); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(traversal) << "failed: " << i->id << " " << i->addr; -#endif - m_results.erase(i); - } - if (prevent_request) - { - --m_branch_factor; - if (m_branch_factor <= 0) m_branch_factor = 1; - } - else - { - m_table.node_failed(id); - } - add_requests(); - if (m_invoke_count == 0) done(); -} - -namespace -{ - bool bitwise_nand(unsigned char lhs, unsigned char rhs) - { - return (lhs & rhs) == 0; - } -} - -void traversal_algorithm::add_requests() -{ - while (m_invoke_count < m_branch_factor) - { - // Find the first node that hasn't already been queried. - // TODO: Better heuristic - std::vector::iterator i = std::find_if( - m_results.begin() - , last_iterator() - , bind( - &bitwise_nand - , bind(&result::flags, _1) - , (unsigned char)result::queried - ) - ); -#ifdef TORRENT_DHT_VERBOSE_LOGGING - TORRENT_LOG(traversal) << "nodes left (" << this << "): " << (last_iterator() - i); -#endif - - if (i == last_iterator()) break; - - try - { - invoke(i->id, i->addr); - ++m_invoke_count; - i->flags |= result::queried; - } - catch (std::exception& e) {} - } -} - -std::vector::iterator traversal_algorithm::last_iterator() -{ - return (int)m_results.size() >= m_max_results ? - m_results.begin() + m_max_results - : m_results.end(); -} - -} } // namespace libtorrent::dht - diff --git a/libtorrent/src/logger.cpp b/libtorrent/src/logger.cpp deleted file mode 100644 index 6881c5e7b..000000000 --- a/libtorrent/src/logger.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include - -#include "libtorrent/extensions/logger.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/peer_request.hpp" -#include "libtorrent/peer_connection.hpp" - -namespace libtorrent { namespace -{ - - struct logger_peer_plugin : peer_plugin - { - logger_peer_plugin(std::string const& filename) - { - using namespace boost::filesystem; - path dir(complete("libtorrent_ext_logs")); - if (!exists(dir)) create_directories(dir); - m_file.open(dir / filename, std::ios_base::out | std::ios_base::out); - m_file << "\n\n\n"; - log_timestamp(); - m_file << "*** starting log ***\n"; - } - - void log_timestamp() - { - m_file << time_now_string() << ": "; - } - - // can add entries to the extension handshake - virtual void add_handshake(entry&) {} - - // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(entry const& h) - { - log_timestamp(); - m_file << "<== EXTENSION_HANDSHAKE\n"; - h.print(m_file); - return true; - } - - // returning true from any of the message handlers - // indicates that the plugin has handeled the message. - // it will break the plugin chain traversing and not let - // anyone else handle the message, including the default - // handler. - - virtual bool on_choke() - { - log_timestamp(); - m_file << "<== CHOKE\n"; - m_file.flush(); - return false; - } - - virtual bool on_unchoke() - { - log_timestamp(); - m_file << "<== UNCHOKE\n"; - m_file.flush(); - return false; - } - - virtual bool on_interested() - { - log_timestamp(); - m_file << "<== INTERESTED\n"; - m_file.flush(); - return false; - } - - virtual bool on_not_interested() - { - log_timestamp(); - m_file << "<== NOT_INTERESTED\n"; - m_file.flush(); - return false; - } - - virtual bool on_have(int index) - { - log_timestamp(); - m_file << "<== HAVE [" << index << "]\n"; - m_file.flush(); - return false; - } - - virtual bool on_bitfield(std::vector const& bitfield) - { - log_timestamp(); - m_file << "<== BITFIELD\n"; - m_file.flush(); - return false; - } - - virtual bool on_request(peer_request const& r) - { - log_timestamp(); - m_file << "<== REQUEST [ piece: " << r.piece << " | s: " << r.start - << " | l: " << r.length << " ]\n"; - m_file.flush(); - return false; - } - - virtual bool on_piece(peer_request const& r, char const*) - { - log_timestamp(); - m_file << "<== PIECE [ piece: " << r.piece << " | s: " << r.start - << " | l: " << r.length << " ]\n"; - m_file.flush(); - return false; - } - - virtual bool on_cancel(peer_request const& r) - { - log_timestamp(); - m_file << "<== CANCEL [ piece: " << r.piece << " | s: " << r.start - << " | l: " << r.length << " ]\n"; - m_file.flush(); - return false; - } - - // called when an extended message is received. If returning true, - // the message is not processed by any other plugin and if false - // is returned the next plugin in the chain will receive it to - // be able to handle it - virtual bool on_extended(int length - , int msg, buffer::const_interval body) - { return false; } - - virtual bool on_unknown_message(int length, int msg - , buffer::const_interval body) - { - if (body.left() < length) return false; - log_timestamp(); - m_file << "<== UNKNOWN [ msg: " << msg - << " | l: " << length << " ]\n"; - m_file.flush(); - return false; - } - - virtual void on_piece_pass(int index) - { - log_timestamp(); - m_file << "*** HASH PASSED *** [ piece: " << index << " ]\n"; - m_file.flush(); - } - - virtual void on_piece_failed(int index) - { - log_timestamp(); - m_file << "*** HASH FAILED *** [ piece: " << index << " ]\n"; - m_file.flush(); - } - - private: - boost::filesystem::ofstream m_file; - }; - - struct logger_plugin : torrent_plugin - { - virtual boost::shared_ptr new_connection( - peer_connection* pc) - { - return boost::shared_ptr(new logger_peer_plugin( - pc->remote().address().to_string() + "_" - + boost::lexical_cast(pc->remote().port()) + ".log")); - } - }; - -} } - -namespace libtorrent -{ - - boost::shared_ptr create_logger_plugin(torrent*) - { - return boost::shared_ptr(new logger_plugin()); - } - -} - - diff --git a/libtorrent/src/lsd.cpp b/libtorrent/src/lsd.cpp deleted file mode 100644 index b73e407bc..000000000 --- a/libtorrent/src/lsd.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/lsd.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/xml_parse.hpp" -#include -#include -#include -#include -#include -#include -#include - -using boost::bind; -using namespace libtorrent; - -namespace libtorrent -{ - // defined in upnp.cpp - address_v4 guess_local_address(asio::io_service&); -} - -address_v4 lsd::lsd_multicast_address; -udp::endpoint lsd::lsd_multicast_endpoint; - -lsd::lsd(io_service& ios, address const& listen_interface - , peer_callback_t const& cb) - : m_callback(cb) - , m_retry_count(0) - , m_socket(ios) - , m_broadcast_timer(ios) - , m_disabled(false) -{ - // Bittorrent Local discovery multicast address and port - lsd_multicast_address = address_v4::from_string("239.192.152.143"); - lsd_multicast_endpoint = udp::endpoint(lsd_multicast_address, 6771); - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc); -#endif - assert(lsd_multicast_address.is_multicast()); - rebind(listen_interface); -} - -lsd::~lsd() {} - -void lsd::rebind(address const& listen_interface) -{ - address_v4 local_ip = address_v4::any(); - if (listen_interface.is_v4() && listen_interface != address_v4::any()) - { - local_ip = listen_interface.to_v4(); - } - - try - { - // the local interface hasn't changed - if (m_socket.is_open() - && m_socket.local_endpoint().address() == local_ip) - return; - - m_socket.close(); - - using namespace asio::ip::multicast; - - m_socket.open(udp::v4()); - m_socket.set_option(datagram_socket::reuse_address(true)); - m_socket.bind(udp::endpoint(local_ip, 6771)); - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "local ip: " << local_ip << std::endl; -#endif - - m_socket.set_option(join_group(lsd_multicast_address)); - m_socket.set_option(outbound_interface(local_ip)); - m_socket.set_option(enable_loopback(true)); - m_socket.set_option(hops(255)); - } - catch (std::exception& e) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "socket multicast error " << e.what() - << ". disabling local service discovery" << std::endl; -#endif - m_disabled = true; - return; - } - m_disabled = false; - - setup_receive(); -} - -void lsd::announce(sha1_hash const& ih, int listen_port) -{ - if (m_disabled) return; - - std::stringstream btsearch; - btsearch << "BT-SEARCH * HTTP/1.1\r\n" - "Host: 239.192.152.143:6771\r\n" - "Port: " << listen_port << "\r\n" - "Infohash: " << ih << "\r\n" - "\r\n\r\n"; - std::string const& msg = btsearch.str(); - - m_retry_count = 0; - asio::error_code ec; - m_socket.send_to(asio::buffer(msg.c_str(), msg.size() - 1) - , lsd_multicast_endpoint, 0, ec); - if (ec) - { - m_disabled = true; - return; - } - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " ==> announce: ih: " << ih << " port: " << listen_port << std::endl; -#endif - - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); - m_broadcast_timer.async_wait(bind(&lsd::resend_announce, this, _1, msg)); -} - -void lsd::resend_announce(asio::error_code const& e, std::string msg) try -{ - if (e) return; - - m_socket.send_to(asio::buffer(msg, msg.size() - 1) - , lsd_multicast_endpoint); - - ++m_retry_count; - if (m_retry_count >= 5) - return; - - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); - m_broadcast_timer.async_wait(bind(&lsd::resend_announce, this, _1, msg)); -} -catch (std::exception&) -{} - -void lsd::on_announce(asio::error_code const& e - , std::size_t bytes_transferred) -{ - using namespace libtorrent::detail; - if (e) return; - - char* p = m_receive_buffer; - char* end = m_receive_buffer + bytes_transferred; - char* line = std::find(p, end, '\n'); - for (char* i = p; i < line; ++i) *i = std::tolower(*i); -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== announce: " << std::string(p, line) << std::endl; -#endif - if (line == end || (line - p >= 9 && std::memcmp("bt-search", p, 9))) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " *** assumed 'bt-search', ignoring" << std::endl; -#endif - setup_receive(); - return; - } - p = line + 1; - int port = 0; - sha1_hash ih(0); - while (p != end) - { - line = std::find(p, end, '\n'); - if (line == end) break; - *line = 0; - for (char* i = p; i < line; ++i) *i = std::tolower(*i); - if (line - p >= 5 && memcmp(p, "port:", 5) == 0) - { - p += 5; - while (*p == ' ') ++p; - port = atoi(p); - } - else if (line - p >= 9 && memcmp(p, "infohash:", 9) == 0) - { - p += 9; - while (*p == ' ') ++p; - if (line - p > 40) p[40] = 0; - try { ih = boost::lexical_cast(p); } - catch (std::exception&) {} - } - p = line + 1; - } - - if (!ih.is_all_zeros() && port != 0) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " *** incoming local announce " << m_remote.address() - << ":" << port << " ih: " << ih << std::endl; -#endif - // we got an announce, pass it on through the callback - try { m_callback(tcp::endpoint(m_remote.address(), port), ih); } - catch (std::exception&) {} - } - setup_receive(); -} - -void lsd::setup_receive() try -{ - assert(m_socket.is_open()); - m_socket.async_receive_from(asio::buffer(m_receive_buffer - , sizeof(m_receive_buffer)), m_remote, bind(&lsd::on_announce, this, _1, _2)); -} -catch (std::exception&) -{} - -void lsd::close() -{ - m_socket.close(); -} - diff --git a/libtorrent/src/metadata_transfer.cpp b/libtorrent/src/metadata_transfer.cpp deleted file mode 100644 index fe308f926..000000000 --- a/libtorrent/src/metadata_transfer.cpp +++ /dev/null @@ -1,568 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include -#include -#include - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/extensions/metadata_transfer.hpp" - -namespace libtorrent { namespace -{ - int div_round_up(int numerator, int denominator) - { - return (numerator + denominator - 1) / denominator; - } - - std::pair req_to_offset(std::pair req, int total_size) - { - assert(req.first >= 0); - assert(req.second > 0); - assert(req.second <= 256); - assert(req.first + req.second <= 256); - - int start = div_round_up(req.first * total_size, 256); - int size = div_round_up((req.first + req.second) * total_size, 256) - start; - return std::make_pair(start, size); - } - - std::pair offset_to_req(std::pair offset, int total_size) - { - int start = offset.first * 256 / total_size; - int size = (offset.first + offset.second) * 256 / total_size - start; - - std::pair ret(start, size); - - assert(start >= 0); - assert(size > 0); - assert(start <= 256); - assert(start + size <= 256); - - // assert the identity of this function -#ifndef NDEBUG - std::pair identity = req_to_offset(ret, total_size); - assert(offset == identity); -#endif - return ret; - } - - - struct metadata_plugin : torrent_plugin - { - metadata_plugin(torrent& t) - : m_torrent(t) - , m_metadata_progress(0) - , m_metadata_size(0) - { - m_requested_metadata.resize(256, 0); - } - - virtual void on_files_checked() - { - // if the torrent is a seed, copy the metadata from - // the torrent before it is deallocated - if (m_torrent.is_seed()) - metadata(); - } - - virtual boost::shared_ptr new_connection( - peer_connection* pc); - - std::vector const& metadata() const - { - if (m_metadata.empty()) - { - bencode(std::back_inserter(m_metadata) - , m_torrent.torrent_file().create_info_metadata()); - - assert(hasher(&m_metadata[0], m_metadata.size()).final() - == m_torrent.torrent_file().info_hash()); - } - assert(!m_metadata.empty()); - return m_metadata; - } - - bool received_metadata(char const* buf, int size, int offset, int total_size) - { - if (m_torrent.valid_metadata()) return false; - - if ((int)m_metadata.size() < total_size) - m_metadata.resize(total_size); - - std::copy( - buf - , buf + size - , &m_metadata[offset]); - - if (m_have_metadata.empty()) - m_have_metadata.resize(256, false); - - std::pair req = offset_to_req(std::make_pair(offset, size) - , total_size); - - assert(req.first + req.second <= (int)m_have_metadata.size()); - - std::fill( - m_have_metadata.begin() + req.first - , m_have_metadata.begin() + req.first + req.second - , true); - - bool have_all = std::count( - m_have_metadata.begin() - , m_have_metadata.end() - , true) == 256; - - if (!have_all) return false; - - hasher h; - h.update(&m_metadata[0], (int)m_metadata.size()); - sha1_hash info_hash = h.final(); - - if (info_hash != m_torrent.torrent_file().info_hash()) - { - std::fill( - m_have_metadata.begin() - , m_have_metadata.begin() + req.first + req.second - , false); - m_metadata_progress = 0; - m_metadata_size = 0; - // TODO: allow plugins to post alerts -/* - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(metadata_failed_alert( - get_handle(), "invalid metadata received from swarm")); - } -*/ - return false; - } - - entry metadata = bdecode(m_metadata.begin(), m_metadata.end()); - m_torrent.set_metadata(metadata); - - // clear the storage for the bitfield - std::vector().swap(m_have_metadata); - std::vector().swap(m_requested_metadata); - - return true; - } - - // returns a range of the metadata that - // we should request. - std::pair metadata_request(); - - void cancel_metadata_request(std::pair req) - { - for (int i = req.first; i < req.first + req.second; ++i) - { - assert(m_requested_metadata[i] > 0); - if (m_requested_metadata[i] > 0) - --m_requested_metadata[i]; - } - } - - // this is called from the peer_connection for - // each piece of metadata it receives - void metadata_progress(int total_size, int received) - { - m_metadata_progress += received; - m_metadata_size = total_size; - } - - void piece_pass(int) - { - // if we became a seed, copy the metadata from - // the torrent before it is deallocated - if (m_torrent.is_seed()) - metadata(); - } - - private: - torrent& m_torrent; - - // this buffer is filled with the info-section of - // the metadata file while downloading it from - // peers, and while sending it. - // it is mutable because it's generated lazily - mutable std::vector m_metadata; - - int m_metadata_progress; - int m_metadata_size; - - // this is a bitfield of size 256, each bit represents - // a piece of the metadata. It is set to one if we - // have that piece. This vector may be empty - // (size 0) if we haven't received any metadata - // or if we already have all metadata - std::vector m_have_metadata; - // this vector keeps track of how many times each meatdata - // block has been requested - std::vector m_requested_metadata; - }; - - - struct metadata_peer_plugin : peer_plugin - { - metadata_peer_plugin(torrent& t, peer_connection& pc - , metadata_plugin& tp) - : m_waiting_metadata_request(false) - , m_message_index(0) - , m_metadata_progress(0) - , m_no_metadata(min_time()) - , m_metadata_request(min_time()) - , m_torrent(t) - , m_pc(pc) - , m_tp(tp) - {} - - // can add entries to the extension handshake - virtual void add_handshake(entry& h) - { - entry& messages = h["m"]; - messages["LT_metadata"] = 14; - } - - // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(entry const& h) - { - entry const& messages = h["m"]; - if (entry const* index = messages.find_key("LT_metadata")) - { - m_message_index = index->integer(); - return true; - } - else - { - m_message_index = 0; - return false; - } - } - - void write_metadata_request(std::pair req) - { - assert(req.first >= 0); - assert(req.second > 0); - assert(req.first + req.second <= 256); - assert(!m_pc.associated_torrent().expired()); - assert(!m_pc.associated_torrent().lock()->valid_metadata()); - - int start = req.first; - int size = req.second; - - // abort if the peer doesn't support the metadata extension - if (m_message_index == 0) return; - - buffer::interval i = m_pc.allocate_send_buffer(9); - - detail::write_uint32(1 + 1 + 3, i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - // means 'request data' - detail::write_uint8(0, i.begin); - detail::write_uint8(start, i.begin); - detail::write_uint8(size - 1, i.begin); - assert(i.begin == i.end); - m_pc.setup_send(); - } - - void write_metadata(std::pair req) - { - assert(req.first >= 0); - assert(req.second > 0); - assert(req.second <= 256); - assert(req.first + req.second <= 256); - assert(!m_pc.associated_torrent().expired()); - - // abort if the peer doesn't support the metadata extension - if (m_message_index == 0) return; - - // only send metadata if the torrent is non-private - if (m_torrent.valid_metadata() && !m_torrent.torrent_file().priv()) - { - std::pair offset - = req_to_offset(req, (int)m_tp.metadata().size()); - - buffer::interval i = m_pc.allocate_send_buffer(15 + offset.second); - - // yes, we have metadata, send it - detail::write_uint32(11 + offset.second, i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - // means 'data packet' - detail::write_uint8(1, i.begin); - detail::write_uint32((int)m_tp.metadata().size(), i.begin); - detail::write_uint32(offset.first, i.begin); - std::vector const& metadata = m_tp.metadata(); - std::copy(metadata.begin() + offset.first - , metadata.begin() + offset.first + offset.second, i.begin); - i.begin += offset.second; - assert(i.begin == i.end); - } - else - { - buffer::interval i = m_pc.allocate_send_buffer(4 + 3); - // we don't have the metadata, reply with - // don't have-message - detail::write_uint32(1 + 2, i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - // means 'have no data' - detail::write_uint8(2, i.begin); - assert(i.begin == i.end); - } - m_pc.setup_send(); - } - - virtual bool on_extended(int length - , int msg, buffer::const_interval body) - { - if (msg != 14) return false; - if (m_message_index == 0) return false; - - if (length > 500 * 1024) - throw protocol_error("LT_metadata message larger than 500 kB"); - - if (body.left() < 1) return true; - int type = detail::read_uint8(body.begin); - - switch (type) - { - case 0: // request - { - if (body.left() < 2) return true; - int start = detail::read_uint8(body.begin); - int size = detail::read_uint8(body.begin) + 1; - - if (length != 3) - { - // invalid metadata request - throw protocol_error("invalid metadata request"); - } - - write_metadata(std::make_pair(start, size)); - } - break; - case 1: // data - { - if (body.left() < 8) return true; - - int total_size = detail::read_int32(body.begin); - int offset = detail::read_int32(body.begin); - int data_size = length - 9; - - if (total_size > 500 * 1024) - throw protocol_error("metadata size larger than 500 kB"); - if (total_size <= 0) - throw protocol_error("invalid metadata size"); - if (offset > total_size || offset < 0) - throw protocol_error("invalid metadata offset"); - if (offset + data_size > total_size) - throw protocol_error("invalid metadata message"); - - m_tp.metadata_progress(total_size - , body.left() - m_metadata_progress); - m_metadata_progress = body.left(); - - if (body.left() < data_size) return true; - - m_waiting_metadata_request = false; - m_tp.received_metadata(body.begin, data_size - , offset, total_size); - m_metadata_progress = 0; - } - break; - case 2: // have no data - m_no_metadata = time_now(); - if (m_waiting_metadata_request) - m_tp.cancel_metadata_request(m_last_metadata_request); - m_waiting_metadata_request = false; - break; - default: - throw protocol_error("unknown metadata extension message: " - + boost::lexical_cast(type)); - } - return true; - } - - virtual void tick() - { - // if we don't have any metadata, and this peer - // supports the request metadata extension - // and we aren't currently waiting for a request - // reply. Then, send a request for some metadata. - if (!m_torrent.valid_metadata() - && m_message_index != 0 - && !m_waiting_metadata_request - && has_metadata()) - { - m_last_metadata_request = m_tp.metadata_request(); - write_metadata_request(m_last_metadata_request); - m_waiting_metadata_request = true; - m_metadata_request = time_now(); - } - } - - bool has_metadata() const - { - return time_now() - m_no_metadata > minutes(5); - } - - private: - - // this is set to true when we send a metadata - // request to this peer, and reset to false when - // we receive a reply to our request. - bool m_waiting_metadata_request; - - // this is the message index the remote peer uses - // for metadata extension messages. - int m_message_index; - - // the number of bytes of metadata we have received - // so far from this per, only counting the current - // request. Any previously finished requests - // that have been forwarded to the torrent object - // do not count. - int m_metadata_progress; - - // this is set to the current time each time we get a - // "I don't have metadata" message. - ptime m_no_metadata; - - // this is set to the time when we last sent - // a request for metadata to this peer - ptime m_metadata_request; - - // if we're waiting for a metadata request - // this was the request we sent - std::pair m_last_metadata_request; - - torrent& m_torrent; - peer_connection& m_pc; - metadata_plugin& m_tp; - }; - - boost::shared_ptr metadata_plugin::new_connection( - peer_connection* pc) - { - bt_peer_connection* c = dynamic_cast(pc); - if (!c) return boost::shared_ptr(); - return boost::shared_ptr(new metadata_peer_plugin(m_torrent, *pc, *this)); - } - - std::pair metadata_plugin::metadata_request() - { - // count the number of peers that supports the - // extension and that has metadata - int peers = 0; -#ifndef TORRENT_DISABLE_EXTENSIONS - typedef std::map conn_map; - for (conn_map::iterator i = m_torrent.begin() - , end(m_torrent.end()); i != end; ++i) - { - bt_peer_connection* c = dynamic_cast(i->second); - if (c == 0) continue; - metadata_peer_plugin* p - = c->supports_extension(); - if (p == 0) continue; - if (!p->has_metadata()) continue; - ++peers; - } -#endif - - // the number of blocks to request - int num_blocks = 256 / (peers + 1); - if (num_blocks < 1) num_blocks = 1; - assert(num_blocks <= 128); - - int min_element = std::numeric_limits::max(); - int best_index = 0; - for (int i = 0; i < 256 - num_blocks + 1; ++i) - { - int min = *std::min_element(m_requested_metadata.begin() + i - , m_requested_metadata.begin() + i + num_blocks); - min += std::accumulate(m_requested_metadata.begin() + i - , m_requested_metadata.begin() + i + num_blocks, (int)0); - - if (min_element > min) - { - best_index = i; - min_element = min; - } - } - - std::pair ret(best_index, num_blocks); - for (int i = ret.first; i < ret.first + ret.second; ++i) - m_requested_metadata[i]++; - - assert(ret.first >= 0); - assert(ret.second > 0); - assert(ret.second <= 256); - assert(ret.first + ret.second <= 256); - - return ret; - } - -} } - -namespace libtorrent -{ - - boost::shared_ptr create_metadata_plugin(torrent* t) - { - return boost::shared_ptr(new metadata_plugin(*t)); - } - -} - - diff --git a/libtorrent/src/natpmp.cpp b/libtorrent/src/natpmp.cpp deleted file mode 100644 index 0a5932a56..000000000 --- a/libtorrent/src/natpmp.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include - -using boost::bind; -using namespace libtorrent; - -enum { num_mappings = 2 }; - -namespace libtorrent -{ - // defined in upnp.cpp - bool is_local(address const& a); - address_v4 guess_local_address(asio::io_service&); -} - -natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb) - : m_callback(cb) - , m_currently_mapping(-1) - , m_retry_count(0) - , m_socket(ios) - , m_send_timer(ios) - , m_refresh_timer(ios) - , m_disabled(false) -{ - m_mappings[0].protocol = 2; // tcp - m_mappings[1].protocol = 1; // udp - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log.open("natpmp.log", std::ios::in | std::ios::out | std::ios::trunc); -#endif - rebind(listen_interface); -} - -void natpmp::rebind(address const& listen_interface) try -{ - address_v4 local = address_v4::any(); - if (listen_interface.is_v4() && listen_interface != address_v4::any()) - { - local = listen_interface.to_v4(); - } - else - { - local = guess_local_address(m_socket.io_service()); - - if (local == address_v4::any()) - { - throw std::runtime_error("local host is probably not on a NATed " - "network. disabling NAT-PMP"); - } - } - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " local ip: " << local.to_string() << std::endl; -#endif - - if (!is_local(local)) - { - // the local address seems to be an external - // internet address. Assume it is not behind a NAT - throw std::runtime_error("local IP is not on a local network"); - } - - m_disabled = false; - - // assume the router is located on the local - // network as x.x.x.1 - udp::endpoint nat_endpoint( - address_v4((local.to_ulong() & 0xffffff00) | 1), 5351); - - if (nat_endpoint == m_nat_endpoint) return; - - // TODO: find a better way to figure out the router IP - m_nat_endpoint = nat_endpoint; - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "assuming router is at: " << m_nat_endpoint.address().to_string() << std::endl; -#endif - - m_socket.open(udp::v4()); - m_socket.bind(udp::endpoint(address_v4::any(), 0)); - - for (int i = 0; i < num_mappings; ++i) - { - if (m_mappings[i].local_port == 0) - continue; - refresh_mapping(i); - } -} -catch (std::exception& e) -{ - m_disabled = true; - std::stringstream msg; - msg << "NAT-PMP disabled: " << e.what(); -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << msg.str() << std::endl; -#endif - m_callback(0, 0, msg.str()); -}; - -void natpmp::set_mappings(int tcp, int udp) -{ - if (m_disabled) return; - update_mapping(0, tcp); - update_mapping(1, udp); -} - -void natpmp::update_mapping(int i, int port) -{ - natpmp::mapping& m = m_mappings[i]; - if (port <= 0) return; - if (m.local_port != port) - m.need_update = true; - - m.local_port = port; - // prefer the same external port as the local port - if (m.external_port == 0) m.external_port = port; - - if (m_currently_mapping == -1) - { - // the socket is not currently in use - // send out a mapping request - m_retry_count = 0; - send_map_request(i); - m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) - , m_remote, bind(&natpmp::on_reply, this, _1, _2)); - } -} - -void natpmp::send_map_request(int i) try -{ - using namespace libtorrent::detail; - - assert(m_currently_mapping == -1 - || m_currently_mapping == i); - m_currently_mapping = i; - mapping& m = m_mappings[i]; - char buf[12]; - char* out = buf; - write_uint8(0, out); // NAT-PMP version - write_uint8(m.protocol, out); // map "protocol" - write_uint16(0, out); // reserved - write_uint16(m.local_port, out); // private port - write_uint16(m.external_port, out); // requested public port - int ttl = m.external_port == 0 ? 0 : 3600; - write_uint32(ttl, out); // port mapping lifetime - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " ==> port map request: " << (m.protocol == 1 ? "udp" : "tcp") - << " local: " << m.local_port << " external: " << m.external_port - << " ttl: " << ttl << std::endl; -#endif - - m_socket.send_to(asio::buffer(buf, 12), m_nat_endpoint); - // linear back-off instead of exponential - ++m_retry_count; - m_send_timer.expires_from_now(milliseconds(250 * m_retry_count)); - m_send_timer.async_wait(bind(&natpmp::resend_request, this, i, _1)); -} -catch (std::exception& e) -{ - std::string err = e.what(); -}; - -void natpmp::resend_request(int i, asio::error_code const& e) -{ - if (e) return; - if (m_currently_mapping != i) return; - if (m_retry_count >= 9) - { - m_mappings[i].need_update = false; - // try again in two hours - m_mappings[i].expires = time_now() + hours(2); - return; - } - send_map_request(i); -} - -void natpmp::on_reply(asio::error_code const& e - , std::size_t bytes_transferred) -{ - using namespace libtorrent::detail; - if (e) return; - - try - { - - if (m_remote != m_nat_endpoint) - { - m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) - , m_remote, bind(&natpmp::on_reply, this, _1, _2)); - return; - } - - m_send_timer.cancel(); - - assert(m_currently_mapping >= 0); - int i = m_currently_mapping; - mapping& m = m_mappings[i]; - - char* in = m_response_buffer; - int version = read_uint8(in); - int cmd = read_uint8(in); - int result = read_uint16(in); - int time = read_uint32(in); - int private_port = read_uint16(in); - int public_port = read_uint16(in); - int lifetime = read_uint32(in); - - (void)time; // to remove warning - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << time_now_string() - << " <== port map response: " << (cmd - 128 == 1 ? "udp" : "tcp") - << " local: " << private_port << " external: " << public_port - << " ttl: " << lifetime << std::endl; -#endif - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - if (version != 0) - { - m_log << "*** unexpected version: " << version << std::endl; - } -#endif - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - if (private_port != m.local_port) - { - m_log << "*** unexpected local port: " << private_port << std::endl; - } -#endif - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - if (cmd != 128 + m.protocol) - { - m_log << "*** unexpected protocol: " << (cmd - 128) << std::endl; - } -#endif - - if (public_port == 0 || lifetime == 0) - { - // this means the mapping was - // successfully closed - m.local_port = 0; - } - else - { - m.expires = time_now() + seconds(int(lifetime * 0.7f)); - m.external_port = public_port; - } - - if (result != 0) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "*** ERROR: " << result << std::endl; -#endif - std::stringstream errmsg; - errmsg << "NAT router reports error (" << result << ") "; - switch (result) - { - case 1: errmsg << "Unsupported protocol version"; break; - case 2: errmsg << "Not authorized to create port map (enable NAT-PMP on your router)"; break; - case 3: errmsg << "Network failure"; break; - case 4: errmsg << "Out of resources"; break; - case 5: errmsg << "Unsupported opcode"; break; - } - throw std::runtime_error(errmsg.str()); - } - - // don't report when we remove mappings - if (m.local_port != 0) - { - int tcp_port = 0; - int udp_port = 0; - if (m.protocol == 1) udp_port = m.external_port; - else tcp_port = public_port; - m_callback(tcp_port, udp_port, ""); - } - } - catch (std::exception& e) - { - // try again in two hours - m_mappings[m_currently_mapping].expires = time_now() + hours(2); - m_callback(0, 0, e.what()); - } - int i = m_currently_mapping; - m_currently_mapping = -1; - m_mappings[i].need_update = false; - m_send_timer.cancel(); - update_expiration_timer(); - try_next_mapping(i); -} - -void natpmp::update_expiration_timer() -{ - ptime now = time_now(); - ptime min_expire = now + seconds(3600); - int min_index = -1; - for (int i = 0; i < num_mappings; ++i) - if (m_mappings[i].expires < min_expire - && m_mappings[i].local_port != 0) - { - min_expire = m_mappings[i].expires; - min_index = i; - } - - if (min_index >= 0) - { - m_refresh_timer.expires_from_now(min_expire - now); - m_refresh_timer.async_wait(bind(&natpmp::mapping_expired, this, _1, min_index)); - } -} - -void natpmp::mapping_expired(asio::error_code const& e, int i) -{ - if (e) return; -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "*** mapping " << i << " expired, updating" << std::endl; -#endif - refresh_mapping(i); -} - -void natpmp::refresh_mapping(int i) -{ - m_mappings[i].need_update = true; - if (m_currently_mapping == -1) - { - // the socket is not currently in use - // send out a mapping request - m_retry_count = 0; - send_map_request(i); - m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16) - , m_remote, bind(&natpmp::on_reply, this, _1, _2)); - } -} - -void natpmp::try_next_mapping(int i) -{ - ++i; - if (i >= num_mappings) i = 0; - if (m_mappings[i].need_update) - refresh_mapping(i); -} - -void natpmp::close() -{ - if (m_disabled) return; - for (int i = 0; i < num_mappings; ++i) - { - if (m_mappings[i].local_port == 0) - continue; - m_mappings[i].external_port = 0; - refresh_mapping(i); - } -} - diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp deleted file mode 100644 index 7ba83e889..000000000 --- a/libtorrent/src/peer_connection.cpp +++ /dev/null @@ -1,2566 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/file.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/socket_type.hpp" - -using boost::bind; -using boost::shared_ptr; -using libtorrent::aux::session_impl; - -namespace libtorrent -{ - - void intrusive_ptr_add_ref(peer_connection const* c) - { - assert(c->m_refs >= 0); - assert(c != 0); - ++c->m_refs; - } - - void intrusive_ptr_release(peer_connection const* c) - { - assert(c->m_refs > 0); - assert(c != 0); - if (--c->m_refs == 0) - delete c; - } - - // outbound connection - peer_connection::peer_connection( - session_impl& ses - , boost::weak_ptr tor - , shared_ptr s - , tcp::endpoint const& remote - , policy::peer* peerinfo) - : -#ifndef NDEBUG - m_last_choke(time_now() - hours(1)) - , -#endif - m_ses(ses) - , m_max_out_request_queue(m_ses.settings().max_out_request_queue) - , m_timeout(m_ses.settings().peer_timeout) - , m_last_piece(time_now()) - , m_packet_size(0) - , m_recv_pos(0) - , m_current_send_buffer(0) - , m_write_pos(0) - , m_last_receive(time_now()) - , m_last_sent(time_now()) - , m_socket(s) - , m_remote(remote) - , m_torrent(tor) - , m_active(true) - , m_peer_interested(false) - , m_peer_choked(true) - , m_interesting(false) - , m_choked(true) - , m_failed(false) - , m_ignore_bandwidth_limits(false) - , m_num_pieces(0) - , m_desired_queue_size(2) - , m_free_upload(0) - , m_trust_points(0) - , m_assume_fifo(false) - , m_num_invalid_requests(0) - , m_disconnecting(false) - , m_became_uninterested(time_now()) - , m_became_uninteresting(time_now()) - , m_connecting(true) - , m_queued(true) - , m_writing(false) - , m_reading(false) - , m_prefer_whole_pieces(false) - , m_on_parole(false) - , m_request_large_blocks(false) - , m_non_prioritized(false) - , m_refs(0) - , m_upload_limit(resource_request::inf) - , m_download_limit(resource_request::inf) - , m_peer_info(peerinfo) - , m_speed(slow) - , m_connection_ticket(-1) -#ifndef NDEBUG - , m_in_constructor(true) -#endif - { -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - std::fill(m_country, m_country + 2, 0); -#endif -#ifdef TORRENT_VERBOSE_LOGGING - m_logger = m_ses.create_log(m_remote.address().to_string() + "_" - + boost::lexical_cast(m_remote.port()), m_ses.listen_port()); - (*m_logger) << "*** OUTGOING CONNECTION\n"; -#endif - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - std::fill(m_peer_id.begin(), m_peer_id.end(), 0); - - if (t->ready_for_connections()) - init(); - } - - // incoming connection - peer_connection::peer_connection( - session_impl& ses - , boost::shared_ptr s - , policy::peer* peerinfo) - : -#ifndef NDEBUG - m_last_choke(time_now() - hours(1)) - , -#endif - m_ses(ses) - , m_max_out_request_queue(m_ses.settings().max_out_request_queue) - , m_timeout(m_ses.settings().peer_timeout) - , m_last_piece(time_now()) - , m_packet_size(0) - , m_recv_pos(0) - , m_current_send_buffer(0) - , m_write_pos(0) - , m_last_receive(time_now()) - , m_last_sent(time_now()) - , m_socket(s) - , m_active(false) - , m_peer_interested(false) - , m_peer_choked(true) - , m_interesting(false) - , m_choked(true) - , m_failed(false) - , m_ignore_bandwidth_limits(false) - , m_num_pieces(0) - , m_desired_queue_size(2) - , m_free_upload(0) - , m_trust_points(0) - , m_assume_fifo(false) - , m_num_invalid_requests(0) - , m_disconnecting(false) - , m_became_uninterested(time_now()) - , m_became_uninteresting(time_now()) - , m_connecting(false) - , m_queued(false) - , m_writing(false) - , m_reading(false) - , m_prefer_whole_pieces(false) - , m_on_parole(false) - , m_request_large_blocks(false) - , m_non_prioritized(false) - , m_refs(0) - , m_upload_limit(resource_request::inf) - , m_download_limit(resource_request::inf) - , m_peer_info(peerinfo) - , m_speed(slow) -#ifndef NDEBUG - , m_in_constructor(true) -#endif - { - tcp::socket::non_blocking_io ioc(true); - m_socket->io_control(ioc); -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - std::fill(m_country, m_country + 2, 0); -#endif - m_remote = m_socket->remote_endpoint(); - -#ifdef TORRENT_VERBOSE_LOGGING - assert(m_socket->remote_endpoint() == remote()); - m_logger = m_ses.create_log(remote().address().to_string() + "_" - + boost::lexical_cast(remote().port()), m_ses.listen_port()); - (*m_logger) << "*** INCOMING CONNECTION\n"; -#endif - - std::fill(m_peer_id.begin(), m_peer_id.end(), 0); - } - - void peer_connection::update_interest() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - bool interested = false; - const std::vector& we_have = t->pieces(); - for (int j = 0; j != (int)we_have.size(); ++j) - { - if (!we_have[j] - && t->piece_priority(j) > 0 - && m_have_piece[j]) - { - interested = true; - break; - } - } - try - { - if (!interested) - send_not_interested(); - else - t->get_policy().peer_is_interesting(*this); - } - // may throw an asio error if socket has disconnected - catch (std::exception& e) {} - - assert(is_interesting() == interested); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - void peer_connection::add_extension(boost::shared_ptr ext) - { - m_extensions.push_back(ext); - } -#endif - - void peer_connection::init() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - assert(t->valid_metadata()); - assert(t->ready_for_connections()); - - m_have_piece.resize(t->torrent_file().num_pieces(), false); - - // now that we have a piece_picker, - // update it with this peers pieces - - int num_pieces = std::count(m_have_piece.begin(), m_have_piece.end(), true); - if (num_pieces == int(m_have_piece.size())) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " *** THIS IS A SEED ***\n"; -#endif - // if this is a web seed. we don't have a peer_info struct - if (m_peer_info) m_peer_info->seed = true; - // if we're a seed too, disconnect - if (t->is_seed()) - { - throw std::runtime_error("seed to seed connection redundant, disconnecting"); - } - m_num_pieces = num_pieces; - t->peer_has_all(); - if (!t->is_finished()) - t->get_policy().peer_is_interesting(*this); - return; - } - - m_num_pieces = num_pieces; - // if we're a seed, we don't keep track of piece availability - if (!t->is_seed()) - { - bool interesting = false; - for (int i = 0; i < int(m_have_piece.size()); ++i) - { - if (m_have_piece[i]) - { - t->peer_has(i); - // if the peer has a piece and we don't, the peer is interesting - if (!t->have_piece(i) - && t->picker().piece_priority(i) != 0) - interesting = true; - } - } - if (interesting) - t->get_policy().peer_is_interesting(*this); - } - } - - peer_connection::~peer_connection() - { -// INVARIANT_CHECK; - assert(m_disconnecting); - -#ifdef TORRENT_VERBOSE_LOGGING - if (m_logger) - { - (*m_logger) << time_now_string() - << " *** CONNECTION CLOSED\n"; - } -#endif -#ifndef NDEBUG - if (m_peer_info) - assert(m_peer_info->connection == 0); - - boost::shared_ptr t = m_torrent.lock(); - if (t) assert(t->connection_for(remote()) != this); -#endif - } - - void peer_connection::announce_piece(int index) - { - // optimization, don't send have messages - // to peers that already have the piece - if (has_piece(index)) return; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> HAVE [ piece: " << index << "]\n"; -#endif - write_have(index); -#ifndef NDEBUG - boost::shared_ptr t = m_torrent.lock(); - assert(t); - assert(t->have_piece(index)); -#endif - } - - bool peer_connection::has_piece(int i) const - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - assert(t->valid_metadata()); - assert(i >= 0); - assert(i < t->torrent_file().num_pieces()); - return m_have_piece[i]; - } - - std::deque const& peer_connection::request_queue() const - { - return m_request_queue; - } - - std::deque const& peer_connection::download_queue() const - { - return m_download_queue; - } - - std::deque const& peer_connection::upload_queue() const - { - return m_requests; - } - - void peer_connection::add_stat(size_type downloaded, size_type uploaded) - { - INVARIANT_CHECK; - - m_statistics.add_stat(downloaded, uploaded); - } - - std::vector const& peer_connection::get_bitfield() const - { - return m_have_piece; - } - - void peer_connection::received_valid_data(int index) - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { (*i)->on_piece_pass(index); } catch (std::exception&) {} - } -#endif - - m_on_parole = false; - - m_trust_points++; - // TODO: make this limit user settable - if (m_trust_points > 20) m_trust_points = 20; - } - - void peer_connection::received_invalid_data(int index) - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { (*i)->on_piece_failed(index); } catch (std::exception&) {} - } -#endif - - m_on_parole = true; - - // we decrease more than we increase, to keep the - // allowed failed/passed ratio low. - // TODO: make this limit user settable - m_trust_points -= 2; - if (m_trust_points < -7) m_trust_points = -7; - } - - int peer_connection::trust_points() const - { - return m_trust_points; - } - - size_type peer_connection::total_free_upload() const - { - return m_free_upload; - } - - void peer_connection::add_free_upload(size_type free_upload) - { - INVARIANT_CHECK; - - m_free_upload += free_upload; - } - - // verifies a piece to see if it is valid (is within a valid range) - // and if it can correspond to a request generated by libtorrent. - bool peer_connection::verify_piece(const peer_request& p) const - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - assert(t->valid_metadata()); - - return p.piece >= 0 - && p.piece < t->torrent_file().num_pieces() - && p.length > 0 - && p.start >= 0 - && (p.length == t->block_size() - || (p.length < t->block_size() - && p.piece == t->torrent_file().num_pieces()-1 - && p.start + p.length == t->torrent_file().piece_size(p.piece)) - || (m_request_large_blocks - && p.length <= t->torrent_file().piece_size(p.piece))) - && p.start + p.length <= t->torrent_file().piece_size(p.piece) - && (p.start % t->block_size() == 0); - } - - struct disconnect_torrent - { - disconnect_torrent(boost::weak_ptr& t): m_t(&t) {} - ~disconnect_torrent() { if (m_t) m_t->reset(); } - void cancel() { m_t = 0; } - private: - boost::weak_ptr* m_t; - }; - - void peer_connection::attach_to_torrent(sha1_hash const& ih) - { - INVARIANT_CHECK; - - assert(!m_disconnecting); - m_torrent = m_ses.find_torrent(ih); - - boost::shared_ptr t = m_torrent.lock(); - - if (t && t->is_aborted()) - { - m_torrent.reset(); - t.reset(); - } - - if (!t) - { - // we couldn't find the torrent! -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " couldn't find a torrent with the given info_hash\n"; -#endif - throw std::runtime_error("got info-hash that is not in our session"); - } - - disconnect_torrent disconnect(m_torrent); - if (t->is_paused()) - { - // paused torrents will not accept - // incoming connections -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " rejected connection to paused torrent\n"; -#endif - throw std::runtime_error("connection rejected by paused torrent"); - } - - // check to make sure we don't have another connection with the same - // info_hash and peer_id. If we do. close this connection. - t->attach_peer(this); - - // if the torrent isn't ready to accept - // connections yet, we'll have to wait with - // our initialization - if (t->ready_for_connections()) init(); - - // assume the other end has no pieces - // if we don't have valid metadata yet, - // leave the vector unallocated - assert(m_num_pieces == 0); - std::fill(m_have_piece.begin(), m_have_piece.end(), false); - disconnect.cancel(); - } - - // message handlers - - // ----------------------------- - // --------- KEEPALIVE --------- - // ----------------------------- - - void peer_connection::incoming_keepalive() - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== KEEPALIVE\n"; -#endif - } - - // ----------------------------- - // ----------- CHOKE ----------- - // ----------------------------- - - void peer_connection::incoming_choke() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_choke()) return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== CHOKE\n"; -#endif - m_peer_choked = true; - t->get_policy().choked(*this); - - if (!t->is_seed()) - { - piece_picker& p = t->picker(); - // remove all pieces from this peers download queue and - // remove the 'downloading' flag from piece_picker. - for (std::deque::iterator i = m_download_queue.begin(); - i != m_download_queue.end(); ++i) - { - p.abort_download(*i); - } - for (std::deque::const_iterator i = m_request_queue.begin() - , end(m_request_queue.end()); i != end; ++i) - { - // since this piece was skipped, clear it and allow it to - // be requested from other peers - p.abort_download(*i); - } - } - - m_download_queue.clear(); - m_request_queue.clear(); - } - - // ----------------------------- - // ---------- UNCHOKE ---------- - // ----------------------------- - - void peer_connection::incoming_unchoke() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_unchoke()) return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== UNCHOKE\n"; -#endif - m_peer_choked = false; - t->get_policy().unchoked(*this); - } - - // ----------------------------- - // -------- INTERESTED --------- - // ----------------------------- - - void peer_connection::incoming_interested() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_interested()) return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== INTERESTED\n"; -#endif - m_peer_interested = true; - t->get_policy().interested(*this); - } - - // ----------------------------- - // ------ NOT INTERESTED ------- - // ----------------------------- - - void peer_connection::incoming_not_interested() - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_not_interested()) return; - } -#endif - - m_became_uninterested = time_now(); - - // clear the request queue if the client isn't interested - m_requests.clear(); -// setup_send(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== NOT_INTERESTED\n"; -#endif - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - m_peer_interested = false; - t->get_policy().not_interested(*this); - } - - // ----------------------------- - // ----------- HAVE ------------ - // ----------------------------- - - void peer_connection::incoming_have(int index) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_have(index)) return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== HAVE [ piece: " << index << "]\n"; -#endif - - // if we got an invalid message, abort - if (index >= (int)m_have_piece.size() || index < 0) - throw protocol_error("got 'have'-message with higher index " - "than the number of pieces"); - - if (m_have_piece[index]) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " got redundant HAVE message for index: " << index << "\n"; -#endif - } - else - { - m_have_piece[index] = true; - - // only update the piece_picker if - // we have the metadata and if - // we're not a seed (in which case - // we won't have a piece picker) - if (t->valid_metadata()) - { - ++m_num_pieces; - t->peer_has(index); - - if (!t->have_piece(index) - && !t->is_seed() - && !is_interesting() - && t->picker().piece_priority(index) != 0) - t->get_policy().peer_is_interesting(*this); - } - - if (is_seed()) - { - assert(m_peer_info); - m_peer_info->seed = true; - if (t->is_seed()) - { - throw protocol_error("seed to seed connection redundant, disconnecting"); - } - } - } - } - - // ----------------------------- - // --------- BITFIELD ---------- - // ----------------------------- - - void peer_connection::incoming_bitfield(std::vector const& bitfield) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_bitfield(bitfield)) return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " <== BITFIELD "; - - for (int i = 0; i < int(bitfield.size()); ++i) - { - if (bitfield[i]) (*m_logger) << "1"; - else (*m_logger) << "0"; - } - (*m_logger) << "\n"; -#endif - - // if we don't have the metedata, we cannot - // verify the bitfield size - if (t->valid_metadata() - && (bitfield.size() / 8) != (m_have_piece.size() / 8)) - throw protocol_error("got bitfield with invalid size: " - + boost::lexical_cast(bitfield.size() / 8) - + "bytes. expected: " - + boost::lexical_cast(m_have_piece.size() / 8) - + "bytes"); - - // if we don't have metadata yet - // just remember the bitmask - // don't update the piecepicker - // (since it doesn't exist yet) - if (!t->ready_for_connections()) - { - m_have_piece = bitfield; - m_num_pieces = std::count(bitfield.begin(), bitfield.end(), true); - - if (m_peer_info) m_peer_info->seed = true; - return; - } - - int num_pieces = std::count(bitfield.begin(), bitfield.end(), true); - if (num_pieces == int(m_have_piece.size())) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " *** THIS IS A SEED ***\n"; -#endif - // if this is a web seed. we don't have a peer_info struct - if (m_peer_info) m_peer_info->seed = true; - // if we're a seed too, disconnect - if (t->is_seed()) - { - throw protocol_error("seed to seed connection redundant, disconnecting"); - } - - std::fill(m_have_piece.begin(), m_have_piece.end(), true); - m_num_pieces = num_pieces; - t->peer_has_all(); - if (!t->is_finished()) - t->get_policy().peer_is_interesting(*this); - return; - } - - // let the torrent know which pieces the - // peer has - // if we're a seed, we don't keep track of piece availability - if (!t->is_seed()) - { - bool interesting = false; - for (int i = 0; i < (int)m_have_piece.size(); ++i) - { - bool have = bitfield[i]; - if (have && !m_have_piece[i]) - { - m_have_piece[i] = true; - ++m_num_pieces; - t->peer_has(i); - if (!t->have_piece(i) && t->picker().piece_priority(i) != 0) - interesting = true; - } - else if (!have && m_have_piece[i]) - { - // this should probably not be allowed - m_have_piece[i] = false; - --m_num_pieces; - t->peer_lost(i); - } - } - - if (interesting) t->get_policy().peer_is_interesting(*this); - } - else - { - for (int i = 0; i < (int)m_have_piece.size(); ++i) - { - bool have = bitfield[i]; - if (have && !m_have_piece[i]) - { - m_have_piece[i] = true; - ++m_num_pieces; - } - else if (!have && m_have_piece[i]) - { - // this should probably not be allowed - m_have_piece[i] = false; - --m_num_pieces; - } - } - } - } - - // ----------------------------- - // ---------- REQUEST ---------- - // ----------------------------- - - void peer_connection::incoming_request(peer_request const& r) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_request(r)) return; - } -#endif - - if (!t->valid_metadata()) - { - // if we don't have valid metadata yet, - // we shouldn't get a request -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== UNEXPECTED_REQUEST [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "i: " << m_peer_interested << " | " - "t: " << (int)t->torrent_file().piece_size(r.piece) << " | " - "n: " << t->torrent_file().num_pieces() << " ]\n"; -#endif - return; - } - - if (int(m_requests.size()) > m_ses.settings().max_allowed_in_request_queue) - { - // don't allow clients to abuse our - // memory consumption. - // ignore requests if the client - // is making too many of them. -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== TOO MANY REQUESTS [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "i: " << m_peer_interested << " | " - "t: " << (int)t->torrent_file().piece_size(r.piece) << " | " - "n: " << t->torrent_file().num_pieces() << " ]\n"; -#endif - return; - } - - // make sure this request - // is legal and that the peer - // is not choked - if (r.piece >= 0 - && r.piece < t->torrent_file().num_pieces() - && t->have_piece(r.piece) - && r.start >= 0 - && r.start < t->torrent_file().piece_size(r.piece) - && r.length > 0 - && r.length + r.start <= t->torrent_file().piece_size(r.piece) - && m_peer_interested) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== REQUEST [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n"; -#endif - // if we have choked the client - // ignore the request - if (m_choked) - return; - - m_requests.push_back(r); - fill_send_buffer(); - } - else - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== INVALID_REQUEST [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "i: " << m_peer_interested << " | " - "t: " << (int)t->torrent_file().piece_size(r.piece) << " | " - "n: " << t->torrent_file().num_pieces() << " | " - "h: " << t->have_piece(r.piece) << " ]\n"; -#endif - - ++m_num_invalid_requests; - - if (t->alerts().should_post(alert::debug)) - { - t->alerts().post_alert(invalid_request_alert( - r - , t->get_handle() - , m_remote - , m_peer_id - , "peer sent an illegal piece request, ignoring")); - } - } - } - - void peer_connection::incoming_piece_fragment() - { - m_last_piece = time_now(); - } - -#ifndef NDEBUG - struct check_postcondition - { - check_postcondition(boost::shared_ptr const& t_ - , bool init_check = true): t(t_) { if (init_check) check(); } - - ~check_postcondition() { check(); } - - void check() - { - if (!t->is_seed()) - { - const int blocks_per_piece = static_cast( - t->torrent_file().piece_length() / t->block_size()); - - std::vector const& dl_queue - = t->picker().get_download_queue(); - - for (std::vector::const_iterator i = - dl_queue.begin(); i != dl_queue.end(); ++i) - { - assert(i->finished < blocks_per_piece); - } - } - } - - shared_ptr t; - }; -#endif - - - // ----------------------------- - // ----------- PIECE ----------- - // ----------------------------- - - void peer_connection::incoming_piece(peer_request const& p, char const* data) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_piece(p, data)) return; - } -#endif - -#ifndef NDEBUG - check_postcondition post_checker_(t); - t->check_invariant(); -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== PIECE [ piece: " << p.piece << " | " - "s: " << p.start << " | " - "l: " << p.length << " | " - "ds: " << statistics().download_rate() << " | " - "qs: " << m_desired_queue_size << " ]\n"; -#endif - - if (!verify_piece(p)) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== INVALID_PIECE [ piece: " << p.piece << " | " - "start: " << p.start << " | " - "length: " << p.length << " ]\n"; -#endif - throw protocol_error("got invalid piece packet"); - } - - // if we're already seeding, don't bother, - // just ignore it - if (t->is_seed()) - { - t->received_redundant_data(p.length); - return; - } - - piece_picker& picker = t->picker(); - piece_manager& fs = t->filesystem(); - policy& pol = t->get_policy(); - - std::vector finished_blocks; - piece_block block_finished(p.piece, p.start / t->block_size()); - assert(p.start % t->block_size() == 0); - assert(p.length == t->block_size() - || p.length == t->torrent_file().total_size() % t->block_size()); - - std::deque::iterator b - = std::find( - m_download_queue.begin() - , m_download_queue.end() - , block_finished); - - // if there's another peer that needs to do another - // piece request, this will point to it - peer_connection* request_peer = 0; - - if (b != m_download_queue.end()) - { - if (m_assume_fifo) - { - for (std::deque::iterator i = m_download_queue.begin(); - i != b; ++i) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** SKIPPED_PIECE [ piece: " << i->piece_index << " | " - "b: " << i->block_index << " ] ***\n"; -#endif - // since this piece was skipped, clear it and allow it to - // be requested from other peers - // TODO: send cancel? - picker.abort_download(*i); - } - - // remove the request that just finished - // from the download queue plus the - // skipped blocks. - m_download_queue.erase(m_download_queue.begin() - , boost::next(b)); - } - else - { - m_download_queue.erase(b); - } - } - else - { - // cancel the block from the - // peer that has taken over it. - boost::optional peer - = t->picker().get_downloader(block_finished); - if (peer) - { - assert(!t->picker().is_finished(block_finished)); - peer_connection* pc = t->connection_for(*peer); - if (pc && pc != this) - { - pc->cancel_request(block_finished); - request_peer = pc; - } - } - else - { - if (t->alerts().should_post(alert::debug)) - { - t->alerts().post_alert( - peer_error_alert( - m_remote - , m_peer_id - , "got a block that was not requested")); - } -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << " *** The block we just got was not in the " - "request queue ***\n"; -#endif - } - } - - // if the block we got is already finished, then ignore it - if (picker.is_finished(block_finished)) - { - t->received_redundant_data(t->block_size()); - pol.block_finished(*this, block_finished); - send_block_requests(); - - if (request_peer && !request_peer->has_peer_choked() && !t->is_seed()) - { - request_a_block(*t, *request_peer); - request_peer->send_block_requests(); - } - return; - } - - fs.write(data, p.piece, p.start, p.length); - - picker.mark_as_finished(block_finished, m_remote); - - try - { - pol.block_finished(*this, block_finished); - send_block_requests(); - } - catch (std::exception const&) {} - - if (request_peer && !request_peer->has_peer_choked() && !t->is_seed()) - { - request_a_block(*t, *request_peer); - request_peer->send_block_requests(); - } - -#ifndef NDEBUG - try - { -#endif - - bool was_seed = t->is_seed(); - bool was_finished = picker.num_filtered() + t->num_pieces() - == t->torrent_file().num_pieces(); - - // did we just finish the piece? - if (picker.is_piece_finished(p.piece)) - { -#ifndef NDEBUG - check_postcondition post_checker2_(t, false); -#endif - bool verified = t->verify_piece(p.piece); - if (verified) - { - // the following call may cause picker to become invalid - // in case we just became a seed - t->announce_piece(p.piece); - assert(t->valid_metadata()); - // if we just became a seed, picker is now invalid, since it - // is deallocated by the torrent once it starts seeding - if (!was_finished - && (t->is_seed() - || picker.num_filtered() + t->num_pieces() - == t->torrent_file().num_pieces())) - { - // torrent finished - // i.e. all the pieces we're interested in have - // been downloaded. Release the files (they will open - // in read only mode if needed) - try { t->finished(); } - catch (std::exception& e) - { -#ifndef NDEBUG - std::cerr << e.what() << std::endl; - assert(false); -#endif - } - } - } - else - { - t->piece_failed(p.piece); - } - -#ifndef NDEBUG - try - { -#endif - - pol.piece_finished(p.piece, verified); - -#ifndef NDEBUG - } - catch (std::exception const& e) - { - std::cerr << e.what() << std::endl; - assert(false); - } -#endif - -#ifndef NDEBUG - try - { -#endif - - if (!was_seed && t->is_seed()) - { - assert(verified); - t->completed(); - } - -#ifndef NDEBUG - } - catch (std::exception const& e) - { - std::cerr << e.what() << std::endl; - assert(false); - } -#endif - - } - -#ifndef NDEBUG - } - catch (std::exception const& e) - { - std::cerr << e.what() << std::endl; - assert(false); - } -#endif - } - - // ----------------------------- - // ---------- CANCEL ----------- - // ----------------------------- - - void peer_connection::incoming_cancel(peer_request const& r) - { - INVARIANT_CHECK; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if ((*i)->on_cancel(r)) return; - } -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== CANCEL [ piece: " << r.piece << " | s: " << r.start << " | l: " << r.length << " ]\n"; -#endif - - std::deque::iterator i - = std::find(m_requests.begin(), m_requests.end(), r); - - if (i != m_requests.end()) - { - m_requests.erase(i); - } - else - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " *** GOT CANCEL NOT IN THE QUEUE\n"; -#endif - } - } - - // ----------------------------- - // --------- DHT PORT ---------- - // ----------------------------- - - void peer_connection::incoming_dht_port(int listen_port) - { - INVARIANT_CHECK; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " <== DHT_PORT [ p: " << listen_port << " ]\n"; -#endif -#ifndef TORRENT_DISABLE_DHT - m_ses.add_dht_node(udp::endpoint( - m_remote.address(), listen_port)); -#endif - } - - void peer_connection::add_request(piece_block const& block) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - assert(t->valid_metadata()); - assert(block.piece_index >= 0); - assert(block.piece_index < t->torrent_file().num_pieces()); - assert(block.block_index >= 0); - assert(block.block_index < t->torrent_file().piece_size(block.piece_index)); - assert(!t->picker().is_downloading(block)); - - piece_picker::piece_state_t state; - peer_speed_t speed = peer_speed(); - if (speed == fast) state = piece_picker::fast; - else if (speed == medium) state = piece_picker::medium; - else state = piece_picker::slow; - - t->picker().mark_as_downloading(block, m_remote, state); - - m_request_queue.push_back(block); - } - - void peer_connection::cancel_request(piece_block const& block) - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - assert(t->valid_metadata()); - - assert(block.piece_index >= 0); - assert(block.piece_index < t->torrent_file().num_pieces()); - assert(block.block_index >= 0); - assert(block.block_index < t->torrent_file().piece_size(block.piece_index)); - assert(t->picker().is_downloading(block)); - - t->picker().abort_download(block); - - std::deque::iterator it - = std::find(m_download_queue.begin(), m_download_queue.end(), block); - if (it == m_download_queue.end()) - { - it = std::find(m_request_queue.begin(), m_request_queue.end(), block); - assert(it != m_request_queue.end()); - if (it == m_request_queue.end()) return; - m_request_queue.erase(it); - // since we found it in the request queue, it means it hasn't been - // sent yet, so we don't have to send a cancel. - return; - } - else - { - m_download_queue.erase(it); - } - - int block_offset = block.block_index * t->block_size(); - int block_size - = std::min((int)t->torrent_file().piece_size(block.piece_index)-block_offset, - t->block_size()); - assert(block_size > 0); - assert(block_size <= t->block_size()); - - peer_request r; - r.piece = block.piece_index; - r.start = block_offset; - r.length = block_size; - - write_cancel(r); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> CANCEL [ piece: " << block.piece_index << " | s: " - << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n"; -#endif - } - - void peer_connection::send_choke() - { - INVARIANT_CHECK; - - if (m_choked) return; - write_choke(); - m_choked = true; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> CHOKE\n"; -#endif -#ifndef NDEBUG - m_last_choke = time_now(); -#endif - m_num_invalid_requests = 0; - m_requests.clear(); - } - - void peer_connection::send_unchoke() - { - INVARIANT_CHECK; - -#ifndef NDEBUG - // TODO: once the policy lowers the interval for optimistic - // unchoke, increase this value that interval - // this condition cannot be guaranteed since if peers disconnect - // a new one will be unchoked ignoring when it was last choked - //assert(time_now() - m_last_choke > seconds(9)); -#endif - - if (!m_choked) return; - write_unchoke(); - m_choked = false; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> UNCHOKE\n"; -#endif - } - - void peer_connection::send_interested() - { - INVARIANT_CHECK; - - if (m_interesting) return; - write_interested(); - m_interesting = true; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> INTERESTED\n"; -#endif - } - - void peer_connection::send_not_interested() - { - INVARIANT_CHECK; - - if (!m_interesting) return; - write_not_interested(); - m_interesting = false; - - m_became_uninteresting = time_now(); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() << " ==> NOT_INTERESTED\n"; -#endif - } - - void peer_connection::send_block_requests() - { - INVARIANT_CHECK; - - if (has_peer_choked()) return; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - assert(!has_peer_choked()); - - if ((int)m_download_queue.size() >= m_desired_queue_size) return; - - while (!m_request_queue.empty() - && (int)m_download_queue.size() < m_desired_queue_size) - { - piece_block block = m_request_queue.front(); - - int block_offset = block.block_index * t->block_size(); - int block_size = std::min((int)t->torrent_file().piece_size( - block.piece_index) - block_offset, t->block_size()); - assert(block_size > 0); - assert(block_size <= t->block_size()); - - peer_request r; - r.piece = block.piece_index; - r.start = block_offset; - r.length = block_size; - - m_request_queue.pop_front(); - m_download_queue.push_back(block); -/* -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** REQUEST-QUEUE** [ " - "piece: " << block.piece_index << " | " - "block: " << block.block_index << " ]\n"; -#endif -*/ - // if we are requesting large blocks, merge the smaller - // blocks that are in the same piece into larger requests - if (m_request_large_blocks) - { - while (!m_request_queue.empty() - && m_request_queue.front().piece_index == r.piece - && m_request_queue.front().block_index == block.block_index + 1) - { - block = m_request_queue.front(); - m_request_queue.pop_front(); - m_download_queue.push_back(block); -/* -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** REQUEST-QUEUE** [ " - "piece: " << block.piece_index << " | " - "block: " << block.block_index << " ]\n"; -#endif -*/ - block_offset = block.block_index * t->block_size(); - block_size = std::min((int)t->torrent_file().piece_size( - block.piece_index) - block_offset, t->block_size()); - assert(block_size > 0); - assert(block_size <= t->block_size()); - - r.length += block_size; - } - } - - assert(verify_piece(r)); - -#ifndef TORRENT_DISABLE_EXTENSIONS - bool handled = false; - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - if (handled = (*i)->write_request(r)) break; - } - if (!handled) write_request(r); -#else - write_request(r); -#endif - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> REQUEST [ " - "piece: " << r.piece << " | " - "s: " << r.start << " | " - "l: " << r.length << " | " - "ds: " << statistics().download_rate() << " B/s | " - "qs: " << m_desired_queue_size << " ]\n"; -#endif - } - m_last_piece = time_now(); - } - - - void close_socket_ignore_error(boost::shared_ptr s) - { - try { s->close(); } catch (std::exception& e) {} - } - - void peer_connection::timed_out() - { - if (m_peer_info) ++m_peer_info->failcount; -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "CONNECTION TIMED OUT: " << m_remote.address().to_string() - << "\n"; -#endif - m_ses.connection_failed(m_socket, m_remote, "timed out"); - } - - void peer_connection::disconnect() - { - boost::intrusive_ptr me(this); - - INVARIANT_CHECK; - - if (m_disconnecting) return; - m_disconnecting = true; - if (m_connecting) - m_ses.m_half_open.done(m_connection_ticket); - - m_ses.m_io_service.post(boost::bind(&close_socket_ignore_error, m_socket)); - - boost::shared_ptr t = m_torrent.lock(); - - if (t) - { - if (t->has_picker()) - { - piece_picker& picker = t->picker(); - - while (!m_download_queue.empty()) - { - picker.abort_download(m_download_queue.back()); - m_download_queue.pop_back(); - } - while (!m_request_queue.empty()) - { - picker.abort_download(m_request_queue.back()); - m_request_queue.pop_back(); - } - } - - t->remove_peer(this); - - m_torrent.reset(); - } - - m_ses.close_connection(me); - } - - void peer_connection::set_upload_limit(int limit) - { - assert(limit >= -1); - if (limit == -1) limit = resource_request::inf; - if (limit < 10) limit = 10; - m_upload_limit = limit; - m_bandwidth_limit[upload_channel].throttle(m_upload_limit); - } - - void peer_connection::set_download_limit(int limit) - { - assert(limit >= -1); - if (limit == -1) limit = resource_request::inf; - if (limit < 10) limit = 10; - m_download_limit = limit; - m_bandwidth_limit[download_channel].throttle(m_download_limit); - } - - size_type peer_connection::share_diff() const - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - float ratio = t->ratio(); - - // if we have an infinite ratio, just say we have downloaded - // much more than we have uploaded. And we'll keep uploading. - if (ratio == 0.f) - return std::numeric_limits::max(); - - return m_free_upload - + static_cast(m_statistics.total_payload_download() * ratio) - - m_statistics.total_payload_upload(); - } - - // defined in upnp.cpp - bool is_local(address const& a); - - bool peer_connection::on_local_network() const - { - if (libtorrent::is_local(m_remote.address())) return true; - return false; - } - - - void peer_connection::cut_receive_buffer(int size, int packet_size) - { - INVARIANT_CHECK; - - assert(packet_size > 0); - assert(int(m_recv_buffer.size()) >= size); - assert(int(m_recv_buffer.size()) >= m_recv_pos); - assert(m_recv_pos >= size); - - std::memmove(&m_recv_buffer[0], &m_recv_buffer[0] + size, m_recv_pos - size); - - m_recv_pos -= size; - -#ifndef NDEBUG - std::fill(m_recv_buffer.begin() + m_recv_pos, m_recv_buffer.end(), 0); -#endif - - m_packet_size = packet_size; - if (m_packet_size >= m_recv_pos) m_recv_buffer.resize(m_packet_size); - } - - void peer_connection::second_tick(float tick_interval) - { - INVARIANT_CHECK; - - ptime now(time_now()); - - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - on_tick(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - (*i)->tick(); - } -#endif - - m_ignore_bandwidth_limits = m_ses.settings().ignore_limits_on_local_network - && on_local_network(); - - m_statistics.second_tick(tick_interval); - - if (!t->valid_metadata()) return; - - // calculate the desired download queue size - const float queue_time = m_ses.settings().request_queue_time; - // (if the latency is more than this, the download will stall) - // so, the queue size is queue_time * down_rate / 16 kiB - // (16 kB is the size of each request) - // the minimum number of requests is 2 and the maximum is 48 - // the block size doesn't have to be 16. So we first query the - // torrent for it - const int block_size = m_request_large_blocks - ? t->torrent_file().piece_length() : t->block_size(); - assert(block_size > 0); - - m_desired_queue_size = static_cast(queue_time - * statistics().download_rate() / block_size); - if (m_desired_queue_size > m_max_out_request_queue) - m_desired_queue_size = m_max_out_request_queue; - if (m_desired_queue_size < min_request_queue) - m_desired_queue_size = min_request_queue; - - if (!m_download_queue.empty() - && now - m_last_piece > seconds(m_ses.settings().piece_timeout)) - { - // this peer isn't sending the pieces we've - // requested (this has been observed by BitComet) - // in this case we'll clear our download queue and - // re-request the blocks. -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** PIECE_REQUESTS TIMED OUT [ " << (int)m_download_queue.size() - << " " << total_seconds(now - m_last_piece) << "] ***\n"; -#endif - - if (t->is_seed()) - { - m_download_queue.clear(); - m_request_queue.clear(); - } - else - { - piece_picker& picker = t->picker(); - while (!m_download_queue.empty()) - { - picker.abort_download(m_download_queue.back()); - m_download_queue.pop_back(); - } - while (!m_request_queue.empty()) - { - picker.abort_download(m_request_queue.back()); - m_request_queue.pop_back(); - } - - // TODO: If we have a limited number of upload - // slots, choke this peer - - m_assume_fifo = true; - - request_a_block(*t, *this); - send_block_requests(); - } - } - - // If the client sends more data - // we send it data faster, otherwise, slower. - // It will also depend on how much data the - // client has sent us. This is the mean to - // maintain the share ratio given by m_ratio - // with all peers. - - if (t->is_seed() || is_choked() || t->ratio() == 0.0f) - { - // if we have downloaded more than one piece more - // than we have uploaded OR if we are a seed - // have an unlimited upload rate - m_bandwidth_limit[upload_channel].throttle(m_upload_limit); - } - else - { - size_type bias = 0x10000 + 2 * t->block_size() + m_free_upload; - - double break_even_time = 15; // seconds. - size_type have_uploaded = m_statistics.total_payload_upload(); - size_type have_downloaded = m_statistics.total_payload_download(); - double download_speed = m_statistics.download_rate(); - - size_type soon_downloaded = - have_downloaded + (size_type)(download_speed * break_even_time*1.5); - - if (t->ratio() != 1.f) - soon_downloaded = (size_type)(soon_downloaded*(double)t->ratio()); - - double upload_speed_limit = std::min((soon_downloaded - have_uploaded - + bias) / break_even_time, double(m_upload_limit)); - - upload_speed_limit = std::min(upload_speed_limit, - (double)std::numeric_limits::max()); - - m_bandwidth_limit[upload_channel].throttle( - std::min(std::max((int)upload_speed_limit, 20) - , m_upload_limit)); - } - - fill_send_buffer(); -/* - size_type diff = share_diff(); - - enum { block_limit = 2 }; // how many blocks difference is considered unfair - - // if the peer has been choked, send the current piece - // as fast as possible - if (diff > block_limit*m_torrent->block_size() || m_torrent->is_seed() || is_choked()) - { - // if we have downloaded more than one piece more - // than we have uploaded OR if we are a seed - // have an unlimited upload rate - m_ul_bandwidth_quota.wanted = std::numeric_limits::max(); - } - else - { - float ratio = m_torrent->ratio(); - // if we have downloaded too much, response with an - // upload rate of 10 kB/s more than we dowlload - // if we have uploaded too much, send with a rate of - // 10 kB/s less than we receive - int bias = 0; - if (diff > -block_limit*m_torrent->block_size()) - { - bias = static_cast(m_statistics.download_rate() * ratio) / 2; - if (bias < 10*1024) bias = 10*1024; - } - else - { - bias = -static_cast(m_statistics.download_rate() * ratio) / 2; - } - m_ul_bandwidth_quota.wanted = static_cast(m_statistics.download_rate()) + bias; - - // the maximum send_quota given our download rate from this peer - if (m_ul_bandwidth_quota.wanted < 256) m_ul_bandwidth_quota.wanted = 256; - } -*/ - } - - void peer_connection::fill_send_buffer() - { - INVARIANT_CHECK; - - boost::shared_ptr t = m_torrent.lock(); - if (!t) return; - - // only add new piece-chunks if the send buffer is small enough - // otherwise there will be no end to how large it will be! - - int buffer_size_watermark = int(m_statistics.upload_rate()) / 2; - if (buffer_size_watermark < 1024) buffer_size_watermark = 1024; - else if (buffer_size_watermark > 80 * 1024) buffer_size_watermark = 80 * 1024; - - while (!m_requests.empty() - && (send_buffer_size() < buffer_size_watermark) - && !m_choked) - { - assert(t->valid_metadata()); - peer_request& r = m_requests.front(); - - assert(r.piece >= 0); - assert(r.piece < (int)m_have_piece.size()); - assert(t->have_piece(r.piece)); - assert(r.start + r.length <= t->torrent_file().piece_size(r.piece)); - assert(r.length > 0 && r.start >= 0); - - write_piece(r); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " ==> PIECE [ piece: " << r.piece << " | s: " << r.start - << " | l: " << r.length << " ]\n"; -#endif - - m_requests.erase(m_requests.begin()); - - if (m_requests.empty() - && m_num_invalid_requests > 0 - && is_peer_interested() - && !is_seed()) - { - // this will make the peer clear - // its download queue and re-request - // pieces. Hopefully it will not - // send invalid requests then - send_choke(); - send_unchoke(); - } - } - } - - void peer_connection::assign_bandwidth(int channel, int amount) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "bandwidth [ " << channel << " ] + " << amount << "\n"; -#endif - - m_bandwidth_limit[channel].assign(amount); - if (channel == upload_channel) - { - m_writing = false; - setup_send(); - } - else if (channel == download_channel) - { - m_reading = false; - setup_receive(); - } - } - - void peer_connection::expire_bandwidth(int channel, int amount) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - m_bandwidth_limit[channel].expire(amount); - if (channel == upload_channel) - { - setup_send(); - } - else if (channel == download_channel) - { - setup_receive(); - } - } - - void peer_connection::setup_send() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (m_writing) return; - - shared_ptr t = m_torrent.lock(); - - if (m_bandwidth_limit[upload_channel].quota_left() == 0 - && (!m_send_buffer[m_current_send_buffer].empty() - || !m_send_buffer[(m_current_send_buffer + 1) & 1].empty()) - && !m_connecting - && t - && !m_ignore_bandwidth_limits) - { - // in this case, we have data to send, but no - // bandwidth. So, we simply request bandwidth - // from the torrent - assert(t); - if (m_bandwidth_limit[upload_channel].max_assignable() > 0) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "req bandwidth [ " << upload_channel << " ]\n"; -#endif - - // peers that we are not interested in are non-prioritized - t->request_bandwidth(upload_channel, self() - , !(is_interesting() && !has_peer_choked())); - m_writing = true; - } - return; - } - - if (!can_write()) return; - - assert(!m_writing); - - int sending_buffer = (m_current_send_buffer + 1) & 1; - if (m_send_buffer[sending_buffer].empty()) - { - // this means we have to swap buffer, because there's no - // previous buffer we're still waiting for. - std::swap(m_current_send_buffer, sending_buffer); - m_write_pos = 0; - } - - // send the actual buffer - if (!m_send_buffer[sending_buffer].empty()) - { - int amount_to_send = (int)m_send_buffer[sending_buffer].size() - m_write_pos; - int quota_left = m_bandwidth_limit[upload_channel].quota_left(); - if (!m_ignore_bandwidth_limits && amount_to_send > quota_left) - amount_to_send = quota_left; - - assert(amount_to_send > 0); - - assert(m_write_pos < (int)m_send_buffer[sending_buffer].size()); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "async_write " << amount_to_send << " bytes\n"; -#endif - m_socket->async_write_some(asio::buffer( - &m_send_buffer[sending_buffer][m_write_pos], amount_to_send) - , bind(&peer_connection::on_send_data, self(), _1, _2)); - - m_writing = true; - } - } - - void peer_connection::setup_receive() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (m_reading) return; - - shared_ptr t = m_torrent.lock(); - - if (m_bandwidth_limit[download_channel].quota_left() == 0 - && !m_connecting - && t - && !m_ignore_bandwidth_limits) - { - if (m_bandwidth_limit[download_channel].max_assignable() > 0) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "req bandwidth [ " << download_channel << " ]\n"; -#endif - t->request_bandwidth(download_channel, self(), m_non_prioritized); - m_reading = true; - } - return; - } - - if (!can_read()) return; - - assert(m_packet_size > 0); - int max_receive = m_packet_size - m_recv_pos; - int quota_left = m_bandwidth_limit[download_channel].quota_left(); - if (!m_ignore_bandwidth_limits && max_receive > quota_left) - max_receive = quota_left; - - assert(max_receive > 0); - - assert(m_recv_pos >= 0); - assert(m_packet_size > 0); - assert(max_receive > 0); - - assert(can_read()); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "async_read " << max_receive << " bytes\n"; -#endif - m_socket->async_read_some(asio::buffer(&m_recv_buffer[m_recv_pos] - , max_receive), bind(&peer_connection::on_receive_data, self(), _1, _2)); - m_reading = true; - } - - void peer_connection::reset_recv_buffer(int packet_size) - { - assert(packet_size > 0); - if (m_recv_pos > m_packet_size) - { - cut_receive_buffer(m_packet_size, packet_size); - return; - } - m_recv_pos = 0; - m_packet_size = packet_size; - if (int(m_recv_buffer.size()) < m_packet_size) - m_recv_buffer.resize(m_packet_size); - } - - void peer_connection::send_buffer(char const* begin, char const* end) - { - std::vector& buf = m_send_buffer[m_current_send_buffer]; - buf.insert(buf.end(), begin, end); - setup_send(); - } - -// TODO: change this interface to automatically call setup_send() when the -// return value is destructed - buffer::interval peer_connection::allocate_send_buffer(int size) - { - std::vector& buf = m_send_buffer[m_current_send_buffer]; - buf.resize(buf.size() + size); - buffer::interval ret(&buf[0] + buf.size() - size, &buf[0] + buf.size()); - return ret; - } - - template - struct set_to_zero - { - set_to_zero(T& v, bool cond): m_val(v), m_cond(cond) {} - void fire() { if (!m_cond) return; m_cond = false; m_val = 0; } - ~set_to_zero() { if (m_cond) m_val = 0; } - private: - T& m_val; - bool m_cond; - }; - - // -------------------------- - // RECEIVE DATA - // -------------------------- - - // throws exception when the client should be disconnected - void peer_connection::on_receive_data(const asio::error_code& error - , std::size_t bytes_transferred) try - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - assert(m_reading); - m_reading = false; - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "read " << bytes_transferred << " bytes\n"; -#endif - - if (error) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "**ERROR**: " << error.message() << "\n"; -#endif - on_receive(error, bytes_transferred); - throw std::runtime_error(error.message()); - } - - do - { - // correct the dl quota usage, if not all of the buffer was actually read - if (!m_ignore_bandwidth_limits) - m_bandwidth_limit[download_channel].use_quota(bytes_transferred); - - if (m_disconnecting) return; - - assert(m_packet_size > 0); - assert(bytes_transferred > 0); - - m_last_receive = time_now(); - m_recv_pos += bytes_transferred; - assert(m_recv_pos <= int(m_recv_buffer.size())); - - { - INVARIANT_CHECK; - on_receive(error, bytes_transferred); - } - - assert(m_packet_size > 0); - - if (m_peer_choked - && m_recv_pos == 0 - && (m_recv_buffer.capacity() - m_packet_size) > 128) - { - std::vector(m_packet_size).swap(m_recv_buffer); - } - - int max_receive = m_packet_size - m_recv_pos; - int quota_left = m_bandwidth_limit[download_channel].quota_left(); - if (!m_ignore_bandwidth_limits && max_receive > quota_left) - max_receive = quota_left; - - if (max_receive == 0) break; - - asio::error_code ec; - bytes_transferred = m_socket->read_some(asio::buffer(&m_recv_buffer[m_recv_pos] - , max_receive), ec); - if (ec && ec != asio::error::would_block) - throw asio::system_error(ec); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "read_some " << bytes_transferred << " bytes\n"; -#endif - } - while (bytes_transferred > 0); - - setup_receive(); - } - catch (file_error& e) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - boost::shared_ptr t = m_torrent.lock(); - if (!t) - { - m_ses.connection_failed(m_socket, remote(), e.what()); - return; - } - - if (t->alerts().should_post(alert::fatal)) - { - t->alerts().post_alert( - file_error_alert(t->get_handle() - , std::string("torrent paused: ") + e.what())); - } - t->pause(); - } - catch (std::exception& e) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(m_socket, remote(), e.what()); - } - catch (...) - { - // all exceptions should derive from std::exception - assert(false); - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(m_socket, remote(), "connection failed for unkown reason"); - } - - bool peer_connection::can_write() const - { - INVARIANT_CHECK; - - // if we have requests or pending data to be sent or announcements to be made - // we want to send data - return (!m_send_buffer[m_current_send_buffer].empty() - || !m_send_buffer[(m_current_send_buffer + 1) & 1].empty()) - && (m_bandwidth_limit[upload_channel].quota_left() > 0 - || m_ignore_bandwidth_limits) - && !m_connecting; - } - - bool peer_connection::can_read() const - { - INVARIANT_CHECK; - - return (m_bandwidth_limit[download_channel].quota_left() > 0 - || m_ignore_bandwidth_limits) - && !m_connecting; - } - - void peer_connection::connect(int ticket) - { - INVARIANT_CHECK; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "CONNECTING: " << m_remote.address().to_string() - << ":" << m_remote.port() << "\n"; -#endif - - m_connection_ticket = ticket; - boost::shared_ptr t = m_torrent.lock(); - assert(t); - - m_queued = false; - assert(m_connecting); - m_socket->open(t->get_interface().protocol()); - - // set the socket to non-blocking, so that we can - // read the entire buffer on each read event we get - tcp::socket::non_blocking_io ioc(true); - m_socket->io_control(ioc); - m_socket->bind(t->get_interface()); - m_socket->async_connect(m_remote - , bind(&peer_connection::on_connection_complete, self(), _1)); - - if (t->alerts().should_post(alert::debug)) - { - t->alerts().post_alert(peer_error_alert( - m_remote, m_peer_id, "connecting to peer")); - } - } - - void peer_connection::on_connection_complete(asio::error_code const& e) try - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (m_disconnecting) return; - - m_connecting = false; - m_ses.m_half_open.done(m_connection_ticket); - - if (e) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "CONNECTION FAILED: " << m_remote.address().to_string() - << ": " << e.message() << "\n"; -#endif - m_ses.connection_failed(m_socket, m_remote, e.message().c_str()); - return; - } - - if (m_disconnecting) return; - m_last_receive = time_now(); - - // this means the connection just succeeded - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "COMPLETED: " << m_remote.address().to_string() << "\n"; -#endif - - on_connected(); - setup_send(); - setup_receive(); - } - catch (std::exception& ex) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(m_socket, remote(), ex.what()); - } - catch (...) - { - // all exceptions should derive from std::exception - assert(false); - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(m_socket, remote(), "connection failed for unkown reason"); - } - - // -------------------------- - // SEND DATA - // -------------------------- - - // throws exception when the client should be disconnected - void peer_connection::on_send_data(asio::error_code const& error - , std::size_t bytes_transferred) try - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - assert(m_writing); - m_writing = false; - - if (!m_ignore_bandwidth_limits) - m_bandwidth_limit[upload_channel].use_quota(bytes_transferred); - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "wrote " << bytes_transferred << " bytes\n"; -#endif - - m_write_pos += bytes_transferred; - - if (error) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "**ERROR**: " << error.message() << "\n"; -#endif - throw std::runtime_error(error.message()); - } - if (m_disconnecting) return; - - assert(!m_connecting); - assert(bytes_transferred > 0); - - int sending_buffer = (m_current_send_buffer + 1) & 1; - - assert(int(m_send_buffer[sending_buffer].size()) >= m_write_pos); - if (int(m_send_buffer[sending_buffer].size()) == m_write_pos) - { - m_send_buffer[sending_buffer].clear(); - m_write_pos = 0; - } - - m_last_sent = time_now(); - - on_sent(error, bytes_transferred); - fill_send_buffer(); - - if (m_choked) - { - for (int i = 0; i < 2; ++i) - { - if (int(m_send_buffer[i].size()) < 64 - && int(m_send_buffer[i].capacity()) > 128) - { - std::vector tmp(m_send_buffer[i]); - tmp.swap(m_send_buffer[i]); - assert(m_send_buffer[i].capacity() == m_send_buffer[i].size()); - } - } - } - - setup_send(); - } - catch (std::exception& e) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(m_socket, remote(), e.what()); - } - catch (...) - { - // all exceptions should derive from std::exception - assert(false); - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.connection_failed(m_socket, remote(), "connection failed for unkown reason"); - } - - -#ifndef NDEBUG - void peer_connection::check_invariant() const - { - if (m_peer_info) - assert(m_peer_info->connection == this - || m_peer_info->connection == 0); - - boost::shared_ptr t = m_torrent.lock(); - if (!t) - { - typedef session_impl::torrent_map torrent_map; - torrent_map& m = m_ses.m_torrents; - for (torrent_map::iterator i = m.begin(), end(m.end()); i != end; ++i) - { - torrent& t = *i->second; - assert(t.connection_for(m_remote) != this); - } - return; - } - - if (!m_in_constructor && t->connection_for(remote()) != this - && !m_ses.settings().allow_multiple_connections_per_ip) - { - assert(false); - } - -// expensive when using checked iterators -/* - if (t->valid_metadata()) - { - int piece_count = std::count(m_have_piece.begin() - , m_have_piece.end(), true); - if (m_num_pieces != piece_count) - { - assert(false); - } - } -*/ - assert(m_write_pos <= int(m_send_buffer[ - (m_current_send_buffer + 1) & 1].size())); - -// extremely expensive invariant check -/* - if (!t->is_seed()) - { - piece_picker& p = t->picker(); - const std::vector& dlq = p.get_download_queue(); - const int blocks_per_piece = static_cast( - t->torrent_file().piece_length() / t->block_size()); - - for (std::vector::const_iterator i = - dlq.begin(); i != dlq.end(); ++i) - { - for (int j = 0; j < blocks_per_piece; ++j) - { - if (std::find(m_request_queue.begin(), m_request_queue.end() - , piece_block(i->index, j)) != m_request_queue.end() - || - std::find(m_download_queue.begin(), m_download_queue.end() - , piece_block(i->index, j)) != m_download_queue.end()) - { - assert(i->info[j].peer == m_remote); - } - else - { - assert(i->info[j].peer != m_remote || i->info[j].finished); - } - } - } - } -*/ - } -#endif - - bool peer_connection::has_timed_out() const - { - // TODO: the timeout should be called by an event - INVARIANT_CHECK; - -#ifndef NDEBUG - // allow step debugging without timing out - return false; -#endif - - ptime now(time_now()); - - // if the socket is still connecting, don't - // consider it timed out. Because Windows XP SP2 - // may delay connection attempts. - if (m_connecting) return false; - - // if the peer hasn't said a thing for a certain - // time, it is considered to have timed out - time_duration d; - d = time_now() - m_last_receive; - if (d > seconds(m_timeout)) return true; - - // if the peer hasn't become interested and we haven't - // become interested in the peer for 10 minutes, it - // has also timed out. - time_duration d1; - time_duration d2; - d1 = now - m_became_uninterested; - d2 = now - m_became_uninteresting; - // TODO: these timeouts should be user settable - if (!m_interesting - && !m_peer_interested - && d1 > minutes(10) - && d2 > minutes(10)) - { - return true; - } - - return false; - } - - peer_connection::peer_speed_t peer_connection::peer_speed() - { - shared_ptr t = m_torrent.lock(); - assert(t); - - int download_rate = int(statistics().download_payload_rate()); - int torrent_download_rate = int(t->statistics().download_payload_rate()); - - if (download_rate > 512 && download_rate > torrent_download_rate / 16) - m_speed = fast; - else if (download_rate > 4096 && download_rate > torrent_download_rate / 64) - m_speed = medium; - else if (download_rate < torrent_download_rate / 15 && m_speed == fast) - m_speed = medium; - else if (download_rate < torrent_download_rate / 63 && m_speed == medium) - m_speed = slow; - - return m_speed; - } - - void peer_connection::keep_alive() - { - INVARIANT_CHECK; - - time_duration d; - d = time_now() - m_last_sent; - if (total_seconds(d) < m_timeout / 2) return; - - if (m_connecting) return; - - write_keepalive(); - } - - bool peer_connection::is_seed() const - { - INVARIANT_CHECK; - // if m_num_pieces == 0, we probably doesn't have the - // metadata yet. - return m_num_pieces == (int)m_have_piece.size() && m_num_pieces > 0; - } -} - diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp deleted file mode 100644 index cf6eb4a0e..000000000 --- a/libtorrent/src/piece_picker.cpp +++ /dev/null @@ -1,1446 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include - -// non-standard header, is_sorted() -//#include - -#include "libtorrent/piece_picker.hpp" -#include "libtorrent/aux_/session_impl.hpp" - -#ifndef NDEBUG -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/torrent.hpp" -#endif - -#define TORRENT_PIECE_PICKER_INVARIANT_CHECK INVARIANT_CHECK -//#define TORRENT_PIECE_PICKER_INVARIANT_CHECK - -namespace libtorrent -{ - - piece_picker::piece_picker(int blocks_per_piece, int total_num_blocks) - : m_piece_info(2) - , m_piece_map((total_num_blocks + blocks_per_piece-1) / blocks_per_piece) - , m_num_filtered(0) - , m_num_have_filtered(0) - , m_num_have(0) - , m_sequenced_download_threshold(100) - { - assert(blocks_per_piece > 0); - assert(total_num_blocks >= 0); -#ifndef NDEBUG - m_files_checked_called = false; -#endif - - // the piece index is stored in 20 bits, which limits the allowed - // number of pieces somewhat - if (m_piece_map.size() >= piece_pos::we_have_index) - throw std::runtime_error("too many pieces in torrent"); - - m_blocks_per_piece = blocks_per_piece; - m_blocks_in_last_piece = total_num_blocks % blocks_per_piece; - if (m_blocks_in_last_piece == 0) m_blocks_in_last_piece = blocks_per_piece; - - assert(m_blocks_in_last_piece <= m_blocks_per_piece); - - // allocate the piece_map to cover all pieces - // and make them invalid (as if though we already had every piece) - std::fill(m_piece_map.begin(), m_piece_map.end() - , piece_pos(0, piece_pos::we_have_index)); - m_num_have = m_piece_map.size(); - } - - // pieces is a bitmask with the pieces we have - void piece_picker::files_checked( - const std::vector& pieces - , const std::vector& unfinished) - { -#ifndef NDEBUG - m_files_checked_called = true; -#endif - for (std::vector::const_iterator i = pieces.begin(); - i != pieces.end(); ++i) - { - if (*i) continue; - int index = static_cast(i - pieces.begin()); - m_piece_map[index].index = 0; - --m_num_have; - if (m_piece_map[index].filtered()) - { - ++m_num_filtered; - --m_num_have_filtered; - } - } - - // if we have fast resume info - // use it - if (!unfinished.empty()) - { - for (std::vector::const_iterator i - = unfinished.begin(); i != unfinished.end(); ++i) - { - tcp::endpoint peer; - for (int j = 0; j < m_blocks_per_piece; ++j) - { - if (i->info[j].finished) - mark_as_finished(piece_block(i->index, j), peer); - } - if (is_piece_finished(i->index)) - { - // TODO: handle this case by verifying the - // piece and either accept it or discard it - assert(false); - } - } - } - } - - void piece_picker::set_sequenced_download_threshold( - int sequenced_download_threshold) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - if (sequenced_download_threshold == m_sequenced_download_threshold) - return; - - assert(sequenced_download_threshold > 0); - - int old_limit = m_sequenced_download_threshold; - m_sequenced_download_threshold = sequenced_download_threshold; - - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - if (i->priority(old_limit) != i->priority(m_sequenced_download_threshold)) - { - piece_pos& p = *i; - int prev_priority = p.priority(old_limit); - if (prev_priority == 0) continue; - move(prev_priority, p.index); - } - } - - typedef std::vector info_t; - - if (old_limit < sequenced_download_threshold) - { - // the threshold was incremented, in case - // the previous max availability was reached - // we need to shuffle that bucket, if not, we - // don't have to do anything - if (int(m_piece_info.size()) > old_limit) - { - info_t& in = m_piece_info[old_limit]; - std::random_shuffle(in.begin(), in.end()); - int c = 0; - for (info_t::iterator i = in.begin() - , end(in.end()); i != end; ++i) - { - m_piece_map[*i].index = c++; - assert(m_piece_map[*i].priority(old_limit) == old_limit); - } - } - } - else if (int(m_piece_info.size()) > sequenced_download_threshold) - { - info_t& in = m_piece_info[sequenced_download_threshold]; - std::sort(in.begin(), in.end()); - int c = 0; - for (info_t::iterator i = in.begin() - , end(in.end()); i != end; ++i) - { - m_piece_map[*i].index = c++; - assert(m_piece_map[*i].priority( - sequenced_download_threshold) == sequenced_download_threshold); - } - } - } - - piece_picker::downloading_piece& piece_picker::add_download_piece() - { - int num_downloads = m_downloads.size(); - int block_index = num_downloads * m_blocks_per_piece; - if (int(m_block_info.size()) < block_index + m_blocks_per_piece) - { - m_block_info.resize(block_index + m_blocks_per_piece); - if (!m_downloads.empty() && &m_block_info[0] != m_downloads.front().info) - { - // this means the memory was reallocated, update the pointers - for (int i = 0; i < int(m_downloads.size()); ++i) - m_downloads[i].info = &m_block_info[i * m_blocks_per_piece]; - } - } - m_downloads.push_back(downloading_piece()); - downloading_piece& ret = m_downloads.back(); - ret.info = &m_block_info[block_index]; - for (int i = 0; i < m_blocks_per_piece; ++i) - { - ret.info[i].num_downloads = 0; - ret.info[i].requested = 0; - ret.info[i].finished = 0; - ret.info[i].peer = tcp::endpoint(); - } - return ret; - } - - void piece_picker::erase_download_piece(std::vector::iterator i) - { - if (i != m_downloads.end() - 1) - { - int remove_index = i - m_downloads.begin(); - int last_index = m_downloads.size() - 1; - assert(remove_index < last_index); - - assert(int(m_block_info.size()) >= last_index * m_blocks_per_piece + m_blocks_per_piece); - std::copy(m_block_info.begin() + (last_index * m_blocks_per_piece) - , m_block_info.begin() + (last_index * m_blocks_per_piece + m_blocks_per_piece) - , m_block_info.begin() + (remove_index * m_blocks_per_piece)); - m_downloads[remove_index] = m_downloads[last_index]; - m_downloads[remove_index].info = &m_block_info[remove_index * m_blocks_per_piece]; - } - - m_downloads.pop_back(); - } -#ifndef NDEBUG - - void piece_picker::check_invariant(const torrent* t) const - { - assert(sizeof(piece_pos) == 4); - - assert(m_piece_info.empty() || m_piece_info[0].empty()); - - if (t != 0) - assert((int)m_piece_map.size() == t->torrent_file().num_pieces()); - - for (int i = m_sequenced_download_threshold * 2 + 1; i < int(m_piece_info.size()); ++i) - assert(m_piece_info[i].empty()); - - for (std::vector::const_iterator i = m_downloads.begin() - , end(m_downloads.end()); i != end; ++i) - { - bool blocks_requested = false; - int num_blocks = blocks_in_piece(i->index); - int num_requested = 0; - int num_finished = 0; - for (int k = 0; k < num_blocks; ++k) - { - if (i->info[k].finished) - { - ++num_finished; - assert(i->info[k].requested); - ++num_requested; - continue; - } - if (i->info[k].requested) - { - ++num_requested; - blocks_requested = true; - } - } - assert(blocks_requested == (i->state != none)); - assert(num_requested == i->requested); - assert(num_finished == i->finished); - assert(num_finished <= num_requested); - } - - - int num_filtered = 0; - int num_have_filtered = 0; - int num_have = 0; - for (std::vector::const_iterator i = m_piece_map.begin(); - i != m_piece_map.end(); ++i) - { - int index = static_cast(i - m_piece_map.begin()); - if (i->filtered()) - { - if (i->index != piece_pos::we_have_index) - ++num_filtered; - else - ++num_have_filtered; - } - if (i->index == piece_pos::we_have_index) - ++num_have; - -#if 0 - if (t != 0) - { - int actual_peer_count = 0; - for (torrent::const_peer_iterator peer = t->begin(); - peer != t->end(); ++peer) - { - if (peer->second->has_piece(index)) actual_peer_count++; - } - - assert((int)i->peer_count == actual_peer_count); -/* - int num_downloaders = 0; - for (std::vector::const_iterator peer = t->begin(); - peer != t->end(); - ++peer) - { - const std::vector& queue = (*peer)->download_queue(); - if (std::find_if(queue.begin(), queue.end(), has_index(index)) == queue.end()) continue; - - ++num_downloaders; - } - - if (i->downloading) - { - assert(num_downloaders == 1); - } - else - { - assert(num_downloaders == 0); - } -*/ - } -#endif - - if (i->index == piece_pos::we_have_index) - { - assert(t == 0 || t->have_piece(index)); - assert(i->downloading == 0); -/* - // make sure there's no entry - // with this index. (there shouldn't - // be since the piece_map is piece_pos::we_have_index) - for (int i = 0; i < int(m_piece_info.size()); ++i) - { - for (int j = 0; j < int(m_piece_info[i].size()); ++j) - { - assert(m_piece_info[i][j] != index); - } - } -*/ - } - else - { - if (t != 0) - assert(!t->have_piece(index)); - - int prio = i->priority(m_sequenced_download_threshold); - if (prio > 0) - { - const std::vector& vec = m_piece_info[prio]; - assert (i->index < vec.size()); - assert(vec[i->index] == index); - } -/* - for (int k = 0; k < int(m_piece_info.size()); ++k) - { - for (int j = 0; j < int(m_piece_info[k].size()); ++j) - { - assert(int(m_piece_info[k][j]) != index - || (prio > 0 && prio == k && int(i->index) == j)); - } - } -*/ - } - - int count = std::count_if(m_downloads.begin(), m_downloads.end() - , has_index(index)); - if (i->downloading == 1) - { - assert(count == 1); - } - else - { - assert(count == 0); - } - } - assert(num_have == m_num_have); - assert(num_filtered == m_num_filtered); - assert(num_have_filtered == m_num_have_filtered); - } -#endif - - float piece_picker::distributed_copies() const - { - const float num_pieces = static_cast(m_piece_map.size()); - - int min_availability = piece_pos::max_peer_count; - // find the lowest availability count - // count the number of pieces that have that availability - // and also the number of pieces that have more than that. - int integer_part = 0; - int fraction_part = 0; - for (std::vector::const_iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - int peer_count = int(i->peer_count); - // take ourself into account - if (i->have()) ++peer_count; - if (min_availability > peer_count) - { - min_availability = i->peer_count; - fraction_part += integer_part; - integer_part = 1; - } - else if (peer_count == min_availability) - { - ++integer_part; - } - else - { - assert(peer_count > min_availability); - ++fraction_part; - } - } - assert(integer_part + fraction_part == num_pieces); - return float(min_availability) + (fraction_part / num_pieces); - } - - void piece_picker::add(int index) - { - assert(index >= 0); - assert(index < int(m_piece_map.size())); - piece_pos& p = m_piece_map[index]; - assert(!p.filtered()); - assert(!p.have()); - - int priority = p.priority(m_sequenced_download_threshold); - assert(priority > 0); - if (int(m_piece_info.size()) <= priority) - m_piece_info.resize(priority + 1); - - assert(int(m_piece_info.size()) > priority); - - if (is_ordered(priority)) - { - // the piece should be inserted ordered, not randomly - std::vector& v = m_piece_info[priority]; -// assert(is_sorted(v.begin(), v.end()/*, std::greater()*/)); - std::vector::iterator i = std::lower_bound(v.begin(), v.end() - , index/*, std::greater()*/); - p.index = i - v.begin(); - v.insert(i, index); - i = v.begin() + p.index + 1; - for (;i != v.end(); ++i) - { - ++m_piece_map[*i].index; - assert(v[m_piece_map[*i].index] == *i); - } -// assert(is_sorted(v.begin(), v.end()/*, std::greater()*/)); - } - else if (m_piece_info[priority].size() < 2) - { - p.index = m_piece_info[priority].size(); - m_piece_info[priority].push_back(index); - } - else - { - // find a random position in the destination vector where we will place - // this entry. - int dst_index = rand() % m_piece_info[priority].size(); - - // copy the entry at that position to the back - m_piece_map[m_piece_info[priority][dst_index]].index - = m_piece_info[priority].size(); - m_piece_info[priority].push_back(m_piece_info[priority][dst_index]); - - // and then replace the one at dst_index with the one we're moving. - // this procedure is to make sure there's no ordering when pieces - // are moved in sequenced order. - p.index = dst_index; - m_piece_info[priority][p.index] = index; - } - } - - // will update the piece with the given properties (priority, elem_index) - // to place it at the correct position in the vectors. - void piece_picker::move(int priority, int elem_index) - { - assert(priority > 0); - assert(elem_index >= 0); - assert(m_files_checked_called); - - assert(int(m_piece_info.size()) > priority); - assert(int(m_piece_info[priority].size()) > elem_index); - - int index = m_piece_info[priority][elem_index]; - // update the piece_map - piece_pos& p = m_piece_map[index]; - assert(int(p.index) == elem_index || p.have()); - - int new_priority = p.priority(m_sequenced_download_threshold); - - if (new_priority == priority) return; - - if (int(m_piece_info.size()) <= new_priority - && new_priority > 0) - { - m_piece_info.resize(new_priority + 1); - assert(int(m_piece_info.size()) > new_priority); - } - - if (new_priority == 0) - { - // this means the piece should not have an entry - } - else if (is_ordered(new_priority)) - { - // the piece should be inserted ordered, not randomly - std::vector& v = m_piece_info[new_priority]; -// assert(is_sorted(v.begin(), v.end()/*, std::greater()*/)); - std::vector::iterator i = std::lower_bound(v.begin(), v.end() - , index/*, std::greater()*/); - p.index = i - v.begin(); - v.insert(i, index); - i = v.begin() + p.index + 1; - for (;i != v.end(); ++i) - { - ++m_piece_map[*i].index; - assert(v[m_piece_map[*i].index] == *i); - } -// assert(is_sorted(v.begin(), v.end()/*, std::greater()*/)); - } - else if (m_piece_info[new_priority].size() < 2) - { - p.index = m_piece_info[new_priority].size(); - m_piece_info[new_priority].push_back(index); - } - else - { - // find a random position in the destination vector where we will place - // this entry. - int dst_index = rand() % m_piece_info[new_priority].size(); - - // copy the entry at that position to the back - m_piece_map[m_piece_info[new_priority][dst_index]].index - = m_piece_info[new_priority].size(); - m_piece_info[new_priority].push_back(m_piece_info[new_priority][dst_index]); - - // and then replace the one at dst_index with the one we're moving. - // this procedure is to make sure there's no ordering when pieces - // are moved in sequenced order. - p.index = dst_index; - m_piece_info[new_priority][p.index] = index; - } - assert(new_priority == 0 || p.index < m_piece_info[p.priority(m_sequenced_download_threshold)].size()); - assert(new_priority == 0 || m_piece_info[p.priority(m_sequenced_download_threshold)][p.index] == index); - - if (is_ordered(priority)) - { - // remove the element from the source vector and preserve the order - std::vector& v = m_piece_info[priority]; - v.erase(v.begin() + elem_index); - for (std::vector::iterator i = v.begin() + elem_index; - i != v.end(); ++i) - { - --m_piece_map[*i].index; - assert(v[m_piece_map[*i].index] == *i); - } - } - else - { - // this will remove elem from the source vector without - // preserving order, but the order is random anyway - int replace_index = m_piece_info[priority][elem_index] = m_piece_info[priority].back(); - if (index != replace_index) - { - // update the entry we moved from the back - m_piece_map[replace_index].index = elem_index; - - assert(int(m_piece_info[priority].size()) > elem_index); - // this may not necessarily be the case. If we've just updated the threshold and are updating - // the piece map -// assert((int)m_piece_map[replace_index].priority(m_sequenced_download_threshold) == priority); - assert(int(m_piece_map[replace_index].index) == elem_index); - assert(m_piece_info[priority][elem_index] == replace_index); - } - else - { - assert(int(m_piece_info[priority].size()) == elem_index+1); - } - - m_piece_info[priority].pop_back(); - } - } - - void piece_picker::restore_piece(int index) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - assert(index >= 0); - assert(index < (int)m_piece_map.size()); - assert(m_files_checked_called); - - assert(m_piece_map[index].downloading == 1); - - std::vector::iterator i - = std::find_if(m_downloads.begin(), - m_downloads.end(), - has_index(index)); - assert(i != m_downloads.end()); - erase_download_piece(i); - - piece_pos& p = m_piece_map[index]; - int prev_priority = p.priority(m_sequenced_download_threshold); - p.downloading = 0; - int new_priority = p.priority(m_sequenced_download_threshold); - - if (new_priority == prev_priority) return; - - if (prev_priority == 0) - { - add(index); - } - else - { - move(prev_priority, p.index); - } - } - - void piece_picker::inc_refcount_all() - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - assert(m_files_checked_called); - - // in general priority = availability * 2 - // see piece_block::priority() - - // this will insert two empty vectors at the start of the - // piece_info vector. It is done like this as an optimization, - // to swap vectors instead of copying them - while (m_piece_info.size() < 3 - || (!m_piece_info.rbegin()->empty()) - || (!(m_piece_info.rbegin()+1)->empty())) - { - m_piece_info.push_back(std::vector()); - } - assert(m_piece_info.rbegin()->empty()); - assert((m_piece_info.rbegin()+1)->empty()); - typedef std::vector > piece_info_t; - for (piece_info_t::reverse_iterator i = m_piece_info.rbegin(), j(i+1) - , k(j+1), end(m_piece_info.rend()); k != end; ++i, ++j, ++k) - { - k->swap(*i); - } - assert(m_piece_info.begin()->empty()); - assert((m_piece_info.begin()+1)->empty()); - - // if we have some priorities that are clamped to the - // sequenced download, move that vector back down - int last_index = m_piece_info.size() - 1; - int cap_index = m_sequenced_download_threshold * 2; - if (last_index == cap_index) - { - // this is the case when the top bucket - // was moved up into the sequenced download bucket. - m_piece_info.push_back(std::vector()); - m_piece_info[cap_index].swap(m_piece_info[cap_index+1]); - ++last_index; - } - else if (last_index > cap_index) - { - if (last_index - cap_index == 1) - { - m_piece_info.push_back(std::vector()); - ++last_index; - } - m_piece_info[cap_index+1].swap(m_piece_info[cap_index+2]); - m_piece_info[cap_index].swap(m_piece_info[cap_index+1]); - } - - // now, increase the peer count of all the pieces. - // because of different priorities, some pieces may have - // ended up in the wrong priority bucket. Adjust that. - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - int prev_prio = i->priority(m_sequenced_download_threshold); - ++i->peer_count; - // if the assumption that the priority would - // increase by 2 when increasing the availability - // by one isn't true for this particular piece, correct it. - // that assumption is true for all pieces with priority 0 or 1 - int new_prio = i->priority(m_sequenced_download_threshold); - assert(new_prio <= cap_index); - if (prev_prio == 0 && new_prio > 0) - { - add(i - m_piece_map.begin()); - continue; - } - if (new_prio == 0) - { - assert(prev_prio == 0); - continue; - } - if (prev_prio == cap_index) - { - assert(new_prio == cap_index); - continue; - } - if (new_prio == prev_prio + 2 && new_prio != cap_index) - { - assert(new_prio != cap_index); - continue; - } - if (prev_prio + 2 >= cap_index) - { - // these two vectors will have moved one extra step - // passed the sequenced download threshold - ++prev_prio; - } - assert(prev_prio + 2 != cap_index); - assert(prev_prio + 2 != new_prio); - move(prev_prio + 2, i->index); - } - } - - void piece_picker::dec_refcount_all() - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - assert(m_files_checked_called); - assert(m_piece_info.size() >= 2); - assert(m_piece_info.front().empty()); - // swap all vectors two steps down - if (m_piece_info.size() > 2) - { - typedef std::vector > piece_info_t; - for (piece_info_t::iterator i = m_piece_info.begin(), j(i+1) - , k(j+1), end(m_piece_info.end()); k != end; ++i, ++j, ++k) - { - k->swap(*i); - } - } - else - { - m_piece_info.resize(3); - } - int last_index = m_piece_info.size() - 1; - if ((m_piece_info.size() & 1) == 0) - { - // if there's an even number of vectors, swap - // the last two to get the same layout in both cases - m_piece_info[last_index].swap(m_piece_info[last_index-1]); - } - assert(m_piece_info.back().empty()); - int pushed_out_index = m_piece_info.size() - 2; - - int cap_index = m_sequenced_download_threshold * 2; - assert(m_piece_info[last_index].empty()); - if (last_index >= cap_index) - { - assert(pushed_out_index == cap_index - 1 - || m_piece_info[cap_index - 1].empty()); - m_piece_info[cap_index].swap(m_piece_info[cap_index - 2]); - if (cap_index == pushed_out_index) - pushed_out_index = cap_index - 2; - } - - // first is the vector that were - // bumped down to 0. The should always be moved - // since they have to be removed or reinserted - std::vector().swap(m_piece_info.front()); - - for (std::vector::iterator i = m_piece_map.begin() - , end(m_piece_map.end()); i != end; ++i) - { - int prev_prio = i->priority(m_sequenced_download_threshold); - assert(i->peer_count > 0); - --i->peer_count; - // if the assumption that the priority would - // decrease by 2 when decreasing the availability - // by one isn't true for this particular piece, correct it. - // that assumption is true for all pieces with priority 0 or 1 - if (prev_prio == 0) - { - assert(i->priority(m_sequenced_download_threshold) == 0); - continue; - } - - int new_prio = i->priority(m_sequenced_download_threshold); - if (prev_prio == cap_index) - { - if (new_prio == cap_index) continue; - prev_prio += 2; - } - else if (new_prio == prev_prio - 2) - { - continue; - } - else if (prev_prio == 2) - { - // if this piece was pushed down to priority 0, it was - // removed - assert(new_prio > 0); - add(i - m_piece_map.begin()); - continue; - } - else if (prev_prio == 1) - { - // if this piece was one of the vectors that was pushed to the - // top, adjust the prev_prio to point to that vector, so that - // the pieces are moved from there - prev_prio = pushed_out_index + 2; - } - move(prev_prio - 2, i->index); - } - } - - void piece_picker::inc_refcount(int i) - { -// TORRENT_PIECE_PICKER_INVARIANT_CHECK; - assert(i >= 0); - assert(i < (int)m_piece_map.size()); - assert(m_files_checked_called); - - piece_pos& p = m_piece_map[i]; - int index = p.index; - int prev_priority = p.priority(m_sequenced_download_threshold); - - assert(p.peer_count < piece_pos::max_peer_count); - p.peer_count++; - assert(p.peer_count != 0); - - // if we have the piece or if it's filtered - // we don't have to move any entries in the piece_info vector - if (p.priority(m_sequenced_download_threshold) == prev_priority) return; - - if (prev_priority == 0) - { - add(i); - } - else - { - move(prev_priority, index); - } - -#ifndef NDEBUG -// integrity_check(); -#endif - return; - } - - void piece_picker::dec_refcount(int i) - { -// TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - assert(m_files_checked_called); - assert(i >= 0); - assert(i < (int)m_piece_map.size()); - - piece_pos& p = m_piece_map[i]; - int prev_priority = p.priority(m_sequenced_download_threshold); - int index = p.index; - assert(p.peer_count > 0); - - if (p.peer_count > 0) - p.peer_count--; - - if (p.priority(m_sequenced_download_threshold) == prev_priority) return; - - move(prev_priority, index); - } - - // this is used to indicate that we succesfully have - // downloaded a piece, and that no further attempts - // to pick that piece should be made. The piece will - // be removed from the available piece list. - void piece_picker::we_have(int index) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - assert(index >= 0); - assert(index < (int)m_piece_map.size()); - - piece_pos& p = m_piece_map[index]; - int info_index = p.index; - int priority = p.priority(m_sequenced_download_threshold); - - assert(p.downloading == 1); - assert(!p.have()); - - std::vector::iterator i - = std::find_if(m_downloads.begin() - , m_downloads.end() - , has_index(index)); - assert(i != m_downloads.end()); - erase_download_piece(i); - p.downloading = 0; - - assert(std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(index)) == m_downloads.end()); - - if (p.have()) return; - if (p.filtered()) - { - --m_num_filtered; - ++m_num_have_filtered; - } - ++m_num_have; - p.set_have(); - if (priority == 0) return; - assert(p.priority(m_sequenced_download_threshold) == 0); - move(priority, info_index); - } - - - void piece_picker::set_piece_priority(int index, int new_piece_priority) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - assert(new_piece_priority >= 0); - assert(new_piece_priority <= 7); - assert(index >= 0); - assert(index < (int)m_piece_map.size()); - - piece_pos& p = m_piece_map[index]; - - // if the priority isn't changed, don't do anything - if (new_piece_priority == int(p.piece_priority)) return; - - int prev_priority = p.priority(m_sequenced_download_threshold); - - if (new_piece_priority == piece_pos::filter_priority - && p.piece_priority != piece_pos::filter_priority) - { - // the piece just got filtered - if (p.have()) ++m_num_have_filtered; - else ++m_num_filtered; - } - else if (new_piece_priority != piece_pos::filter_priority - && p.piece_priority == piece_pos::filter_priority) - { - // the piece just got unfiltered - if (p.have()) --m_num_have_filtered; - else --m_num_filtered; - } - assert(m_num_filtered >= 0); - assert(m_num_have_filtered >= 0); - - p.piece_priority = new_piece_priority; - int new_priority = p.priority(m_sequenced_download_threshold); - - if (new_priority == prev_priority) return; - - if (prev_priority == 0) - { - add(index); - } - else - { - move(prev_priority, p.index); - } - } - - int piece_picker::piece_priority(int index) const - { - assert(index >= 0); - assert(index < (int)m_piece_map.size()); - - return m_piece_map[index].piece_priority; - } - - void piece_picker::piece_priorities(std::vector& pieces) const - { - pieces.resize(m_piece_map.size()); - std::vector::iterator j = pieces.begin(); - for (std::vector::const_iterator i = m_piece_map.begin(), - end(m_piece_map.end()); i != end; ++i, ++j) - { - *j = i->piece_priority; - } - } - - // ============ start deprecation ============== - - void piece_picker::filtered_pieces(std::vector& mask) const - { - mask.resize(m_piece_map.size()); - std::vector::iterator j = mask.begin(); - for (std::vector::const_iterator i = m_piece_map.begin(), - end(m_piece_map.end()); i != end; ++i, ++j) - { - *j = i->filtered(); - } - } - - // ============ end deprecation ============== - - // pieces describes which pieces the peer we're requesting from - // has. - // interesting_blocks is an out parameter, and will be filled - // with (up to) num_blocks of interesting blocks that the peer has. - // prefer_whole_pieces can be set if this peer should download - // whole pieces rather than trying to download blocks from the - // same piece as other peers. - // the endpoint is the address of the peer we're picking pieces - // from. This is used when downloading whole pieces, to only - // pick from the same piece the same peer is downloading from. - // state is supposed to be set to fast if the peer is downloading - // relatively fast, by some notion. Slow peers will prefer not - // to pick blocks from the same pieces as fast peers, and vice - // versa. Downloading pieces are marked as being fast, medium - // or slow once they're started. - void piece_picker::pick_pieces(const std::vector& pieces - , std::vector& interesting_blocks - , int num_blocks, bool prefer_whole_pieces - , tcp::endpoint peer, piece_state_t speed) const - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - assert(num_blocks > 0); - assert(pieces.size() == m_piece_map.size()); - assert(m_files_checked_called); - - assert(m_piece_info.begin() != m_piece_info.end()); - - // this will be filled with blocks that we should not request - // unless we can't find num_blocks among the other ones. - // blocks that belong to pieces with a mismatching speed - // category for instance, or if we prefer whole pieces, - // blocks belonging to a piece that others have - // downloaded to - std::vector backup_blocks; - - // this loop will loop from pieces with priority 1 and up - // until we either reach the end of the piece list or - // has filled the interesting_blocks with num_blocks - // blocks. - - // When prefer_whole_pieces is set (usually set when downloading from - // fast peers) the partial pieces will not be prioritized, but actually - // ignored as long as possible. - - // +1 is to ignore pieces that no peer has. The bucket with index 0 contains - // pieces that 0 other peers have. bucket will point to a bucket with - // pieces with the same priority. It will be iterated in priority - // order (high priority/rare pices first). The content of each - // bucket is randomized - for (std::vector >::const_iterator bucket - = m_piece_info.begin() + 1; bucket != m_piece_info.end(); - ++bucket) - { - if (bucket->empty()) continue; - num_blocks = add_interesting_blocks(*bucket, pieces - , interesting_blocks, backup_blocks, num_blocks - , prefer_whole_pieces, peer, speed); - assert(num_blocks >= 0); - if (num_blocks == 0) return; - } - - assert(num_blocks > 0); - - if (!backup_blocks.empty()) - interesting_blocks.insert(interesting_blocks.end() - , backup_blocks.begin(), backup_blocks.begin() - + (std::min)(num_blocks, (int)backup_blocks.size())); - } - - namespace - { - bool exclusively_requested_from(piece_picker::downloading_piece const& p - , int num_blocks_in_piece, tcp::endpoint peer) - { - for (int j = 0; j < num_blocks_in_piece; ++j) - { - piece_picker::block_info const& info = p.info[j]; - if ((info.finished == 1 - || info.requested == 1) - && info.peer != peer - && info.peer != tcp::endpoint()) - { - return false; - } - } - return true; - } - } - - int piece_picker::add_interesting_blocks(std::vector const& piece_list - , std::vector const& pieces - , std::vector& interesting_blocks - , std::vector& backup_blocks - , int num_blocks, bool prefer_whole_pieces - , tcp::endpoint peer, piece_state_t speed) const - { - for (std::vector::const_iterator i = piece_list.begin(); - i != piece_list.end(); ++i) - { - assert(*i >= 0); - assert(*i < (int)m_piece_map.size()); - - // if the peer doesn't have the piece - // skip it - if (!pieces[*i]) continue; - - // if we have less than 1% of the pieces, ignore speed priorities and just try - // to finish any downloading piece - bool ignore_speed_categories = (m_num_have * 100 / m_piece_map.size()) < 1; - - int num_blocks_in_piece = blocks_in_piece(*i); - - if (m_piece_map[*i].downloading == 1) - { - std::vector::const_iterator p - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(*i)); - assert(p != m_downloads.end()); - - // is true if all the other pieces that are currently - // requested from this piece are from the same - // peer as 'peer'. - bool only_same_peer = exclusively_requested_from(*p - , num_blocks_in_piece, peer); - - // this means that this partial piece has - // been downloaded/requested partially from - // another peer that isn't us. And since - // we prefer whole pieces, add this piece's - // blocks to the backup list. If the prioritized - // blocks aren't enough, blocks from this list - // will be picked. - if (prefer_whole_pieces && !only_same_peer) - { - if (int(backup_blocks.size()) >= num_blocks) continue; - for (int j = 0; j < num_blocks_in_piece; ++j) - { - block_info const& info = p->info[j]; - if (info.finished) continue; - if (info.requested - && info.peer == peer) continue; - backup_blocks.push_back(piece_block(*i, j)); - } - continue; - } - - for (int j = 0; j < num_blocks_in_piece; ++j) - { - // ignore completed blocks - block_info const& info = p->info[j]; - if (info.finished) continue; - // ignore blocks requested from this peer already - if (info.requested && info.peer == peer) continue; - // if the piece is fast and the peer is slow, or vice versa, - // add the block as a backup. - // override this behavior if all the other blocks - // have been requested from the same peer or - // if the state of the piece is none (the - // piece will in that case change state). - if (p->state != none && p->state != speed - && !only_same_peer - && !ignore_speed_categories) - { - if (int(backup_blocks.size()) >= num_blocks) continue; - backup_blocks.push_back(piece_block(*i, j)); - continue; - } - // this block is interesting (we don't have it - // yet). But it may already have been requested - // from another peer. We have to add it anyway - // to allow the requester to determine if the - // block should be requested from more than one - // peer. If it is being downloaded, we continue - // to look for blocks until we have num_blocks - // blocks that have not been requested from any - // other peer. - interesting_blocks.push_back(piece_block(*i, j)); - if (p->info[j].requested == 0) - { - // we have found a block that's free to download - num_blocks--; - // if we prefer whole pieces, continue picking from this - // piece even though we have num_blocks - if (prefer_whole_pieces) continue; - assert(num_blocks >= 0); - if (num_blocks == 0) return num_blocks; - } - } - assert(num_blocks >= 0 || prefer_whole_pieces); - if (num_blocks < 0) num_blocks = 0; - } - else - { - if (!prefer_whole_pieces && num_blocks_in_piece > num_blocks) - num_blocks_in_piece = num_blocks; - for (int j = 0; j < num_blocks_in_piece; ++j) - { - interesting_blocks.push_back(piece_block(*i, j)); - } - num_blocks -= (std::min)(num_blocks_in_piece, num_blocks); - } - assert(num_blocks >= 0); - if (num_blocks == 0) return num_blocks; - } - return num_blocks; - } - - bool piece_picker::is_piece_finished(int index) const - { - assert(index < (int)m_piece_map.size()); - assert(index >= 0); - - if (m_piece_map[index].downloading == 0) - { - assert(std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(index)) == m_downloads.end()); - return false; - } - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index)); - assert(i != m_downloads.end()); - assert((int)i->finished <= m_blocks_per_piece); - int max_blocks = blocks_in_piece(index); - if ((int)i->finished < max_blocks) return false; - - assert((int)i->requested == max_blocks); - return true; - } - - bool piece_picker::is_downloading(piece_block block) const - { - assert(block.piece_index >= 0); - assert(block.block_index >= 0); - assert(block.piece_index < (int)m_piece_map.size()); - - if (m_piece_map[block.piece_index].downloading == 0) return false; - std::vector::const_iterator i - = std::find_if( - m_downloads.begin() - , m_downloads.end() - , has_index(block.piece_index)); - - assert(i != m_downloads.end()); - return i->info[block.block_index].requested; - } - - bool piece_picker::is_finished(piece_block block) const - { - assert(block.piece_index >= 0); - assert(block.block_index >= 0); - assert(block.piece_index < (int)m_piece_map.size()); - - if (m_piece_map[block.piece_index].index == piece_pos::we_have_index) return true; - if (m_piece_map[block.piece_index].downloading == 0) return false; - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - assert(i != m_downloads.end()); - return i->info[block.block_index].finished; - } - - - void piece_picker::mark_as_downloading(piece_block block - , const tcp::endpoint& peer, piece_state_t state) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - assert(block.piece_index >= 0); - assert(block.block_index >= 0); - assert(block.piece_index < (int)m_piece_map.size()); - assert(block.block_index < blocks_in_piece(block.piece_index)); - - piece_pos& p = m_piece_map[block.piece_index]; - if (p.downloading == 0) - { - int prio = p.priority(m_sequenced_download_threshold); - p.downloading = 1; - move(prio, p.index); - - downloading_piece& dp = add_download_piece(); - dp.state = state; - dp.index = block.piece_index; - block_info& info = dp.info[block.block_index]; - info.requested = 1; - info.peer = peer; - ++dp.requested; - } - else - { - std::vector::iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - assert(i != m_downloads.end()); - block_info& info = i->info[block.block_index]; - assert(info.requested == 0); - info.peer = peer; - info.requested = 1; - ++i->requested; - if (i->state == none) i->state = state; - } - } - - void piece_picker::mark_as_finished(piece_block block, const tcp::endpoint& peer) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - assert(block.piece_index >= 0); - assert(block.block_index >= 0); - assert(block.piece_index < (int)m_piece_map.size()); - assert(block.block_index < blocks_in_piece(block.piece_index)); - - piece_pos& p = m_piece_map[block.piece_index]; - int prio = p.priority(m_sequenced_download_threshold); - - if (p.downloading == 0) - { - p.downloading = 1; - if (prio > 0) move(prio, p.index); - else assert(p.priority(m_sequenced_download_threshold) == 0); - - downloading_piece& dp = add_download_piece(); - dp.state = none; - dp.index = block.piece_index; - block_info& info = dp.info[block.block_index]; - info.requested = 1; - info.finished = 1; - ++dp.requested; - ++dp.finished; - dp.info[block.block_index].peer = peer; - } - else - { - std::vector::iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index)); - assert(i != m_downloads.end()); - block_info& info = i->info[block.block_index]; - info.peer = peer; - if (!info.requested) ++i->requested; - info.requested = 1; - if (!info.finished) ++i->finished; - info.finished = 1; - - if (i->requested == i->finished) - { - // there are no blocks requested in this piece. - // remove the fast/slow state from it - i->state = none; - } - } - } - - void piece_picker::get_downloaders(std::vector& d, int index) const - { - assert(index >= 0 && index <= (int)m_piece_map.size()); - std::vector::const_iterator i - = std::find_if(m_downloads.begin(), m_downloads.end(), has_index(index)); - assert(i != m_downloads.end()); - - d.clear(); - for (int j = 0; j < blocks_in_piece(index); ++j) - { - d.push_back(i->info[j].peer); - } - } - - boost::optional piece_picker::get_downloader(piece_block block) const - { - std::vector::const_iterator i = std::find_if( - m_downloads.begin() - , m_downloads.end() - , has_index(block.piece_index)); - - if (i == m_downloads.end()) - return boost::optional(); - - assert(block.block_index >= 0); - - if (i->info[block.block_index].requested == false - || i->info[block.block_index].requested == true) - return boost::optional(); - - return boost::optional(i->info[block.block_index].peer); - } - - void piece_picker::abort_download(piece_block block) - { - TORRENT_PIECE_PICKER_INVARIANT_CHECK; - - assert(block.piece_index >= 0); - assert(block.block_index >= 0); - assert(block.piece_index < (int)m_piece_map.size()); - assert(block.block_index < blocks_in_piece(block.piece_index)); - - if (m_piece_map[block.piece_index].downloading == 0) - { - assert(std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(block.piece_index)) == m_downloads.end()); - return; - } - - std::vector::iterator i = std::find_if(m_downloads.begin() - , m_downloads.end(), has_index(block.piece_index)); - assert(i != m_downloads.end()); - - if (i->info[block.block_index].finished) - { - assert(i->info[block.block_index].requested); - return; - } - - assert(block.block_index < blocks_in_piece(block.piece_index)); - assert(i->info[block.block_index].requested); - - // clear this block as being downloaded - i->info[block.block_index].requested = false; - --i->requested; - - // clear the downloader of this block - i->info[block.block_index].peer = tcp::endpoint(); - - // if there are no other blocks in this piece - // that's being downloaded, remove it from the list - if (i->requested == 0) - { - erase_download_piece(i); - piece_pos& p = m_piece_map[block.piece_index]; - int prio = p.priority(m_sequenced_download_threshold); - p.downloading = 0; - if (prio > 0) move(prio, p.index); - - assert(std::find_if(m_downloads.begin(), m_downloads.end() - , has_index(block.piece_index)) == m_downloads.end()); - } - else if (i->requested == i->finished) - { - // there are no blocks requested in this piece. - // remove the fast/slow state from it - i->state = none; - } - } - - int piece_picker::unverified_blocks() const - { - int counter = 0; - for (std::vector::const_iterator i = m_downloads.begin(); - i != m_downloads.end(); ++i) - { - counter += (int)i->finished; - } - return counter; - } - -} - diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp deleted file mode 100644 index bba04f429..000000000 --- a/libtorrent/src/policy.cpp +++ /dev/null @@ -1,1435 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/web_peer_connection.hpp" -#include "libtorrent/policy.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/time.hpp" -#include "libtorrent/aux_/session_impl.hpp" - -namespace libtorrent -{ - class peer_connection; -} - -using boost::bind; - -namespace -{ - using namespace libtorrent; - - size_type collect_free_download( - torrent::peer_iterator start - , torrent::peer_iterator end) - { - size_type accumulator = 0; - for (torrent::peer_iterator i = start; i != end; ++i) - { - // if the peer is interested in us, it means it may - // want to trade it's surplus uploads for downloads itself - // (and we should not consider it free). If the share diff is - // negative, there's no free download to get from this peer. - size_type diff = i->second->share_diff(); - assert(diff < std::numeric_limits::max()); - if (i->second->is_peer_interested() || diff <= 0) - continue; - - assert(diff > 0); - i->second->add_free_upload(-diff); - accumulator += diff; - assert(accumulator > 0); - } - assert(accumulator >= 0); - return accumulator; - } - - - // returns the amount of free upload left after - // it has been distributed to the peers - size_type distribute_free_upload( - torrent::peer_iterator start - , torrent::peer_iterator end - , size_type free_upload) - { - if (free_upload <= 0) return free_upload; - int num_peers = 0; - size_type total_diff = 0; - for (torrent::peer_iterator i = start; i != end; ++i) - { - size_type d = i->second->share_diff(); - assert(d < std::numeric_limits::max()); - total_diff += d; - if (!i->second->is_peer_interested() || i->second->share_diff() >= 0) continue; - ++num_peers; - } - - if (num_peers == 0) return free_upload; - size_type upload_share; - if (total_diff >= 0) - { - upload_share = std::min(free_upload, total_diff) / num_peers; - } - else - { - upload_share = (free_upload + total_diff) / num_peers; - } - if (upload_share < 0) return free_upload; - - for (torrent::peer_iterator i = start; i != end; ++i) - { - peer_connection* p = i->second; - if (!p->is_peer_interested() || p->share_diff() >= 0) continue; - p->add_free_upload(upload_share); - free_upload -= upload_share; - } - return free_upload; - } - - struct match_peer_ip - { - match_peer_ip(tcp::endpoint const& ip) - : m_ip(ip) - {} - - bool operator()(policy::peer const& p) const - { return p.ip.address() == m_ip.address(); } - - tcp::endpoint m_ip; - }; - - struct match_peer_connection - { - match_peer_connection(peer_connection const& c) - : m_conn(c) - {} - - bool operator()(policy::peer const& p) const - { return p.connection == &m_conn; } - - const peer_connection& m_conn; - }; - - -} - -namespace libtorrent -{ - // the case where ignore_peer is motivated is if two peers - // have only one piece that we don't have, and it's the - // same piece for both peers. Then they might get into an - // infinite loop, fighting to request the same blocks. - void request_a_block( - torrent& t - , peer_connection& c - , std::vector ignore) - { - assert(!t.is_seed()); - assert(!c.has_peer_choked()); - int num_requests = c.desired_queue_size() - - (int)c.download_queue().size() - - (int)c.request_queue().size(); - - assert(c.desired_queue_size() > 0); - // if our request queue is already full, we - // don't have to make any new requests yet - if (num_requests <= 0) return; - - piece_picker& p = t.picker(); - std::vector interesting_pieces; - interesting_pieces.reserve(100); - - bool prefer_whole_pieces = c.prefer_whole_pieces() - || c.on_parole(); - - if (!prefer_whole_pieces) - { - prefer_whole_pieces = c.statistics().download_payload_rate() - * t.settings().whole_pieces_threshold - > t.torrent_file().piece_length(); - } - - // if we prefer whole pieces, the piece picker will pick at least - // the number of blocks we want, but it will try to make the picked - // blocks be from whole pieces, possibly by returning more blocks - // than we requested. - assert(c.remote() == c.get_socket()->remote_endpoint()); - - piece_picker::piece_state_t state; - peer_connection::peer_speed_t speed = c.peer_speed(); - if (speed == peer_connection::fast) state = piece_picker::fast; - else if (speed == peer_connection::medium) state = piece_picker::medium; - else state = piece_picker::slow; - - // picks the interesting pieces from this peer - // the integer is the number of pieces that - // should be guaranteed to be available for download - // (if num_requests is too big, too many pieces are - // picked and cpu-time is wasted) - // the last argument is if we should prefer whole pieces - // for this peer. If we're downloading one piece in 20 seconds - // then use this mode. - p.pick_pieces(c.get_bitfield(), interesting_pieces - , num_requests, prefer_whole_pieces, c.remote(), state); - - // this vector is filled with the interesting pieces - // that some other peer is currently downloading - // we should then compare this peer's download speed - // with the other's, to see if we should abort another - // peer_connection in favour of this one - std::vector busy_pieces; - busy_pieces.reserve(10); - - for (std::vector::iterator i = interesting_pieces.begin(); - i != interesting_pieces.end(); ++i) - { - if (p.is_downloading(*i)) - { - busy_pieces.push_back(*i); - continue; - } - - // ok, we found a piece that's not being downloaded - // by somebody else. request it from this peer - // and return - c.add_request(*i); - num_requests--; - } - - c.send_block_requests(); - - // in this case, we could not find any blocks - // that was free. If we couldn't find any busy - // blocks as well, we cannot download anything - // more from this peer. - - if (busy_pieces.empty()) return; - - // first look for blocks that are just queued - // and not actually sent to us yet - // (then we can cancel those and request them - // from this peer instead) - - while (num_requests > 0) - { - peer_connection* peer = 0; - - const int initial_queue_size = (int)c.download_queue().size() - + (int)c.request_queue().size(); - - // This peer's weight will be the minimum, to prevent - // cancelling requests from a faster peer. - float min_weight = initial_queue_size == 0 - ? std::numeric_limits::max() - : c.statistics().download_payload_rate() / initial_queue_size; - - // find the peer with the lowest download - // speed that also has a piece that this - // peer could send us - for (torrent::peer_iterator i = t.begin(); - i != t.end(); ++i) - { - // don't try to take over blocks from ourself - if (i->second == &c) - continue; - - // ignore all peers in the ignore list - if (std::find(ignore.begin(), ignore.end(), i->second) != ignore.end()) - continue; - - const std::deque& download_queue = i->second->download_queue(); - const std::deque& request_queue = i->second->request_queue(); - const int queue_size = (int)i->second->download_queue().size() - + (int)i->second->request_queue().size(); - - bool in_request_queue = std::find_first_of( - busy_pieces.begin() - , busy_pieces.end() - , request_queue.begin() - , request_queue.end()) != busy_pieces.end(); - - bool in_download_queue = std::find_first_of( - busy_pieces.begin() - , busy_pieces.end() - , download_queue.begin() - , download_queue.end()) != busy_pieces.end(); - - // if the block is in the request queue rather than the download queue - // (i.e. the request message hasn't been sent yet) lower the weight in - // order to prioritize it. Taking over a block in the request queue is - // free in terms of redundant download. A block that already has been - // requested is likely to be in transit already, and would in that case - // mean redundant data to receive. - const float weight = (queue_size == 0) - ? std::numeric_limits::max() - : i->second->statistics().download_payload_rate() / queue_size - * in_request_queue ? .1f : 1.f; - - // if the peer's (i) weight is less than the lowest we've found so - // far (weight == priority) and it has blocks in its request- - // or download queue that we could request from this peer (c), - // replace the currently lowest ranking peer. - if (weight < min_weight && (in_request_queue || in_download_queue)) - { - peer = i->second; - min_weight = weight; - } - } - - if (peer == 0) - { - // we probably couldn't request the block because - // we are ignoring some peers - break; - } - - // find a suitable block to take over from this peer - - std::deque::const_reverse_iterator common_block = - std::find_first_of( - peer->request_queue().rbegin() - , peer->request_queue().rend() - , busy_pieces.begin() - , busy_pieces.end()); - - if (common_block == peer->request_queue().rend()) - { - common_block = std::find_first_of( - peer->download_queue().rbegin() - , peer->download_queue().rend() - , busy_pieces.begin() - , busy_pieces.end()); - assert(common_block != peer->download_queue().rend()); - } - - piece_block block = *common_block; - - // the one we interrupted may need to request a new piece. - // make sure it doesn't take over a block from the peer - // that just took over its block (that would cause an - // infinite recursion) - peer->cancel_request(block); - c.add_request(block); - ignore.push_back(&c); - if (!peer->has_peer_choked() && !t.is_seed()) - { - request_a_block(t, *peer, ignore); - peer->send_block_requests(); - } - - num_requests--; - - const int queue_size = (int)c.download_queue().size() - + (int)c.request_queue().size(); - const float weight = queue_size == 0 - ? std::numeric_limits::max() - : c.statistics().download_payload_rate() / queue_size; - - // this peer doesn't have a faster connection than the - // slowest peer. Don't take over any blocks - if (weight <= min_weight) break; - } - c.send_block_requests(); - } - - policy::policy(torrent* t) - : m_torrent(t) - , m_num_unchoked(0) - , m_available_free_upload(0) - , m_last_optimistic_disconnect(min_time()) - { assert(t); } - // finds the peer that has the worst download rate - // and returns it. May return 0 if all peers are - // choked. - policy::iterator policy::find_choke_candidate() - { - INVARIANT_CHECK; - - iterator worst_peer = m_peers.end(); - size_type min_weight = std::numeric_limits::min(); - -#ifndef NDEBUG - int unchoked_counter = m_num_unchoked; -#endif - - // TODO: make this selection better - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - - if (c == 0) continue; - if (c->is_choked()) continue; -#ifndef NDEBUG - unchoked_counter--; -#endif - if (c->is_disconnecting()) continue; - // if the peer isn't interested, just choke it - if (!c->is_peer_interested()) - return i; - - size_type diff = i->total_download() - - i->total_upload(); - - size_type weight = static_cast(c->statistics().download_rate() * 10.f) - + diff - + ((c->is_interesting() && c->has_peer_choked())?-10:10)*1024; - - if (weight >= min_weight && worst_peer != m_peers.end()) continue; - - min_weight = weight; - worst_peer = i; - continue; - } - assert(unchoked_counter == 0); - return worst_peer; - } - - policy::iterator policy::find_unchoke_candidate() - { - INVARIANT_CHECK; - - // if all of our peers are unchoked, there's - // no left to unchoke - if (m_num_unchoked == m_torrent->num_peers()) - return m_peers.end(); - - iterator unchoke_peer = m_peers.end(); - ptime min_time = libtorrent::min_time(); - float max_down_speed = 0.f; - - // TODO: make this selection better - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - if (c == 0) continue; - if (c->is_disconnecting()) continue; - if (!c->is_choked()) continue; - if (!c->is_peer_interested()) continue; - if (c->share_diff() < -free_upload_amount - && m_torrent->ratio() != 0) continue; - if (c->statistics().download_rate() < max_down_speed) continue; - - min_time = i->last_optimistically_unchoked; - max_down_speed = c->statistics().download_rate(); - unchoke_peer = i; - } - return unchoke_peer; - } - - policy::iterator policy::find_disconnect_candidate() - { - INVARIANT_CHECK; - - iterator disconnect_peer = m_peers.end(); - double slowest_transfer_rate = std::numeric_limits::max(); - - ptime now = time_now(); - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - if (c == 0) continue; - if (c->is_disconnecting()) continue; - - // never disconnect an interesting peer if we have a candidate that - // isn't interesting - if (disconnect_peer != m_peers.end() - && c->is_interesting() - && !disconnect_peer->connection->is_interesting()) - continue; - - double transferred_amount - = (double)c->statistics().total_payload_download(); - - time_duration connected_time = now - i->connected; - - double connected_time_in_seconds = total_seconds(connected_time); - - double transfer_rate - = transferred_amount / (connected_time_in_seconds + 1); - - // prefer to disconnect uninteresting peers, and secondly slow peers - if (transfer_rate <= slowest_transfer_rate - || (disconnect_peer != m_peers.end() - && disconnect_peer->connection->is_interesting() - && !c->is_interesting())) - { - slowest_transfer_rate = transfer_rate; - disconnect_peer = i; - } - } - return disconnect_peer; - } - - policy::iterator policy::find_connect_candidate() - { - INVARIANT_CHECK; - - ptime now = time_now(); - ptime min_connect_time(now); - iterator candidate = m_peers.end(); - - int max_failcount = m_torrent->settings().max_failcount; - int min_reconnect_time = m_torrent->settings().min_reconnect_time; - - for (iterator i = m_peers.begin(); i != m_peers.end(); ++i) - { - if (i->connection) continue; - if (i->banned) continue; - if (i->type == peer::not_connectable) continue; - if (i->seed && m_torrent->is_seed()) continue; - if (i->failcount >= max_failcount) continue; - if (now - i->connected < seconds(i->failcount * min_reconnect_time)) - continue; - - assert(i->connected <= now); - - if (i->connected <= min_connect_time) - { - min_connect_time = i->connected; - candidate = i; - } - } - - assert(min_connect_time <= now); - - return candidate; - } - - policy::iterator policy::find_seed_choke_candidate() - { - INVARIANT_CHECK; - - assert(m_num_unchoked > 0); - // first choice candidate. - // it is a candidate we owe nothing to and which has been unchoked - // the longest. - iterator candidate = m_peers.end(); - - // not valid when candidate == 0 - ptime last_unchoke = min_time(); - - // second choice candidate. - // if there is no first choice candidate, this candidate will be chosen. - // it is the candidate that we owe the least to. - iterator second_candidate = m_peers.end(); - size_type lowest_share_diff = 0; // not valid when secondCandidate==0 - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - // ignore peers that are choked or - // whose connection is closed - if (c == 0) continue; - - if (c->is_choked()) continue; - if (c->is_disconnecting()) continue; - - size_type share_diff = c->share_diff(); - - // select as second candidate the one that we owe the least - // to - if (second_candidate == m_peers.end() - || share_diff <= lowest_share_diff) - { - lowest_share_diff = share_diff; - second_candidate = i; - } - - // select as first candidate the one that we don't owe anything to - // and has been waiting for an unchoke the longest - if (share_diff > 0) continue; - if (candidate == m_peers.end() - || last_unchoke > i->last_optimistically_unchoked) - { - last_unchoke = i->last_optimistically_unchoked; - candidate = i; - } - } - if (candidate != m_peers.end()) return candidate; - assert(second_candidate != m_peers.end()); - return second_candidate; - } - - policy::iterator policy::find_seed_unchoke_candidate() - { - INVARIANT_CHECK; - - iterator candidate = m_peers.end(); - ptime last_unchoke = time_now(); - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - if (c == 0) continue; - if (!c->is_choked()) continue; - if (!c->is_peer_interested()) continue; - if (c->is_disconnecting()) continue; - if (last_unchoke < i->last_optimistically_unchoked) continue; - last_unchoke = i->last_optimistically_unchoked; - candidate = i; - } - return candidate; - } - - bool policy::seed_unchoke_one_peer() - { - INVARIANT_CHECK; - - iterator p = find_seed_unchoke_candidate(); - if (p != m_peers.end()) - { - assert(p->connection->is_choked()); - p->connection->send_unchoke(); - p->last_optimistically_unchoked = time_now(); - ++m_num_unchoked; - } - return p != m_peers.end(); - } - - void policy::seed_choke_one_peer() - { - INVARIANT_CHECK; - - iterator p = find_seed_choke_candidate(); - if (p != m_peers.end()) - { - assert(!p->connection->is_choked()); - p->connection->send_choke(); - --m_num_unchoked; - } - } - - void policy::pulse() - { - INVARIANT_CHECK; - - if (m_torrent->is_paused()) return; - - ptime now = time_now(); - // remove old disconnected peers from the list - for (iterator i = m_peers.begin(); i != m_peers.end();) - { - // this timeout has to be customizable! - if (i->connection == 0 - && i->connected != min_time() - && now - i->connected > minutes(120)) - { - m_peers.erase(i++); - } - else - { - ++i; - } - } - - // ------------------------------------- - // maintain the number of connections - // ------------------------------------- - - // count the number of connected peers except for peers - // that are currently in the process of disconnecting - int num_connected_peers = 0; - - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - if (i->connection && !i->connection->is_disconnecting()) - ++num_connected_peers; - } - - if (m_torrent->m_connections_quota.given != std::numeric_limits::max()) - { - - int max_connections = m_torrent->m_connections_quota.given; - - if (num_connected_peers >= max_connections) - { - // every minute, disconnect the worst peer in hope of finding a better peer - - ptime local_time = time_now(); - if (m_last_optimistic_disconnect + seconds(120) <= local_time - && find_connect_candidate() != m_peers.end()) - { - m_last_optimistic_disconnect = local_time; - --max_connections; // this will have the effect of disconnecting the worst peer - } - } - else - { - // don't do a disconnect earlier than 1 minute after some peer was connected - m_last_optimistic_disconnect = time_now(); - } - - while (num_connected_peers > max_connections) - { - bool ret = disconnect_one_peer(); - (void)ret; - assert(ret); - --num_connected_peers; - } - } - - // ------------------------ - // upload shift - // ------------------------ - - // this part will shift downloads - // from peers that are seeds and peers - // that don't want to download from us - // to peers that cannot upload anything - // to us. The shifting will make sure - // that the torrent's share ratio - // will be maintained - - // if the share ratio is 0 (infinite) - // m_available_free_upload isn't used - // because it isn't necessary - if (m_torrent->ratio() != 0.f) - { - // accumulate all the free download we get - // and add it to the available free upload - m_available_free_upload - += collect_free_download( - m_torrent->begin() - , m_torrent->end()); - - // distribute the free upload among the peers - m_available_free_upload = distribute_free_upload( - m_torrent->begin() - , m_torrent->end() - , m_available_free_upload); - } - - // ------------------------ - // seed choking policy - // ------------------------ - if (m_torrent->is_seed()) - { - if (m_num_unchoked > m_torrent->m_uploads_quota.given) - { - do - { - iterator p = find_seed_choke_candidate(); - --m_num_unchoked; - assert(p != m_peers.end()); - if (p == m_peers.end()) break; - - assert(!p->connection->is_choked()); - p->connection->send_choke(); - } while (m_num_unchoked > m_torrent->m_uploads_quota.given); - } - else if (m_num_unchoked > 0) - { - // optimistic unchoke. trade the 'worst' - // unchoked peer with one of the choked - // TODO: This rotation should happen - // far less frequent than this! - assert(m_num_unchoked <= m_torrent->num_peers()); - iterator p = find_seed_unchoke_candidate(); - if (p != m_peers.end()) - { - assert(p->connection->is_choked()); - seed_choke_one_peer(); - p->connection->send_unchoke(); - ++m_num_unchoked; - } - - } - - // make sure we have enough - // unchoked peers - while (m_num_unchoked < m_torrent->m_uploads_quota.given) - { - if (!seed_unchoke_one_peer()) break; - } -#ifndef NDEBUG - check_invariant(); -#endif - } - - // ---------------------------- - // downloading choking policy - // ---------------------------- - else - { - if (m_torrent->ratio() != 0) - { - // choke peers that have leeched too much without giving anything back - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - peer_connection* c = i->connection; - if (c == 0) continue; - - size_type diff = i->connection->share_diff(); - if (diff < -free_upload_amount - && !c->is_choked()) - { - // if we have uploaded more than a piece for free, choke peer and - // wait until we catch up with our download. - c->send_choke(); - --m_num_unchoked; - } - } - } - - if (m_torrent->m_uploads_quota.given < m_torrent->num_peers()) - { - assert(m_torrent->m_uploads_quota.given >= 0); - - // make sure we don't have too many - // unchoked peers - if (m_num_unchoked > m_torrent->m_uploads_quota.given) - { - do - { - iterator p = find_choke_candidate(); - if (p == m_peers.end()) break; - assert(p != m_peers.end()); - assert(!p->connection->is_choked()); - p->connection->send_choke(); - --m_num_unchoked; - } while (m_num_unchoked > m_torrent->m_uploads_quota.given); - } - else - { - // optimistic unchoke. trade the 'worst' - // unchoked peer with one of the choked - // TODO: This rotation should happen - // far less frequent than this! - assert(m_num_unchoked <= m_torrent->num_peers()); - iterator p = find_unchoke_candidate(); - if (p != m_peers.end()) - { - assert(p->connection->is_choked()); - choke_one_peer(); - p->connection->send_unchoke(); - ++m_num_unchoked; - } - } - } - - // make sure we have enough - // unchoked peers - while (m_num_unchoked < m_torrent->m_uploads_quota.given - && unchoke_one_peer()); - } - } - - void policy::new_connection(peer_connection& c) - { - assert(!c.is_local()); - - INVARIANT_CHECK; - - // if the connection comes from the tracker, - // it's probably just a NAT-check. Ignore the - // num connections constraint then. - - // TODO: only allow _one_ connection to use this - // override at a time - assert(c.remote() == c.get_socket()->remote_endpoint()); - - if (m_torrent->num_peers() >= m_torrent->m_connections_quota.given - && c.remote().address() != m_torrent->current_tracker().address()) - { - throw protocol_error("too many connections, refusing incoming connection"); // cause a disconnect - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (c.remote().address() == m_torrent->current_tracker().address()) - { - m_torrent->debug_log("overriding connection limit for tracker NAT-check"); - } -#endif - - iterator i; - - if (m_torrent->settings().allow_multiple_connections_per_ip) - { - i = m_peers.end(); - } - else - { - i = std::find_if( - m_peers.begin() - , m_peers.end() - , match_peer_ip(c.remote())); - } - - if (i != m_peers.end()) - { - if (i->banned) - throw protocol_error("ip address banned, closing"); - - if (i->connection != 0) - { - assert(i->connection != &c); - // the new connection is a local (outgoing) connection - // or the current one is already connected - if (!i->connection->is_connecting() || c.is_local()) - { - throw protocol_error("duplicate connection, closing"); - } - else - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - m_torrent->debug_log("duplicate connection. existing connection" - " is connecting and this connection is incoming. closing existing " - "connection in favour of this one"); -#endif - i->connection->disconnect(); - } - } - } - else - { - // we don't have ny info about this peer. - // add a new entry - assert(c.remote() == c.get_socket()->remote_endpoint()); - - peer p(c.remote(), peer::not_connectable, 0); - m_peers.push_back(p); - i = boost::prior(m_peers.end()); - } - - c.set_peer_info(&*i); - assert(i->connection == 0); - c.add_stat(i->prev_amount_download, i->prev_amount_upload); - i->prev_amount_download = 0; - i->prev_amount_upload = 0; - i->connection = &c; - assert(i->connection); - i->connected = time_now(); - m_last_optimistic_disconnect = time_now(); - } - - void policy::peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid - , int src, char flags) - { - INVARIANT_CHECK; - - // just ignore the obviously invalid entries - if(remote.address() == address() || remote.port() == 0) - return; - - try - { - iterator i; - - if (m_torrent->settings().allow_multiple_connections_per_ip) - { - i = m_peers.end(); - } - else - { - i = std::find_if( - m_peers.begin() - , m_peers.end() - , match_peer_ip(remote)); - } - - if (i == m_peers.end()) - { - aux::session_impl& ses = m_torrent->session(); - - // if the IP is blocked, don't add it - if (ses.m_ip_filter.access(remote.address()) & ip_filter::blocked) - { - if (ses.m_alerts.should_post(alert::info)) - { - ses.m_alerts.post_alert(peer_blocked_alert(remote.address() - , "blocked peer not added to peer list")); - } - return; - } - - // we don't have any info about this peer. - // add a new entry - peer p(remote, peer::connectable, src); - m_peers.push_back(p); - // the iterator is invalid - // because of the push_back() - i = boost::prior(m_peers.end()); - if (flags & 0x02) p.seed = true; - - // try to send a DHT ping to this peer - // as well, to figure out if it supports - // DHT (uTorrent and BitComet doesn't - // advertise support) -#ifndef TORRENT_DISABLE_DHT - udp::endpoint node(remote.address(), remote.port()); - m_torrent->session().add_dht_node(node); -#endif - } - else - { - i->type = peer::connectable; - - // in case we got the ip from a remote connection, port is - // not known, so save it. Client may also have changed port - // for some reason. - i->ip = remote; - i->source |= src; - - // if this peer has failed before, decrease the - // counter to allow it another try, since somebody - // else is appearantly able to connect to it - // if it comes from the DHT it might be stale though - if (i->failcount > 0 && src != peer_info::dht) - --i->failcount; - - if (flags & 0x02) i->seed = true; - - if (i->connection) - { - // this means we're already connected - // to this peer. don't connect to - // it again. - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - m_torrent->debug_log("already connected to peer: " + remote.address().to_string() + ":" - + boost::lexical_cast(remote.port()) + " " - + boost::lexical_cast(i->connection->pid())); -#endif - - assert(i->connection->associated_torrent().lock().get() == m_torrent); - return; - } - } - } - catch(std::exception& e) - { - if (m_torrent->alerts().should_post(alert::debug)) - { - m_torrent->alerts().post_alert( - peer_error_alert(remote, pid, e.what())); - } - } - } - - // this is called when we are choked by a peer - // i.e. a peer lets us know that we will not receive - // anything for a while - void policy::choked(peer_connection&) - { - } - - void policy::piece_finished(int index, bool successfully_verified) - { - INVARIANT_CHECK; - - assert(index >= 0 && index < m_torrent->torrent_file().num_pieces()); - - if (successfully_verified) - { - // have all peers update their interested-flag - for (iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - if (i->connection == 0) continue; - // if we're not interested, we will not become interested - if (!i->connection->is_interesting()) continue; - if (!i->connection->has_piece(index)) continue; - - i->connection->update_interest(); - } - } - } - - // TODO: we must be able to get interested - // in a peer again, if a piece fails that - // this peer has. - void policy::block_finished(peer_connection& c, piece_block) - { - INVARIANT_CHECK; - - // if the peer hasn't choked us, ask for another piece - if (!c.has_peer_choked() && !m_torrent->is_seed()) - request_a_block(*m_torrent, c); - } - - // this is called when we are unchoked by a peer - // i.e. a peer lets us know that we will receive - // data from now on - void policy::unchoked(peer_connection& c) - { - INVARIANT_CHECK; - if (c.is_interesting()) - { - request_a_block(*m_torrent, c); - } - } - - // called when a peer is interested in us - void policy::interested(peer_connection& c) - { - INVARIANT_CHECK; - - assert(std::find_if(m_peers.begin(), m_peers.end() - , boost::bind(std::equal_to(), bind(&peer::connection, _1) - , &c)) != m_peers.end()); - - // if the peer is choked and we have upload slots left, - // then unchoke it. Another condition that has to be met - // is that the torrent doesn't keep track of the individual - // up/down ratio for each peer (ratio == 0) or (if it does - // keep track) this particular connection isn't a leecher. - // If the peer was choked because it was leeching, don't - // unchoke it again. - // The exception to this last condition is if we're a seed. - // In that case we don't care if people are leeching, they - // can't pay for their downloads anyway. - if (c.is_choked() - && m_num_unchoked < m_torrent->m_uploads_quota.given - && (m_torrent->ratio() == 0 - || c.share_diff() >= -free_upload_amount - || m_torrent->is_seed())) - { - c.send_unchoke(); - ++m_num_unchoked; - } - } - - // called when a peer is no longer interested in us - void policy::not_interested(peer_connection& c) - { - INVARIANT_CHECK; - - if (m_torrent->ratio() != 0.f) - { - assert(c.share_diff() < std::numeric_limits::max()); - size_type diff = c.share_diff(); - if (diff > 0 && c.is_seed()) - { - // the peer is a seed and has sent - // us more than we have sent it back. - // consider the download as free download - m_available_free_upload += diff; - c.add_free_upload(-diff); - } - } - if (!c.is_choked()) - { - c.send_choke(); - --m_num_unchoked; - - if (m_torrent->is_seed()) seed_unchoke_one_peer(); - else unchoke_one_peer(); - } - } - - bool policy::unchoke_one_peer() - { - INVARIANT_CHECK; - - iterator p = find_unchoke_candidate(); - if (p == m_peers.end()) return false; - assert(p->connection); - assert(!p->connection->is_disconnecting()); - - assert(p->connection->is_choked()); - p->connection->send_unchoke(); - p->last_optimistically_unchoked = time_now(); - ++m_num_unchoked; - return true; - } - - void policy::choke_one_peer() - { - INVARIANT_CHECK; - - iterator p = find_choke_candidate(); - if (p == m_peers.end()) return; - assert(p->connection); - assert(!p->connection->is_disconnecting()); - assert(!p->connection->is_choked()); - p->connection->send_choke(); - --m_num_unchoked; - } - - bool policy::connect_one_peer() - { - INVARIANT_CHECK; - - assert(m_torrent->want_more_peers()); - - iterator p = find_connect_candidate(); - if (p == m_peers.end()) return false; - - assert(!p->banned); - assert(!p->connection); - assert(p->type == peer::connectable); - - try - { - p->connected = m_last_optimistic_disconnect = time_now(); - p->connection = m_torrent->connect_to_peer(&*p); - if (p->connection == 0) return false; - p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload); - p->prev_amount_download = 0; - p->prev_amount_upload = 0; - return true; - } - catch (std::exception& e) - { -#if defined(TORRENT_VERBOSE_LOGGING) - (*m_torrent->session().m_logger) << "*** CONNECTION FAILED '" - << e.what() << "'\n"; -#endif - ++p->failcount; - return false; - } - } - - bool policy::disconnect_one_peer() - { - iterator p = find_disconnect_candidate(); - if (p == m_peers.end()) - return false; -#if defined(TORRENT_VERBOSE_LOGGING) - (*p->connection->m_logger) << "*** CLOSING CONNECTION 'too many connections'\n"; -#endif - - p->connection->disconnect(); - return true; - } - - // this is called whenever a peer connection is closed - void policy::connection_closed(const peer_connection& c) try - { - INVARIANT_CHECK; - -// assert(c.is_disconnecting()); - bool unchoked = false; - - iterator i = std::find_if( - m_peers.begin() - , m_peers.end() - , match_peer_connection(c)); - - // if we couldn't find the connection in our list, just ignore it. - if (i == m_peers.end()) return; - assert(i->connection == &c); - i->connection = 0; - - i->connected = time_now(); - if (!c.is_choked() && !m_torrent->is_aborted()) - { - unchoked = true; - } - - if (c.failed()) - { - ++i->failcount; - i->connected = time_now(); - } - - // if the share ratio is 0 (infinite), the - // m_available_free_upload isn't used, - // because it isn't necessary. - if (m_torrent->ratio() != 0.f) - { - assert(c.associated_torrent().lock().get() == m_torrent); - assert(c.share_diff() < std::numeric_limits::max()); - m_available_free_upload += c.share_diff(); - } - i->prev_amount_download += c.statistics().total_payload_download(); - i->prev_amount_upload += c.statistics().total_payload_upload(); - - if (unchoked) - { - // if the peer that is diconnecting is unchoked - // then unchoke another peer in order to maintain - // the total number of unchoked peers - --m_num_unchoked; - if (m_torrent->is_seed()) seed_unchoke_one_peer(); - else unchoke_one_peer(); - } - } - catch (std::exception& e) - { -#ifndef NDEBUG - std::string err = e.what(); -#endif - assert(false); - } - - void policy::peer_is_interesting(peer_connection& c) - { - INVARIANT_CHECK; - - c.send_interested(); - if (c.has_peer_choked()) return; - request_a_block(*m_torrent, c); - } - -#ifndef NDEBUG - bool policy::has_connection(const peer_connection* c) - { - INVARIANT_CHECK; - - assert(c); - assert(c->remote() == c->get_socket()->remote_endpoint()); - - return std::find_if( - m_peers.begin() - , m_peers.end() - , match_peer_connection(*c)) != m_peers.end(); - } - - void policy::check_invariant() const - { - if (m_torrent->is_aborted()) return; - int actual_unchoked = 0; - int connected_peers = 0; - - int total_connections = 0; - int nonempty_connections = 0; - - std::set
unique_test; - for (const_iterator i = m_peers.begin(); - i != m_peers.end(); ++i) - { - if (!m_torrent->settings().allow_multiple_connections_per_ip) - assert(unique_test.find(i->ip.address()) == unique_test.end()); - unique_test.insert(i->ip.address()); - ++total_connections; - if (!i->connection) continue; - assert(i->connection->peer_info_struct() == 0 - || i->connection->peer_info_struct() == &*i); - ++nonempty_connections; - if (!i->connection->is_disconnecting()) - ++connected_peers; - if (!i->connection->is_choked()) ++actual_unchoked; - } -// assert(actual_unchoked <= m_torrent->m_uploads_quota.given); - assert(actual_unchoked == m_num_unchoked); - - int num_torrent_peers = 0; - for (torrent::const_peer_iterator i = m_torrent->begin(); - i != m_torrent->end(); ++i) - { - if (i->second->is_disconnecting()) continue; - // ignore web_peer_connections since they are not managed - // by the policy class - if (dynamic_cast(i->second)) continue; - ++num_torrent_peers; - } - - // this invariant is a bit complicated. - // the usual case should be that connected_peers - // == num_torrent_peers. But when there's an incoming - // connection, it will first be added to the policy - // and then be added to the torrent. - // When there's an outgoing connection, it will first - // be added to the torrent and then to the policy. - // that's why the two second cases are in there. -/* - assert(connected_peers == num_torrent_peers - || (connected_peers == num_torrent_peers + 1 - && connected_peers > 0) - || (connected_peers + 1 == num_torrent_peers - && num_torrent_peers > 0)); -*/ - } -#endif - - policy::peer::peer(const tcp::endpoint& ip_, peer::connection_type t, int src) - : ip(ip_) - , type(t) - , failcount(0) - , seed(false) - , last_optimistically_unchoked(min_time()) - , connected(min_time()) - , prev_amount_upload(0) - , prev_amount_download(0) - , banned(false) - , source(src) - , connection(0) - { - assert(connected < time_now()); - } - - size_type policy::peer::total_download() const - { - if (connection != 0) - { - assert(prev_amount_download == 0); - return connection->statistics().total_payload_download(); - } - else - { - return prev_amount_download; - } - } - - size_type policy::peer::total_upload() const - { - if (connection != 0) - { - assert(prev_amount_upload == 0); - return connection->statistics().total_payload_upload(); - } - else - { - return prev_amount_upload; - } - } -} - diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp deleted file mode 100644 index 229f251c6..000000000 --- a/libtorrent/src/session.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg, Magnus Jonsson -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/file.hpp" -#include "libtorrent/allocate_resources.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/ip_filter.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" - -using boost::shared_ptr; -using boost::weak_ptr; -using boost::bind; -using boost::mutex; -using libtorrent::aux::session_impl; - -namespace libtorrent -{ - - namespace aux - { - filesystem_init::filesystem_init() - { -#if BOOST_VERSION < 103400 - using namespace boost::filesystem; - if (path::default_name_check_writable()) - path::default_name_check(no_check); -#endif - } - } - - session::session( - fingerprint const& id - , std::pair listen_port_range - , char const* listen_interface) - : m_impl(new session_impl(listen_port_range, id, listen_interface)) - { - // turn off the filename checking in boost.filesystem - assert(listen_port_range.first > 0); - assert(listen_port_range.first < listen_port_range.second); -#ifndef NDEBUG - // this test was added after it came to my attention - // that devstudios managed c++ failed to generate - // correct code for boost.function - boost::function0 test = boost::ref(*m_impl); - assert(!test.empty()); -#endif - } - - session::session(fingerprint const& id) - : m_impl(new session_impl(std::make_pair(0, 0), id)) - { -#ifndef NDEBUG - boost::function0 test = boost::ref(*m_impl); - assert(!test.empty()); -#endif - } - - session::~session() - { - assert(m_impl); - // if there is at least one destruction-proxy - // abort the session and let the destructor - // of the proxy to syncronize - if (!m_impl.unique()) - m_impl->abort(); - } - - void session::add_extension(boost::function(torrent*)> ext) - { - m_impl->add_extension(ext); - } - - void session::set_ip_filter(ip_filter const& f) - { - m_impl->set_ip_filter(f); - } - - void session::set_peer_id(peer_id const& id) - { - m_impl->set_peer_id(id); - } - - void session::set_key(int key) - { - m_impl->set_key(key); - } - - std::vector session::get_torrents() const - { - return m_impl->get_torrents(); - } - - torrent_handle session::find_torrent(sha1_hash const& info_hash) const - { - return m_impl->find_torrent_handle(info_hash); - } - - - // if the torrent already exists, this will throw duplicate_torrent - torrent_handle session::add_torrent( - torrent_info const& ti - , boost::filesystem::path const& save_path - , entry const& resume_data - , bool compact_mode - , int block_size - , storage_constructor_type sc) - { - return m_impl->add_torrent(ti, save_path, resume_data - , compact_mode, block_size, sc); - } - - torrent_handle session::add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , boost::filesystem::path const& save_path - , entry const& e - , bool compact_mode - , int block_size - , storage_constructor_type sc) - { - return m_impl->add_torrent(tracker_url, info_hash, name, save_path, e - , compact_mode, block_size, sc); - } - - void session::remove_torrent(const torrent_handle& h) - { - m_impl->remove_torrent(h); - } - - bool session::listen_on( - std::pair const& port_range - , const char* net_interface) - { - return m_impl->listen_on(port_range, net_interface); - } - - unsigned short session::listen_port() const - { - return m_impl->listen_port(); - } - - session_status session::status() const - { - return m_impl->status(); - } - -#ifndef TORRENT_DISABLE_DHT - - void session::start_dht(entry const& startup_state) - { - m_impl->start_dht(startup_state); - } - - void session::stop_dht() - { - m_impl->stop_dht(); - } - - void session::set_dht_settings(dht_settings const& settings) - { - m_impl->set_dht_settings(settings); - } - - entry session::dht_state() const - { - return m_impl->dht_state(); - } - - void session::add_dht_node(std::pair const& node) - { - m_impl->add_dht_node(node); - } - - void session::add_dht_router(std::pair const& node) - { - m_impl->add_dht_router(node); - } - -#endif - - bool session::is_listening() const - { - return m_impl->is_listening(); - } - - void session::set_settings(session_settings const& s) - { - m_impl->set_settings(s); - } - - session_settings const& session::settings() - { - return m_impl->settings(); - } - - void session::set_peer_proxy(proxy_settings const& s) - { - m_impl->set_peer_proxy(s); - } - - void session::set_web_seed_proxy(proxy_settings const& s) - { - m_impl->set_web_seed_proxy(s); - } - - void session::set_tracker_proxy(proxy_settings const& s) - { - m_impl->set_tracker_proxy(s); - } - - proxy_settings const& session::peer_proxy() const - { - return m_impl->peer_proxy(); - } - - proxy_settings const& session::web_seed_proxy() const - { - return m_impl->web_seed_proxy(); - } - - proxy_settings const& session::tracker_proxy() const - { - return m_impl->tracker_proxy(); - } - - -#ifndef TORRENT_DISABLE_DHT - void session::set_dht_proxy(proxy_settings const& s) - { - m_impl->set_dht_proxy(s); - } - - proxy_settings const& session::dht_proxy() const - { - return m_impl->dht_proxy(); - } -#endif - - void session::set_max_uploads(int limit) - { - m_impl->set_max_uploads(limit); - } - - void session::set_max_connections(int limit) - { - m_impl->set_max_connections(limit); - } - - void session::set_max_half_open_connections(int limit) - { - m_impl->set_max_half_open_connections(limit); - } - - int session::upload_rate_limit() const - { - return m_impl->upload_rate_limit(); - } - - int session::download_rate_limit() const - { - return m_impl->download_rate_limit(); - } - - void session::set_upload_rate_limit(int bytes_per_second) - { - m_impl->set_upload_rate_limit(bytes_per_second); - } - - void session::set_download_rate_limit(int bytes_per_second) - { - m_impl->set_download_rate_limit(bytes_per_second); - } - - int session::num_uploads() const - { - return m_impl->num_uploads(); - } - - int session::num_connections() const - { - return m_impl->num_connections(); - } - - std::auto_ptr session::pop_alert() - { - return m_impl->pop_alert(); - } - - void session::set_severity_level(alert::severity_t s) - { - m_impl->set_severity_level(s); - } - - connection_queue& session::get_connection_queue() - { - return m_impl->m_half_open; - } -} - diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp deleted file mode 100644 index 2e2238465..000000000 --- a/libtorrent/src/session_impl.cpp +++ /dev/null @@ -1,2063 +0,0 @@ -/* - -Copyright (c) 2006, Arvid Norberg, Magnus Jonsson -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/fingerprint.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/file.hpp" -#include "libtorrent/allocate_resources.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/ip_filter.hpp" -#include "libtorrent/socket.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/kademlia/dht_tracker.hpp" - -using boost::shared_ptr; -using boost::weak_ptr; -using boost::bind; -using boost::mutex; -using libtorrent::aux::session_impl; - -namespace libtorrent { namespace detail -{ - - std::string generate_auth_string(std::string const& user - , std::string const& passwd) - { - if (user.empty()) return std::string(); - return user + ":" + passwd; - } - - - } namespace aux { - // This is the checker thread - // it is looping in an infinite loop - // until the session is aborted. It will - // normally just block in a wait() call, - // waiting for a signal from session that - // there's a new torrent to check. - - void checker_impl::operator()() - { - eh_initializer(); - // if we're currently performing a full file check, - // this is the torrent being processed - boost::shared_ptr processing; - boost::shared_ptr t; - for (;;) - { - // temporary torrent used while checking fastresume data - try - { - t.reset(); - { - boost::mutex::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - // if the job queue is empty and - // we shouldn't abort - // wait for a signal - while (m_torrents.empty() && !m_abort && !processing) - m_cond.wait(l); - - if (m_abort) - { - // no lock is needed here, because the main thread - // has already been shut down by now - processing.reset(); - t.reset(); - std::for_each(m_torrents.begin(), m_torrents.end() - , boost::bind(&torrent::abort - , boost::bind(&shared_ptr::get - , boost::bind(&piece_checker_data::torrent_ptr, _1)))); - m_torrents.clear(); - std::for_each(m_processing.begin(), m_processing.end() - , boost::bind(&torrent::abort - , boost::bind(&shared_ptr::get - , boost::bind(&piece_checker_data::torrent_ptr, _1)))); - m_processing.clear(); - return; - } - - if (!m_torrents.empty()) - { - t = m_torrents.front(); - if (t->abort) - { - // make sure the locking order is - // consistent to avoid dead locks - // we need to lock the session because closing - // torrents assume to have access to it - l.unlock(); - session_impl::mutex_t::scoped_lock l2(m_ses.m_mutex); - l.lock(); - - t->torrent_ptr->abort(); - m_torrents.pop_front(); - continue; - } - } - } - - if (t) - { - std::string error_msg; - t->parse_resume_data(t->resume_data, t->torrent_ptr->torrent_file() - , error_msg); - - if (!error_msg.empty() && m_ses.m_alerts.should_post(alert::warning)) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.m_alerts.post_alert(fastresume_rejected_alert( - t->torrent_ptr->get_handle() - , error_msg)); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "fastresume data for " - << t->torrent_ptr->torrent_file().name() << " rejected: " - << error_msg << "\n"; -#endif - } - - // lock the session to add the new torrent - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - mutex::scoped_lock l2(m_mutex); - // clear the resume data now that it has been used - // (the fast resume data is now parsed and stored in t) - t->resume_data = entry(); - bool up_to_date = t->torrent_ptr->check_fastresume(*t); - - if (up_to_date) - { - INVARIANT_CHECK; - - assert(m_torrents.front() == t); - - t->torrent_ptr->files_checked(t->unfinished_pieces); - m_torrents.pop_front(); - - // we cannot add the torrent if the session is aborted. - if (!m_ses.is_aborted()) - { - m_ses.m_torrents.insert(std::make_pair(t->info_hash, t->torrent_ptr)); - if (t->torrent_ptr->is_seed() && m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(torrent_finished_alert( - t->torrent_ptr->get_handle() - , "torrent is complete")); - } - - peer_id id; - std::fill(id.begin(), id.end(), 0); - for (std::vector::const_iterator i = t->peers.begin(); - i != t->peers.end(); ++i) - { - t->torrent_ptr->get_policy().peer_from_tracker(*i, id - , peer_info::resume_data, 0); - } - } - else - { - t->torrent_ptr->abort(); - } - t.reset(); - continue; - } - - l.unlock(); - - // move the torrent from - // m_torrents to m_processing - assert(m_torrents.front() == t); - - m_torrents.pop_front(); - m_processing.push_back(t); - if (!processing) - { - processing = t; - processing->processing = true; - t.reset(); - } - } - } - catch (const std::exception& e) - { - // This will happen if the storage fails to initialize - // for example if one of the files has an invalid filename. - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - mutex::scoped_lock l2(m_mutex); - - if (m_ses.m_alerts.should_post(alert::fatal)) - { - m_ses.m_alerts.post_alert( - file_error_alert( - t->torrent_ptr->get_handle() - , e.what())); - } - t->torrent_ptr->abort(); - - assert(!m_torrents.empty()); - m_torrents.pop_front(); - } - catch(...) - { -#ifndef NDEBUG - std::cerr << "error while checking resume data\n"; -#endif - mutex::scoped_lock l(m_mutex); - assert(!m_torrents.empty()); - m_torrents.pop_front(); - assert(false); - } - - if (!processing) continue; - - try - { - assert(processing); - - float finished = false; - float progress = 0.f; - boost::tie(finished, progress) = processing->torrent_ptr->check_files(); - - { - mutex::scoped_lock l(m_mutex); - - INVARIANT_CHECK; - - processing->progress = progress; - if (processing->abort) - { - assert(!m_processing.empty()); - assert(m_processing.front() == processing); - - processing->torrent_ptr->abort(); - - processing.reset(); - m_processing.pop_front(); - if (!m_processing.empty()) - { - processing = m_processing.front(); - processing->processing = true; - } - continue; - } - } - if (finished) - { - // lock the session to add the new torrent - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - mutex::scoped_lock l2(m_mutex); - - INVARIANT_CHECK; - - assert(!m_processing.empty()); - assert(m_processing.front() == processing); - - // TODO: factor out the adding of torrents to the session - // and to the checker thread to avoid duplicating the - // check for abortion. - if (!m_ses.is_aborted()) - { - processing->torrent_ptr->files_checked(processing->unfinished_pieces); - m_ses.m_torrents.insert(std::make_pair( - processing->info_hash, processing->torrent_ptr)); - if (processing->torrent_ptr->is_seed() - && m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(torrent_finished_alert( - processing->torrent_ptr->get_handle() - , "torrent is complete")); - } - - peer_id id; - std::fill(id.begin(), id.end(), 0); - for (std::vector::const_iterator i = processing->peers.begin(); - i != processing->peers.end(); ++i) - { - processing->torrent_ptr->get_policy().peer_from_tracker(*i, id - , peer_info::resume_data, 0); - } - } - else - { - processing->torrent_ptr->abort(); - } - processing.reset(); - m_processing.pop_front(); - if (!m_processing.empty()) - { - processing = m_processing.front(); - processing->processing = true; - } - } - } - catch(std::exception const& e) - { - // This will happen if the storage fails to initialize - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - mutex::scoped_lock l2(m_mutex); - - if (m_ses.m_alerts.should_post(alert::fatal)) - { - m_ses.m_alerts.post_alert( - file_error_alert( - processing->torrent_ptr->get_handle() - , e.what())); - } - assert(!m_processing.empty()); - - processing->torrent_ptr->abort(); - - processing.reset(); - m_processing.pop_front(); - if (!m_processing.empty()) - { - processing = m_processing.front(); - processing->processing = true; - } - } - catch(...) - { -#ifndef NDEBUG - std::cerr << "error while checking files\n"; -#endif - mutex::scoped_lock l(m_mutex); - assert(!m_processing.empty()); - - processing.reset(); - m_processing.pop_front(); - if (!m_processing.empty()) - { - processing = m_processing.front(); - processing->processing = true; - } - - assert(false); - } - } - } - - aux::piece_checker_data* checker_impl::find_torrent(sha1_hash const& info_hash) - { - INVARIANT_CHECK; - for (std::deque >::iterator i - = m_torrents.begin(); i != m_torrents.end(); ++i) - { - if ((*i)->info_hash == info_hash) return i->get(); - } - for (std::deque >::iterator i - = m_processing.begin(); i != m_processing.end(); ++i) - { - - if ((*i)->info_hash == info_hash) return i->get(); - } - - return 0; - } - - void checker_impl::remove_torrent(sha1_hash const& info_hash) - { - INVARIANT_CHECK; - for (std::deque >::iterator i - = m_torrents.begin(); i != m_torrents.end(); ++i) - { - if ((*i)->info_hash == info_hash) - { - assert((*i)->processing == false); - m_torrents.erase(i); - return; - } - } - for (std::deque >::iterator i - = m_processing.begin(); i != m_processing.end(); ++i) - { - if ((*i)->info_hash == info_hash) - { - assert((*i)->processing == false); - m_processing.erase(i); - return; - } - } - - assert(false); - } - -#ifndef NDEBUG - void checker_impl::check_invariant() const - { - for (std::deque >::const_iterator i - = m_torrents.begin(); i != m_torrents.end(); ++i) - { - assert(*i); - assert((*i)->torrent_ptr); - } - for (std::deque >::const_iterator i - = m_processing.begin(); i != m_processing.end(); ++i) - { - assert(*i); - assert((*i)->torrent_ptr); - } - } -#endif - - struct seed_random_generator - { - seed_random_generator() - { - std::srand(total_microseconds(time_now() - min_time())); - } - }; - - session_impl::session_impl( - std::pair listen_port_range - , fingerprint const& cl_fprint - , char const* listen_interface) - : m_strand(m_io_service) - , m_files(40) - , m_half_open(m_io_service) - , m_dl_bandwidth_manager(m_io_service, peer_connection::download_channel) - , m_ul_bandwidth_manager(m_io_service, peer_connection::upload_channel) - , m_tracker_manager(m_settings, m_tracker_proxy) - , m_listen_port_range(listen_port_range) - , m_listen_interface(address::from_string(listen_interface), listen_port_range.first) - , m_external_listen_port(0) - , m_abort(false) - , m_max_uploads(-1) - , m_max_connections(-1) - , m_incoming_connection(false) - , m_last_tick(time_now()) -#ifndef TORRENT_DISABLE_DHT - , m_dht_same_port(true) - , m_external_udp_port(0) -#endif - , m_natpmp(m_io_service, m_listen_interface.address() - , bind(&session_impl::on_port_mapping, this, _1, _2, _3)) - , m_upnp(m_io_service, m_half_open, m_listen_interface.address() - , m_settings.user_agent - , bind(&session_impl::on_port_mapping, this, _1, _2, _3)) - , m_lsd(m_io_service, m_listen_interface.address() - , bind(&session_impl::on_lsd_peer, this, _1, _2)) - , m_timer(m_io_service) - , m_next_connect_torrent(0) - , m_checker_impl(*this) - { - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - m_logger = create_log("main_session", listen_port(), false); - (*m_logger) << time_now_string() << "\n"; - - m_dl_bandwidth_manager.m_ses = this; - m_ul_bandwidth_manager.m_ses = this; -#endif - -#ifdef TORRENT_STATS - m_stats_logger.open("session_stats.log"); - m_stats_logger << - "1. second\n" - "2. upload rate\n" - "3. download rate\n" - "4. downloading torrents\n" - "5. seeding torrents\n" - "6. peers\n" - "7. connecting peers\n" - "\n"; - m_second_counter = 0; -#endif - - // ---- generate a peer id ---- - static seed_random_generator seeder; - - m_key = rand() + (rand() << 15) + (rand() << 30); - std::string print = cl_fprint.to_string(); - assert(print.length() <= 20); - - // the client's fingerprint - std::copy( - print.begin() - , print.begin() + print.length() - , m_peer_id.begin()); - - // http-accepted characters: - static char const printable[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz-_.!~*'()"; - - // the random number - for (unsigned char* i = m_peer_id.begin() + print.length(); - i != m_peer_id.end(); ++i) - { - *i = printable[rand() % (sizeof(printable)-1)]; - } - - m_timer.expires_from_now(seconds(1)); - m_timer.async_wait(m_strand.wrap( - bind(&session_impl::second_tick, this, _1))); - - m_thread.reset(new boost::thread(boost::ref(*this))); - m_checker_thread.reset(new boost::thread(boost::ref(m_checker_impl))); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - void session_impl::add_extension( - boost::function(torrent*)> ext) - { - m_extensions.push_back(ext); - } -#endif - -#ifndef TORRENT_DISABLE_DHT - void session_impl::add_dht_node(udp::endpoint n) - { - if (m_dht) m_dht->add_node(n); - } -#endif - - void session_impl::abort() - { - mutex_t::scoped_lock l(m_mutex); - assert(!m_abort); - // abort the main thread - m_abort = true; - m_io_service.stop(); - l.unlock(); - - mutex::scoped_lock l2(m_checker_impl.m_mutex); - // abort the checker thread - m_checker_impl.m_abort = true; - } - - void session_impl::set_ip_filter(ip_filter const& f) - { - mutex_t::scoped_lock l(m_mutex); - m_ip_filter = f; - - // Close connections whose endpoint is filtered - // by the new ip-filter - for (session_impl::connection_map::iterator i - = m_connections.begin(); i != m_connections.end();) - { - tcp::endpoint sender = i->first->remote_endpoint(); - if (m_ip_filter.access(sender.address()) & ip_filter::blocked) - { -#if defined(TORRENT_VERBOSE_LOGGING) - (*i->second->m_logger) << "*** CONNECTION FILTERED\n"; -#endif - if (m_alerts.should_post(alert::info)) - { - m_alerts.post_alert(peer_blocked_alert(sender.address() - , "peer connection closed by IP filter")); - } - - session_impl::connection_map::iterator j = i; - ++i; - j->second->disconnect(); - } - else ++i; - } - } - - void session_impl::set_settings(session_settings const& s) - { - mutex_t::scoped_lock l(m_mutex); - m_settings = s; - m_files.resize(m_settings.file_pool_size); - // replace all occurances of '\n' with ' '. - std::string::iterator i = m_settings.user_agent.begin(); - while ((i = std::find(i, m_settings.user_agent.end(), '\n')) - != m_settings.user_agent.end()) - *i = ' '; - } - - void session_impl::open_listen_port() - { - try - { - // create listener socket - m_listen_socket = boost::shared_ptr(new socket_acceptor(m_io_service)); - - for(;;) - { - try - { - m_listen_socket->open(m_listen_interface.protocol()); - m_listen_socket->bind(m_listen_interface); - m_listen_socket->listen(); - m_external_listen_port = m_listen_interface.port(); - break; - } - catch (asio::system_error& e) - { - // TODO: make sure this is correct - if (e.code() == asio::error::host_not_found) - { - if (m_alerts.should_post(alert::fatal)) - { - std::string msg = "cannot listen on the given interface '" - + m_listen_interface.address().to_string() + "'"; - m_alerts.post_alert(listen_failed_alert(msg)); - } -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - std::string msg = "cannot listen on the given interface '" - + m_listen_interface.address().to_string() + "'"; - (*m_logger) << msg << "\n"; -#endif - assert(m_listen_socket.unique()); - m_listen_socket.reset(); - break; - } - m_listen_socket->close(); - m_listen_interface.port(m_listen_interface.port() + 1); - if (m_listen_interface.port() > m_listen_port_range.second) - { - std::stringstream msg; - msg << "none of the ports in the range [" - << m_listen_port_range.first - << ", " << m_listen_port_range.second - << "] could be opened for listening"; - m_alerts.post_alert(listen_failed_alert(msg.str())); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << msg.str() << "\n"; -#endif - m_listen_socket.reset(); - break; - } - } - } - } - catch (asio::system_error& e) - { - if (m_alerts.should_post(alert::fatal)) - { - m_alerts.post_alert(listen_failed_alert( - std::string("failed to open listen port: ") + e.what())); - } - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (m_listen_socket) - { - (*m_logger) << "listening on port: " << m_listen_interface.port() - << " external port: " << m_external_listen_port << "\n"; - } -#endif - if (m_listen_socket) async_accept(); - } - - void session_impl::async_accept() - { - shared_ptr c(new socket_type(m_io_service)); - c->instantiate(); - m_listen_socket->async_accept(c->get() - , bind(&session_impl::on_incoming_connection, this, c - , weak_ptr(m_listen_socket), _1)); - } - - void session_impl::on_incoming_connection(shared_ptr const& s - , weak_ptr const& listen_socket, asio::error_code const& e) try - { - if (listen_socket.expired()) - return; - - if (e == asio::error::operation_aborted) - return; - - mutex_t::scoped_lock l(m_mutex); - assert(listen_socket.lock() == m_listen_socket); - - if (m_abort) return; - - async_accept(); - if (e) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - std::string msg = "error accepting connection on '" - + m_listen_interface.address().to_string() + "'"; - (*m_logger) << msg << "\n"; -#endif - assert(m_listen_socket.unique()); - return; - } - - // we got a connection request! - m_incoming_connection = true; - tcp::endpoint endp = s->remote_endpoint(); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << endp << " <== INCOMING CONNECTION\n"; -#endif - if (m_ip_filter.access(endp.address()) & ip_filter::blocked) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << "filtered blocked ip\n"; -#endif - if (m_alerts.should_post(alert::info)) - { - m_alerts.post_alert(peer_blocked_alert(endp.address() - , "incoming connection blocked by IP filter")); - } - return; - } - - boost::intrusive_ptr c( - new bt_peer_connection(*this, s, 0)); -#ifndef NDEBUG - c->m_in_constructor = false; -#endif - - m_connections.insert(std::make_pair(s, c)); - } - catch (std::exception& exc) - { -#ifndef NDEBUG - std::string err = exc.what(); -#endif - }; - - void session_impl::connection_failed(boost::shared_ptr const& s - , tcp::endpoint const& a, char const* message) -#ifndef NDEBUG - try -#endif - { - mutex_t::scoped_lock l(m_mutex); - - connection_map::iterator p = m_connections.find(s); - - // the connection may have been disconnected in the receive or send phase - if (p == m_connections.end()) return; - if (m_alerts.should_post(alert::debug)) - { - m_alerts.post_alert( - peer_error_alert( - a - , p->second->pid() - , message)); - } - -#if defined(TORRENT_VERBOSE_LOGGING) - (*p->second->m_logger) << "*** CONNECTION FAILED " << message << "\n"; -#endif - p->second->set_failed(); - p->second->disconnect(); - } -#ifndef NDEBUG - catch (...) - { - assert(false); - }; -#endif - - void session_impl::close_connection(boost::intrusive_ptr const& p) - { - mutex_t::scoped_lock l(m_mutex); - - assert(p->is_disconnecting()); - connection_map::iterator i = m_connections.find(p->get_socket()); - if (i != m_connections.end()) - m_connections.erase(i); - } - - void session_impl::set_peer_id(peer_id const& id) - { - mutex_t::scoped_lock l(m_mutex); - m_peer_id = id; - } - - void session_impl::set_key(int key) - { - mutex_t::scoped_lock l(m_mutex); - m_key = key; - } - - void session_impl::second_tick(asio::error_code const& e) try - { - session_impl::mutex_t::scoped_lock l(m_mutex); - - if (e) - { -#if defined(TORRENT_LOGGING) - (*m_logger) << "*** SECOND TIMER FAILED " << e.message() << "\n"; -#endif - m_abort = true; - m_io_service.stop(); - return; - } - - if (m_abort) return; - float tick_interval = total_microseconds(time_now() - m_last_tick) / 1000000.f; - m_last_tick = time_now(); - - m_timer.expires_from_now(seconds(1)); - m_timer.async_wait(m_strand.wrap( - bind(&session_impl::second_tick, this, _1))); - -#ifdef TORRENT_STATS - ++m_second_counter; - int downloading_torrents = 0; - int seeding_torrents = 0; - for (torrent_map::iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; ++i) - { - if (i->second->is_seed()) - ++seeding_torrents; - else - ++downloading_torrents; - } - int num_connections = 0; - int num_half_open = 0; - for (connection_map::iterator i = m_connections.begin() - , end(m_connections.end()); i != end; ++i) - { - if (i->second->is_connecting()) - ++num_half_open; - else - ++num_connections; - } - - m_stats_logger - << m_second_counter << "\t" - << m_stat.upload_rate() << "\t" - << m_stat.download_rate() << "\t" - << downloading_torrents << "\t" - << seeding_torrents << "\t" - << num_connections << "\t" - << num_half_open << "\t" - << std::endl; -#endif - - - // let torrents connect to peers if they want to - // if there are any torrents and any free slots - if (!m_torrents.empty() && m_half_open.free_slots()) - { - torrent_map::iterator next_connect_torrent = m_torrents.begin(); - if (m_next_connect_torrent < int(m_torrents.size())) - std::advance(next_connect_torrent, m_next_connect_torrent); - else - m_next_connect_torrent = 0; - torrent_map::iterator i = next_connect_torrent; - do - { - torrent& t = *i->second; - if (t.want_more_peers()) - t.try_connect_peer(); - ++m_next_connect_torrent; - if (!m_half_open.free_slots()) break; - ++i; - if (i == m_torrents.end()) - { - assert(m_next_connect_torrent == int(m_torrents.size())); - i = m_torrents.begin(); - m_next_connect_torrent = 0; - } - } while (i != next_connect_torrent); - } - - // do the second_tick() on each connection - // this will update their statistics (download and upload speeds) - // also purge sockets that have timed out - // and keep sockets open by keeping them alive. - for (connection_map::iterator i = m_connections.begin(); - i != m_connections.end();) - { - // we need to do like this because j->second->disconnect() will - // erase the connection from the map we're iterating - connection_map::iterator j = i; - ++i; - // if this socket has timed out - // close it. - peer_connection& c = *j->second; - if (c.has_timed_out()) - { - if (m_alerts.should_post(alert::debug)) - { - m_alerts.post_alert( - peer_error_alert( - c.remote() - , c.pid() - , "connection timed out")); - } -#if defined(TORRENT_VERBOSE_LOGGING) - (*c.m_logger) << "*** CONNECTION TIMED OUT\n"; -#endif - - c.set_failed(); - c.disconnect(); - continue; - } - - try - { - c.keep_alive(); - } - catch (std::exception& exc) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*c.m_logger) << "**ERROR**: " << exc.what() << "\n"; -#endif - c.set_failed(); - c.disconnect(); - } - } - - // check each torrent for tracker updates - // TODO: do this in a timer-event in each torrent instead - for (torrent_map::iterator i = m_torrents.begin(); - i != m_torrents.end();) - { - torrent& t = *i->second; - assert(!t.is_aborted()); - if (t.should_request()) - { - tracker_request req = t.generate_tracker_request(); - req.listen_port = m_external_listen_port; - req.key = m_key; - m_tracker_manager.queue_request(m_strand, m_half_open, req - , t.tracker_login(), m_listen_interface.address(), i->second); - - if (m_alerts.should_post(alert::info)) - { - m_alerts.post_alert( - tracker_announce_alert( - t.get_handle(), "tracker announce")); - } - } - - // second_tick() will set the used upload quota - t.second_tick(m_stat, tick_interval); - ++i; - } - - m_stat.second_tick(tick_interval); - // distribute the maximum upload rate among the torrents - - assert(m_max_uploads >= -1); - assert(m_max_connections >= -1); - - allocate_resources(m_max_uploads == -1 - ? std::numeric_limits::max() - : m_max_uploads - , m_torrents - , &torrent::m_uploads_quota); - - allocate_resources(m_max_connections == -1 - ? std::numeric_limits::max() - : m_max_connections - , m_torrents - , &torrent::m_connections_quota); - - for (std::map >::iterator i - = m_torrents.begin(); i != m_torrents.end(); ++i) - { -#ifndef NDEBUG - i->second->check_invariant(); -#endif - i->second->distribute_resources(tick_interval); - } - } - catch (std::exception& exc) - { -#ifndef NDEBUG - std::cerr << exc.what() << std::endl; - assert(false); -#endif - }; // msvc 7.1 seems to require this -/* - void session_impl::connection_completed( - boost::intrusive_ptr const& p) try - { - mutex_t::scoped_lock l(m_mutex); - - connection_map::iterator i = m_half_open.find(p->get_socket()); - m_connections.insert(std::make_pair(p->get_socket(), p)); - assert(i != m_half_open.end()); - if (i != m_half_open.end()) m_half_open.erase(i); - - if (m_abort) return; - - process_connection_queue(); - } - catch (std::exception& e) - { -#ifndef NDEBUG - std::cerr << e.what() << std::endl; - assert(false); -#endif - }; -*/ - void session_impl::operator()() - { - eh_initializer(); - - if (m_listen_port_range.first != 0 && m_listen_port_range.second != 0) - { - session_impl::mutex_t::scoped_lock l(m_mutex); - open_listen_port(); - m_natpmp.set_mappings(m_listen_interface.port(), 0); - m_upnp.set_mappings(m_listen_interface.port(), 0); - } - - ptime timer = time_now(); - - do - { - try - { - m_io_service.run(); - assert(m_abort == true); - } - catch (std::exception& e) - { -#ifndef NDEBUG - std::cerr << e.what() << "\n"; - std::string err = e.what(); -#endif - assert(false); - } - } - while (!m_abort); - - deadline_timer tracker_timer(m_io_service); - // this will remove the port mappings - m_natpmp.close(); - m_upnp.close(); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " locking mutex\n"; -#endif - session_impl::mutex_t::scoped_lock l(m_mutex); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " aborting all tracker requests\n"; -#endif - m_tracker_manager.abort_all_requests(); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " sending stopped to all torrent's trackers\n"; -#endif - for (std::map >::iterator i = - m_torrents.begin(); i != m_torrents.end(); ++i) - { - i->second->abort(); - // generate a tracker request in case the torrent is not paused - // (in which case it's not currently announced with the tracker) - // or if the torrent itself thinks we should request. Do not build - // a request in case the torrent doesn't have any trackers - if ((!i->second->is_paused() || i->second->should_request()) - && !i->second->trackers().empty()) - { - tracker_request req = i->second->generate_tracker_request(); - assert(m_external_listen_port > 0); - req.listen_port = m_external_listen_port; - req.key = m_key; - std::string login = i->second->tracker_login(); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr tl(new tracker_logger(*this)); - m_tracker_loggers.push_back(tl); - m_tracker_manager.queue_request(m_strand, m_half_open, req, login - , m_listen_interface.address(), tl); -#else - m_tracker_manager.queue_request(m_strand, m_half_open, req, login - , m_listen_interface.address()); -#endif - } - } - - ptime start(time_now()); - l.unlock(); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " waiting for trackers to respond (" - << m_settings.stop_tracker_timeout << " seconds timeout)\n"; -#endif - - while (time_now() - start < seconds( - m_settings.stop_tracker_timeout) - && !m_tracker_manager.empty()) - { - tracker_timer.expires_from_now(milliseconds(100)); - tracker_timer.async_wait(m_strand.wrap( - bind(&io_service::stop, &m_io_service))); - - m_io_service.reset(); - m_io_service.run(); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " tracker shutdown complete, locking mutex\n"; -#endif - - l.lock(); - assert(m_abort); - m_abort = true; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " cleaning up connections\n"; -#endif - while (!m_connections.empty()) - m_connections.begin()->second->disconnect(); - -#ifndef NDEBUG - for (torrent_map::iterator i = m_torrents.begin(); - i != m_torrents.end(); ++i) - { - assert(i->second->num_peers() == 0); - } -#endif - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " cleaning up torrents\n"; -#endif - m_torrents.clear(); - - assert(m_torrents.empty()); - assert(m_connections.empty()); - } - - - // the return value from this function is valid only as long as the - // session is locked! - boost::weak_ptr session_impl::find_torrent(sha1_hash const& info_hash) - { - std::map >::iterator i - = m_torrents.find(info_hash); -#ifndef NDEBUG - for (std::map >::iterator j - = m_torrents.begin(); j != m_torrents.end(); ++j) - { - torrent* p = boost::get_pointer(j->second); - assert(p); - } -#endif - if (i != m_torrents.end()) return i->second; - return boost::weak_ptr(); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr session_impl::create_log(std::string const& name - , int instance, bool append) - { - // current options are file_logger, cout_logger and null_logger - return boost::shared_ptr(new logger(name + ".log", instance, append)); - } -#endif - - std::vector session_impl::get_torrents() - { - mutex_t::scoped_lock l(m_mutex); - mutex::scoped_lock l2(m_checker_impl.m_mutex); - std::vector ret; - for (std::deque >::iterator i - = m_checker_impl.m_torrents.begin() - , end(m_checker_impl.m_torrents.end()); i != end; ++i) - { - if ((*i)->abort) continue; - ret.push_back(torrent_handle(this, &m_checker_impl - , (*i)->info_hash)); - } - - for (std::deque >::iterator i - = m_checker_impl.m_processing.begin() - , end(m_checker_impl.m_processing.end()); i != end; ++i) - { - if ((*i)->abort) continue; - ret.push_back(torrent_handle(this, &m_checker_impl - , (*i)->info_hash)); - } - - for (session_impl::torrent_map::iterator i - = m_torrents.begin(), end(m_torrents.end()); - i != end; ++i) - { - if (i->second->is_aborted()) continue; - ret.push_back(torrent_handle(this, &m_checker_impl - , i->first)); - } - return ret; - } - - torrent_handle session_impl::find_torrent_handle(sha1_hash const& info_hash) - { - return torrent_handle(this, &m_checker_impl, info_hash); - } - - torrent_handle session_impl::add_torrent( - torrent_info const& ti - , boost::filesystem::path const& save_path - , entry const& resume_data - , bool compact_mode - , int block_size - , storage_constructor_type sc) - { - // if you get this assert, you haven't managed to - // open a listen port. call listen_on() first. - assert(m_external_listen_port > 0); - - // make sure the block_size is an even power of 2 -#ifndef NDEBUG - for (int i = 0; i < 32; ++i) - { - if (block_size & (1 << i)) - { - assert((block_size & ~(1 << i)) == 0); - break; - } - } -#endif - - assert(!save_path.empty()); - - if (ti.begin_files() == ti.end_files()) - throw std::runtime_error("no files in torrent"); - - // lock the session and the checker thread (the order is important!) - mutex_t::scoped_lock l(m_mutex); - mutex::scoped_lock l2(m_checker_impl.m_mutex); - - if (is_aborted()) - throw std::runtime_error("session is closing"); - - // is the torrent already active? - if (!find_torrent(ti.info_hash()).expired()) - throw duplicate_torrent(); - - // is the torrent currently being checked? - if (m_checker_impl.find_torrent(ti.info_hash())) - throw duplicate_torrent(); - - // create the torrent and the data associated with - // the checker thread and store it before starting - // the thread - boost::shared_ptr torrent_ptr( - new torrent(*this, m_checker_impl, ti, save_path - , m_listen_interface, compact_mode, block_size - , settings(), sc)); - torrent_ptr->start(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr tp((*i)(torrent_ptr.get())); - if (tp) torrent_ptr->add_extension(tp); - } -#endif - - boost::shared_ptr d( - new aux::piece_checker_data); - d->torrent_ptr = torrent_ptr; - d->save_path = save_path; - d->info_hash = ti.info_hash(); - d->resume_data = resume_data; - -#ifndef TORRENT_DISABLE_DHT - if (m_dht) - { - torrent_info::nodes_t const& nodes = ti.nodes(); - std::for_each(nodes.begin(), nodes.end(), bind( - (void(dht::dht_tracker::*)(std::pair const&)) - &dht::dht_tracker::add_node - , boost::ref(m_dht), _1)); - } -#endif - - // add the torrent to the queue to be checked - m_checker_impl.m_torrents.push_back(d); - // and notify the thread that it got another - // job in its queue - m_checker_impl.m_cond.notify_one(); - - return torrent_handle(this, &m_checker_impl, ti.info_hash()); - } - - torrent_handle session_impl::add_torrent( - char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , boost::filesystem::path const& save_path - , entry const& - , bool compact_mode - , int block_size - , storage_constructor_type sc) - { - // make sure the block_size is an even power of 2 -#ifndef NDEBUG - for (int i = 0; i < 32; ++i) - { - if (block_size & (1 << i)) - { - assert((block_size & ~(1 << i)) == 0); - break; - } - } -#endif - - // TODO: support resume data in this case - assert(!save_path.empty()); - { - // lock the checker_thread - mutex::scoped_lock l(m_checker_impl.m_mutex); - - // is the torrent currently being checked? - if (m_checker_impl.find_torrent(info_hash)) - throw duplicate_torrent(); - } - - // lock the session - session_impl::mutex_t::scoped_lock l(m_mutex); - - // is the torrent already active? - if (!find_torrent(info_hash).expired()) - throw duplicate_torrent(); - - // you cannot add new torrents to a session that is closing down - assert(!is_aborted()); - - // create the torrent and the data associated with - // the checker thread and store it before starting - // the thread - boost::shared_ptr torrent_ptr( - new torrent(*this, m_checker_impl, tracker_url, info_hash, name - , save_path, m_listen_interface, compact_mode, block_size - , settings(), sc)); - torrent_ptr->start(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr tp((*i)(torrent_ptr.get())); - if (tp) torrent_ptr->add_extension(tp); - } -#endif - - m_torrents.insert( - std::make_pair(info_hash, torrent_ptr)).first; - - return torrent_handle(this, &m_checker_impl, info_hash); - } - - void session_impl::remove_torrent(const torrent_handle& h) - { - if (h.m_ses != this) return; - assert(h.m_chk == &m_checker_impl || h.m_chk == 0); - assert(h.m_ses != 0); - - mutex_t::scoped_lock l(m_mutex); - session_impl::torrent_map::iterator i = - m_torrents.find(h.m_info_hash); - if (i != m_torrents.end()) - { - torrent& t = *i->second; - t.abort(); - - if ((!t.is_paused() || t.should_request()) - && !t.torrent_file().trackers().empty()) - { - tracker_request req = t.generate_tracker_request(); - assert(req.event == tracker_request::stopped); - assert(m_external_listen_port > 0); - req.listen_port = m_external_listen_port; - req.key = m_key; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - boost::shared_ptr tl(new tracker_logger(*this)); - m_tracker_loggers.push_back(tl); - m_tracker_manager.queue_request(m_strand, m_half_open, req - , t.tracker_login(), m_listen_interface.address(), tl); -#else - m_tracker_manager.queue_request(m_strand, m_half_open, req - , t.tracker_login(), m_listen_interface.address()); -#endif - - if (m_alerts.should_post(alert::info)) - { - m_alerts.post_alert( - tracker_announce_alert( - t.get_handle(), "tracker announce, event=stopped")); - } - } -#ifndef NDEBUG - sha1_hash i_hash = t.torrent_file().info_hash(); -#endif - m_torrents.erase(i); - assert(m_torrents.find(i_hash) == m_torrents.end()); - return; - } - l.unlock(); - - if (h.m_chk) - { - mutex::scoped_lock l(m_checker_impl.m_mutex); - - aux::piece_checker_data* d = m_checker_impl.find_torrent(h.m_info_hash); - if (d != 0) - { - if (d->processing) d->abort = true; - else m_checker_impl.remove_torrent(h.m_info_hash); - return; - } - } - } - - bool session_impl::listen_on( - std::pair const& port_range - , const char* net_interface) - { - session_impl::mutex_t::scoped_lock l(m_mutex); - - tcp::endpoint new_interface; - if (net_interface && std::strlen(net_interface) > 0) - new_interface = tcp::endpoint(address::from_string(net_interface), port_range.first); - else - new_interface = tcp::endpoint(address(), port_range.first); - - m_listen_port_range = port_range; - - // if the interface is the same and the socket is open - // don't do anything - if (new_interface == m_listen_interface - && m_listen_socket) return true; - - if (m_listen_socket) - m_listen_socket.reset(); - - m_incoming_connection = false; - m_listen_interface = new_interface; - - open_listen_port(); - - bool new_listen_address = m_listen_interface.address() != new_interface.address(); - - if (new_listen_address) - { - m_natpmp.rebind(new_interface.address()); - m_upnp.rebind(new_interface.address()); - m_lsd.rebind(new_interface.address()); - } - - m_natpmp.set_mappings(m_listen_interface.port(), 0); - m_upnp.set_mappings(m_listen_interface.port(), 0); - -#ifndef TORRENT_DISABLE_DHT - if ((new_listen_address || m_dht_same_port) && m_dht) - { - if (m_dht_same_port) - m_dht_settings.service_port = new_interface.port(); - // the listen interface changed, rebind the dht listen socket as well - m_dht->rebind(new_interface.address() - , m_dht_settings.service_port); - m_natpmp.set_mappings(0, m_dht_settings.service_port); - m_upnp.set_mappings(0, m_dht_settings.service_port); - } -#endif - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - m_logger = create_log("main_session", listen_port(), false); - (*m_logger) << time_now_string() << "\n"; -#endif - - return m_listen_socket; - } - - unsigned short session_impl::listen_port() const - { - mutex_t::scoped_lock l(m_mutex); - return m_external_listen_port; - } - - void session_impl::announce_lsd(sha1_hash const& ih) - { - mutex_t::scoped_lock l(m_mutex); - // use internal listen port for local peers - m_lsd.announce(ih, m_listen_interface.port()); - } - - void session_impl::on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih) - { - mutex_t::scoped_lock l(m_mutex); - - boost::shared_ptr t = find_torrent(ih).lock(); - if (!t) return; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() - << ": added peer from local discovery: " << peer << "\n"; -#endif - t->get_policy().peer_from_tracker(peer, peer_id(0), peer_info::lsd, 0); - } - - void session_impl::on_port_mapping(int tcp_port, int udp_port - , std::string const& errmsg) - { -#ifndef TORRENT_DISABLE_DHT - if (udp_port != 0) - { - m_external_udp_port = udp_port; - m_dht_settings.service_port = udp_port; - if (m_alerts.should_post(alert::info)) - { - std::stringstream msg; - msg << "successfully mapped UDP port " << udp_port; - m_alerts.post_alert(portmap_alert(msg.str())); - } - } -#endif - - if (tcp_port != 0) - { - m_external_listen_port = tcp_port; - if (m_alerts.should_post(alert::info)) - { - std::stringstream msg; - msg << "successfully mapped TCP port " << tcp_port; - m_alerts.post_alert(portmap_alert(msg.str())); - } - } - - if (!errmsg.empty()) - { - if (m_alerts.should_post(alert::warning)) - { - std::stringstream msg; - msg << "Error while mapping ports on NAT router: " << errmsg; - m_alerts.post_alert(portmap_error_alert(msg.str())); - } - } - } - - session_status session_impl::status() const - { - mutex_t::scoped_lock l(m_mutex); - session_status s; - s.has_incoming_connections = m_incoming_connection; - s.num_peers = (int)m_connections.size(); - - s.download_rate = m_stat.download_rate(); - s.upload_rate = m_stat.upload_rate(); - - s.payload_download_rate = m_stat.download_payload_rate(); - s.payload_upload_rate = m_stat.upload_payload_rate(); - - s.total_download = m_stat.total_protocol_download() - + m_stat.total_payload_download(); - - s.total_upload = m_stat.total_protocol_upload() - + m_stat.total_payload_upload(); - - s.total_payload_download = m_stat.total_payload_download(); - s.total_payload_upload = m_stat.total_payload_upload(); - -#ifndef TORRENT_DISABLE_DHT - if (m_dht) - { - m_dht->dht_status(s); - } - else - { - s.dht_nodes = 0; - s.dht_node_cache = 0; - s.dht_torrents = 0; - s.dht_global_nodes = 0; - } -#endif - - return s; - } - -#ifndef TORRENT_DISABLE_DHT - - void session_impl::start_dht(entry const& startup_state) - { - mutex_t::scoped_lock l(m_mutex); - if (m_dht) - { - m_dht->stop(); - m_dht = 0; - } - if (m_dht_settings.service_port == 0 - || m_dht_same_port) - { - m_dht_same_port = true; - // if you hit this assert you are trying to start the - // DHT with the same port as the tcp listen port - // (which is default) _before_ you have opened the - // tcp listen port (so there is no configured port to use) - // basically, make sure you call listen_on() before - // start_dht(). See documentation for listen_on() for - // more information. - assert(m_listen_interface.port() > 0); - m_dht_settings.service_port = m_listen_interface.port(); - } - m_external_udp_port = m_dht_settings.service_port; - m_natpmp.set_mappings(0, m_dht_settings.service_port); - m_upnp.set_mappings(0, m_dht_settings.service_port); - m_dht = new dht::dht_tracker(m_io_service - , m_dht_settings, m_listen_interface.address() - , startup_state); - } - - void session_impl::stop_dht() - { - mutex_t::scoped_lock l(m_mutex); - if (!m_dht) return; - m_dht->stop(); - m_dht = 0; - } - - void session_impl::set_dht_settings(dht_settings const& settings) - { - mutex_t::scoped_lock l(m_mutex); - // only change the dht listen port in case the settings - // contains a vaiid port, and if it is different from - // the current setting - if (settings.service_port != 0) - m_dht_same_port = false; - else - m_dht_same_port = true; - if (!m_dht_same_port - && settings.service_port != m_dht_settings.service_port - && m_dht) - { - m_dht->rebind(m_listen_interface.address() - , settings.service_port); - m_natpmp.set_mappings(0, m_dht_settings.service_port); - m_upnp.set_mappings(0, m_dht_settings.service_port); - m_external_udp_port = settings.service_port; - } - m_dht_settings = settings; - if (m_dht_same_port) - m_dht_settings.service_port = m_listen_interface.port(); - } - - entry session_impl::dht_state() const - { - assert(m_dht); - mutex_t::scoped_lock l(m_mutex); - return m_dht->state(); - } - - void session_impl::add_dht_node(std::pair const& node) - { - assert(m_dht); - mutex_t::scoped_lock l(m_mutex); - m_dht->add_node(node); - } - - void session_impl::add_dht_router(std::pair const& node) - { - assert(m_dht); - mutex_t::scoped_lock l(m_mutex); - m_dht->add_router_node(node); - } - -#endif - - void session_impl::set_download_rate_limit(int bytes_per_second) - { - assert(bytes_per_second > 0 || bytes_per_second == -1); - mutex_t::scoped_lock l(m_mutex); - if (bytes_per_second == -1) bytes_per_second = bandwidth_limit::inf; - m_dl_bandwidth_manager.throttle(bytes_per_second); - } - - bool session_impl::is_listening() const - { - mutex_t::scoped_lock l(m_mutex); - return m_listen_socket; - } - - session_impl::~session_impl() - { -#ifndef TORRENT_DISABLE_DHT - stop_dht(); -#endif - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n"; -#endif - // lock the main thread and abort it - mutex_t::scoped_lock l(m_mutex); - m_abort = true; - m_io_service.stop(); - l.unlock(); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " waiting for main thread\n"; -#endif - m_thread->join(); - - assert(m_torrents.empty()); - - // it's important that the main thread is closed completely before - // the checker thread is terminated. Because all the connections - // have to be closed and removed from the torrents before they - // can be destructed. (because the weak pointers in the - // peer_connections will be invalidated when the torrents are - // destructed and then the invariant will be broken). - - { - mutex::scoped_lock l(m_checker_impl.m_mutex); - // abort the checker thread - m_checker_impl.m_abort = true; - - // abort the currently checking torrent - if (!m_checker_impl.m_torrents.empty()) - { - m_checker_impl.m_torrents.front()->abort = true; - } - m_checker_impl.m_cond.notify_one(); - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " waiting for checker thread\n"; -#endif - m_checker_thread->join(); - - assert(m_torrents.empty()); - assert(m_connections.empty()); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_logger) << time_now_string() << " shutdown complete!\n"; -#endif - } - - void session_impl::set_max_uploads(int limit) - { - assert(limit > 0 || limit == -1); - mutex_t::scoped_lock l(m_mutex); - m_max_uploads = limit; - } - - void session_impl::set_max_connections(int limit) - { - assert(limit > 0 || limit == -1); - mutex_t::scoped_lock l(m_mutex); - m_max_connections = limit; - } - - void session_impl::set_max_half_open_connections(int limit) - { - assert(limit > 0 || limit == -1); - mutex_t::scoped_lock l(m_mutex); - - m_half_open.limit(limit); - } - - void session_impl::set_upload_rate_limit(int bytes_per_second) - { - assert(bytes_per_second > 0 || bytes_per_second == -1); - mutex_t::scoped_lock l(m_mutex); - if (bytes_per_second == -1) bytes_per_second = bandwidth_limit::inf; - m_ul_bandwidth_manager.throttle(bytes_per_second); - } - - int session_impl::num_uploads() const - { - int uploads = 0; - mutex_t::scoped_lock l(m_mutex); - for (torrent_map::const_iterator i = m_torrents.begin() - , end(m_torrents.end()); i != end; i++) - { - uploads += i->second->get_policy().num_uploads(); - } - return uploads; - } - - int session_impl::num_connections() const - { - mutex_t::scoped_lock l(m_mutex); - return m_connections.size(); - } - - - std::auto_ptr session_impl::pop_alert() - { - mutex_t::scoped_lock l(m_mutex); - if (m_alerts.pending()) - return m_alerts.get(); - return std::auto_ptr(0); - } - - void session_impl::set_severity_level(alert::severity_t s) - { - mutex_t::scoped_lock l(m_mutex); - m_alerts.set_severity(s); - } - - int session_impl::upload_rate_limit() const - { - mutex_t::scoped_lock l(m_mutex); - return m_ul_bandwidth_manager.throttle(); - } - - int session_impl::download_rate_limit() const - { - mutex_t::scoped_lock l(m_mutex); - return m_dl_bandwidth_manager.throttle(); - } - -#ifndef NDEBUG - void session_impl::check_invariant(const char *place) - { - assert(place); - for (connection_map::iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - assert(i->second); - boost::shared_ptr t = i->second->associated_torrent().lock(); - - if (t) - { - assert(t->get_policy().has_connection(boost::get_pointer(i->second))); - } - } - } -#endif - - void piece_checker_data::parse_resume_data( - const entry& resume_data - , const torrent_info& info - , std::string& error) - { - // if we don't have any resume data, return - if (resume_data.type() == entry::undefined_t) return; - - entry rd = resume_data; - - try - { - if (rd["file-format"].string() != "libtorrent resume file") - { - error = "missing file format tag"; - return; - } - - if (rd["file-version"].integer() > 1) - { - error = "incompatible file version " - + boost::lexical_cast(rd["file-version"].integer()); - return; - } - - // verify info_hash - sha1_hash hash = rd["info-hash"].string(); - if (hash != info.info_hash()) - { - error = "mismatching info-hash: " + boost::lexical_cast(hash); - return; - } - - // the peers - - if (rd.find_key("peers")) - { - entry::list_type& peer_list = rd["peers"].list(); - - std::vector tmp_peers; - tmp_peers.reserve(peer_list.size()); - for (entry::list_type::iterator i = peer_list.begin(); - i != peer_list.end(); ++i) - { - tcp::endpoint a( - address::from_string((*i)["ip"].string()) - , (unsigned short)(*i)["port"].integer()); - tmp_peers.push_back(a); - } - - peers.swap(tmp_peers); - } - - // read piece map - const entry::list_type& slots = rd["slots"].list(); - if ((int)slots.size() > info.num_pieces()) - { - error = "file has more slots than torrent (slots: " - + boost::lexical_cast(slots.size()) + " size: " - + boost::lexical_cast(info.num_pieces()) + " )"; - return; - } - - std::vector tmp_pieces; - tmp_pieces.reserve(slots.size()); - for (entry::list_type::const_iterator i = slots.begin(); - i != slots.end(); ++i) - { - int index = (int)i->integer(); - if (index >= info.num_pieces() || index < -2) - { - error = "too high index number in slot map (index: " - + boost::lexical_cast(index) + " size: " - + boost::lexical_cast(info.num_pieces()) + ")"; - return; - } - tmp_pieces.push_back(index); - } - - // only bother to check the partial pieces if we have the same block size - // as in the fast resume data. If the blocksize has changed, then throw - // away all partial pieces. - std::vector tmp_unfinished; - int num_blocks_per_piece = (int)rd["blocks per piece"].integer(); - if (num_blocks_per_piece == info.piece_length() / torrent_ptr->block_size()) - { - // the unfinished pieces - - entry::list_type& unfinished = rd["unfinished"].list(); - int unfinished_size = int(unfinished.size()); - block_info.resize(num_blocks_per_piece * unfinished_size); - tmp_unfinished.reserve(unfinished_size); - int index = 0; - for (entry::list_type::iterator i = unfinished.begin(); - i != unfinished.end(); ++i, ++index) - { - piece_picker::downloading_piece p; - p.info = &block_info[index * num_blocks_per_piece]; - p.index = (int)(*i)["piece"].integer(); - if (p.index < 0 || p.index >= info.num_pieces()) - { - error = "invalid piece index in unfinished piece list (index: " - + boost::lexical_cast(p.index) + " size: " - + boost::lexical_cast(info.num_pieces()) + ")"; - return; - } - - const std::string& bitmask = (*i)["bitmask"].string(); - - const int num_bitmask_bytes = std::max(num_blocks_per_piece / 8, 1); - if ((int)bitmask.size() != num_bitmask_bytes) - { - error = "invalid size of bitmask (" + boost::lexical_cast(bitmask.size()) + ")"; - return; - } - for (int j = 0; j < num_bitmask_bytes; ++j) - { - unsigned char bits = bitmask[j]; - for (int k = 0; k < 8; ++k) - { - const int bit = j * 8 + k; - if (bits & (1 << k)) - { - p.info[bit].finished = true; - ++p.finished; - } - } - } - - if (p.finished == 0) continue; - - std::vector::iterator slot_iter - = std::find(tmp_pieces.begin(), tmp_pieces.end(), p.index); - if (slot_iter == tmp_pieces.end()) - { - // this piece is marked as unfinished - // but doesn't have any storage - error = "piece " + boost::lexical_cast(p.index) + " is " - "marked as unfinished, but doesn't have any storage"; - return; - } - - assert(*slot_iter == p.index); - int slot_index = static_cast(slot_iter - tmp_pieces.begin()); - unsigned long adler - = torrent_ptr->filesystem().piece_crc( - slot_index - , torrent_ptr->block_size() - , p.info); - - const entry& ad = (*i)["adler32"]; - - // crc's didn't match, don't use the resume data - if (ad.integer() != entry::integer_type(adler)) - { - error = "checksum mismatch on piece " - + boost::lexical_cast(p.index); - return; - } - - tmp_unfinished.push_back(p); - } - } - - if (!torrent_ptr->verify_resume_data(rd, error)) - return; - - piece_map.swap(tmp_pieces); - unfinished_pieces.swap(tmp_unfinished); - } - catch (invalid_encoding&) - { - return; - } - catch (type_error&) - { - return; - } - catch (file_error&) - { - return; - } - } -}} - diff --git a/libtorrent/src/sha1.cpp b/libtorrent/src/sha1.cpp deleted file mode 100644 index a7ea67113..000000000 --- a/libtorrent/src/sha1.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/* -SHA-1 C++ conversion - -original version: - -SHA-1 in C -By Steve Reid -100% Public Domain - -changelog at the end of the file. -*/ - -#include "libtorrent/pch.hpp" - -#include -#include - -// if you don't want boost -// replace with -// #include - -#include -using boost::uint32_t; -using boost::uint8_t; - -#include "libtorrent/config.hpp" - -struct TORRENT_EXPORT SHA_CTX -{ - uint32_t state[5]; - uint32_t count[2]; - uint8_t buffer[64]; -}; - -TORRENT_EXPORT void SHA1_Init(SHA_CTX* context); -TORRENT_EXPORT void SHA1_Update(SHA_CTX* context, uint8_t const* data, uint32_t len); -TORRENT_EXPORT void SHA1_Final(uint8_t* digest, SHA_CTX* context); - -namespace -{ - union CHAR64LONG16 - { - uint8_t c[64]; - uint32_t l[16]; - }; - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -// blk0() and blk() perform the initial expand. -// I got the idea of expanding during the round function from SSLeay - struct little_endian_blk0 - { - static uint32_t apply(CHAR64LONG16* block, int i) - { - return block->l[i] = (rol(block->l[i],24)&0xFF00FF00) - | (rol(block->l[i],8)&0x00FF00FF); - } - }; - - struct big_endian_blk0 - { - static uint32_t apply(CHAR64LONG16* block, int i) - { - return block->l[i]; - } - }; - - -#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ - ^block->l[(i+2)&15]^block->l[i&15],1)) - -// (R0+R1), R2, R3, R4 are the different operations used in SHA1 -#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+BlkFun::apply(block, i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); -#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); -#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); -#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); - - // Hash a single 512-bit block. This is the core of the algorithm. - template - void SHA1Transform(uint32_t state[5], uint8_t const buffer[64]) - { - using namespace std; - uint32_t a, b, c, d, e; - - CHAR64LONG16* block; - uint8_t workspace[64]; - block = (CHAR64LONG16*)workspace; - memcpy(block, buffer, 64); - - // Copy context->state[] to working vars - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - // 4 rounds of 20 operations each. Loop unrolled. - R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); - R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); - R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); - R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); - R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); - R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); - R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); - R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); - R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); - R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); - R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); - R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); - R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); - R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); - R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); - R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); - R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); - R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); - R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); - R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); - // Add the working vars back into context.state[] - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; - // Wipe variables - a = b = c = d = e = 0; - } - - void SHAPrintContext(SHA_CTX *context, char *msg) - { - using namespace std; - printf("%s (%d,%d) %x %x %x %x %x\n" - , msg, context->count[0], context->count[1] - , context->state[0], context->state[1] - , context->state[2], context->state[3] - , context->state[4]); - } - - template - void internal_update(SHA_CTX* context, uint8_t const* data, uint32_t len) - { - using namespace std; - uint32_t i, j; // JHB - -#ifdef VERBOSE - SHAPrintContext(context, "before"); -#endif - j = (context->count[0] >> 3) & 63; - if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; - context->count[1] += (len >> 29); - if ((j + len) > 63) - { - memcpy(&context->buffer[j], data, (i = 64-j)); - SHA1Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) - { - SHA1Transform(context->state, &data[i]); - } - j = 0; - } - else - { - i = 0; - } - memcpy(&context->buffer[j], &data[i], len - i); -#ifdef VERBOSE - SHAPrintContext(context, "after "); -#endif - } - - bool is_big_endian() - { - uint32_t test = 1; - return *reinterpret_cast(&test) == 0; - } -} - -// SHA1Init - Initialize new context - -void SHA1_Init(SHA_CTX* context) -{ - // SHA1 initialization constants - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -// Run your data through this. - -void SHA1_Update(SHA_CTX* context, uint8_t const* data, uint32_t len) -{ -#if defined __BIG_ENDIAN__ - internal_update(context, data, len); -#elif defined LITTLE_ENDIAN - internal_update(context, data, len); -#else - // select different functions depending on endianess - // and figure out the endianess runtime - if (is_big_endian()) - internal_update(context, data, len); - else - internal_update(context, data, len); -#endif -} - - -// Add padding and return the message digest. - -void SHA1_Final(uint8_t* digest, SHA_CTX* context) -{ - uint8_t finalcount[8]; - - for (uint32_t i = 0; i < 8; ++i) - { - // Endian independent - finalcount[i] = static_cast( - (context->count[(i >= 4 ? 0 : 1)] - >> ((3-(i & 3)) * 8) ) & 255); - } - - SHA1_Update(context, (uint8_t const*)"\200", 1); - while ((context->count[0] & 504) != 448) - SHA1_Update(context, (uint8_t const*)"\0", 1); - SHA1_Update(context, finalcount, 8); // Should cause a SHA1Transform() - - for (uint32_t i = 0; i < 20; ++i) - { - digest[i] = static_cast( - (context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); - } -} - -/************************************************************ - ------------------ -Modified 7/98 -By James H. Brown -Still 100% Public Domain - -Corrected a problem which generated improper hash values on 16 bit machines -Routine SHA1Update changed from - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int -len) -to - void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned -long len) - -The 'len' parameter was declared an int which works fine on 32 bit machines. -However, on 16 bit machines an int is too small for the shifts being done -against -it. This caused the hash function to generate incorrect values if len was -greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). - -Since the file IO in main() reads 16K at a time, any file 8K or larger would -be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million -"a"s). - -I also changed the declaration of variables i & j in SHA1Update to -unsigned long from unsigned int for the same reason. - -These changes should make no difference to any 32 bit implementations since -an -int and a long are the same size in those environments. - --- -I also corrected a few compiler warnings generated by Borland C. -1. Added #include for exit() prototype -2. Removed unused variable 'j' in SHA1Final -3. Changed exit(0) to return(0) at end of main. - -ALL changes I made can be located by searching for comments containing 'JHB' ------------------ -Modified 8/98 -By Steve Reid -Still 100% public domain - -1- Removed #include and used return() instead of exit() -2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) -3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net - ------------------ -Modified 4/01 -By Saul Kravitz -Still 100% PD -Modified to run on Compaq Alpha hardware. - ------------------ -Converted to C++ 6/04 -By Arvid Norberg -1- made the input buffer const, and made the - previous SHA1HANDSOFF implicit -2- uses C99 types with size guarantees - from boost -3- if none of __BIG_ENDIAN__ or LITTLE_ENDIAN - are defined, endianess is determined - at runtime. templates are used to duplicate - the transform function for each endianess -4- using anonymous namespace to avoid external - linkage on internal functions -5- using standard C++ includes -6- made API compatible with openssl - -still 100% PD -*/ - -/* -Test Vectors (from FIPS PUB 180-1) -"abc" - A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D -"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 -A million repetitions of "a" - 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F -*/ diff --git a/libtorrent/src/socks5_stream.cpp b/libtorrent/src/socks5_stream.cpp deleted file mode 100644 index b1679c4ac..000000000 --- a/libtorrent/src/socks5_stream.cpp +++ /dev/null @@ -1,315 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/socks5_stream.hpp" - -namespace libtorrent -{ - - void socks5_stream::name_lookup(asio::error_code const& e, tcp::resolver::iterator i - , boost::shared_ptr h) - { - if (e || i == tcp::resolver::iterator()) - { - (*h)(e); - close(); - return; - } - - m_sock.async_connect(i->endpoint(), boost::bind( - &socks5_stream::connected, this, _1, h)); - } - - void socks5_stream::connected(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - using namespace libtorrent::detail; - // send SOCKS5 authentication methods - m_buffer.resize(m_user.empty()?3:4); - char* p = &m_buffer[0]; - write_uint8(5, p); // SOCKS VERSION 5 - if (m_user.empty()) - { - write_uint8(1, p); // 1 authentication method (no auth) - write_uint8(0, p); // no authentication - } - else - { - write_uint8(2, p); // 2 authentication methods - write_uint8(0, p); // no authentication - write_uint8(2, p); // username/password - } - asio::async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::handshake1, this, _1, h)); - } - - void socks5_stream::handshake1(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - m_buffer.resize(2); - asio::async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::handshake2, this, _1, h)); - } - - void socks5_stream::handshake2(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - using namespace libtorrent::detail; - - char* p = &m_buffer[0]; - int version = read_uint8(p); - int method = read_uint8(p); - - if (version < 5) - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - - if (method == 0) - { - socks_connect(h); - } - else if (method == 2) - { - if (m_user.empty()) - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - - // start sub-negotiation - m_buffer.resize(m_user.size() + m_password.size() + 3); - char* p = &m_buffer[0]; - write_uint8(1, p); - write_uint8(m_user.size(), p); - write_string(m_user, p); - write_uint8(m_password.size(), p); - write_string(m_password, p); - asio::async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::handshake3, this, _1, h)); - } - else - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - } - - void socks5_stream::handshake3(asio::error_code const& e - , boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - m_buffer.resize(2); - asio::async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::handshake4, this, _1, h)); - } - - void socks5_stream::handshake4(asio::error_code const& e - , boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - using namespace libtorrent::detail; - - char* p = &m_buffer[0]; - int version = read_uint8(p); - int status = read_uint8(p); - - if (version != 1) - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - - if (status != 0) - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - - std::vector().swap(m_buffer); - (*h)(e); - } - - void socks5_stream::socks_connect(boost::shared_ptr h) - { - using namespace libtorrent::detail; - - // send SOCKS5 connect command - m_buffer.resize(6 + (m_remote_endpoint.address().is_v4()?4:16)); - char* p = &m_buffer[0]; - write_uint8(5, p); // SOCKS VERSION 5 - write_uint8(1, p); // CONNECT command - write_uint8(0, p); // reserved - write_uint8(m_remote_endpoint.address().is_v4()?1:4, p); // address type - write_address(m_remote_endpoint.address(), p); - write_uint16(m_remote_endpoint.port(), p); - assert(p - &m_buffer[0] == int(m_buffer.size())); - - asio::async_write(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::connect1, this, _1, h)); - } - - void socks5_stream::connect1(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - m_buffer.resize(6 + 4); // assume an IPv4 address - asio::async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::connect2, this, _1, h)); - } - - void socks5_stream::connect2(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - using namespace libtorrent::detail; - - // send SOCKS5 connect command - char* p = &m_buffer[0]; - int version = read_uint8(p); - if (version < 5) - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - int response = read_uint8(p); - if (response != 0) - { - asio::error_code e = asio::error::fault; - switch (response) - { - case 1: e = asio::error::fault; break; - case 2: e = asio::error::no_permission; break; - case 3: e = asio::error::network_unreachable; break; - case 4: e = asio::error::host_unreachable; break; - case 5: e = asio::error::connection_refused; break; - case 6: e = asio::error::timed_out; break; - case 7: e = asio::error::operation_not_supported; break; - case 8: e = asio::error::address_family_not_supported; break; - } - (*h)(e); - close(); - return; - } - p += 1; // reserved - int atyp = read_uint8(p); - // we ignore the proxy IP it was bound to - if (atyp == 1) - { - std::vector().swap(m_buffer); - (*h)(e); - return; - } - int skip_bytes = 0; - if (atyp == 4) - { - skip_bytes = 12; - } - else if (atyp == 3) - { - skip_bytes = read_uint8(p) - 3; - } - else - { - (*h)(asio::error::operation_not_supported); - close(); - return; - } - m_buffer.resize(skip_bytes); - - asio::async_read(m_sock, asio::buffer(m_buffer) - , boost::bind(&socks5_stream::connect3, this, _1, h)); - } - - void socks5_stream::connect3(asio::error_code const& e, boost::shared_ptr h) - { - if (e) - { - (*h)(e); - close(); - return; - } - - std::vector().swap(m_buffer); - (*h)(e); - } -} - diff --git a/libtorrent/src/stat.cpp b/libtorrent/src/stat.cpp deleted file mode 100644 index d695edc42..000000000 --- a/libtorrent/src/stat.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - -Copyright (c) 2003, 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. - -*/ - -// TODO: Use two algorithms to estimate transfer rate. -// one (simple) for transfer rates that are >= 1 packet -// per second and one (low pass-filter) for rates < 1 -// packet per second. - -#include "libtorrent/pch.hpp" - -#include -#include - -#include "libtorrent/stat.hpp" -#include "libtorrent/invariant_check.hpp" - -#if defined _MSC_VER && _MSC_VER <= 1200 -#define for if (false) {} else for -#endif - -using namespace libtorrent; - -void libtorrent::stat::second_tick(float tick_interval) -{ - INVARIANT_CHECK; - - for (int i = history - 2; i >= 0; --i) - { - m_download_rate_history[i + 1] = m_download_rate_history[i]; - m_upload_rate_history[i + 1] = m_upload_rate_history[i]; - m_download_payload_rate_history[i + 1] = m_download_payload_rate_history[i]; - m_upload_payload_rate_history[i + 1] = m_upload_payload_rate_history[i]; - } - - m_download_rate_history[0] = (m_downloaded_payload + m_downloaded_protocol) - / tick_interval; - m_upload_rate_history[0] = (m_uploaded_payload + m_uploaded_protocol) - / tick_interval; - m_download_payload_rate_history[0] = m_downloaded_payload / tick_interval; - m_upload_payload_rate_history[0] = m_uploaded_payload / tick_interval; - - m_downloaded_payload = 0; - m_uploaded_payload = 0; - m_downloaded_protocol = 0; - m_uploaded_protocol = 0; - - m_mean_download_rate = 0; - m_mean_upload_rate = 0; - m_mean_download_payload_rate = 0; - m_mean_upload_payload_rate = 0; - - for (int i = 0; i < history; ++i) - { - m_mean_download_rate += m_download_rate_history[i]; - m_mean_upload_rate += m_upload_rate_history[i]; - m_mean_download_payload_rate += m_download_payload_rate_history[i]; - m_mean_upload_payload_rate += m_upload_payload_rate_history[i]; - } - - m_mean_download_rate /= history; - m_mean_upload_rate /= history; - m_mean_download_payload_rate /= history; - m_mean_upload_payload_rate /= history; -} diff --git a/libtorrent/src/storage.cpp b/libtorrent/src/storage.cpp deleted file mode 100644 index 0623dfeb6..000000000 --- a/libtorrent/src/storage.cpp +++ /dev/null @@ -1,2325 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg, Daniel Wallin -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/storage.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/file.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/file_pool.hpp" -#include "libtorrent/aux_/session_impl.hpp" - -#ifndef NDEBUG -#include -#include -#include -#include -#endif - -#if defined(__APPLE__) -// for getattrlist() -#include -#include -// for statfs() -#include -#include -#endif - -#if defined(__linux__) -#include -#endif - -#if defined(_WIN32) && defined(UNICODE) - -#include -#include -#include "libtorrent/utf8.hpp" - -namespace libtorrent -{ - std::wstring safe_convert(std::string const& s) - { - try - { - return libtorrent::utf8_wchar(s); - } - catch (std::exception) - { - std::wstring ret; - const char* end = &s[0] + s.size(); - for (const char* i = &s[0]; i < end;) - { - wchar_t c = '.'; - int result = std::mbtowc(&c, i, end - i); - if (result > 0) i += result; - else ++i; - ret += c; - } - return ret; - } - } -} -#endif - -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 -namespace -{ - using libtorrent::safe_convert; - using namespace boost::filesystem; - - // based on code from Boost.Fileystem - bool create_directories_win(const path& ph) - { - if (ph.empty() || exists(ph)) - { - if ( !ph.empty() && !is_directory(ph) ) - boost::throw_exception( filesystem_error( - "boost::filesystem::create_directories", - ph, "path exists and is not a directory", - not_directory_error ) ); - return false; - } - - // First create branch, by calling ourself recursively - create_directories_win(ph.branch_path()); - // Now that parent's path exists, create the directory - std::wstring wph(safe_convert(ph.native_directory_string())); - CreateDirectory(wph.c_str(), 0); - return true; - } - - bool exists_win( const path & ph ) - { - std::wstring wpath(safe_convert(ph.string())); - if(::GetFileAttributes( wpath.c_str() ) == 0xFFFFFFFF) - { - UINT err = ::GetLastError(); - if((err == ERROR_FILE_NOT_FOUND) - || (err == ERROR_INVALID_PARAMETER) - || (err == ERROR_NOT_READY) - || (err == ERROR_PATH_NOT_FOUND) - || (err == ERROR_INVALID_NAME) - || (err == ERROR_BAD_NETPATH )) - return false; // GetFileAttributes failed because the path does not exist - // for any other error we assume the file does exist and fall through, - // this may not be the best policy though... (JM 20040330) - return true; - } - return true; - } - - boost::intmax_t file_size_win( const path & ph ) - { - std::wstring wpath(safe_convert(ph.string())); - // by now, intmax_t is 64-bits on all Windows compilers - WIN32_FILE_ATTRIBUTE_DATA fad; - if ( !::GetFileAttributesExW( wpath.c_str(), - ::GetFileExInfoStandard, &fad ) ) - boost::throw_exception( filesystem_error( - "boost::filesystem::file_size", - ph, detail::system_error_code() ) ); - if ( (fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0 ) - boost::throw_exception( filesystem_error( - "boost::filesystem::file_size", - ph, "invalid: is a directory", - is_directory_error ) ); - return (static_cast(fad.nFileSizeHigh) - << (sizeof(fad.nFileSizeLow)*8)) - + fad.nFileSizeLow; - } - - std::time_t last_write_time_win( const path & ph ) - { - struct _stat path_stat; - std::wstring wph(safe_convert(ph.native_file_string())); - if ( ::_wstat( wph.c_str(), &path_stat ) != 0 ) - boost::throw_exception( filesystem_error( - "boost::filesystem::last_write_time", - ph, detail::system_error_code() ) ); - return path_stat.st_mtime; - } - - void rename_win( const path & old_path, - const path & new_path ) - { - std::wstring wold_path(safe_convert(old_path.string())); - std::wstring wnew_path(safe_convert(new_path.string())); - if ( !::MoveFile( wold_path.c_str(), wnew_path.c_str() ) ) - boost::throw_exception( filesystem_error( - "boost::filesystem::rename", - old_path, new_path, detail::system_error_code() ) ); - } - -} // anonymous namespace - -#endif - -#if BOOST_VERSION < 103200 -bool operator<(boost::filesystem::path const& lhs - , boost::filesystem::path const& rhs) -{ - return lhs.string() < rhs.string(); -} -#endif - -using namespace boost::filesystem; -using boost::bind; -using namespace ::boost::multi_index; -using boost::multi_index::multi_index_container; - -#if !defined(NDEBUG) && defined(TORRENT_STORAGE_DEBUG) -namespace -{ - using namespace libtorrent; - - void print_to_log(const std::string& s) - { - static std::ofstream log("log.txt"); - log << s; - log.flush(); - } -} -#endif - -namespace libtorrent -{ - - std::vector > get_filesizes( - torrent_info const& t, path p) - { - p = complete(p); - std::vector > sizes; - for (torrent_info::file_iterator i = t.begin_files(); - i != t.end_files(); ++i) - { - size_type size = 0; - std::time_t time = 0; - try - { - path f = p / i->path; -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 - size = file_size_win(f); - time = last_write_time_win(f); -#else - size = file_size(f); - time = last_write_time(f); -#endif - } - catch (std::exception&) {} - sizes.push_back(std::make_pair(size, time)); - } - return sizes; - } - - // matches the sizes and timestamps of the files passed in - // in non-compact mode, actual file sizes and timestamps - // are allowed to be bigger and more recent than the fast - // resume data. This is because full allocation will not move - // pieces, so any older version of the resume data will - // still be a correct subset of the actual data on disk. - bool match_filesizes( - torrent_info const& t - , path p - , std::vector > const& sizes - , bool compact_mode - , std::string* error) - { - if ((int)sizes.size() != t.num_files()) - { - if (error) *error = "mismatching number of files"; - return false; - } - p = complete(p); - - std::vector >::const_iterator s - = sizes.begin(); - for (torrent_info::file_iterator i = t.begin_files(); - i != t.end_files(); ++i, ++s) - { - size_type size = 0; - std::time_t time = 0; - try - { - path f = p / i->path; -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 - size = file_size_win(f); - time = last_write_time_win(f); -#else - size = file_size(f); - time = last_write_time(f); -#endif - } - catch (std::exception&) {} - if (size != s->first - || (!compact_mode && size < s->first)) - { - if (error) *error = "filesize mismatch for file '" - + i->path.native_file_string() - + "', size: " + boost::lexical_cast(size) - + ", expected to be " + boost::lexical_cast(s->first) - + " bytes"; - return false; - } - if (time != s->second - || (!compact_mode && time < s->second)) - { - if (error) *error = "timestamp mismatch for file '" - + i->path.native_file_string() - + "', modification date: " + boost::lexical_cast(time) - + ", expected to have modification date " - + boost::lexical_cast(s->second); - return false; - } - } - return true; - } - - struct thread_safe_storage - { - thread_safe_storage(std::size_t n) - : slots(n, false) - {} - - boost::mutex mutex; - boost::condition condition; - std::vector slots; - }; - - struct slot_lock - { - slot_lock(thread_safe_storage& s, int slot_) - : storage_(s) - , slot(slot_) - { - assert(slot_>=0 && slot_ < (int)s.slots.size()); - boost::mutex::scoped_lock lock(storage_.mutex); - - while (storage_.slots[slot]) - storage_.condition.wait(lock); - storage_.slots[slot] = true; - } - - ~slot_lock() - { - storage_.slots[slot] = false; - storage_.condition.notify_all(); - } - - thread_safe_storage& storage_; - int slot; - }; - - class storage : public storage_interface, thread_safe_storage, boost::noncopyable - { - public: - storage(torrent_info const& info, path const& path, file_pool& fp) - : thread_safe_storage(info.num_pieces()) - , m_info(info) - , m_files(fp) - { - assert(info.begin_files() != info.end_files()); - m_save_path = complete(path); - assert(m_save_path.is_complete()); - } - - void release_files(); - void initialize(bool allocate_files); - bool move_storage(path save_path); - size_type read(char* buf, int slot, int offset, int size); - void write(const char* buf, int slot, int offset, int size); - void move_slot(int src_slot, int dst_slot); - void swap_slots(int slot1, int slot2); - void swap_slots3(int slot1, int slot2, int slot3); - bool verify_resume_data(entry& rd, std::string& error); - void write_resume_data(entry& rd) const; - - size_type read_impl(char* buf, int slot, int offset, int size, bool fill_zero); - - ~storage() - { - m_files.release(this); - } - - torrent_info const& m_info; - path m_save_path; - // the file pool is typically stored in - // the session, to make all storage - // instances use the same pool - file_pool& m_files; - - // temporary storage for moving pieces - std::vector m_scratch_buffer; - }; - - void storage::initialize(bool allocate_files) - { - // first, create all missing directories - path last_path; - for (torrent_info::file_iterator file_iter = m_info.begin_files(), - end_iter = m_info.end_files(); file_iter != end_iter; ++file_iter) - { - path dir = (m_save_path / file_iter->path).branch_path(); - - if (dir != last_path) - { - last_path = dir; - -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 - if (!exists_win(last_path)) - create_directories_win(last_path); -#else - if (!exists(last_path)) - create_directories(last_path); -#endif - } - - // if the file is empty, just create it. But also make sure - // the directory exits. - if (file_iter->size == 0) - { - file(m_save_path / file_iter->path, file::out); - continue; - } - - if (allocate_files) - { - m_files.open_file(this, m_save_path / file_iter->path, file::in | file::out) - ->set_size(file_iter->size); - } - } - } - - void storage::release_files() - { - m_files.release(this); - std::vector().swap(m_scratch_buffer); - } - - void storage::write_resume_data(entry& rd) const - { - std::vector > file_sizes - = get_filesizes(m_info, m_save_path); - - rd["file sizes"] = entry::list_type(); - entry::list_type& fl = rd["file sizes"].list(); - for (std::vector >::iterator i - = file_sizes.begin(), end(file_sizes.end()); i != end; ++i) - { - entry::list_type p; - p.push_back(entry(i->first)); - p.push_back(entry(i->second)); - fl.push_back(entry(p)); - } - } - - bool storage::verify_resume_data(entry& rd, std::string& error) - { - std::vector > file_sizes; - entry::list_type& l = rd["file sizes"].list(); - - for (entry::list_type::iterator i = l.begin(); - i != l.end(); ++i) - { - file_sizes.push_back(std::pair( - i->list().front().integer() - , i->list().back().integer())); - } - - if (file_sizes.empty()) - { - error = "the number of files in resume data is 0"; - return false; - } - - entry::list_type& slots = rd["slots"].list(); - bool seed = int(slots.size()) == m_info.num_pieces() - && std::find_if(slots.begin(), slots.end() - , boost::bind(std::less() - , boost::bind((size_type const& (entry::*)() const) - &entry::integer, _1), 0)) == slots.end(); - - bool full_allocation_mode = false; - try - { - full_allocation_mode = rd["allocation"].string() == "full"; - } - catch (std::exception&) {} - - if (seed) - { - if (m_info.num_files() != (int)file_sizes.size()) - { - error = "the number of files does not match the torrent (num: " - + boost::lexical_cast(file_sizes.size()) + " actual: " - + boost::lexical_cast(m_info.num_files()) + ")"; - return false; - } - - std::vector >::iterator - fs = file_sizes.begin(); - // the resume data says we have the entire torrent - // make sure the file sizes are the right ones - for (torrent_info::file_iterator i = m_info.begin_files() - , end(m_info.end_files()); i != end; ++i, ++fs) - { - if (i->size != fs->first) - { - error = "file size for '" + i->path.native_file_string() - + "' was expected to be " - + boost::lexical_cast(i->size) + " bytes"; - return false; - } - } - return true; - } - - return match_filesizes(m_info, m_save_path, file_sizes - , !full_allocation_mode, &error); - } - - // returns true on success - bool storage::move_storage(path save_path) - { - path old_path; - path new_path; - - save_path = complete(save_path); - -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 - std::wstring wsave_path(safe_convert(save_path.native_file_string())); - if (!exists_win(save_path)) - { - CreateDirectory(wsave_path.c_str(), 0); - } - else if ((GetFileAttributes(wsave_path.c_str()) & FILE_ATTRIBUTE_DIRECTORY) == 0) - { - return false; - } -#else - if (!exists(save_path)) - create_directory(save_path); - else if (!is_directory(save_path)) - return false; -#endif - - m_files.release(this); - - old_path = m_save_path / m_info.name(); - new_path = save_path / m_info.name(); - - try - { -#if defined(_WIN32) && defined(UNICODE) && BOOST_VERSION < 103400 - rename_win(old_path, new_path); -#else - rename(old_path, new_path); -#endif - m_save_path = save_path; - return true; - } - catch (std::exception&) {} - return false; - } - -#ifndef NDEBUG -/* - void storage::shuffle() - { - int num_pieces = m_info.num_pieces(); - - std::vector pieces(num_pieces); - for (std::vector::iterator i = pieces.begin(); - i != pieces.end(); ++i) - { - *i = static_cast(i - pieces.begin()); - } - std::srand((unsigned int)std::time(0)); - std::vector targets(pieces); - std::random_shuffle(pieces.begin(), pieces.end()); - std::random_shuffle(targets.begin(), targets.end()); - - for (int i = 0; i < (std::max)(num_pieces / 50, 1); ++i) - { - const int slot_index = targets[i]; - const int piece_index = pieces[i]; - const int slot_size =static_cast(m_info.piece_size(slot_index)); - std::vector buf(slot_size); - read(&buf[0], piece_index, 0, slot_size); - write(&buf[0], slot_index, 0, slot_size); - } - } -*/ -#endif - - void storage::move_slot(int src_slot, int dst_slot) - { - int piece_size = m_info.piece_size(dst_slot); - m_scratch_buffer.resize(piece_size); - read_impl(&m_scratch_buffer[0], src_slot, 0, piece_size, true); - write(&m_scratch_buffer[0], dst_slot, 0, piece_size); - } - - void storage::swap_slots(int slot1, int slot2) - { - // the size of the target slot is the size of the piece - int piece_size = m_info.piece_length(); - int piece1_size = m_info.piece_size(slot2); - int piece2_size = m_info.piece_size(slot1); - m_scratch_buffer.resize(piece_size * 2); - read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); - read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); - write(&m_scratch_buffer[0], slot2, 0, piece1_size); - write(&m_scratch_buffer[piece_size], slot1, 0, piece2_size); - } - - void storage::swap_slots3(int slot1, int slot2, int slot3) - { - // the size of the target slot is the size of the piece - int piece_size = m_info.piece_length(); - int piece1_size = m_info.piece_size(slot2); - int piece2_size = m_info.piece_size(slot3); - int piece3_size = m_info.piece_size(slot1); - m_scratch_buffer.resize(piece_size * 2); - read_impl(&m_scratch_buffer[0], slot1, 0, piece1_size, true); - read_impl(&m_scratch_buffer[piece_size], slot2, 0, piece2_size, true); - write(&m_scratch_buffer[0], slot2, 0, piece1_size); - read_impl(&m_scratch_buffer[0], slot3, 0, piece3_size, true); - write(&m_scratch_buffer[piece_size], slot3, 0, piece2_size); - write(&m_scratch_buffer[0], slot1, 0, piece3_size); - } - - size_type storage::read( - char* buf - , int slot - , int offset - , int size) - { - return read_impl(buf, slot, offset, size, false); - } - - size_type storage::read_impl( - char* buf - , int slot - , int offset - , int size - , bool fill_zero) - { - assert(buf != 0); - assert(slot >= 0 && slot < m_info.num_pieces()); - assert(offset >= 0); - assert(offset < m_info.piece_size(slot)); - assert(size > 0); - - slot_lock lock(*this, slot); - -#ifndef NDEBUG - std::vector slices - = m_info.map_block(slot, offset, size); - assert(!slices.empty()); -#endif - - size_type start = slot * (size_type)m_info.piece_length() + offset; - assert(start + size <= m_info.total_size()); - - // find the file iterator and file offset - size_type file_offset = start; - std::vector::const_iterator file_iter; - - for (file_iter = m_info.begin_files();;) - { - if (file_offset < file_iter->size) - break; - - file_offset -= file_iter->size; - ++file_iter; - } - - int buf_pos = 0; - boost::shared_ptr in(m_files.open_file( - this, m_save_path / file_iter->path, file::in)); - - assert(file_offset < file_iter->size); - - assert(slices[0].offset == file_offset); - - size_type new_pos = in->seek(file_offset); - if (new_pos != file_offset) - { - // the file was not big enough - if (!fill_zero) - throw file_error("slot has no storage"); - std::memset(buf + buf_pos, 0, size - buf_pos); - return size; - } - -#ifndef NDEBUG - size_type in_tell = in->tell(); - assert(in_tell == file_offset); -#endif - - int left_to_read = size; - int slot_size = static_cast(m_info.piece_size(slot)); - - if (offset + left_to_read > slot_size) - left_to_read = slot_size - offset; - - assert(left_to_read >= 0); - - size_type result = left_to_read; - -#ifndef NDEBUG - int counter = 0; -#endif - - while (left_to_read > 0) - { - int read_bytes = left_to_read; - if (file_offset + read_bytes > file_iter->size) - read_bytes = static_cast(file_iter->size - file_offset); - - if (read_bytes > 0) - { -#ifndef NDEBUG - assert(int(slices.size()) > counter); - size_type slice_size = slices[counter].size; - assert(slice_size == read_bytes); - assert(m_info.file_at(slices[counter].file_index).path - == file_iter->path); -#endif - - size_type actual_read = in->read(buf + buf_pos, read_bytes); - - if (read_bytes != actual_read) - { - // the file was not big enough - if (actual_read > 0) buf_pos += actual_read; - if (!fill_zero) - throw file_error("slot has no storage"); - std::memset(buf + buf_pos, 0, size - buf_pos); - return size; - } - - left_to_read -= read_bytes; - buf_pos += read_bytes; - assert(buf_pos >= 0); - file_offset += read_bytes; - } - - if (left_to_read > 0) - { - ++file_iter; -#ifndef NDEBUG - // empty files are not returned by map_block, so if - // this file was empty, don't increment the slice counter - if (read_bytes > 0) ++counter; -#endif - path path = m_save_path / file_iter->path; - - file_offset = 0; - in = m_files.open_file( - this, path, file::in); - in->seek(0); - } - } - return result; - } - - // throws file_error if it fails to write - void storage::write( - const char* buf - , int slot - , int offset - , int size) - { - assert(buf != 0); - assert(slot >= 0); - assert(slot < m_info.num_pieces()); - assert(offset >= 0); - assert(size > 0); - - slot_lock lock(*this, slot); - -#ifndef NDEBUG - std::vector slices - = m_info.map_block(slot, offset, size); - assert(!slices.empty()); -#endif - - size_type start = slot * (size_type)m_info.piece_length() + offset; - - // find the file iterator and file offset - size_type file_offset = start; - std::vector::const_iterator file_iter; - - for (file_iter = m_info.begin_files();;) - { - if (file_offset < file_iter->size) - break; - - file_offset -= file_iter->size; - ++file_iter; - assert(file_iter != m_info.end_files()); - } - - path p(m_save_path / file_iter->path); - boost::shared_ptr out = m_files.open_file( - this, p, file::out | file::in); - - assert(file_offset < file_iter->size); - assert(slices[0].offset == file_offset); - - size_type pos = out->seek(file_offset); - - if (pos != file_offset) - { - std::stringstream s; - s << "no storage for slot " << slot; - throw file_error(s.str()); - } - - int left_to_write = size; - int slot_size = static_cast(m_info.piece_size(slot)); - - if (offset + left_to_write > slot_size) - left_to_write = slot_size - offset; - - assert(left_to_write >= 0); - - int buf_pos = 0; -#ifndef NDEBUG - int counter = 0; -#endif - while (left_to_write > 0) - { - int write_bytes = left_to_write; - if (file_offset + write_bytes > file_iter->size) - { - assert(file_iter->size >= file_offset); - write_bytes = static_cast(file_iter->size - file_offset); - } - - if (write_bytes > 0) - { - assert(int(slices.size()) > counter); - assert(slices[counter].size == write_bytes); - assert(m_info.file_at(slices[counter].file_index).path - == file_iter->path); - - assert(buf_pos >= 0); - assert(write_bytes >= 0); - size_type written = out->write(buf + buf_pos, write_bytes); - - if (written != write_bytes) - { - std::stringstream s; - s << "no storage for slot " << slot; - throw file_error(s.str()); - } - - left_to_write -= write_bytes; - buf_pos += write_bytes; - assert(buf_pos >= 0); - file_offset += write_bytes; - assert(file_offset <= file_iter->size); - } - - if (left_to_write > 0) - { - #ifndef NDEBUG - if (write_bytes > 0) ++counter; - #endif - ++file_iter; - - assert(file_iter != m_info.end_files()); - path p = m_save_path / file_iter->path; - file_offset = 0; - out = m_files.open_file( - this, p, file::out | file::in); - - out->seek(0); - } - } - } - - storage_interface* default_storage_constructor(torrent_info const& ti - , boost::filesystem::path const& path, file_pool& fp) - { - return new storage(ti, path, fp); - } - - bool supports_sparse_files(path const& p) - { - assert(p.is_complete()); -#if defined(_WIN32) - // assume windows API is available - DWORD max_component_len = 0; - DWORD volume_flags = 0; - std::string root_device = p.root_name() + "\\"; -#if defined(UNICODE) - std::wstring wph(safe_convert(root_device)); - bool ret = ::GetVolumeInformation(wph.c_str(), 0 - , 0, 0, &max_component_len, &volume_flags, 0, 0); -#else - bool ret = ::GetVolumeInformation(root_device.c_str(), 0 - , 0, 0, &max_component_len, &volume_flags, 0, 0); -#endif - - if (!ret) return false; - if (volume_flags & FILE_SUPPORTS_SPARSE_FILES) - return true; -#endif - -#if defined(__APPLE__) || defined(__linux__) - // find the last existing directory of the save path - path query_path = p; - while (!query_path.empty() && !exists(query_path)) - query_path = query_path.branch_path(); -#endif - -#if defined(__APPLE__) - - struct statfs fsinfo; - int ret = statfs(query_path.native_directory_string().c_str(), &fsinfo); - if (ret != 0) return false; - - attrlist request; - request.bitmapcount = ATTR_BIT_MAP_COUNT; - request.reserved = 0; - request.commonattr = 0; - request.volattr = ATTR_VOL_CAPABILITIES; - request.dirattr = 0; - request.fileattr = 0; - request.forkattr = 0; - - struct vol_capabilities_attr_buf - { - unsigned long length; - vol_capabilities_attr_t info; - } vol_cap; - - ret = getattrlist(fsinfo.f_mntonname, &request, &vol_cap - , sizeof(vol_cap), 0); - if (ret != 0) return false; - - if (vol_cap.info.capabilities[VOL_CAPABILITIES_FORMAT] - & (VOL_CAP_FMT_SPARSE_FILES | VOL_CAP_FMT_ZERO_RUNS)) - { - return true; - } - - return true; -#endif - -#if defined(__linux__) - struct statfs buf; - int err = statfs(query_path.native_directory_string().c_str(), &buf); - if (err == 0) - { -#ifndef NDEBUG - std::cerr << "buf.f_type " << std::hex << buf.f_type << std::endl; -#endif - switch (buf.f_type) - { - case 0x5346544e: // NTFS - case 0xEF51: // EXT2 OLD - case 0xEF53: // EXT2 and EXT3 - case 0x00011954: // UFS - case 0x52654973: // ReiserFS - case 0x58465342: // XFS - return true; - } - } -#ifndef NDEBUG - else - { - std::cerr << "statfs returned " << err << std::endl; - std::cerr << "errno: " << errno << std::endl; - std::cerr << "path: " << query_path.native_directory_string() << std::endl; - } -#endif -#endif - - // TODO: POSIX implementation - return false; - } - - // -- piece_manager ----------------------------------------------------- - - class piece_manager::impl - { - friend class invariant_access; - public: - - impl( - torrent_info const& info - , path const& path - , file_pool& fp - , storage_constructor_type sc); - - bool check_fastresume( - aux::piece_checker_data& d - , std::vector& pieces - , int& num_pieces - , bool compact_mode); - - std::pair check_files( - std::vector& pieces - , int& num_pieces, boost::recursive_mutex& mutex); - - void release_files(); - - bool allocate_slots(int num_slots, bool abort_on_disk = false); - void mark_failed(int index); - unsigned long piece_crc( - int slot_index - , int block_size - , piece_picker::block_info const* bi); - - int slot_for_piece(int piece_index) const; - - size_type read( - char* buf - , int piece_index - , int offset - , int size); - - void write( - const char* buf - , int piece_index - , int offset - , int size); - - path const& save_path() const - { return m_save_path; } - - bool move_storage(path save_path) - { - if (m_storage->move_storage(save_path)) - { - m_save_path = complete(save_path); - return true; - } - return false; - } - - void export_piece_map(std::vector& p) const; - - // returns the slot currently associated with the given - // piece or assigns the given piece_index to a free slot - - int identify_data( - const std::vector& piece_data - , int current_slot - , std::vector& have_pieces - , int& num_pieces - , const std::multimap& hash_to_piece - , boost::recursive_mutex& mutex); - - int allocate_slot_for_piece(int piece_index); -#ifndef NDEBUG - void check_invariant() const; -#ifdef TORRENT_STORAGE_DEBUG - void debug_log() const; -#endif -#endif - boost::scoped_ptr m_storage; - - // if this is true, pieces are always allocated at the - // lowest possible slot index. If it is false, pieces - // are always written to their final place immediately - bool m_compact_mode; - - // if this is true, pieces that haven't been downloaded - // will be filled with zeroes. Not filling with zeroes - // will not work in some cases (where a seek cannot pass - // the end of the file). - bool m_fill_mode; - - // a bitmask representing the pieces we have - std::vector m_have_piece; - - torrent_info const& m_info; - - // slots that haven't had any file storage allocated - std::vector m_unallocated_slots; - // slots that have file storage, but isn't assigned to a piece - std::vector m_free_slots; - - enum - { - has_no_slot = -3 // the piece has no storage - }; - - // maps piece indices to slots. If a piece doesn't - // have any storage, it is set to 'has_no_slot' - std::vector m_piece_to_slot; - - enum - { - unallocated = -1, // the slot is unallocated - unassigned = -2 // the slot is allocated but not assigned to a piece - }; - - // maps slots to piece indices, if a slot doesn't have a piece - // it can either be 'unassigned' or 'unallocated' - std::vector m_slot_to_piece; - - path m_save_path; - - mutable boost::recursive_mutex m_mutex; - - bool m_allocating; - boost::mutex m_allocating_monitor; - boost::condition m_allocating_condition; - - // these states are used while checking/allocating the torrent - - enum { - // the default initial state - state_none, - // the file checking is complete - state_finished, - // creating the directories - state_create_files, - // checking the files - state_full_check, - // allocating files (in non-compact mode) - state_allocating - } m_state; - int m_current_slot; - - std::vector m_piece_data; - - // this maps a piece hash to piece index. It will be - // build the first time it is used (to save time if it - // isn't needed) - std::multimap m_hash_to_piece; - }; - - piece_manager::impl::impl( - torrent_info const& info - , path const& save_path - , file_pool& fp - , storage_constructor_type sc) - : m_storage(sc(info, save_path, fp)) - , m_compact_mode(false) - , m_fill_mode(true) - , m_info(info) - , m_save_path(complete(save_path)) - , m_allocating(false) - { - m_fill_mode = !supports_sparse_files(save_path); - } - - piece_manager::piece_manager( - torrent_info const& info - , path const& save_path - , file_pool& fp - , storage_constructor_type sc) - : m_pimpl(new impl(info, save_path, fp, sc)) - { - } - - piece_manager::~piece_manager() - { - } - - void piece_manager::write_resume_data(entry& rd) const - { - m_pimpl->m_storage->write_resume_data(rd); - } - - bool piece_manager::verify_resume_data(entry& rd, std::string& error) - { - return m_pimpl->m_storage->verify_resume_data(rd, error); - } - - void piece_manager::release_files() - { - m_pimpl->release_files(); - } - - void piece_manager::impl::release_files() - { - // synchronization ------------------------------------------------------ - boost::recursive_mutex::scoped_lock lock(m_mutex); - // ---------------------------------------------------------------------- - - m_storage->release_files(); - } - - void piece_manager::impl::export_piece_map( - std::vector& p) const - { - // synchronization ------------------------------------------------------ - boost::recursive_mutex::scoped_lock lock(m_mutex); - // ---------------------------------------------------------------------- - - INVARIANT_CHECK; - - p.clear(); - std::vector::const_reverse_iterator last; - for (last = m_slot_to_piece.rbegin(); - last != m_slot_to_piece.rend(); ++last) - { - if (*last != unallocated) break; - } - - for (std::vector::const_iterator i = - m_slot_to_piece.begin(); - i != last.base(); ++i) - { - p.push_back(*i); - } - } - - bool piece_manager::compact_allocation() const - { return m_pimpl->m_compact_mode; } - - void piece_manager::export_piece_map( - std::vector& p) const - { - m_pimpl->export_piece_map(p); - } - - void piece_manager::impl::mark_failed(int piece_index) - { - // synchronization ------------------------------------------------------ - boost::recursive_mutex::scoped_lock lock(m_mutex); - // ---------------------------------------------------------------------- - - INVARIANT_CHECK; - - assert(piece_index >= 0 && piece_index < (int)m_piece_to_slot.size()); - assert(m_piece_to_slot[piece_index] >= 0); - - int slot_index = m_piece_to_slot[piece_index]; - - assert(slot_index >= 0); - - m_slot_to_piece[slot_index] = unassigned; - m_piece_to_slot[piece_index] = has_no_slot; - m_free_slots.push_back(slot_index); - } - - void piece_manager::mark_failed(int index) - { - m_pimpl->mark_failed(index); - } - - bool piece_manager::is_allocating() const - { - return m_pimpl->m_state - == impl::state_allocating; - } - - int piece_manager::slot_for_piece(int piece_index) const - { - return m_pimpl->slot_for_piece(piece_index); - } - - int piece_manager::impl::slot_for_piece(int piece_index) const - { - assert(piece_index >= 0 && piece_index < m_info.num_pieces()); - return m_piece_to_slot[piece_index]; - } - - unsigned long piece_manager::piece_crc( - int index - , int block_size - , piece_picker::block_info const* bi) - { - return m_pimpl->piece_crc(index, block_size, bi); - } - - unsigned long piece_manager::impl::piece_crc( - int slot_index - , int block_size - , piece_picker::block_info const* bi) - try - { - assert(slot_index >= 0); - assert(slot_index < m_info.num_pieces()); - assert(block_size > 0); - - adler32_crc crc; - std::vector buf(block_size); - int num_blocks = static_cast(m_info.piece_size(slot_index)) / block_size; - int last_block_size = static_cast(m_info.piece_size(slot_index)) % block_size; - if (last_block_size == 0) last_block_size = block_size; - - for (int i = 0; i < num_blocks-1; ++i) - { - if (!bi[i].finished) continue; - m_storage->read( - &buf[0] - , slot_index - , i * block_size - , block_size); - crc.update(&buf[0], block_size); - } - if (bi[num_blocks - 1].finished) - { - m_storage->read( - &buf[0] - , slot_index - , block_size * (num_blocks - 1) - , last_block_size); - crc.update(&buf[0], last_block_size); - } - return crc.final(); - } - catch (std::exception&) - { - return 0; - } - - size_type piece_manager::impl::read( - char* buf - , int piece_index - , int offset - , int size) - { - assert(buf); - assert(offset >= 0); - assert(size > 0); - assert(piece_index >= 0 && piece_index < (int)m_piece_to_slot.size()); - assert(m_piece_to_slot[piece_index] >= 0 - && m_piece_to_slot[piece_index] < (int)m_slot_to_piece.size()); - int slot = m_piece_to_slot[piece_index]; - assert(slot >= 0 && slot < (int)m_slot_to_piece.size()); - return m_storage->read(buf, slot, offset, size); - } - - size_type piece_manager::read( - char* buf - , int piece_index - , int offset - , int size) - { - return m_pimpl->read(buf, piece_index, offset, size); - } - - void piece_manager::impl::write( - const char* buf - , int piece_index - , int offset - , int size) - { - assert(buf); - assert(offset >= 0); - assert(size > 0); - assert(piece_index >= 0 && piece_index < (int)m_piece_to_slot.size()); - int slot = allocate_slot_for_piece(piece_index); - assert(slot >= 0 && slot < (int)m_slot_to_piece.size()); - m_storage->write(buf, slot, offset, size); - } - - void piece_manager::write( - const char* buf - , int piece_index - , int offset - , int size) - { - m_pimpl->write(buf, piece_index, offset, size); - } - - int piece_manager::impl::identify_data( - const std::vector& piece_data - , int current_slot - , std::vector& have_pieces - , int& num_pieces - , const std::multimap& hash_to_piece - , boost::recursive_mutex& mutex) - { -// INVARIANT_CHECK; - - assert((int)have_pieces.size() == m_info.num_pieces()); - - const int piece_size = static_cast(m_info.piece_length()); - const int last_piece_size = static_cast(m_info.piece_size( - m_info.num_pieces() - 1)); - - assert((int)piece_data.size() >= last_piece_size); - - // calculate a small digest, with the same - // size as the last piece. And a large digest - // which has the same size as a normal piece - hasher small_digest; - small_digest.update(&piece_data[0], last_piece_size); - hasher large_digest(small_digest); - assert(piece_size - last_piece_size >= 0); - if (piece_size - last_piece_size > 0) - { - large_digest.update( - &piece_data[last_piece_size] - , piece_size - last_piece_size); - } - sha1_hash large_hash = large_digest.final(); - sha1_hash small_hash = small_digest.final(); - - typedef std::multimap::const_iterator map_iter; - map_iter begin1; - map_iter end1; - map_iter begin2; - map_iter end2; - - // makes the lookups for the small digest and the large digest - boost::tie(begin1, end1) = hash_to_piece.equal_range(small_hash); - boost::tie(begin2, end2) = hash_to_piece.equal_range(large_hash); - - // copy all potential piece indices into this vector - std::vector matching_pieces; - for (map_iter i = begin1; i != end1; ++i) - matching_pieces.push_back(i->second); - for (map_iter i = begin2; i != end2; ++i) - matching_pieces.push_back(i->second); - - // no piece matched the data in the slot - if (matching_pieces.empty()) - return unassigned; - - // ------------------------------------------ - // CHECK IF THE PIECE IS IN ITS CORRECT PLACE - // ------------------------------------------ - - if (std::find( - matching_pieces.begin() - , matching_pieces.end() - , current_slot) != matching_pieces.end()) - { - const int piece_index = current_slot; - - // lock because we're writing to have_pieces - boost::recursive_mutex::scoped_lock l(mutex); - - if (have_pieces[piece_index]) - { - // we have already found a piece with - // this index. - int other_slot = m_piece_to_slot[piece_index]; - assert(other_slot >= 0); - - // take one of the other matching pieces - // that hasn't already been assigned - int other_piece = -1; - for (std::vector::iterator i = matching_pieces.begin(); - i != matching_pieces.end(); ++i) - { - if (have_pieces[*i] || *i == piece_index) continue; - other_piece = *i; - break; - } - if (other_piece >= 0) - { - // replace the old slot with 'other_piece' - assert(have_pieces[other_piece] == false); - have_pieces[other_piece] = true; - m_slot_to_piece[other_slot] = other_piece; - m_piece_to_slot[other_piece] = other_slot; - ++num_pieces; - } - else - { - // this index is the only piece with this - // hash. The previous slot we found with - // this hash must be the same piece. Mark - // that piece as unassigned, since this slot - // is the correct place for the piece. - m_slot_to_piece[other_slot] = unassigned; - m_free_slots.push_back(other_slot); - } - assert(m_piece_to_slot[piece_index] != current_slot); - assert(m_piece_to_slot[piece_index] >= 0); - m_piece_to_slot[piece_index] = has_no_slot; -#ifndef NDEBUG - // to make the assert happy, a few lines down - have_pieces[piece_index] = false; -#endif - } - else - { - ++num_pieces; - } - - assert(have_pieces[piece_index] == false); - assert(m_piece_to_slot[piece_index] == has_no_slot); - have_pieces[piece_index] = true; - - return piece_index; - } - - // find a matching piece that hasn't - // already been assigned - int free_piece = unassigned; - for (std::vector::iterator i = matching_pieces.begin(); - i != matching_pieces.end(); ++i) - { - if (have_pieces[*i]) continue; - free_piece = *i; - break; - } - - if (free_piece >= 0) - { - // lock because we're writing to have_pieces - boost::recursive_mutex::scoped_lock l(mutex); - - assert(have_pieces[free_piece] == false); - assert(m_piece_to_slot[free_piece] == has_no_slot); - have_pieces[free_piece] = true; - ++num_pieces; - - return free_piece; - } - else - { - assert(free_piece == unassigned); - return unassigned; - } - } - - // check if the fastresume data is up to date - // if it is, use it and return true. If it - // isn't return false and the full check - // will be run - bool piece_manager::impl::check_fastresume( - aux::piece_checker_data& data - , std::vector& pieces - , int& num_pieces, bool compact_mode) - { - assert(m_info.piece_length() > 0); - // synchronization ------------------------------------------------------ - boost::recursive_mutex::scoped_lock lock(m_mutex); - // ---------------------------------------------------------------------- - - INVARIANT_CHECK; - - m_compact_mode = compact_mode; - - // This will corrupt the storage - // use while debugging to find - // states that cannot be scanned - // by check_pieces. -// m_storage->shuffle(); - - m_piece_to_slot.resize(m_info.num_pieces(), has_no_slot); - m_slot_to_piece.resize(m_info.num_pieces(), unallocated); - m_free_slots.clear(); - m_unallocated_slots.clear(); - - pieces.clear(); - pieces.resize(m_info.num_pieces(), false); - num_pieces = 0; - - // if we have fast-resume info - // use it instead of doing the actual checking - if (!data.piece_map.empty() - && data.piece_map.size() <= m_slot_to_piece.size()) - { - for (int i = 0; i < (int)data.piece_map.size(); ++i) - { - m_slot_to_piece[i] = data.piece_map[i]; - if (data.piece_map[i] >= 0) - { - m_piece_to_slot[data.piece_map[i]] = i; - int found_piece = data.piece_map[i]; - - // if the piece is not in the unfinished list - // we have all of it - if (std::find_if( - data.unfinished_pieces.begin() - , data.unfinished_pieces.end() - , piece_picker::has_index(found_piece)) - == data.unfinished_pieces.end()) - { - ++num_pieces; - pieces[found_piece] = true; - } - } - else if (data.piece_map[i] == unassigned) - { - m_free_slots.push_back(i); - } - else - { - assert(data.piece_map[i] == unallocated); - m_unallocated_slots.push_back(i); - } - } - - m_unallocated_slots.reserve(int(pieces.size() - data.piece_map.size())); - for (int i = (int)data.piece_map.size(); i < (int)pieces.size(); ++i) - { - m_unallocated_slots.push_back(i); - } - - if (!m_compact_mode && !m_unallocated_slots.empty()) - { - m_state = state_allocating; - return false; - } - else - { - m_state = state_finished; - return true; - } - } - - m_state = state_create_files; - return false; - } - - // performs the full check and full allocation - // (if necessary). returns true if finished and - // false if it should be called again - // the second return value is the progress the - // file check is at. 0 is nothing done, and 1 - // is finished - std::pair piece_manager::impl::check_files( - std::vector& pieces, int& num_pieces, boost::recursive_mutex& mutex) - { - assert(num_pieces == std::count(pieces.begin(), pieces.end(), true)); - - if (m_state == state_allocating) - { - if (m_compact_mode) - { - m_state = state_finished; - return std::make_pair(true, 1.f); - } - - if (m_unallocated_slots.empty()) - { - m_state = state_finished; - return std::make_pair(true, 1.f); - } - - // if we're not in compact mode, make sure the - // pieces are spread out and placed at their - // final position. - assert(!m_unallocated_slots.empty()); - - if (!m_fill_mode) - { - // if we're not filling the allocation - // just make sure we move the current pieces - // into place, and just skip all other - // allocation - // allocate_slots returns true if it had to - // move any data - allocate_slots(m_unallocated_slots.size(), true); - } - else - { - allocate_slots(1); - } - - return std::make_pair(false, 1.f - (float)m_unallocated_slots.size() - / (float)m_slot_to_piece.size()); - } - - if (m_state == state_create_files) - { - m_storage->initialize(!m_fill_mode && !m_compact_mode); - - m_current_slot = 0; - m_state = state_full_check; - m_piece_data.resize(int(m_info.piece_length())); - return std::make_pair(false, 0.f); - } - - assert(m_state == state_full_check); - - // ------------------------ - // DO THE FULL CHECK - // ------------------------ - - try - { - - int piece_size = int(m_info.piece_size(m_current_slot)); - int num_read = m_storage->read(&m_piece_data[0] - , m_current_slot, 0, piece_size); - - // if the file is incomplete, skip the rest of it - if (num_read != piece_size) - throw file_error(""); - - if (m_hash_to_piece.empty()) - { - for (int i = 0; i < m_info.num_pieces(); ++i) - { - m_hash_to_piece.insert(std::make_pair(m_info.hash_for_piece(i), i)); - } - } - - int piece_index = identify_data(m_piece_data, m_current_slot - , pieces, num_pieces, m_hash_to_piece, mutex); - - assert(num_pieces == std::count(pieces.begin(), pieces.end(), true)); - assert(piece_index == unassigned || piece_index >= 0); - - const bool this_should_move = piece_index >= 0 && m_slot_to_piece[piece_index] != unallocated; - const bool other_should_move = m_piece_to_slot[m_current_slot] != has_no_slot; - - // check if this piece should be swapped with any other slot - // this section will ensure that the storage is correctly sorted - // libtorrent will never leave the storage in a state that - // requires this sorting, but other clients may. - - // example of worst case: - // | m_current_slot = 5 - // V - // +---+- - - +---+- - - +---+- - - // | x | | 5 | | 3 | <- piece data in slots - // +---+- - - +---+- - - +---+- - - // 3 y 5 <- slot index - - // in this example, the data in the m_current_slot (5) - // is piece 3. It has to be moved into slot 3. The data - // in slot y (piece 5) should be moved into the m_current_slot. - // and the data in slot 3 (piece x) should be moved to slot y. - - // there are three possible cases. - // 1. There's another piece that should be placed into this slot - // 2. This piece should be placed into another slot. - // 3. There's another piece that should be placed into this slot - // and this piece should be placed into another slot - - // swap piece_index with this slot - - // case 1 - if (this_should_move && !other_should_move) - { - assert(piece_index != m_current_slot); - - const int other_slot = piece_index; - assert(other_slot >= 0); - int other_piece = m_slot_to_piece[other_slot]; - - m_slot_to_piece[other_slot] = piece_index; - m_slot_to_piece[m_current_slot] = other_piece; - m_piece_to_slot[piece_index] = piece_index; - if (other_piece >= 0) m_piece_to_slot[other_piece] = m_current_slot; - - if (other_piece == unassigned) - { - std::vector::iterator i = - std::find(m_free_slots.begin(), m_free_slots.end(), other_slot); - assert(i != m_free_slots.end()); - m_free_slots.erase(i); - m_free_slots.push_back(m_current_slot); - } - - if (other_piece >= 0) - m_storage->swap_slots(other_slot, m_current_slot); - else - m_storage->move_slot(m_current_slot, other_slot); - - assert(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - // case 2 - else if (!this_should_move && other_should_move) - { - assert(piece_index != m_current_slot); - - const int other_piece = m_current_slot; - const int other_slot = m_piece_to_slot[other_piece]; - assert(other_slot >= 0); - - m_slot_to_piece[m_current_slot] = other_piece; - m_slot_to_piece[other_slot] = piece_index; - m_piece_to_slot[other_piece] = m_current_slot; - - if (piece_index == unassigned) - m_free_slots.push_back(other_slot); - - if (piece_index >= 0) - { - m_piece_to_slot[piece_index] = other_slot; - m_storage->swap_slots(other_slot, m_current_slot); - } - else - { - m_storage->move_slot(other_slot, m_current_slot); - } - assert(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - else if (this_should_move && other_should_move) - { - assert(piece_index != m_current_slot); - assert(piece_index >= 0); - - const int piece1 = m_slot_to_piece[piece_index]; - const int piece2 = m_current_slot; - const int slot1 = piece_index; - const int slot2 = m_piece_to_slot[piece2]; - - assert(slot1 >= 0); - assert(slot2 >= 0); - assert(piece2 >= 0); - - if (slot1 == slot2) - { - // this means there are only two pieces involved in the swap - assert(piece1 >= 0); - - // movement diagram: - // +-------------------------------+ - // | | - // +--> slot1 --> m_current_slot --+ - - m_slot_to_piece[slot1] = piece_index; - m_slot_to_piece[m_current_slot] = piece1; - - m_piece_to_slot[piece_index] = slot1; - m_piece_to_slot[piece1] = m_current_slot; - - assert(piece1 == m_current_slot); - assert(piece_index == slot1); - - m_storage->swap_slots(m_current_slot, slot1); - - assert(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - else - { - assert(slot1 != slot2); - assert(piece1 != piece2); - - // movement diagram: - // +-----------------------------------------+ - // | | - // +--> slot1 --> slot2 --> m_current_slot --+ - - m_slot_to_piece[slot1] = piece_index; - m_slot_to_piece[slot2] = piece1; - m_slot_to_piece[m_current_slot] = piece2; - - m_piece_to_slot[piece_index] = slot1; - m_piece_to_slot[m_current_slot] = piece2; - - if (piece1 == unassigned) - { - std::vector::iterator i = - std::find(m_free_slots.begin(), m_free_slots.end(), slot1); - assert(i != m_free_slots.end()); - m_free_slots.erase(i); - m_free_slots.push_back(slot2); - } - - if (piece1 >= 0) - { - m_piece_to_slot[piece1] = slot2; - m_storage->swap_slots3(m_current_slot, slot1, slot2); - } - else - { - m_storage->move_slot(m_current_slot, slot1); - m_storage->move_slot(slot2, m_current_slot); - } - - assert(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - } - else - { - assert(m_piece_to_slot[m_current_slot] == has_no_slot || piece_index != m_current_slot); - assert(m_slot_to_piece[m_current_slot] == unallocated); - assert(piece_index == unassigned || m_piece_to_slot[piece_index] == has_no_slot); - - // the slot was identified as piece 'piece_index' - if (piece_index != unassigned) - m_piece_to_slot[piece_index] = m_current_slot; - else - m_free_slots.push_back(m_current_slot); - - m_slot_to_piece[m_current_slot] = piece_index; - - assert(m_slot_to_piece[m_current_slot] == unassigned - || m_piece_to_slot[m_slot_to_piece[m_current_slot]] == m_current_slot); - } - } - catch (file_error&) - { - // find the file that failed, and skip all the blocks in that file - size_type file_offset = 0; - size_type current_offset = m_current_slot * m_info.piece_length(); - for (torrent_info::file_iterator i = m_info.begin_files(); - i != m_info.end_files(); ++i) - { - file_offset += i->size; - if (file_offset > current_offset) break; - } - - assert(file_offset > current_offset); - int skip_blocks = static_cast( - (file_offset - current_offset + m_info.piece_length() - 1) - / m_info.piece_length()); - - for (int i = m_current_slot; i < m_current_slot + skip_blocks; ++i) - { - assert(m_slot_to_piece[i] == unallocated); - m_unallocated_slots.push_back(i); - } - - // current slot will increase by one at the end of the for-loop too - m_current_slot += skip_blocks - 1; - } - ++m_current_slot; - - if (m_current_slot >= m_info.num_pieces()) - { - assert(m_current_slot == m_info.num_pieces()); - - // clear the memory we've been using - std::vector().swap(m_piece_data); - std::multimap().swap(m_hash_to_piece); - m_state = state_allocating; - assert(num_pieces == std::count(pieces.begin(), pieces.end(), true)); - return std::make_pair(false, 1.f); - } - - assert(num_pieces == std::count(pieces.begin(), pieces.end(), true)); - - return std::make_pair(false, (float)m_current_slot / m_info.num_pieces()); - } - - bool piece_manager::check_fastresume( - aux::piece_checker_data& d, std::vector& pieces - , int& num_pieces, bool compact_mode) - { - return m_pimpl->check_fastresume(d, pieces, num_pieces, compact_mode); - } - - std::pair piece_manager::check_files( - std::vector& pieces - , int& num_pieces - , boost::recursive_mutex& mutex) - { - return m_pimpl->check_files(pieces, num_pieces, mutex); - } - - int piece_manager::impl::allocate_slot_for_piece(int piece_index) - { - // synchronization ------------------------------------------------------ - boost::recursive_mutex::scoped_lock lock(m_mutex); - // ---------------------------------------------------------------------- - -// INVARIANT_CHECK; - - assert(piece_index >= 0); - assert(piece_index < (int)m_piece_to_slot.size()); - assert(m_piece_to_slot.size() == m_slot_to_piece.size()); - - int slot_index = m_piece_to_slot[piece_index]; - - if (slot_index != has_no_slot) - { - assert(slot_index >= 0); - assert(slot_index < (int)m_slot_to_piece.size()); - return slot_index; - } - - if (m_free_slots.empty()) - { - allocate_slots(1); - assert(!m_free_slots.empty()); - } - - std::vector::iterator iter( - std::find( - m_free_slots.begin() - , m_free_slots.end() - , piece_index)); - - if (iter == m_free_slots.end()) - { - assert(m_slot_to_piece[piece_index] != unassigned); - assert(!m_free_slots.empty()); - iter = m_free_slots.end() - 1; - - // special case to make sure we don't use the last slot - // when we shouldn't, since it's smaller than ordinary slots - if (*iter == m_info.num_pieces() - 1 && piece_index != *iter) - { - if (m_free_slots.size() == 1) - allocate_slots(1); - assert(m_free_slots.size() > 1); - // assumes that all allocated slots - // are put at the end of the free_slots vector - iter = m_free_slots.end() - 1; - } - } - - slot_index = *iter; - m_free_slots.erase(iter); - - assert(m_slot_to_piece[slot_index] == unassigned); - - m_slot_to_piece[slot_index] = piece_index; - m_piece_to_slot[piece_index] = slot_index; - - // there is another piece already assigned to - // the slot we are interested in, swap positions - if (slot_index != piece_index - && m_slot_to_piece[piece_index] >= 0) - { - -#if !defined(NDEBUG) && defined(TORRENT_STORAGE_DEBUG) - std::stringstream s; - - s << "there is another piece at our slot, swapping.."; - - s << "\n piece_index: "; - s << piece_index; - s << "\n slot_index: "; - s << slot_index; - s << "\n piece at our slot: "; - s << m_slot_to_piece[piece_index]; - s << "\n"; - - print_to_log(s.str()); - debug_log(); -#endif - - int piece_at_our_slot = m_slot_to_piece[piece_index]; - assert(m_piece_to_slot[piece_at_our_slot] == piece_index); - - std::swap( - m_slot_to_piece[piece_index] - , m_slot_to_piece[slot_index]); - - std::swap( - m_piece_to_slot[piece_index] - , m_piece_to_slot[piece_at_our_slot]); - - m_storage->move_slot(piece_index, slot_index); - - assert(m_slot_to_piece[piece_index] == piece_index); - assert(m_piece_to_slot[piece_index] == piece_index); - - slot_index = piece_index; - -#if !defined(NDEBUG) && defined(TORRENT_STORAGE_DEBUG) - debug_log(); -#endif - } - - assert(slot_index >= 0); - assert(slot_index < (int)m_slot_to_piece.size()); - return slot_index; - } - - namespace - { - // this is used to notify potential other - // threads that the allocation-function has exited - struct allocation_syncronization - { - allocation_syncronization( - bool& flag - , boost::condition& cond - , boost::mutex& monitor) - : m_flag(flag) - , m_cond(cond) - , m_monitor(monitor) - { - boost::mutex::scoped_lock lock(m_monitor); - - while (m_flag) - m_cond.wait(lock); - - m_flag = true; - } - - ~allocation_syncronization() - { - boost::mutex::scoped_lock lock(m_monitor); - m_flag = false; - m_cond.notify_one(); - } - - bool& m_flag; - boost::condition& m_cond; - boost::mutex& m_monitor; - }; - - } - - bool piece_manager::impl::allocate_slots(int num_slots, bool abort_on_disk) - { - assert(num_slots > 0); - - // this object will syncronize the allocation with - // potential other threads - allocation_syncronization sync_obj( - m_allocating - , m_allocating_condition - , m_allocating_monitor); - - // synchronization ------------------------------------------------------ - boost::recursive_mutex::scoped_lock lock(m_mutex); - // ---------------------------------------------------------------------- - -// INVARIANT_CHECK; - - assert(!m_unallocated_slots.empty()); - - const int stack_buffer_size = 16*1024; - char zeroes[stack_buffer_size]; - memset(zeroes, 0, stack_buffer_size); - - bool written = false; - - for (int i = 0; i < num_slots && !m_unallocated_slots.empty(); ++i) - { -// INVARIANT_CHECK; - - int pos = m_unallocated_slots.front(); - assert(m_slot_to_piece[pos] == unallocated); - assert(m_piece_to_slot[pos] != pos); - - int new_free_slot = pos; - if (m_piece_to_slot[pos] != has_no_slot) - { - new_free_slot = m_piece_to_slot[pos]; - m_storage->move_slot(new_free_slot, pos); - m_slot_to_piece[pos] = pos; - m_piece_to_slot[pos] = pos; - written = true; - } - else if (m_fill_mode) - { - int piece_size = int(m_info.piece_size(pos)); - int offset = 0; - for (; piece_size > 0; piece_size -= stack_buffer_size - , offset += stack_buffer_size) - { - m_storage->write(zeroes, pos, offset - , std::min(piece_size, stack_buffer_size)); - } - written = true; - } - m_unallocated_slots.erase(m_unallocated_slots.begin()); - m_slot_to_piece[new_free_slot] = unassigned; - m_free_slots.push_back(new_free_slot); - if (abort_on_disk && written) return true; - } - - assert(m_free_slots.size() > 0); - return written; - } - - bool piece_manager::allocate_slots(int num_slots, bool abort_on_disk) - { - return m_pimpl->allocate_slots(num_slots, abort_on_disk); - } - - path const& piece_manager::save_path() const - { - return m_pimpl->save_path(); - } - - bool piece_manager::move_storage(path const& save_path) - { - return m_pimpl->move_storage(save_path); - } - -#ifndef NDEBUG - void piece_manager::impl::check_invariant() const - { - // synchronization ------------------------------------------------------ - boost::recursive_mutex::scoped_lock lock(m_mutex); - // ---------------------------------------------------------------------- - if (m_piece_to_slot.empty()) return; - - assert((int)m_piece_to_slot.size() == m_info.num_pieces()); - assert((int)m_slot_to_piece.size() == m_info.num_pieces()); - - for (std::vector::const_iterator i = m_free_slots.begin(); - i != m_free_slots.end(); ++i) - { - assert(*i < (int)m_slot_to_piece.size()); - assert(*i >= 0); - assert(m_slot_to_piece[*i] == unassigned); - assert(std::find(i+1, m_free_slots.end(), *i) - == m_free_slots.end()); - } - - for (std::vector::const_iterator i = m_unallocated_slots.begin(); - i != m_unallocated_slots.end(); ++i) - { - assert(*i < (int)m_slot_to_piece.size()); - assert(*i >= 0); - assert(m_slot_to_piece[*i] == unallocated); - assert(std::find(i+1, m_unallocated_slots.end(), *i) - == m_unallocated_slots.end()); - } - - for (int i = 0; i < m_info.num_pieces(); ++i) - { - // Check domain of piece_to_slot's elements - if (m_piece_to_slot[i] != has_no_slot) - { - assert(m_piece_to_slot[i] >= 0); - assert(m_piece_to_slot[i] < (int)m_slot_to_piece.size()); - } - - // Check domain of slot_to_piece's elements - if (m_slot_to_piece[i] != unallocated - && m_slot_to_piece[i] != unassigned) - { - assert(m_slot_to_piece[i] >= 0); - assert(m_slot_to_piece[i] < (int)m_piece_to_slot.size()); - } - - // do more detailed checks on piece_to_slot - if (m_piece_to_slot[i] >= 0) - { - assert(m_slot_to_piece[m_piece_to_slot[i]] == i); - if (m_piece_to_slot[i] != i) - { - assert(m_slot_to_piece[i] == unallocated); - } - } - else - { - assert(m_piece_to_slot[i] == has_no_slot); - } - - // do more detailed checks on slot_to_piece - - if (m_slot_to_piece[i] >= 0) - { - assert(m_slot_to_piece[i] < (int)m_piece_to_slot.size()); - assert(m_piece_to_slot[m_slot_to_piece[i]] == i); -#ifdef TORRENT_STORAGE_DEBUG - assert( - std::find( - m_unallocated_slots.begin() - , m_unallocated_slots.end() - , i) == m_unallocated_slots.end() - ); - assert( - std::find( - m_free_slots.begin() - , m_free_slots.end() - , i) == m_free_slots.end() - ); -#endif - } - else if (m_slot_to_piece[i] == unallocated) - { -#ifdef TORRENT_STORAGE_DEBUG - assert(m_unallocated_slots.empty() - || (std::find( - m_unallocated_slots.begin() - , m_unallocated_slots.end() - , i) != m_unallocated_slots.end()) - ); -#endif - } - else if (m_slot_to_piece[i] == unassigned) - { -#ifdef TORRENT_STORAGE_DEBUG - assert( - std::find( - m_free_slots.begin() - , m_free_slots.end() - , i) != m_free_slots.end() - ); -#endif - } - else - { - assert(false && "m_slot_to_piece[i] is invalid"); - } - } - } - -#ifdef TORRENT_STORAGE_DEBUG - void piece_manager::impl::debug_log() const - { - std::stringstream s; - - s << "index\tslot\tpiece\n"; - - for (int i = 0; i < m_info.num_pieces(); ++i) - { - s << i << "\t" << m_slot_to_piece[i] << "\t"; - s << m_piece_to_slot[i] << "\n"; - } - - s << "---------------------------------\n"; - - print_to_log(s.str()); - } -#endif -#endif -} // namespace libtorrent - diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp deleted file mode 100644 index 7310c7b78..000000000 --- a/libtorrent/src/torrent.cpp +++ /dev/null @@ -1,2768 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_handle.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/peer.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/web_peer_connection.hpp" -#include "libtorrent/peer_id.hpp" -#include "libtorrent/alert.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/extensions.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/instantiate_connection.hpp" - -using namespace libtorrent; -using boost::tuples::tuple; -using boost::tuples::get; -using boost::tuples::make_tuple; -using boost::filesystem::complete; -using boost::bind; -using boost::mutex; -using libtorrent::aux::session_impl; - -namespace -{ - - enum - { - // wait 60 seconds before retrying a failed tracker - tracker_retry_delay_min = 60 - // when tracker_failed_max trackers - // has failed, wait 10 minutes instead - , tracker_retry_delay_max = 10 * 60 - , tracker_failed_max = 5 - }; - - int calculate_block_size(const torrent_info& i, int default_block_size) - { - if (default_block_size < 1024) default_block_size = 1024; - - // if pieces are too small, adjust the block size - if (i.piece_length() < default_block_size) - { - return static_cast(i.piece_length()); - } - - // otherwise, go with the default - return default_block_size; - } - - struct find_peer_by_ip - { - find_peer_by_ip(tcp::endpoint const& a, const torrent* t) - : ip(a) - , tor(t) - { assert(t != 0); } - - bool operator()(const session_impl::connection_map::value_type& c) const - { - tcp::endpoint sender = c.first->remote_endpoint(); - if (sender.address() != ip.address()) return false; - if (tor != c.second->associated_torrent().lock().get()) return false; - return true; - } - - tcp::endpoint const& ip; - torrent const* tor; - }; - - struct peer_by_id - { - peer_by_id(const peer_id& i): pid(i) {} - - bool operator()(const std::pair& p) const - { - if (p.second->pid() != pid) return false; - // have a special case for all zeros. We can have any number - // of peers with that pid, since it's used to indicate no pid. - if (std::count(pid.begin(), pid.end(), 0) == 20) return false; - return true; - } - - peer_id const& pid; - }; - -#ifdef TORRENT_LOGGING - void print_legend(boost::shared_ptr l) - { - (*l) << "1. time, seconds\n" - << "2. hard send quota, bytes\n" - << "3. soft send quota, bytes\n" - << "4. excess bytes sent\n" - << "5. excess bytes sent last time slice\n" - << "6. hard receive quota, bytes\n" - << "7. soft receive quota, bytes\n" - << "8. excess bytes received\n" - << "9. excess bytes received last time slice\n" - << "10. num peers\n" - << "11. max ul quota limit\n" - << "12. max dl quota limit\n" - << "13. bytes sent\n" - << "14. bytes sent 10 seconds mean\n" - << "15. bytes received\n" - << "16. bytes received 10 seconds mean\n" - << "17. total payload download\n" - << "18. total web seed payload download\n" - << "19. total redundant bytes downloaded\n" - << "\n"; - } -#endif - -} - -namespace libtorrent -{ - torrent::torrent( - session_impl& ses - , aux::checker_impl& checker - , torrent_info const& tf - , boost::filesystem::path const& save_path - , tcp::endpoint const& net_interface - , bool compact_mode - , int block_size - , session_settings const& s - , storage_constructor_type sc) - : m_torrent_file(tf) - , m_abort(false) - , m_paused(false) - , m_just_paused(false) - , m_event(tracker_request::started) - , m_block_size(0) - , m_storage(0) - , m_next_request(time_now()) - , m_duration(1800) - , m_complete(-1) - , m_incomplete(-1) - , m_host_resolver(ses.m_io_service) -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - , m_resolving_country(false) - , m_resolve_countries(false) -#endif - , m_announce_timer(ses.m_io_service) - , m_last_dht_announce(time_now() - minutes(15)) - , m_policy() - , m_ses(ses) - , m_checker(checker) - , m_picker(0) - , m_trackers(m_torrent_file.trackers()) - , m_last_working_tracker(-1) - , m_currently_trying_tracker(0) - , m_failed_trackers(0) - , m_time_scaler(0) - , m_num_pieces(0) - , m_sequenced_download_threshold(0) - , m_got_tracker_response(false) - , m_ratio(0.f) - , m_total_failed_bytes(0) - , m_total_redundant_bytes(0) - , m_net_interface(net_interface.address(), 0) - , m_save_path(complete(save_path)) - , m_compact_mode(compact_mode) - , m_default_block_size(block_size) - , m_connections_initialized(true) - , m_settings(s) - , m_storage_constructor(sc) - { -#ifndef NDEBUG - m_initial_done = 0; -#endif -#ifdef TORRENT_LOGGING - m_log = ses.create_log("torrent_" - + boost::lexical_cast(tf.info_hash()) - , m_ses.listen_port(), false); - print_legend(m_log); - m_second_count = 0; - std::fill_n(m_ul_history, 10, 0); - std::fill_n(m_dl_history, 10, 0); - - m_peer_log = ses.create_log("torrent_peers_" - + boost::lexical_cast(tf.info_hash()) - , m_ses.listen_port(), false); - -#endif - INVARIANT_CHECK; - - m_uploads_quota.min = 2; - m_connections_quota.min = 2; - // this will be corrected the next time the main session - // distributes resources, i.e. on average in 0.5 seconds - m_connections_quota.given = 100; - m_uploads_quota.max = std::numeric_limits::max(); - m_connections_quota.max = std::numeric_limits::max(); - m_policy.reset(new policy(this)); - init(); - } - - - torrent::torrent( - session_impl& ses - , aux::checker_impl& checker - , char const* tracker_url - , sha1_hash const& info_hash - , char const* name - , boost::filesystem::path const& save_path - , tcp::endpoint const& net_interface - , bool compact_mode - , int block_size - , session_settings const& s - , storage_constructor_type sc) - : m_torrent_file(info_hash) - , m_abort(false) - , m_paused(false) - , m_just_paused(false) - , m_event(tracker_request::started) - , m_block_size(0) - , m_storage(0) - , m_next_request(time_now()) - , m_duration(1800) - , m_complete(-1) - , m_incomplete(-1) - , m_host_resolver(ses.m_io_service) -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - , m_resolving_country(false) - , m_resolve_countries(false) -#endif - , m_announce_timer(ses.m_io_service) - , m_last_dht_announce(time_now() - minutes(15)) - , m_policy() - , m_ses(ses) - , m_checker(checker) - , m_picker(0) - , m_last_working_tracker(-1) - , m_currently_trying_tracker(0) - , m_failed_trackers(0) - , m_time_scaler(0) - , m_num_pieces(0) - , m_sequenced_download_threshold(0) - , m_got_tracker_response(false) - , m_ratio(0.f) - , m_total_failed_bytes(0) - , m_total_redundant_bytes(0) - , m_net_interface(net_interface.address(), 0) - , m_save_path(complete(save_path)) - , m_compact_mode(compact_mode) - , m_default_block_size(block_size) - , m_connections_initialized(false) - , m_settings(s) - , m_storage_constructor(sc) - { -#ifndef NDEBUG - m_initial_done = 0; -#endif - -#ifdef TORRENT_LOGGING - m_log = ses.create_log("torrent_" - + boost::lexical_cast(info_hash) - , m_ses.listen_port(), true); - print_legend(m_log); - m_second_count = 0; - std::fill_n(m_ul_history, 10, 0); - std::fill_n(m_dl_history, 10, 0); -#endif - - INVARIANT_CHECK; - - if (name) m_name.reset(new std::string(name)); - - m_uploads_quota.min = 2; - m_connections_quota.min = 2; - // this will be corrected the next time the main session - // distributes resources, i.e. on average in 0.5 seconds - m_connections_quota.given = 100; - m_uploads_quota.max = std::numeric_limits::max(); - m_connections_quota.max = std::numeric_limits::max(); - if (tracker_url) - { - m_trackers.push_back(announce_entry(tracker_url)); - m_torrent_file.add_tracker(tracker_url); - } - - m_policy.reset(new policy(this)); - } - - void torrent::start() - { - boost::weak_ptr self(shared_from_this()); - m_announce_timer.expires_from_now(seconds(1)); - m_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_announce_disp, self, _1))); - } - -#ifndef TORRENT_DISABLE_DHT - bool torrent::should_announce_dht() const - { - // don't announce private torrents - if (m_torrent_file.is_valid() && m_torrent_file.priv()) return false; - - if (m_trackers.empty()) return true; - - return m_failed_trackers > 0 || !m_ses.settings().use_dht_as_fallback; - } -#endif - - torrent::~torrent() - { - // The invariant can't be maintained here, since the torrent - // is being destructed, all weak references to it have been - // reset, which means that all its peers already have an - // invalidated torrent pointer (so it cannot be verified to be correct) - - // i.e. the invariant can only be maintained if all connections have - // been closed by the time the torrent is destructed. And they are - // supposed to be closed. So we can still do the invariant check. - - assert(m_connections.empty()); - - INVARIANT_CHECK; - - if (m_ses.is_aborted()) - m_abort = true; - if (!m_connections.empty()) - disconnect_all(); - } - - std::string torrent::name() const - { - if (valid_metadata()) return m_torrent_file.name(); - if (m_name) return *m_name; - return ""; - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - void torrent::add_extension(boost::shared_ptr ext) - { - m_extensions.push_back(ext); - } -#endif - - void torrent::init() - { - INVARIANT_CHECK; - - assert(m_torrent_file.is_valid()); - assert(m_torrent_file.num_files() > 0); - assert(m_torrent_file.total_size() >= 0); - - m_have_pieces.resize(m_torrent_file.num_pieces(), false); - m_storage.reset(new piece_manager(m_torrent_file, m_save_path - , m_ses.m_files, m_storage_constructor)); - m_block_size = calculate_block_size(m_torrent_file, m_default_block_size); - m_picker.reset(new piece_picker( - static_cast(m_torrent_file.piece_length() / m_block_size) - , static_cast((m_torrent_file.total_size()+m_block_size-1)/m_block_size))); - - std::vector const& url_seeds = m_torrent_file.url_seeds(); - std::copy(url_seeds.begin(), url_seeds.end(), std::inserter(m_web_seeds - , m_web_seeds.begin())); - } - - void torrent::use_interface(const char* net_interface) - { - INVARIANT_CHECK; - - m_net_interface = tcp::endpoint(address::from_string(net_interface), 0); - } - - void torrent::on_announce_disp(boost::weak_ptr p - , asio::error_code const& e) - { - if (e) return; - boost::shared_ptr t = p.lock(); - if (!t) return; - t->on_announce(); - } - - void torrent::on_announce() -#ifndef NDEBUG - try -#endif - { - boost::weak_ptr self(shared_from_this()); - - // announce on local network every 5 minutes - m_announce_timer.expires_from_now(minutes(5)); - m_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_announce_disp, self, _1))); - - // announce with the local discovery service - m_ses.announce_lsd(m_torrent_file.info_hash()); - -#ifndef TORRENT_DISABLE_DHT - if (!m_ses.m_dht) return; - ptime now = time_now(); - if (should_announce_dht() && now - m_last_dht_announce > minutes(14)) - { - m_last_dht_announce = now; - // TODO: There should be a way to abort an announce operation on the dht. - // when the torrent is destructed - assert(m_ses.m_external_listen_port > 0); - m_ses.m_dht->announce(m_torrent_file.info_hash() - , m_ses.m_external_listen_port - , m_ses.m_strand.wrap(bind(&torrent::on_dht_announce_response_disp, self, _1))); - } -#endif - } -#ifndef NDEBUG - catch (std::exception& e) - { - std::cerr << e.what() << std::endl; - assert(false); - }; -#endif - -#ifndef TORRENT_DISABLE_DHT - - void torrent::on_dht_announce_response_disp(boost::weak_ptr t - , std::vector const& peers) - { - boost::shared_ptr tor = t.lock(); - if (!tor) return; - tor->on_dht_announce_response(peers); - } - - void torrent::on_dht_announce_response(std::vector const& peers) - { - if (peers.empty()) return; - - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(tracker_reply_alert( - get_handle(), peers.size(), "Got peers from DHT")); - } - std::for_each(peers.begin(), peers.end(), bind( - &policy::peer_from_tracker, boost::ref(m_policy), _1, peer_id(0) - , peer_info::dht, 0)); - } - -#endif - - // returns true if it is time for this torrent to make another - // tracker request - bool torrent::should_request() - { - INVARIANT_CHECK; - - if (m_torrent_file.trackers().empty()) return false; - - if (m_just_paused) - { - m_just_paused = false; - return true; - } - return !m_paused && m_next_request < time_now(); - } - - void torrent::tracker_warning(std::string const& msg) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (m_ses.m_alerts.should_post(alert::warning)) - { - m_ses.m_alerts.post_alert(tracker_warning_alert(get_handle(), msg)); - } - } - - void torrent::tracker_response( - tracker_request const& - , std::vector& peer_list - , int interval - , int complete - , int incomplete) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - m_failed_trackers = 0; - // announce intervals less than 5 minutes - // are insane. - if (interval < 60 * 5) interval = 60 * 5; - - m_last_working_tracker - = prioritize_tracker(m_currently_trying_tracker); - m_currently_trying_tracker = 0; - - m_duration = interval; - m_next_request = time_now() + seconds(m_duration); - - if (complete >= 0) m_complete = complete; - if (incomplete >= 0) m_incomplete = incomplete; - - // connect to random peers from the list - std::random_shuffle(peer_list.begin(), peer_list.end()); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - std::stringstream s; - s << "TRACKER RESPONSE:\n" - "interval: " << m_duration << "\n" - "peers:\n"; - for (std::vector::const_iterator i = peer_list.begin(); - i != peer_list.end(); ++i) - { - s << " " << std::setfill(' ') << std::setw(16) << i->ip - << " " << std::setw(5) << std::dec << i->port << " "; - if (!i->pid.is_all_zeros()) s << " " << i->pid << " " << identify_client(i->pid); - s << "\n"; - } - debug_log(s.str()); -#endif - // for each of the peers we got from the tracker - for (std::vector::iterator i = peer_list.begin(); - i != peer_list.end(); ++i) - { - // don't make connections to ourself - if (i->pid == m_ses.get_peer_id()) - continue; - - try - { - tcp::endpoint a(address::from_string(i->ip), i->port); - - if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - debug_log("blocked ip from tracker: " + i->ip); -#endif - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(peer_blocked_alert(a.address() - , "peer from tracker blocked by IP filter")); - } - - continue; - } - - m_policy->peer_from_tracker(a, i->pid, peer_info::tracker, 0); - } - catch (std::exception&) - { - // assume this is because we got a hostname instead of - // an ip address from the tracker - - tcp::resolver::query q(i->ip, boost::lexical_cast(i->port)); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_peer_name_lookup, shared_from_this(), _1, _2, i->pid))); - } - } - m_policy->pulse(); - - if (m_ses.m_alerts.should_post(alert::info)) - { - std::stringstream s; - s << "Got response from tracker: " - << m_trackers[m_last_working_tracker].url; - m_ses.m_alerts.post_alert(tracker_reply_alert( - get_handle(), peer_list.size(), s.str())); - } - m_got_tracker_response = true; - } - - void torrent::on_peer_name_lookup(asio::error_code const& e, tcp::resolver::iterator host - , peer_id pid) try - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (e || host == tcp::resolver::iterator() || - m_ses.is_aborted()) return; - - if (m_ses.m_ip_filter.access(host->endpoint().address()) & ip_filter::blocked) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - debug_log("blocked ip from tracker: " + host->endpoint().address().to_string()); -#endif - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(peer_blocked_alert(host->endpoint().address() - , "peer from tracker blocked by IP filter")); - } - - return; - } - - m_policy->peer_from_tracker(*host, pid, peer_info::tracker, 0); - } - catch (std::exception&) - {}; - - size_type torrent::bytes_left() const - { - // if we don't have the metadata yet, we - // cannot tell how big the torrent is. - if (!valid_metadata()) return -1; - return m_torrent_file.total_size() - - quantized_bytes_done(); - } - - size_type torrent::quantized_bytes_done() const - { -// INVARIANT_CHECK; - - if (!valid_metadata()) return 0; - - if (m_torrent_file.num_pieces() == 0) - return 0; - - if (is_seed()) return m_torrent_file.total_size(); - - const int last_piece = m_torrent_file.num_pieces() - 1; - - size_type total_done - = m_num_pieces * m_torrent_file.piece_length(); - - // if we have the last piece, we have to correct - // the amount we have, since the first calculation - // assumed all pieces were of equal size - if (m_have_pieces[last_piece]) - { - int corr = m_torrent_file.piece_size(last_piece) - - m_torrent_file.piece_length(); - total_done += corr; - } - return total_done; - } - - // the first value is the total number of bytes downloaded - // the second value is the number of bytes of those that haven't - // been filtered as not wanted we have downloaded - tuple torrent::bytes_done() const - { - INVARIANT_CHECK; - - if (!valid_metadata() || m_torrent_file.num_pieces() == 0) - return tuple(0,0); - - const int last_piece = m_torrent_file.num_pieces() - 1; - - if (is_seed()) - return make_tuple(m_torrent_file.total_size() - , m_torrent_file.total_size()); - - size_type wanted_done = (m_num_pieces - m_picker->num_have_filtered()) - * m_torrent_file.piece_length(); - - size_type total_done - = m_num_pieces * m_torrent_file.piece_length(); - assert(m_num_pieces < m_torrent_file.num_pieces()); - - // if we have the last piece, we have to correct - // the amount we have, since the first calculation - // assumed all pieces were of equal size - if (m_have_pieces[last_piece]) - { - int corr = m_torrent_file.piece_size(last_piece) - - m_torrent_file.piece_length(); - total_done += corr; - if (m_picker->piece_priority(last_piece) != 0) - wanted_done += corr; - } - - assert(total_done <= m_torrent_file.total_size()); - assert(wanted_done <= m_torrent_file.total_size()); - - const std::vector& dl_queue - = m_picker->get_download_queue(); - - const int blocks_per_piece = static_cast( - m_torrent_file.piece_length() / m_block_size); - - for (std::vector::const_iterator i = - dl_queue.begin(); i != dl_queue.end(); ++i) - { - int corr = 0; - int index = i->index; - assert(!m_have_pieces[index]); - assert(i->finished < m_picker->blocks_in_piece(index)); - -#ifndef NDEBUG - for (std::vector::const_iterator j = boost::next(i); - j != dl_queue.end(); ++j) - { - assert(j->index != index); - } -#endif - - for (int j = 0; j < blocks_per_piece; ++j) - { - assert(i->info[j].finished == 0 || i->info[j].finished == 1); - assert(m_picker->is_finished(piece_block(index, j)) == i->info[j].finished); - corr += i->info[j].finished * m_block_size; - assert(index != last_piece || j < m_picker->blocks_in_last_piece() - || i->info[j].finished == 0); - } - - // correction if this was the last piece - // and if we have the last block - if (i->index == last_piece - && i->info[m_picker->blocks_in_last_piece()-1].finished) - { - corr -= m_block_size; - corr += m_torrent_file.piece_size(last_piece) % m_block_size; - } - total_done += corr; - if (m_picker->piece_priority(index) != 0) - wanted_done += corr; - } - - assert(total_done < m_torrent_file.total_size()); - assert(wanted_done < m_torrent_file.total_size()); - - std::map downloading_piece; - for (const_peer_iterator i = begin(); i != end(); ++i) - { - peer_connection* pc = i->second; - boost::optional p - = pc->downloading_piece_progress(); - if (p) - { - if (m_have_pieces[p->piece_index]) - continue; - - piece_block block(p->piece_index, p->block_index); - if (m_picker->is_finished(block)) - continue; - - std::map::iterator dp - = downloading_piece.find(block); - if (dp != downloading_piece.end()) - { - if (dp->second < p->bytes_downloaded) - dp->second = p->bytes_downloaded; - } - else - { - downloading_piece[block] = p->bytes_downloaded; - } -#ifndef NDEBUG - assert(p->bytes_downloaded <= p->full_block_bytes); - int last_piece = m_torrent_file.num_pieces() - 1; - if (p->piece_index == last_piece - && p->block_index == m_torrent_file.piece_size(last_piece) / block_size()) - assert(p->full_block_bytes == m_torrent_file.piece_size(last_piece) % block_size()); - else - assert(p->full_block_bytes == block_size()); -#endif - } - } - for (std::map::iterator i = downloading_piece.begin(); - i != downloading_piece.end(); ++i) - { - total_done += i->second; - if (m_picker->piece_priority(i->first.piece_index) != 0) - wanted_done += i->second; - } - -#ifndef NDEBUG - - if (total_done >= m_torrent_file.total_size()) - { - std::copy(m_have_pieces.begin(), m_have_pieces.end() - , std::ostream_iterator(std::cerr, " ")); - std::cerr << std::endl; - std::cerr << "num_pieces: " << m_num_pieces << std::endl; - - std::cerr << "unfinished:" << std::endl; - - for (std::vector::const_iterator i = - dl_queue.begin(); i != dl_queue.end(); ++i) - { - std::cerr << " " << i->index << " "; - for (int j = 0; j < blocks_per_piece; ++j) - { - std::cerr << i->info[j].finished; - } - std::cerr << std::endl; - } - - std::cerr << "downloading pieces:" << std::endl; - - for (std::map::iterator i = downloading_piece.begin(); - i != downloading_piece.end(); ++i) - { - std::cerr << " " << i->first.piece_index << ":" << i->first.block_index - << " " << i->second << std::endl; - } - - } - - assert(total_done < m_torrent_file.total_size()); - assert(wanted_done < m_torrent_file.total_size()); - -#endif - - assert(total_done >= wanted_done); - return make_tuple(total_done, wanted_done); - } - - void torrent::piece_failed(int index) - { - // if the last piece fails the peer connection will still - // think that it has received all of it until this function - // resets the download queue. So, we cannot do the - // invariant check here since it assumes: - // (total_done == m_torrent_file.total_size()) => is_seed() -// INVARIANT_CHECK; - - assert(m_storage.get()); - assert(m_picker.get()); - assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); - - if (m_ses.m_alerts.should_post(alert::info)) - { - std::stringstream s; - s << "hash for piece " << index << " failed"; - m_ses.m_alerts.post_alert(hash_failed_alert(get_handle(), index, s.str())); - } - // increase the total amount of failed bytes - m_total_failed_bytes += m_torrent_file.piece_size(index); - - std::vector downloaders; - m_picker->get_downloaders(downloaders, index); - - // decrease the trust point of all peers that sent - // parts of this piece. - // first, build a set of all peers that participated - std::set peers; - std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { (*i)->on_piece_failed(index); } catch (std::exception&) {} - } -#endif - - for (std::set::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - peer_iterator p = m_connections.find(*i); - if (p == m_connections.end()) continue; - p->second->received_invalid_data(index); - - // either, we have received too many failed hashes - // or this was the only peer that sent us this piece. - // TODO: make this a changable setting - if (p->second->trust_points() <= -7 || peers.size() == 1) - { - // we don't trust this peer anymore - // ban it. - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(peer_ban_alert( - p->first - , get_handle() - , "banning peer because of too many corrupt pieces")); - } - - // mark the peer as banned - policy::peer* peerinfo = p->second->peer_info_struct(); - if (peerinfo) - { - peerinfo->banned = true; - } - else - { - // it might be a web seed - if (web_peer_connection const* wpc - = dynamic_cast(p->second)) - { - remove_url_seed(wpc->url()); - } - } - -#if defined(TORRENT_VERBOSE_LOGGING) - (*p->second->m_logger) << "*** BANNING PEER 'too many corrupt pieces'\n"; -#endif - p->second->disconnect(); - } - } - - // we have to let the piece_picker know that - // this piece failed the check as it can restore it - // and mark it as being interesting for download - // TODO: do this more intelligently! and keep track - // of how much crap (data that failed hash-check) and - // how much redundant data we have downloaded - // if some clients has sent more than one piece - // start with redownloading the pieces that the client - // that has sent the least number of pieces - m_picker->restore_piece(index); - m_storage->mark_failed(index); - - assert(m_have_pieces[index] == false); - } - - void torrent::abort() - { - INVARIANT_CHECK; - - m_abort = true; - // if the torrent is paused, it doesn't need - // to announce with even=stopped again. - if (!m_paused) - m_event = tracker_request::stopped; - // disconnect all peers and close all - // files belonging to the torrents - disconnect_all(); - if (m_storage.get()) m_storage->release_files(); - } - - void torrent::announce_piece(int index) - { -// INVARIANT_CHECK; - - assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); - - std::vector downloaders; - m_picker->get_downloaders(downloaders, index); - - // increase the trust point of all peers that sent - // parts of this piece. - std::set peers; - std::copy(downloaders.begin(), downloaders.end(), std::inserter(peers, peers.begin())); - - if (!m_have_pieces[index]) - m_num_pieces++; - m_have_pieces[index] = true; - - assert(std::accumulate(m_have_pieces.begin(), m_have_pieces.end(), 0) - == m_num_pieces); - - m_picker->we_have(index); - for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) - try { i->second->announce_piece(index); } catch (std::exception&) {} - - for (std::set::iterator i = peers.begin() - , end(peers.end()); i != end; ++i) - { - peer_iterator p = m_connections.find(*i); - if (p == m_connections.end()) continue; - p->second->received_valid_data(index); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { (*i)->on_piece_pass(index); } catch (std::exception&) {} - } -#endif - if (is_seed()) - { - m_picker.reset(); - m_torrent_file.seed_free(); - } - } - - std::string torrent::tracker_login() const - { - if (m_username.empty() && m_password.empty()) return ""; - return m_username + ":" + m_password; - } - - - - void torrent::set_piece_priority(int index, int priority) - { - INVARIANT_CHECK; - - assert(valid_metadata()); - if (is_seed()) return; - - // this call is only valid on torrents with metadata - assert(m_picker.get()); - assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); - - m_picker->set_piece_priority(index, priority); - update_peer_interest(); - } - - int torrent::piece_priority(int index) const - { - INVARIANT_CHECK; - - assert(valid_metadata()); - if (is_seed()) return 1; - - // this call is only valid on torrents with metadata - assert(m_picker.get()); - assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); - - return m_picker->piece_priority(index); - } - - void torrent::prioritize_pieces(std::vector const& pieces) - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - assert(valid_metadata()); - if (is_seed()) return; - - assert(m_picker.get()); - - int index = 0; - for (std::vector::const_iterator i = pieces.begin() - , end(pieces.end()); i != end; ++i, ++index) - { - assert(*i >= 0); - assert(*i <= 7); - m_picker->set_piece_priority(index, *i); - } - update_peer_interest(); - } - - void torrent::piece_priorities(std::vector& pieces) const - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - assert(valid_metadata()); - if (is_seed()) - { - pieces.clear(); - pieces.resize(m_torrent_file.num_pieces(), 1); - return; - } - - assert(m_picker.get()); - m_picker->piece_priorities(pieces); - } - - namespace - { - void set_if_greater(int& piece_prio, int file_prio) - { - if (file_prio > piece_prio) piece_prio = file_prio; - } - } - - void torrent::prioritize_files(std::vector const& files) - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - if (!valid_metadata() || is_seed()) return; - - // the bitmask need to have exactly one bit for every file - // in the torrent - assert(int(files.size()) == m_torrent_file.num_files()); - - size_type position = 0; - - if (m_torrent_file.num_pieces() == 0) return; - - int piece_length = m_torrent_file.piece_length(); - // initialize the piece priorities to 0, then only allow - // setting higher priorities - std::vector pieces(m_torrent_file.num_pieces(), 0); - for (int i = 0; i < int(files.size()); ++i) - { - size_type start = position; - size_type size = m_torrent_file.file_at(i).size; - if (size == 0) continue; - position += size; - // mark all pieces of the file with this file's priority - // but only if the priority is higher than the pieces - // already set (to avoid problems with overlapping pieces) - int start_piece = int(start / piece_length); - int last_piece = int((position - 1) / piece_length); - assert(last_piece <= int(pieces.size())); - // if one piece spans several files, we might - // come here several times with the same start_piece, end_piece - std::for_each(pieces.begin() + start_piece - , pieces.begin() + last_piece + 1 - , bind(&set_if_greater, _1, files[i])); - } - prioritize_pieces(pieces); - update_peer_interest(); - } - - // updates the interested flag in peers - void torrent::update_peer_interest() - { - for (peer_iterator i = begin(); i != end(); ++i) - i->second->update_interest(); - } - - void torrent::filter_piece(int index, bool filter) - { - INVARIANT_CHECK; - - assert(valid_metadata()); - if (is_seed()) return; - - // this call is only valid on torrents with metadata - assert(m_picker.get()); - assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); - - m_picker->set_piece_priority(index, filter ? 1 : 0); - update_peer_interest(); - } - - void torrent::filter_pieces(std::vector const& bitmask) - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - assert(valid_metadata()); - if (is_seed()) return; - - assert(m_picker.get()); - - int index = 0; - for (std::vector::const_iterator i = bitmask.begin() - , end(bitmask.end()); i != end; ++i, ++index) - { - if ((m_picker->piece_priority(index) == 0) == *i) continue; - if (*i) - m_picker->set_piece_priority(index, 0); - else - m_picker->set_piece_priority(index, 1); - } - update_peer_interest(); - } - - bool torrent::is_piece_filtered(int index) const - { - // this call is only valid on torrents with metadata - assert(valid_metadata()); - if (is_seed()) return false; - - assert(m_picker.get()); - assert(index >= 0); - assert(index < m_torrent_file.num_pieces()); - - return m_picker->piece_priority(index) == 0; - } - - void torrent::filtered_pieces(std::vector& bitmask) const - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - assert(valid_metadata()); - if (is_seed()) - { - bitmask.clear(); - bitmask.resize(m_torrent_file.num_pieces(), false); - return; - } - - assert(m_picker.get()); - m_picker->filtered_pieces(bitmask); - } - - void torrent::filter_files(std::vector const& bitmask) - { - INVARIANT_CHECK; - - // this call is only valid on torrents with metadata - if (!valid_metadata() || is_seed()) return; - - // the bitmask need to have exactly one bit for every file - // in the torrent - assert((int)bitmask.size() == m_torrent_file.num_files()); - - size_type position = 0; - - if (m_torrent_file.num_pieces()) - { - int piece_length = m_torrent_file.piece_length(); - // mark all pieces as filtered, then clear the bits for files - // that should be downloaded - std::vector piece_filter(m_torrent_file.num_pieces(), true); - for (int i = 0; i < (int)bitmask.size(); ++i) - { - size_type start = position; - position += m_torrent_file.file_at(i).size; - // is the file selected for download? - if (!bitmask[i]) - { - // mark all pieces of the file as downloadable - int start_piece = int(start / piece_length); - int last_piece = int(position / piece_length); - // if one piece spans several files, we might - // come here several times with the same start_piece, end_piece - std::fill(piece_filter.begin() + start_piece, piece_filter.begin() - + last_piece + 1, false); - } - } - filter_pieces(piece_filter); - } - } - - void torrent::replace_trackers(std::vector const& urls) - { - assert(!urls.empty()); - m_trackers = urls; - if (m_currently_trying_tracker >= (int)m_trackers.size()) - m_currently_trying_tracker = (int)m_trackers.size()-1; - m_last_working_tracker = -1; - } - - tracker_request torrent::generate_tracker_request() - { - INVARIANT_CHECK; - - assert(!m_trackers.empty()); - - m_next_request = time_now() + seconds(tracker_retry_delay_max); - - tracker_request req; - req.info_hash = m_torrent_file.info_hash(); - req.pid = m_ses.get_peer_id(); - req.downloaded = m_stat.total_payload_download(); - req.uploaded = m_stat.total_payload_upload(); - req.left = bytes_left(); - if (req.left == -1) req.left = 16*1024; - req.event = m_event; - - if (m_event != tracker_request::stopped) - m_event = tracker_request::none; - req.url = m_trackers[m_currently_trying_tracker].url; - req.num_want = 50; - // if we are aborting. we don't want any new peers - if (req.event == tracker_request::stopped) - req.num_want = 0; - - // default initialize, these should be set by caller - // before passing the request to the tracker_manager - req.listen_port = 0; - req.key = 0; - - return req; - } - - void torrent::remove_peer(peer_connection* p) try - { - INVARIANT_CHECK; - - assert(p != 0); - - peer_iterator i = m_connections.find(p->remote()); - if (i == m_connections.end()) - { - assert(false); - return; - } - - if (ready_for_connections()) - { - assert(p->associated_torrent().lock().get() == this); - - if (p->is_seed()) - { - if (m_picker.get()) - { - assert(!is_seed()); - m_picker->dec_refcount_all(); - } - } - else - { - // if we're a seed, we don't keep track of piece availability - if (!is_seed()) - { - const std::vector& pieces = p->get_bitfield(); - - for (std::vector::const_iterator i = pieces.begin(); - i != pieces.end(); ++i) - { - if (*i) peer_lost(static_cast(i - pieces.begin())); - } - } - } - } - - m_policy->connection_closed(*p); - p->set_peer_info(0); - m_connections.erase(i); -#ifndef NDEBUG - m_policy->check_invariant(); -#endif - } - catch (std::exception& e) - { -#ifndef NDEBUG - std::string err = e.what(); -#endif - assert(false); - }; - - void torrent::connect_to_url_seed(std::string const& url) - { - INVARIANT_CHECK; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << time_now_string() << " resolving: " << url << "\n"; -#endif - - m_resolving_web_seeds.insert(url); - proxy_settings const& ps = m_ses.web_seed_proxy(); - if (ps.type == proxy_settings::http - || ps.type == proxy_settings::http_pw) - { - // use proxy - tcp::resolver::query q(ps.hostname - , boost::lexical_cast(ps.port)); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_proxy_name_lookup, shared_from_this(), _1, _2, url))); - } - else - { - std::string protocol; - std::string auth; - std::string hostname; - int port; - std::string path; - boost::tie(protocol, auth, hostname, port, path) - = parse_url_components(url); - - // TODO: should auth be used here? - - tcp::resolver::query q(hostname, boost::lexical_cast(port)); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url - , tcp::endpoint()))); - } - - } - - void torrent::on_proxy_name_lookup(asio::error_code const& e, tcp::resolver::iterator host - , std::string url) try - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << time_now_string() << " completed resolve proxy hostname for: " << url << "\n"; -#endif - - if (e || host == tcp::resolver::iterator()) - { - if (m_ses.m_alerts.should_post(alert::warning)) - { - std::stringstream msg; - msg << "HTTP seed proxy hostname lookup failed: " << e.message(); - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, msg.str())); - } - - // the name lookup failed for the http host. Don't try - // this host again - remove_url_seed(url); - return; - } - - if (m_ses.is_aborted()) return; - - tcp::endpoint a(host->endpoint()); - - using boost::tuples::ignore; - std::string hostname; - int port; - boost::tie(ignore, ignore, hostname, port, ignore) - = parse_url_components(url); - - if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) - { - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(peer_blocked_alert(a.address() - , "proxy (" + hostname + ") blocked by IP filter")); - } - return; - } - - tcp::resolver::query q(hostname, boost::lexical_cast(port)); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url, a))); - } - catch (std::exception& exc) - { - assert(false); - }; - - void torrent::on_name_lookup(asio::error_code const& e, tcp::resolver::iterator host - , std::string url, tcp::endpoint proxy) try - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << time_now_string() << " completed resolve: " << url << "\n"; -#endif - - std::set::iterator i = m_resolving_web_seeds.find(url); - if (i != m_resolving_web_seeds.end()) m_resolving_web_seeds.erase(i); - - if (e || host == tcp::resolver::iterator()) - { - if (m_ses.m_alerts.should_post(alert::warning)) - { - std::stringstream msg; - msg << "HTTP seed hostname lookup failed: " << e.message(); - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), url, msg.str())); - } -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << url << "\n"; -#endif - - // the name lookup failed for the http host. Don't try - // this host again - remove_url_seed(url); - return; - } - - if (m_ses.is_aborted()) return; - - tcp::endpoint a(host->endpoint()); - - if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) - { - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(peer_blocked_alert(a.address() - , "web seed (" + url + ") blocked by IP filter")); - } - return; - } - - peer_iterator conn = m_connections.find(a); - if (conn != m_connections.end()) - { - if (dynamic_cast(conn->second) == 0 - || conn->second->is_disconnecting()) conn->second->disconnect(); - else return; - } - - boost::shared_ptr s - = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy()); - if (m_ses.web_seed_proxy().type == proxy_settings::http - || m_ses.web_seed_proxy().type == proxy_settings::http_pw) - { - // the web seed connection will talk immediately to - // the proxy, without requiring CONNECT support - s->get().set_no_connect(true); - } - boost::intrusive_ptr c(new web_peer_connection( - m_ses, shared_from_this(), s, a, url, 0)); - -#ifndef NDEBUG - c->m_in_constructor = false; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr pp((*i)->new_connection(c.get())); - if (pp) c->add_extension(pp); - } -#endif - - try - { - assert(m_connections.find(a) == m_connections.end()); - - // add the newly connected peer to this torrent's peer list - m_connections.insert( - std::make_pair(a, boost::get_pointer(c))); - m_ses.m_connections.insert(std::make_pair(s, c)); - - m_ses.m_half_open.enqueue( - bind(&peer_connection::connect, c, _1) - , bind(&peer_connection::timed_out, c) - , seconds(settings().peer_connect_timeout)); - } - catch (std::exception& e) - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n"; -#endif - - // TODO: post an error alert! - std::map::iterator i = m_connections.find(a); - if (i != m_connections.end()) m_connections.erase(i); - m_ses.connection_failed(s, a, e.what()); - c->disconnect(); - } - } - catch (std::exception& exc) - { -#ifndef NDEBUG - std::cerr << exc.what() << std::endl; -#endif - assert(false); - }; - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void torrent::resolve_peer_country(boost::intrusive_ptr const& p) const - { - if (m_resolving_country - || p->has_country() - || p->is_connecting() - || p->is_queued() - || p->in_handshake()) return; - - m_resolving_country = true; - tcp::resolver::query q(boost::lexical_cast(p->remote().address()) - + ".zz.countries.nerd.dk", "0"); - m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( - bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p))); - } - - namespace - { - struct country_entry - { - int code; - char const* name; - }; - } - - void torrent::on_country_lookup(asio::error_code const& error, tcp::resolver::iterator i - , intrusive_ptr p) const - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - m_resolving_country = false; - - // must be ordered in increasing order - country_entry country_map[] = - { - { 4, "AF"}, { 8, "AL"}, { 10, "AQ"}, { 12, "DZ"}, { 16, "AS"} - , { 20, "AD"}, { 24, "AO"}, { 28, "AG"}, { 31, "AZ"}, { 32, "AR"} - , { 36, "AU"}, { 40, "AT"}, { 44, "BS"}, { 48, "BH"}, { 50, "BD"} - , { 51, "AM"}, { 52, "BB"}, { 56, "BE"}, { 60, "BM"}, { 64, "BT"} - , { 68, "BO"}, { 70, "BA"}, { 72, "BW"}, { 74, "BV"}, { 76, "BR"} - , { 84, "BZ"}, { 86, "IO"}, { 90, "SB"}, { 92, "VG"}, { 96, "BN"} - , {100, "BG"}, {104, "MM"}, {108, "BI"}, {112, "BY"}, {116, "KH"} - , {120, "CM"}, {124, "CA"}, {132, "CV"}, {136, "KY"}, {140, "CF"} - , {144, "LK"}, {148, "TD"}, {152, "CL"}, {156, "CN"}, {158, "TW"} - , {162, "CX"}, {166, "CC"}, {170, "CO"}, {174, "KM"}, {175, "YT"} - , {178, "CG"}, {180, "CD"}, {184, "CK"}, {188, "CR"}, {191, "HR"} - , {192, "CU"}, {203, "CZ"}, {204, "BJ"}, {208, "DK"}, {212, "DM"} - , {214, "DO"}, {218, "EC"}, {222, "SV"}, {226, "GQ"}, {231, "ET"} - , {232, "ER"}, {233, "EE"}, {234, "FO"}, {238, "FK"}, {239, "GS"} - , {242, "FJ"}, {246, "FI"}, {248, "AX"}, {250, "FR"}, {254, "GF"} - , {258, "PF"}, {260, "TF"}, {262, "DJ"}, {266, "GA"}, {268, "GE"} - , {270, "GM"}, {275, "PS"}, {276, "DE"}, {288, "GH"}, {292, "GI"} - , {296, "KI"}, {300, "GR"}, {304, "GL"}, {308, "GD"}, {312, "GP"} - , {316, "GU"}, {320, "GT"}, {324, "GN"}, {328, "GY"}, {332, "HT"} - , {334, "HM"}, {336, "VA"}, {340, "HN"}, {344, "HK"}, {348, "HU"} - , {352, "IS"}, {356, "IN"}, {360, "ID"}, {364, "IR"}, {368, "IQ"} - , {372, "IE"}, {376, "IL"}, {380, "IT"}, {384, "CI"}, {388, "JM"} - , {392, "JP"}, {398, "KZ"}, {400, "JO"}, {404, "KE"}, {408, "KP"} - , {410, "KR"}, {414, "KW"}, {417, "KG"}, {418, "LA"}, {422, "LB"} - , {426, "LS"}, {428, "LV"}, {430, "LR"}, {434, "LY"}, {438, "LI"} - , {440, "LT"}, {442, "LU"}, {446, "MO"}, {450, "MG"}, {454, "MW"} - , {458, "MY"}, {462, "MV"}, {466, "ML"}, {470, "MT"}, {474, "MQ"} - , {478, "MR"}, {480, "MU"}, {484, "MX"}, {492, "MC"}, {496, "MN"} - , {498, "MD"}, {500, "MS"}, {504, "MA"}, {508, "MZ"}, {512, "OM"} - , {516, "NA"}, {520, "NR"}, {524, "NP"}, {528, "NL"}, {530, "AN"} - , {533, "AW"}, {540, "NC"}, {548, "VU"}, {554, "NZ"}, {558, "NI"} - , {562, "NE"}, {566, "NG"}, {570, "NU"}, {574, "NF"}, {578, "NO"} - , {580, "MP"}, {581, "UM"}, {583, "FM"}, {584, "MH"}, {585, "PW"} - , {586, "PK"}, {591, "PA"}, {598, "PG"}, {600, "PY"}, {604, "PE"} - , {608, "PH"}, {612, "PN"}, {616, "PL"}, {620, "PT"}, {624, "GW"} - , {626, "TL"}, {630, "PR"}, {634, "QA"}, {634, "QA"}, {638, "RE"} - , {642, "RO"}, {643, "RU"}, {646, "RW"}, {654, "SH"}, {659, "KN"} - , {660, "AI"}, {662, "LC"}, {666, "PM"}, {670, "VC"}, {674, "SM"} - , {678, "ST"}, {682, "SA"}, {686, "SN"}, {690, "SC"}, {694, "SL"} - , {702, "SG"}, {703, "SK"}, {704, "VN"}, {705, "SI"}, {706, "SO"} - , {710, "ZA"}, {716, "ZW"}, {724, "ES"}, {732, "EH"}, {736, "SD"} - , {740, "SR"}, {744, "SJ"}, {748, "SZ"}, {752, "SE"}, {756, "CH"} - , {760, "SY"}, {762, "TJ"}, {764, "TH"}, {768, "TG"}, {772, "TK"} - , {776, "TO"}, {780, "TT"}, {784, "AE"}, {788, "TN"}, {792, "TR"} - , {795, "TM"}, {796, "TC"}, {798, "TV"}, {800, "UG"}, {804, "UA"} - , {807, "MK"}, {818, "EG"}, {826, "GB"}, {834, "TZ"}, {840, "US"} - , {850, "VI"}, {854, "BF"}, {858, "UY"}, {860, "UZ"}, {862, "VE"} - , {876, "WF"}, {882, "WS"}, {887, "YE"}, {891, "CS"}, {894, "ZM"} - }; - - if (error || i == tcp::resolver::iterator()) - { - // this is used to indicate that we shouldn't - // try to resolve it again - p->set_country("--"); - return; - } - - while (i != tcp::resolver::iterator() - && !i->endpoint().address().is_v4()) ++i; - if (i != tcp::resolver::iterator()) - { - // country is an ISO 3166 country code - int country = i->endpoint().address().to_v4().to_ulong() & 0xffff; - - // look up the country code in the map - const int size = sizeof(country_map)/sizeof(country_map[0]); - country_entry tmp = {country, ""}; - country_entry* i = - std::lower_bound(country_map, country_map + size, tmp - , bind(&country_entry::code, _1) < bind(&country_entry::code, _2)); - if (i == country_map + size - || i->code != country) - { - // unknown country! - p->set_country("!!"); -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - (*m_ses.m_logger) << "IP " << p->remote().address() << " was mapped to unknown country: " << country << "\n"; -#endif - return; - } - - p->set_country(i->name); - } - } -#endif - - peer_connection* torrent::connect_to_peer(policy::peer* peerinfo) - { - INVARIANT_CHECK; - - assert(peerinfo); - assert(peerinfo->connection == 0); -#ifndef NDEBUG - // this asserts that we don't have duplicates in the policy's peer list - peer_iterator i_ = m_connections.find(peerinfo->ip); - assert(i_ == m_connections.end() - || i_->second->is_disconnecting() - || dynamic_cast(i_->second) == 0 - || m_ses.settings().allow_multiple_connections_per_ip); -#endif - - assert(want_more_peers()); - - tcp::endpoint const& a(peerinfo->ip); - assert((m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) == 0); - - boost::shared_ptr s - = instantiate_connection(m_ses.m_io_service, m_ses.peer_proxy()); - boost::intrusive_ptr c(new bt_peer_connection( - m_ses, shared_from_this(), s, a, peerinfo)); - -#ifndef NDEBUG - c->m_in_constructor = false; -#endif - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr pp((*i)->new_connection(c.get())); - if (pp) c->add_extension(pp); - } -#endif - - try - { - // add the newly connected peer to this torrent's peer list - m_connections.insert( - std::make_pair(a, boost::get_pointer(c))); - m_ses.m_connections.insert(std::make_pair(s, c)); - - m_ses.m_half_open.enqueue( - bind(&peer_connection::connect, c, _1) - , bind(&peer_connection::timed_out, c) - , seconds(settings().peer_connect_timeout)); - } - catch (std::exception& e) - { - // TODO: post an error alert! - std::map::iterator i = m_connections.find(a); - if (i != m_connections.end()) m_connections.erase(i); - m_ses.connection_failed(s, a, e.what()); - c->disconnect(); - throw; - } - if (c->is_disconnecting()) throw protocol_error("failed to connect"); - return c.get(); - } - - void torrent::set_metadata(entry const& metadata) - { - m_torrent_file.parse_info_section(metadata); - - boost::mutex::scoped_lock(m_checker.m_mutex); - - boost::shared_ptr d( - new aux::piece_checker_data); - d->torrent_ptr = shared_from_this(); - d->save_path = m_save_path; - d->info_hash = m_torrent_file.info_hash(); - // add the torrent to the queue to be checked - m_checker.m_torrents.push_back(d); - typedef session_impl::torrent_map torrent_map; - torrent_map::iterator i = m_ses.m_torrents.find( - m_torrent_file.info_hash()); - assert(i != m_ses.m_torrents.end()); - m_ses.m_torrents.erase(i); - // and notify the thread that it got another - // job in its queue - m_checker.m_cond.notify_one(); - - if (m_ses.m_alerts.should_post(alert::info)) - { - m_ses.m_alerts.post_alert(metadata_received_alert( - get_handle(), "metadata successfully received from swarm")); - } - } - - void torrent::attach_peer(peer_connection* p) - { - INVARIANT_CHECK; - - assert(p != 0); - assert(!p->is_local()); - - std::map::iterator c - = m_connections.find(p->remote()); - if (c != m_connections.end()) - { - // we already have a peer_connection to this ip. - // It may currently be waiting for completing a - // connection attempt that might fail. So, - // prioritize this current connection since - // it has already succeeded. - if (!c->second->is_connecting()) - { - throw protocol_error("already connected to peer"); - } - c->second->disconnect(); - } - - if (m_ses.m_connections.find(p->get_socket()) - == m_ses.m_connections.end()) - { - throw protocol_error("peer is not properly constructed"); - } - - if (m_ses.is_aborted()) - { - throw protocol_error("session is closing"); - } - - peer_iterator ci = m_connections.insert( - std::make_pair(p->remote(), p)).first; - try - { - // if new_connection throws, we have to remove the - // it from the list. - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - boost::shared_ptr pp((*i)->new_connection(p)); - if (pp) p->add_extension(pp); - } -#endif - m_policy->new_connection(*ci->second); - } - catch (std::exception& e) - { - m_connections.erase(ci); - throw; - } - assert(p->remote() == p->get_socket()->remote_endpoint()); - -#ifndef NDEBUG - m_policy->check_invariant(); -#endif - } - - bool torrent::want_more_peers() const - { - return int(m_connections.size()) < m_connections_quota.given - && m_ses.m_half_open.free_slots(); - } - - void torrent::disconnect_all() - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - while (!m_connections.empty()) - { - peer_connection& p = *m_connections.begin()->second; - assert(p.associated_torrent().lock().get() == this); - -#if defined(TORRENT_VERBOSE_LOGGING) - if (m_abort) - (*p.m_logger) << "*** CLOSING CONNECTION 'aborting'\n"; - else - (*p.m_logger) << "*** CLOSING CONNECTION 'pausing'\n"; -#endif -#ifndef NDEBUG - std::size_t size = m_connections.size(); -#endif - p.disconnect(); - assert(m_connections.size() <= size); - } - } - - bool torrent::request_bandwidth_from_session(int channel) const - { - int max_assignable = m_bandwidth_limit[channel].max_assignable(); - return max_assignable > max_bandwidth_block_size - || (m_bandwidth_limit[channel].throttle() < max_bandwidth_block_size - && max_assignable == m_bandwidth_limit[channel].throttle()); - } - - int torrent::bandwidth_throttle(int channel) const - { - return m_bandwidth_limit[channel].throttle(); - } - - void torrent::request_bandwidth(int channel - , boost::intrusive_ptr p - , bool non_prioritized) - { - if (request_bandwidth_from_session(channel)) - { - if (channel == peer_connection::upload_channel) - m_ses.m_ul_bandwidth_manager.request_bandwidth(p, non_prioritized); - else if (channel == peer_connection::download_channel) - m_ses.m_dl_bandwidth_manager.request_bandwidth(p, non_prioritized); - - m_bandwidth_limit[channel].assign(max_bandwidth_block_size); - } - else - { - m_bandwidth_queue[channel].push_back(bw_queue_entry(p, non_prioritized)); - } - } - - void torrent::expire_bandwidth(int channel, int amount) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - assert(amount >= -1); - if (amount == -1) amount = max_bandwidth_block_size; - m_bandwidth_limit[channel].expire(amount); - - while (!m_bandwidth_queue[channel].empty() - && request_bandwidth_from_session(channel)) - { - bw_queue_entry qe = m_bandwidth_queue[channel].front(); - m_bandwidth_queue[channel].pop_front(); - if (channel == peer_connection::upload_channel) - m_ses.m_ul_bandwidth_manager.request_bandwidth(qe.peer, qe.non_prioritized); - else if (channel == peer_connection::download_channel) - m_ses.m_dl_bandwidth_manager.request_bandwidth(qe.peer, qe.non_prioritized); - m_bandwidth_limit[channel].assign(max_bandwidth_block_size); - } - } - - void torrent::assign_bandwidth(int channel, int amount) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - assert(amount >= 0); - if (amount < max_bandwidth_block_size) - expire_bandwidth(channel, max_bandwidth_block_size - amount); - } - - // called when torrent is finished (all interested pieces downloaded) - void torrent::finished() - { - INVARIANT_CHECK; - - if (alerts().should_post(alert::info)) - { - alerts().post_alert(torrent_finished_alert( - get_handle() - , "torrent has finished downloading")); - } - - // disconnect all seeds - // TODO: should disconnect all peers that have the pieces we have - // not just seeds - std::vector seeds; - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - assert(i->second->associated_torrent().lock().get() == this); - if (i->second->is_seed()) - { -#if defined(TORRENT_VERBOSE_LOGGING) - (*i->second->m_logger) << "*** SEED, CLOSING CONNECTION\n"; -#endif - seeds.push_back(i->second); - } - } - std::for_each(seeds.begin(), seeds.end() - , bind(&peer_connection::disconnect, _1)); - - m_storage->release_files(); - } - - // called when torrent is complete (all pieces downloaded) - void torrent::completed() - { - INVARIANT_CHECK; - - // make the next tracker request - // be a completed-event - m_event = tracker_request::completed; - force_tracker_request(); - } - - // this will move the tracker with the given index - // to a prioritized position in the list (move it towards - // the begining) and return the new index to the tracker. - int torrent::prioritize_tracker(int index) - { - INVARIANT_CHECK; - - assert(index >= 0); - if (index >= (int)m_trackers.size()) return (int)m_trackers.size()-1; - - while (index > 0 && m_trackers[index].tier == m_trackers[index-1].tier) - { - std::swap(m_trackers[index].url, m_trackers[index-1].url); - --index; - } - return index; - } - - void torrent::try_next_tracker() - { - INVARIANT_CHECK; - - ++m_currently_trying_tracker; - - if ((unsigned)m_currently_trying_tracker >= m_trackers.size()) - { - int delay = tracker_retry_delay_min - + std::min(m_failed_trackers, (int)tracker_failed_max) - * (tracker_retry_delay_max - tracker_retry_delay_min) - / tracker_failed_max; - - ++m_failed_trackers; - // if we've looped the tracker list, wait a bit before retrying - m_currently_trying_tracker = 0; - m_next_request = time_now() + seconds(delay); - -#ifndef TORRENT_DISABLE_DHT - // only start the announce if we want to announce with the dht - if (should_announce_dht()) - { - // force the DHT to reannounce - m_last_dht_announce = time_now() - minutes(15); - boost::weak_ptr self(shared_from_this()); - m_announce_timer.expires_from_now(seconds(1)); - m_announce_timer.async_wait(m_ses.m_strand.wrap( - bind(&torrent::on_announce_disp, self, _1))); - } -#endif - - } - else - { - // don't delay before trying the next tracker - m_next_request = time_now(); - } - - } - - bool torrent::check_fastresume(aux::piece_checker_data& data) - { - INVARIANT_CHECK; - - if (!m_storage.get()) - { - // this means we have received the metadata through the - // metadata extension, and we have to initialize - init(); - } - - assert(m_storage.get()); - bool done = true; - try - { - done = m_storage->check_fastresume(data, m_have_pieces, m_num_pieces - , m_compact_mode); - } - catch (std::exception& e) - { - // probably means file permission failure or invalid filename - std::fill(m_have_pieces.begin(), m_have_pieces.end(), false); - m_num_pieces = 0; - - if (m_ses.m_alerts.should_post(alert::fatal)) - { - m_ses.m_alerts.post_alert( - file_error_alert( - get_handle() - , e.what())); - } - pause(); - } -#ifndef NDEBUG - m_initial_done = boost::get<0>(bytes_done()); -#endif - return done; - } - - std::pair torrent::check_files() - { - INVARIANT_CHECK; - - assert(m_storage.get()); - - std::pair progress(true, 1.f); - try - { - progress = m_storage->check_files(m_have_pieces, m_num_pieces - , m_ses.m_mutex); - } - catch (std::exception& e) - { - // probably means file permission failure or invalid filename - std::fill(m_have_pieces.begin(), m_have_pieces.end(), false); - m_num_pieces = 0; - - if (m_ses.m_alerts.should_post(alert::fatal)) - { - m_ses.m_alerts.post_alert( - file_error_alert( - get_handle() - , e.what())); - } - pause(); - } - -#ifndef NDEBUG - m_initial_done = boost::get<0>(bytes_done()); -#endif - return progress; - } - - void torrent::files_checked(std::vector const& - unfinished_pieces) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - - if (!is_seed()) - { - m_picker->files_checked(m_have_pieces, unfinished_pieces); - if (m_sequenced_download_threshold > 0) - picker().set_sequenced_download_threshold(m_sequenced_download_threshold); - } - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { (*i)->on_files_checked(); } catch (std::exception&) {} - } -#endif - - if (is_seed()) - { - m_picker.reset(); - m_torrent_file.seed_free(); - } - - if (!m_connections_initialized) - { - m_connections_initialized = true; - // all peer connections have to initialize themselves now that the metadata - // is available - typedef std::map conn_map; - for (conn_map::iterator i = m_connections.begin() - , end(m_connections.end()); i != end;) - { - try - { - i->second->init(); - i->second->on_metadata(); - ++i; - } - catch (std::exception& e) - { - // the connection failed, close it - conn_map::iterator j = i; - ++j; - m_ses.connection_failed(i->second->get_socket() - , i->first, e.what()); - i = j; - } - } - } -#ifndef NDEBUG - m_initial_done = boost::get<0>(bytes_done()); -#endif - } - - alert_manager& torrent::alerts() const - { - return m_ses.m_alerts; - } - - boost::filesystem::path torrent::save_path() const - { - return m_save_path; - } - - bool torrent::move_storage(boost::filesystem::path const& save_path) - { - INVARIANT_CHECK; - - bool ret = true; - if (m_storage.get()) - { - ret = m_storage->move_storage(save_path); - m_save_path = m_storage->save_path(); - } - else - { - m_save_path = save_path; - } - return ret; - } - - piece_manager& torrent::filesystem() - { - INVARIANT_CHECK; - - assert(m_storage.get()); - return *m_storage; - } - - - torrent_handle torrent::get_handle() const - { - INVARIANT_CHECK; - - return torrent_handle(&m_ses, &m_checker, m_torrent_file.info_hash()); - } - - session_settings const& torrent::settings() const - { -// INVARIANT_CHECK; - - return m_ses.settings(); - } - -#ifndef NDEBUG - void torrent::check_invariant() const - { -// size_type download = m_stat.total_payload_download(); -// size_type done = boost::get<0>(bytes_done()); -// assert(download >= done - m_initial_done); - for (const_peer_iterator i = begin(); i != end(); ++i) - { - peer_connection const& p = *i->second; - torrent* associated_torrent = p.associated_torrent().lock().get(); - if (associated_torrent != this) - assert(false); - } - - if (valid_metadata()) - { - assert(int(m_have_pieces.size()) == m_torrent_file.num_pieces()); - } - else - { - assert(m_have_pieces.empty()); - } - - size_type total_done = quantized_bytes_done(); - if (m_torrent_file.is_valid()) - { - if (is_seed()) - assert(total_done == m_torrent_file.total_size()); - else - assert(total_done != m_torrent_file.total_size()); - } - else - { - assert(total_done == 0); - } - -// This check is very expensive. - assert(m_num_pieces - == std::count(m_have_pieces.begin(), m_have_pieces.end(), true)); - assert(!valid_metadata() || m_block_size > 0); - assert(!valid_metadata() || (m_torrent_file.piece_length() % m_block_size) == 0); -// if (is_seed()) assert(m_picker.get() == 0); - } -#endif - - void torrent::set_sequenced_download_threshold(int threshold) - { - if (has_picker()) - { - picker().set_sequenced_download_threshold(threshold); - } - else - { - m_sequenced_download_threshold = threshold; - } - } - - - void torrent::set_max_uploads(int limit) - { - assert(limit >= -1); - if (limit == -1) limit = std::numeric_limits::max(); - m_uploads_quota.max = std::max(m_uploads_quota.min, limit); - } - - void torrent::set_max_connections(int limit) - { - assert(limit >= -1); - if (limit == -1) limit = std::numeric_limits::max(); - m_connections_quota.max = std::max(m_connections_quota.min, limit); - } - - void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit) - { - assert(limit >= -1); - peer_connection* p = connection_for(ip); - if (p == 0) return; - p->set_upload_limit(limit); - } - - void torrent::set_peer_download_limit(tcp::endpoint ip, int limit) - { - assert(limit >= -1); - peer_connection* p = connection_for(ip); - if (p == 0) return; - p->set_download_limit(limit); - } - - void torrent::set_upload_limit(int limit) - { - assert(limit >= -1); - if (limit == -1) limit = std::numeric_limits::max(); - if (limit < num_peers() * 10) limit = num_peers() * 10; - m_bandwidth_limit[peer_connection::upload_channel].throttle(limit); - } - - int torrent::upload_limit() const - { - int limit = m_bandwidth_limit[peer_connection::upload_channel].throttle(); - if (limit == std::numeric_limits::max()) limit = -1; - return limit; - } - - void torrent::set_download_limit(int limit) - { - assert(limit >= -1); - if (limit == -1) limit = std::numeric_limits::max(); - if (limit < num_peers() * 10) limit = num_peers() * 10; - m_bandwidth_limit[peer_connection::download_channel].throttle(limit); - } - - int torrent::download_limit() const - { - int limit = m_bandwidth_limit[peer_connection::download_channel].throttle(); - if (limit == std::numeric_limits::max()) limit = -1; - return limit; - } - - void torrent::pause() - { - INVARIANT_CHECK; - - if (m_paused) return; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { if ((*i)->on_pause()) return; } catch (std::exception&) {} - } -#endif - - disconnect_all(); - m_paused = true; - // tell the tracker that we stopped - m_event = tracker_request::stopped; - m_just_paused = true; - // this will make the storage close all - // files and flush all cached data - if (m_storage.get()) m_storage->release_files(); - } - - void torrent::resume() - { - INVARIANT_CHECK; - - if (!m_paused) return; - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { if ((*i)->on_resume()) return; } catch (std::exception&) {} - } -#endif - - m_paused = false; - m_uploads_quota.min = 2; - m_connections_quota.min = 2; - m_uploads_quota.max = std::numeric_limits::max(); - m_connections_quota.max = std::numeric_limits::max(); - - // tell the tracker that we're back - m_event = tracker_request::started; - force_tracker_request(); - - // make pulse be called as soon as possible - m_time_scaler = 0; - } - - void torrent::second_tick(stat& accumulator, float tick_interval) - { - INVARIANT_CHECK; - - m_connections_quota.used = (int)m_connections.size(); - m_uploads_quota.used = m_policy->num_uploads(); - -#ifndef TORRENT_DISABLE_EXTENSIONS - for (extension_list_t::iterator i = m_extensions.begin() - , end(m_extensions.end()); i != end; ++i) - { - try { (*i)->tick(); } catch (std::exception&) {} - } -#endif - - if (m_paused) - { - // let the stats fade out to 0 - m_stat.second_tick(tick_interval); - m_connections_quota.min = 0; - m_connections_quota.max = 0; - m_uploads_quota.min = 0; - m_uploads_quota.max = 0; - return; - } - - // ---- WEB SEEDS ---- - - // if we have everything we want we don't need to connect to any web-seed - if (!is_finished() && !m_web_seeds.empty()) - { - // keep trying web-seeds if there are any - // first find out which web seeds we are connected to - std::set web_seeds; - for (peer_iterator i = m_connections.begin(); - i != m_connections.end(); ++i) - { - web_peer_connection* p - = dynamic_cast(i->second); - if (!p) continue; - web_seeds.insert(p->url()); - } - - for (std::set::iterator i = m_resolving_web_seeds.begin() - , end(m_resolving_web_seeds.end()); i != end; ++i) - web_seeds.insert(web_seeds.begin(), *i); - - // from the list of available web seeds, subtract the ones we are - // already connected to. - std::vector not_connected_web_seeds; - std::set_difference(m_web_seeds.begin(), m_web_seeds.end(), web_seeds.begin() - , web_seeds.end(), std::back_inserter(not_connected_web_seeds)); - - // connect to all of those that we aren't connected to - std::for_each(not_connected_web_seeds.begin(), not_connected_web_seeds.end() - , bind(&torrent::connect_to_url_seed, this, _1)); - } - - for (peer_iterator i = m_connections.begin(); - i != m_connections.end();) - { - peer_connection* p = i->second; - ++i; - m_stat += p->statistics(); - // updates the peer connection's ul/dl bandwidth - // resource requests - try - { - p->second_tick(tick_interval); - } - catch (std::exception& e) - { -#ifdef TORRENT_VERBOSE_LOGGING - (*p->m_logger) << "**ERROR**: " << e.what() << "\n"; -#endif - p->set_failed(); - p->disconnect(); - } - } - accumulator += m_stat; - m_stat.second_tick(tick_interval); - } - - void torrent::try_connect_peer() - { - assert(want_more_peers()); - m_policy->connect_one_peer(); - } - - void torrent::distribute_resources(float tick_interval) - { - INVARIANT_CHECK; - - m_time_scaler--; - if (m_time_scaler <= 0) - { - m_time_scaler = 10; - m_policy->pulse(); - } - } - - bool torrent::verify_piece(int piece_index) - { -// INVARIANT_CHECK; - - assert(m_storage.get()); - assert(piece_index >= 0); - assert(piece_index < m_torrent_file.num_pieces()); - assert(piece_index < (int)m_have_pieces.size()); - - int size = static_cast(m_torrent_file.piece_size(piece_index)); - std::vector buffer(size); - assert(size > 0); - m_storage->read(&buffer[0], piece_index, 0, size); - - hasher h; - h.update(&buffer[0], size); - sha1_hash digest = h.final(); - - if (m_torrent_file.hash_for_piece(piece_index) != digest) - return false; - - return true; - } - - const tcp::endpoint& torrent::current_tracker() const - { - return m_tracker_address; - } - - bool torrent::is_allocating() const - { return m_storage.get() && m_storage->is_allocating(); } - - void torrent::file_progress(std::vector& fp) const - { - assert(valid_metadata()); - - fp.clear(); - fp.resize(m_torrent_file.num_files(), 0.f); - - for (int i = 0; i < m_torrent_file.num_files(); ++i) - { - peer_request ret = m_torrent_file.map_file(i, 0, 0); - size_type size = m_torrent_file.file_at(i).size; - -// zero sized files are considered -// 100% done all the time - if (size == 0) - { - fp[i] = 1.f; - continue; - } - - size_type done = 0; - while (size > 0) - { - size_type bytes_step = std::min(m_torrent_file.piece_size(ret.piece) - - ret.start, size); - if (m_have_pieces[ret.piece]) done += bytes_step; - ++ret.piece; - ret.start = 0; - size -= bytes_step; - } - assert(size == 0); - - fp[i] = static_cast(done) / m_torrent_file.file_at(i).size; - } - } - - torrent_status torrent::status() const - { - INVARIANT_CHECK; - - assert(std::accumulate( - m_have_pieces.begin() - , m_have_pieces.end() - , 0) == m_num_pieces); - - torrent_status st; - - st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end(), - boost::bind(std::logical_not(), boost::bind(&peer_connection::is_connecting, - boost::bind(&std::map::value_type::second, _1)))); - - st.num_complete = m_complete; - st.num_incomplete = m_incomplete; - st.paused = m_paused; - boost::tie(st.total_done, st.total_wanted_done) = bytes_done(); - - // payload transfer - st.total_payload_download = m_stat.total_payload_download(); - st.total_payload_upload = m_stat.total_payload_upload(); - - // total transfer - st.total_download = m_stat.total_payload_download() - + m_stat.total_protocol_download(); - st.total_upload = m_stat.total_payload_upload() - + m_stat.total_protocol_upload(); - - // failed bytes - st.total_failed_bytes = m_total_failed_bytes; - st.total_redundant_bytes = m_total_redundant_bytes; - - // transfer rate - st.download_rate = m_stat.download_rate(); - st.upload_rate = m_stat.upload_rate(); - st.download_payload_rate = m_stat.download_payload_rate(); - st.upload_payload_rate = m_stat.upload_payload_rate(); - - st.next_announce = boost::posix_time::seconds( - total_seconds(next_announce() - time_now())); - if (st.next_announce.is_negative()) - st.next_announce = boost::posix_time::seconds(0); - - st.announce_interval = boost::posix_time::seconds(m_duration); - - if (m_last_working_tracker >= 0) - { - st.current_tracker - = m_trackers[m_last_working_tracker].url; - } - - // if we don't have any metadata, stop here - - if (!valid_metadata()) - { - if (m_got_tracker_response == false) - st.state = torrent_status::connecting_to_tracker; - else - st.state = torrent_status::downloading_metadata; - -// TODO: add a progress member to the torrent that will be used in this case -// and that may be set by a plugin -// if (m_metadata_size == 0) st.progress = 0.f; -// else st.progress = std::min(1.f, m_metadata_progress / (float)m_metadata_size); - st.progress = 0.f; - - st.block_size = 0; - - return st; - } - - st.block_size = block_size(); - - // fill in status that depends on metadata - - st.total_wanted = m_torrent_file.total_size(); - - if (m_picker.get() && (m_picker->num_filtered() > 0 - || m_picker->num_have_filtered() > 0)) - { - int filtered_pieces = m_picker->num_filtered() - + m_picker->num_have_filtered(); - int last_piece_index = m_torrent_file.num_pieces() - 1; - if (m_picker->piece_priority(last_piece_index) == 0) - { - st.total_wanted -= m_torrent_file.piece_size(last_piece_index); - --filtered_pieces; - } - - st.total_wanted -= filtered_pieces * m_torrent_file.piece_length(); - } - - assert(st.total_wanted >= st.total_wanted_done); - - if (st.total_wanted == 0) st.progress = 1.f; - else st.progress = st.total_wanted_done - / static_cast(st.total_wanted); - - st.pieces = &m_have_pieces; - st.num_pieces = m_num_pieces; - - if (m_got_tracker_response == false) - { - st.state = torrent_status::connecting_to_tracker; - } - else if (is_seed()) - { - assert(st.total_done == m_torrent_file.total_size()); - st.state = torrent_status::seeding; - } - else if (st.total_wanted_done == st.total_wanted) - { - assert(st.total_done != m_torrent_file.total_size()); - st.state = torrent_status::finished; - } - else - { - st.state = torrent_status::downloading; - } - - st.num_seeds = num_seeds(); - if (m_picker.get()) - st.distributed_copies = m_picker->distributed_copies(); - else - st.distributed_copies = -1; - return st; - } - - int torrent::num_seeds() const - { - INVARIANT_CHECK; - - return (int)std::count_if(m_connections.begin(), m_connections.end(), - boost::bind(&peer_connection::is_seed, - boost::bind(&std::map::value_type::second, _1))); - } - - void torrent::tracker_request_timed_out( - tracker_request const&) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - debug_log("*** tracker timed out"); -#endif - - if (m_ses.m_alerts.should_post(alert::warning)) - { - std::stringstream s; - s << "tracker: \"" - << m_trackers[m_currently_trying_tracker].url - << "\" timed out"; - m_ses.m_alerts.post_alert(tracker_alert(get_handle() - , m_failed_trackers + 1, 0, s.str())); - } - try_next_tracker(); - } - - // TODO: with some response codes, we should just consider - // the tracker as a failure and not retry - // it anymore - void torrent::tracker_request_error(tracker_request const& - , int response_code, const std::string& str) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - - INVARIANT_CHECK; - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - debug_log(std::string("*** tracker error: ") + str); -#endif - if (m_ses.m_alerts.should_post(alert::warning)) - { - std::stringstream s; - s << "tracker: \"" - << m_trackers[m_currently_trying_tracker].url - << "\" " << str; - m_ses.m_alerts.post_alert(tracker_alert(get_handle() - , m_failed_trackers + 1, response_code, s.str())); - } - - try_next_tracker(); - } - - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - void torrent::debug_log(const std::string& line) - { - (*m_ses.m_logger) << line << "\n"; - } -#endif - -} - diff --git a/libtorrent/src/torrent_handle.cpp b/libtorrent/src/torrent_handle.cpp deleted file mode 100644 index da571ab63..000000000 --- a/libtorrent/src/torrent_handle.cpp +++ /dev/null @@ -1,774 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_id.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/aux_/session_impl.hpp" -#include "libtorrent/invariant_check.hpp" - -#if defined(_MSC_VER) && _MSC_VER < 1300 -namespace std -{ - using ::srand; - using ::isalnum; -}; -#endif - -using boost::bind; -using boost::mutex; -using libtorrent::aux::session_impl; - -namespace libtorrent -{ - namespace - { - void throw_invalid_handle() - { - throw invalid_handle(); - } - - template - Ret call_member( - session_impl* ses - , aux::checker_impl* chk - , sha1_hash const& hash - , F f) - { - if (ses == 0) throw_invalid_handle(); - - if (chk) - { - mutex::scoped_lock l(chk->m_mutex); - aux::piece_checker_data* d = chk->find_torrent(hash); - if (d != 0) return f(*d->torrent_ptr); - } - - { - session_impl::mutex_t::scoped_lock l(ses->m_mutex); - boost::shared_ptr t = ses->find_torrent(hash).lock(); - if (t) return f(*t); - } - - // throwing directly instead of calling - // the throw_invalid_handle() function - // avoids a warning in gcc - throw invalid_handle(); - } - } - -#ifndef NDEBUG - - void torrent_handle::check_invariant() const - { - assert((m_ses == 0 && m_chk == 0) || (m_ses != 0)); - } - -#endif - - void torrent_handle::set_max_uploads(int max_uploads) const - { - INVARIANT_CHECK; - - assert(max_uploads >= 2 || max_uploads == -1); - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_max_uploads, _1, max_uploads)); - } - - void torrent_handle::use_interface(const char* net_interface) const - { - INVARIANT_CHECK; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::use_interface, _1, net_interface)); - } - - void torrent_handle::set_max_connections(int max_connections) const - { - INVARIANT_CHECK; - - assert(max_connections >= 2 || max_connections == -1); - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_max_connections, _1, max_connections)); - } - - void torrent_handle::set_peer_upload_limit(tcp::endpoint ip, int limit) const - { - INVARIANT_CHECK; - assert(limit >= -1); - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_peer_upload_limit, _1, ip, limit)); - } - - void torrent_handle::set_peer_download_limit(tcp::endpoint ip, int limit) const - { - INVARIANT_CHECK; - assert(limit >= -1); - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_peer_download_limit, _1, ip, limit)); - } - - void torrent_handle::set_upload_limit(int limit) const - { - INVARIANT_CHECK; - - assert(limit >= -1); - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_upload_limit, _1, limit)); - } - - int torrent_handle::upload_limit() const - { - INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::upload_limit, _1)); - } - - void torrent_handle::set_download_limit(int limit) const - { - INVARIANT_CHECK; - - assert(limit >= -1); - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_download_limit, _1, limit)); - } - - int torrent_handle::download_limit() const - { - INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::download_limit, _1)); - } - - bool torrent_handle::move_storage( - boost::filesystem::path const& save_path) const - { - INVARIANT_CHECK; - - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::move_storage, _1, save_path)); - } - - bool torrent_handle::has_metadata() const - { - INVARIANT_CHECK; - - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::valid_metadata, _1)); - } - - bool torrent_handle::is_seed() const - { - INVARIANT_CHECK; - - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::is_seed, _1)); - } - - bool torrent_handle::is_paused() const - { - INVARIANT_CHECK; - - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::is_paused, _1)); - } - - void torrent_handle::pause() const - { - INVARIANT_CHECK; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::pause, _1)); - } - - void torrent_handle::resume() const - { - INVARIANT_CHECK; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::resume, _1)); - } - - void torrent_handle::set_tracker_login(std::string const& name - , std::string const& password) const - { - INVARIANT_CHECK; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_tracker_login, _1, name, password)); - } - - void torrent_handle::file_progress(std::vector& progress) - { - INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - - if (m_chk) - { - mutex::scoped_lock l(m_chk->m_mutex); - - aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d != 0) - { - if (!d->processing) - { - torrent_info const& info = d->torrent_ptr->torrent_file(); - progress.clear(); - progress.resize(info.num_files(), 0.f); - return; - } - d->torrent_ptr->file_progress(progress); - return; - } - } - - { - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (t) return t->file_progress(progress); - } - - throw_invalid_handle(); - } - - torrent_status torrent_handle::status() const - { - INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - - if (m_chk) - { - mutex::scoped_lock l(m_chk->m_mutex); - - aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d != 0) - { - torrent_status st; - - if (d->processing) - { - if (d->torrent_ptr->is_allocating()) - st.state = torrent_status::allocating; - else - st.state = torrent_status::checking_files; - } - else - st.state = torrent_status::queued_for_checking; - st.progress = d->progress; - st.paused = d->torrent_ptr->is_paused(); - return st; - } - } - - { - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (t) return t->status(); - } - - throw_invalid_handle(); - return torrent_status(); - } - - void torrent_handle::set_sequenced_download_threshold(int threshold) const - { - INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_sequenced_download_threshold, _1, threshold)); - } - - std::string torrent_handle::name() const - { - INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::name, _1)); - } - - - void torrent_handle::piece_priority(int index, int priority) const - { - INVARIANT_CHECK; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_piece_priority, _1, index, priority)); - } - - int torrent_handle::piece_priority(int index) const - { - INVARIANT_CHECK; - - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::piece_priority, _1, index)); - } - - void torrent_handle::prioritize_pieces(std::vector const& pieces) const - { - INVARIANT_CHECK; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::prioritize_pieces, _1, boost::cref(pieces))); - } - - std::vector torrent_handle::piece_priorities() const - { - INVARIANT_CHECK; - std::vector ret; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::piece_priorities, _1, boost::ref(ret))); - return ret; - } - - void torrent_handle::prioritize_files(std::vector const& files) const - { - INVARIANT_CHECK; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::prioritize_files, _1, boost::cref(files))); - } - -// ============ start deprecation =============== - - void torrent_handle::filter_piece(int index, bool filter) const - { - INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::filter_piece, _1, index, filter)); - } - - void torrent_handle::filter_pieces(std::vector const& pieces) const - { - INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::filter_pieces, _1, boost::cref(pieces))); - } - - bool torrent_handle::is_piece_filtered(int index) const - { - INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::is_piece_filtered, _1, index)); - } - - std::vector torrent_handle::filtered_pieces() const - { - INVARIANT_CHECK; - std::vector ret; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::filtered_pieces, _1, boost::ref(ret))); - return ret; - } - - void torrent_handle::filter_files(std::vector const& files) const - { - INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::filter_files, _1, files)); - } - -// ============ end deprecation =============== - - - std::vector const& torrent_handle::trackers() const - { - INVARIANT_CHECK; - - return call_member const&>(m_ses - , m_chk, m_info_hash, bind(&torrent::trackers, _1)); - } - - void torrent_handle::add_url_seed(std::string const& url) - { - INVARIANT_CHECK; - - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::add_url_seed, _1, url)); - } - - void torrent_handle::replace_trackers( - std::vector const& urls) const - { - INVARIANT_CHECK; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::replace_trackers, _1, urls)); - } - - torrent_info const& torrent_handle::get_torrent_info() const - { - INVARIANT_CHECK; - - if (!has_metadata()) throw_invalid_handle(); - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::torrent_file, _1)); - } - - bool torrent_handle::is_valid() const - { - INVARIANT_CHECK; - - if (m_ses == 0) return false; - - if (m_chk) - { - mutex::scoped_lock l(m_chk->m_mutex); - aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d != 0) return true; - } - - { - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::weak_ptr t = m_ses->find_torrent(m_info_hash); - if (!t.expired()) return true; - } - - return false; - } - - entry torrent_handle::write_resume_data() const - { - INVARIANT_CHECK; - - std::vector piece_index; - if (m_ses == 0) return entry(); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) return entry(); - - if (!t->valid_metadata()) return entry(); - - t->filesystem().export_piece_map(piece_index); - - entry ret(entry::dictionary_t); - - ret["file-format"] = "libtorrent resume file"; - ret["file-version"] = 1; - - ret["allocation"] = t->filesystem().compact_allocation()?"compact":"full"; - - const sha1_hash& info_hash = t->torrent_file().info_hash(); - ret["info-hash"] = std::string((char*)info_hash.begin(), (char*)info_hash.end()); - - ret["slots"] = entry(entry::list_t); - entry::list_type& slots = ret["slots"].list(); - std::copy(piece_index.begin(), piece_index.end(), std::back_inserter(slots)); - - // blocks per piece - int num_blocks_per_piece = - static_cast(t->torrent_file().piece_length()) / t->block_size(); - ret["blocks per piece"] = num_blocks_per_piece; - - // if this torrent is a seed, we won't have a piece picker - // and there will be no half-finished pieces. - if (!t->is_seed()) - { - const piece_picker& p = t->picker(); - - const std::vector& q - = p.get_download_queue(); - - // unfinished pieces - ret["unfinished"] = entry::list_type(); - entry::list_type& up = ret["unfinished"].list(); - - // info for each unfinished piece - for (std::vector::const_iterator i - = q.begin(); i != q.end(); ++i) - { - if (i->finished == 0) continue; - - entry piece_struct(entry::dictionary_t); - - // the unfinished piece's index - piece_struct["piece"] = i->index; - - std::string bitmask; - const int num_bitmask_bytes - = std::max(num_blocks_per_piece / 8, 1); - - for (int j = 0; j < num_bitmask_bytes; ++j) - { - unsigned char v = 0; - for (int k = 0; k < 8; ++k) - v |= i->info[j*8+k].finished?(1 << k):0; - bitmask.insert(bitmask.end(), v); - } - piece_struct["bitmask"] = bitmask; - - assert(t->filesystem().slot_for_piece(i->index) >= 0); - unsigned long adler - = t->filesystem().piece_crc( - t->filesystem().slot_for_piece(i->index) - , t->block_size() - , i->info); - - piece_struct["adler32"] = adler; - - // push the struct onto the unfinished-piece list - up.push_back(piece_struct); - } - } - // write local peers - - ret["peers"] = entry::list_type(); - entry::list_type& peer_list = ret["peers"].list(); - - policy& pol = t->get_policy(); - - for (policy::iterator i = pol.begin_peer() - , end(pol.end_peer()); i != end; ++i) - { - // we cannot save remote connection - // since we don't know their listen port - // unless they gave us their listen port - // through the extension handshake - // so, if the peer is not connectable (i.e. we - // don't know its listen port) or if it has - // been banned, don't save it. - if (i->type == policy::peer::not_connectable - || i->banned) continue; - - tcp::endpoint ip = i->ip; - entry peer(entry::dictionary_t); - peer["ip"] = ip.address().to_string(); - peer["port"] = ip.port(); - peer_list.push_back(peer); - } - - t->filesystem().write_resume_data(ret); - - return ret; - } - - - boost::filesystem::path torrent_handle::save_path() const - { - INVARIANT_CHECK; - - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::save_path, _1)); - } - - void torrent_handle::connect_peer(tcp::endpoint const& adr, int source) const - { - INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - - if (!t) - { - // the torrent is being checked. Add the peer to its - // peer list. The entries in there will be connected - // once the checking is complete. - mutex::scoped_lock l2(m_chk->m_mutex); - - aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash); - if (d == 0) throw_invalid_handle(); - d->peers.push_back(adr); - return; - } - - peer_id id; - std::fill(id.begin(), id.end(), 0); - t->get_policy().peer_from_tracker(adr, id, source, 0); - } - - void torrent_handle::force_reannounce( - boost::posix_time::time_duration duration) const - { - INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) throw_invalid_handle(); - - t->force_tracker_request(time_now() - + seconds(duration.total_seconds())); - } - - void torrent_handle::force_reannounce() const - { - INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) throw_invalid_handle(); - - t->force_tracker_request(); - } - - void torrent_handle::set_ratio(float ratio) const - { - INVARIANT_CHECK; - - assert(ratio >= 0.f); - - if (ratio < 1.f && ratio > 0.f) - ratio = 1.f; - - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::set_ratio, _1, ratio)); - } - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - void torrent_handle::resolve_countries(bool r) - { - INVARIANT_CHECK; - call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::resolve_countries, _1, r)); - } - - bool torrent_handle::resolve_countries() const - { - INVARIANT_CHECK; - return call_member(m_ses, m_chk, m_info_hash - , bind(&torrent::resolving_countries, _1)); - } -#endif - - void torrent_handle::get_peer_info(std::vector& v) const - { - INVARIANT_CHECK; - - v.clear(); - if (m_ses == 0) throw_invalid_handle(); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - if (!t) return; - - for (torrent::const_peer_iterator i = t->begin(); - i != t->end(); ++i) - { - peer_connection* peer = i->second; - - // peers that haven't finished the handshake should - // not be included in this list - if (peer->associated_torrent().expired()) continue; - - v.push_back(peer_info()); - peer_info& p = v.back(); - - peer->get_peer_info(p); -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - if (t->resolving_countries()) - t->resolve_peer_country(intrusive_ptr(peer)); -#endif - } - } - - void torrent_handle::get_download_queue(std::vector& queue) const - { - INVARIANT_CHECK; - - if (m_ses == 0) throw_invalid_handle(); - - session_impl::mutex_t::scoped_lock l(m_ses->m_mutex); - boost::shared_ptr t = m_ses->find_torrent(m_info_hash).lock(); - - queue.clear(); - if (!t) return; - if (!t->valid_metadata()) return; - // if we're a seed, the piece picker has been removed - if (t->is_seed()) return; - - const piece_picker& p = t->picker(); - - const std::vector& q - = p.get_download_queue(); - - for (std::vector::const_iterator i - = q.begin(); i != q.end(); ++i) - { - partial_piece_info pi; - pi.piece_state = (partial_piece_info::state_t)i->state; - pi.blocks_in_piece = p.blocks_in_piece(i->index); - for (int j = 0; j < pi.blocks_in_piece; ++j) - { - pi.peer[j] = i->info[j].peer; - pi.num_downloads[j] = i->info[j].num_downloads; - pi.finished_blocks[j] = i->info[j].finished; - pi.requested_blocks[j] = i->info[j].requested; - } - pi.piece_index = i->index; - queue.push_back(pi); - } - } - -} - diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp deleted file mode 100644 index e546a1243..000000000 --- a/libtorrent/src/torrent_info.cpp +++ /dev/null @@ -1,856 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/torrent_info.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/hasher.hpp" -#include "libtorrent/entry.hpp" - -namespace pt = boost::posix_time; -namespace gr = boost::gregorian; - -using namespace libtorrent; -using namespace boost::filesystem; - -namespace -{ - void convert_to_utf8(std::string& str, unsigned char chr) - { - str += 0xc0 | ((chr & 0xff) >> 6); - str += 0x80 | (chr & 0x3f); - } - - void verify_encoding(file_entry& target) - { - std::string tmp_path; - std::string file_path = target.path.string(); - bool valid_encoding = true; - for (std::string::iterator i = file_path.begin() - , end(file_path.end()); i != end; ++i) - { - // valid ascii-character - if ((*i & 0x80) == 0) - { - tmp_path += *i; - continue; - } - - if (std::distance(i, end) < 2) - { - convert_to_utf8(tmp_path, *i); - valid_encoding = false; - continue; - } - - // valid 2-byte utf-8 character - if ((i[0] & 0xe0) == 0xc0 - && (i[1] & 0xc0) == 0x80) - { - tmp_path += i[0]; - tmp_path += i[1]; - i += 1; - continue; - } - - if (std::distance(i, end) < 3) - { - convert_to_utf8(tmp_path, *i); - valid_encoding = false; - continue; - } - - // valid 3-byte utf-8 character - if ((i[0] & 0xf0) == 0xe0 - && (i[1] & 0xc0) == 0x80 - && (i[2] & 0xc0) == 0x80) - { - tmp_path += i[0]; - tmp_path += i[1]; - tmp_path += i[2]; - i += 2; - continue; - } - - if (std::distance(i, end) < 4) - { - convert_to_utf8(tmp_path, *i); - valid_encoding = false; - continue; - } - - // valid 4-byte utf-8 character - if ((i[0] & 0xf0) == 0xe0 - && (i[1] & 0xc0) == 0x80 - && (i[2] & 0xc0) == 0x80 - && (i[3] & 0xc0) == 0x80) - { - tmp_path += i[0]; - tmp_path += i[1]; - tmp_path += i[2]; - tmp_path += i[3]; - i += 3; - continue; - } - - convert_to_utf8(tmp_path, *i); - valid_encoding = false; - } - // the encoding was not valid utf-8 - // save the original encoding and replace the - // commonly used path with the correctly - // encoded string - if (!valid_encoding) - { - target.orig_path.reset(new path(target.path)); - target.path = tmp_path; - } - } - - void extract_single_file(const entry& dict, file_entry& target - , std::string const& root_dir) - { - target.size = dict["length"].integer(); - target.path = root_dir; - - - // prefer the name.utf-8 - // because if it exists, it is more - // likely to be correctly encoded - - const entry::list_type* list = 0; - if (entry const* p = dict.find_key("path.utf-8")) - { - list = &p->list(); - } - else - { - list = &dict["path"].list(); - } - - for (entry::list_type::const_iterator i = list->begin(); - i != list->end(); ++i) - { - if (i->string() != "..") - target.path /= i->string(); - } - verify_encoding(target); - if (target.path.is_complete()) throw std::runtime_error("torrent contains " - "a file with an absolute path: '" - + target.path.native_file_string() + "'"); - } - - void extract_files(const entry::list_type& list, std::vector& target - , std::string const& root_dir) - { - size_type offset = 0; - for (entry::list_type::const_iterator i = list.begin(); i != list.end(); ++i) - { - target.push_back(file_entry()); - extract_single_file(*i, target.back(), root_dir); - target.back().offset = offset; - offset += target.back().size; - } - } - - void remove_dir(path& p) - { - assert(p.begin() != p.end()); - path tmp; - for (path::iterator i = boost::next(p.begin()); i != p.end(); ++i) - tmp /= *i; - p = tmp; - } -} - -namespace libtorrent -{ - - // standard constructor that parses a torrent file - torrent_info::torrent_info(const entry& torrent_file) - : m_num_pieces(0) - , m_creation_date(pt::ptime(pt::not_a_date_time)) - , m_multifile(false) - , m_private(false) - , m_extra_info(entry::dictionary_t) -#ifndef NDEBUG - , m_half_metadata(false) -#endif - { - try - { - read_torrent_info(torrent_file); - } - catch(type_error&) - { - throw invalid_torrent_file(); - } - } - - // constructor used for creating new torrents - // will not contain any hashes, comments, creation date - // just the necessary to use it with piece manager - // used for torrents with no metadata - torrent_info::torrent_info(sha1_hash const& info_hash) - : m_piece_length(0) - , m_total_size(0) - , m_num_pieces(0) - , m_info_hash(info_hash) - , m_name() - , m_creation_date(pt::second_clock::universal_time()) - , m_multifile(false) - , m_private(false) - , m_extra_info(entry::dictionary_t) -#ifndef NDEBUG - , m_half_metadata(false) -#endif - { - } - - torrent_info::torrent_info() - : m_piece_length(0) - , m_total_size(0) - , m_num_pieces(0) - , m_info_hash(0) - , m_name() - , m_creation_date(pt::second_clock::universal_time()) - , m_multifile(false) - , m_private(false) - , m_extra_info(entry::dictionary_t) -#ifndef NDEBUG - , m_half_metadata(false) -#endif - { - } - - torrent_info::~torrent_info() - {} - - void torrent_info::set_piece_size(int size) - { - // make sure the size is an even power of 2 -#ifndef NDEBUG - for (int i = 0; i < 32; ++i) - { - if (size & (1 << i)) - { - assert((size & ~(1 << i)) == 0); - break; - } - } -#endif - assert(!m_half_metadata); - m_piece_length = size; - - m_num_pieces = static_cast( - (m_total_size + m_piece_length - 1) / m_piece_length); - int old_num_pieces = static_cast(m_piece_hash.size()); - - m_piece_hash.resize(m_num_pieces); - for (int i = old_num_pieces; i < m_num_pieces; ++i) - { - m_piece_hash[i].clear(); - } - } - - void torrent_info::parse_info_section(entry const& info) - { - // encode the info-field in order to calculate it's sha1-hash - std::vector buf; - bencode(std::back_inserter(buf), info); - hasher h; - h.update(&buf[0], (int)buf.size()); - m_info_hash = h.final(); - - // extract piece length - m_piece_length = (int)info["piece length"].integer(); - if (m_piece_length <= 0) throw std::runtime_error("invalid torrent. piece length <= 0"); - - // extract file name (or the directory name if it's a multifile libtorrent) - if (entry const* e = info.find_key("name.utf-8")) - { m_name = e->string(); } - else - { m_name = info["name"].string(); } - - path tmp = m_name; - if (tmp.is_complete()) throw std::runtime_error("torrent contains " - "a file with an absolute path: '" + m_name + "'"); - if (tmp.has_branch_path()) throw std::runtime_error( - "torrent contains name with directories: '" + m_name + "'"); - - // extract file list - entry const* i = info.find_key("files"); - if (i == 0) - { - // if there's no list of files, there has to be a length - // field. - file_entry e; - e.path = m_name; - e.offset = 0; - e.size = info["length"].integer(); - m_files.push_back(e); - } - else - { - extract_files(i->list(), m_files, m_name); - m_multifile = true; - } - - // calculate total size of all pieces - m_total_size = 0; - for (std::vector::iterator i = m_files.begin(); i != m_files.end(); ++i) - m_total_size += i->size; - - // extract sha-1 hashes for all pieces - // we want this division to round upwards, that's why we have the - // extra addition - - m_num_pieces = static_cast((m_total_size + m_piece_length - 1) / m_piece_length); - m_piece_hash.resize(m_num_pieces); - const std::string& hash_string = info["pieces"].string(); - - if ((int)hash_string.length() != m_num_pieces * 20) - throw invalid_torrent_file(); - - for (int i = 0; i < m_num_pieces; ++i) - std::copy( - hash_string.begin() + i*20 - , hash_string.begin() + (i+1)*20 - , m_piece_hash[i].begin()); - - for (entry::dictionary_type::const_iterator i = info.dict().begin() - , end(info.dict().end()); i != end; ++i) - { - if (i->first == "pieces" - || i->first == "piece length" - || i->first == "length") - continue; - m_extra_info[i->first] = i->second; - } - - if (entry const* priv = info.find_key("private")) - { - if (priv->type() != entry::int_t - || priv->integer() != 0) - { - // this key exists and it's not 0. - // consider the torrent private - m_private = true; - } - } - -#ifndef NDEBUG - std::vector info_section_buf; - entry gen_info_section = create_info_metadata(); - bencode(std::back_inserter(info_section_buf), gen_info_section); - assert(hasher(&info_section_buf[0], info_section_buf.size()).final() - == m_info_hash); -#endif - } - - // extracts information from a libtorrent file and fills in the structures in - // the torrent object - void torrent_info::read_torrent_info(const entry& torrent_file) - { - // extract the url of the tracker - if (entry const* i = torrent_file.find_key("announce-list")) - { - const entry::list_type& l = i->list(); - for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j) - { - const entry::list_type& ll = j->list(); - for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k) - { - announce_entry e(k->string()); - e.tier = (int)std::distance(l.begin(), j); - m_urls.push_back(e); - } - } - - if (m_urls.size() == 0) - { - // the announce-list is empty - // fall back to look for announce - m_urls.push_back(announce_entry( - torrent_file["announce"].string())); - } - // shuffle each tier - std::vector::iterator start = m_urls.begin(); - std::vector::iterator stop; - int current_tier = m_urls.front().tier; - for (stop = m_urls.begin(); stop != m_urls.end(); ++stop) - { - if (stop->tier != current_tier) - { - std::random_shuffle(start, stop); - start = stop; - current_tier = stop->tier; - } - } - std::random_shuffle(start, stop); - } - else if (entry const* i = torrent_file.find_key("announce")) - { - m_urls.push_back(announce_entry(i->string())); - } - - if (entry const* i = torrent_file.find_key("nodes")) - { - entry::list_type const& list = i->list(); - for (entry::list_type::const_iterator i(list.begin()) - , end(list.end()); i != end; ++i) - { - if (i->type() != entry::list_t) continue; - entry::list_type const& l = i->list(); - entry::list_type::const_iterator iter = l.begin(); - if (l.size() < 1) continue; - std::string const& hostname = iter->string(); - ++iter; - int port = 6881; - if (l.end() != iter) port = iter->integer(); - m_nodes.push_back(std::make_pair(hostname, port)); - } - } - - // extract creation date - try - { - m_creation_date = pt::ptime(gr::date(1970, gr::Jan, 1)) - + pt::seconds(long(torrent_file["creation date"].integer())); - } - catch (type_error) {} - - // if there are any url-seeds, extract them - try - { - entry const& url_seeds = torrent_file["url-list"]; - if (url_seeds.type() == entry::string_t) - { - m_url_seeds.push_back(url_seeds.string()); - } - else if (url_seeds.type() == entry::list_t) - { - entry::list_type const& l = url_seeds.list(); - for (entry::list_type::const_iterator i = l.begin(); - i != l.end(); ++i) - { - m_url_seeds.push_back(i->string()); - } - } - } - catch (type_error&) {} - - // extract comment - if (entry const* e = torrent_file.find_key("comment.utf-8")) - { m_comment = e->string(); } - else if (entry const* e = torrent_file.find_key("comment")) - { m_comment = e->string(); } - - if (entry const* e = torrent_file.find_key("created by.utf-8")) - { m_created_by = e->string(); } - else if (entry const* e = torrent_file.find_key("created by")) - { m_created_by = e->string(); } - - parse_info_section(torrent_file["info"]); - } - - boost::optional - torrent_info::creation_date() const - { - if (m_creation_date != pt::ptime(gr::date(pt::not_a_date_time))) - { - return boost::optional(m_creation_date); - } - return boost::optional(); - } - - void torrent_info::add_tracker(std::string const& url, int tier) - { - announce_entry e(url); - e.tier = tier; - m_urls.push_back(e); - - using boost::bind; - std::sort(m_urls.begin(), m_urls.end(), boost::bind(std::less() - , bind(&announce_entry::tier, _1), bind(&announce_entry::tier, _2))); - } - - void torrent_info::add_file(boost::filesystem::path file, size_type size) - { - assert(file.begin() != file.end()); - - if (!file.has_branch_path()) - { - // you have already added at least one file with a - // path to the file (branch_path), which means that - // all the other files need to be in the same top - // directory as the first file. - assert(m_files.empty()); - assert(!m_multifile); - m_name = file.string(); - } - else - { -#ifndef NDEBUG - if (!m_files.empty()) - assert(m_name == *file.begin()); -#endif - m_multifile = true; - m_name = *file.begin(); - } - - file_entry e; - e.path = file; - e.size = size; - e.offset = m_files.empty() ? 0 : m_files.back().offset - + m_files.back().size; - m_files.push_back(e); - - m_total_size += size; - - if (m_piece_length == 0) - m_piece_length = 256 * 1024; - - m_num_pieces = static_cast( - (m_total_size + m_piece_length - 1) / m_piece_length); - int old_num_pieces = static_cast(m_piece_hash.size()); - - m_piece_hash.resize(m_num_pieces); - if (m_num_pieces > old_num_pieces) - std::for_each(m_piece_hash.begin() + old_num_pieces - , m_piece_hash.end(), boost::bind(&sha1_hash::clear, _1)); - } - - void torrent_info::add_url_seed(std::string const& url) - { - m_url_seeds.push_back(url); - } - - void torrent_info::set_comment(char const* str) - { - m_comment = str; - } - - void torrent_info::set_creator(char const* str) - { - m_created_by = str; - } - - entry torrent_info::create_info_metadata() const - { - namespace fs = boost::filesystem; - - // you have to add files to the torrent first - assert(!m_files.empty()); - - entry info(m_extra_info); - - if (!info.find_key("name")) - info["name"] = m_name; - - if (!m_multifile) - { - info["length"] = m_files.front().size; - } - else - { - if (!info.find_key("files")) - { - entry& files = info["files"]; - - for (std::vector::const_iterator i = m_files.begin(); - i != m_files.end(); ++i) - { - files.list().push_back(entry()); - entry& file_e = files.list().back(); - file_e["length"] = i->size; - entry& path_e = file_e["path"]; - - fs::path const* file_path; - if (i->orig_path) file_path = &(*i->orig_path); - else file_path = &i->path; - assert(file_path->has_branch_path()); - assert(*file_path->begin() == m_name); - - for (fs::path::iterator j = boost::next(file_path->begin()); - j != file_path->end(); ++j) - { - path_e.list().push_back(entry(*j)); - } - } - } - } - - info["piece length"] = piece_length(); - entry& pieces = info["pieces"]; - - std::string& p = pieces.string(); - - for (std::vector::const_iterator i = m_piece_hash.begin(); - i != m_piece_hash.end(); ++i) - { - p.append((char*)i->begin(), (char*)i->end()); - } - - return info; - } - - entry torrent_info::create_torrent() const - { - assert(m_piece_length > 0); - - namespace fs = boost::filesystem; - - if ((m_urls.empty() && m_nodes.empty()) || m_files.empty()) - { - // TODO: throw something here - // throw - return entry(); - } - - entry dict; - - if (m_private) dict["private"] = 1; - - if (!m_urls.empty()) - dict["announce"] = m_urls.front().url; - - if (!m_nodes.empty()) - { - entry& nodes = dict["nodes"]; - entry::list_type& nodes_list = nodes.list(); - for (nodes_t::const_iterator i = m_nodes.begin() - , end(m_nodes.end()); i != end; ++i) - { - entry::list_type node; - node.push_back(entry(i->first)); - node.push_back(entry(i->second)); - nodes_list.push_back(entry(node)); - } - } - - if (m_urls.size() > 1) - { - entry trackers(entry::list_t); - entry tier(entry::list_t); - int current_tier = m_urls.front().tier; - for (std::vector::const_iterator i = m_urls.begin(); - i != m_urls.end(); ++i) - { - if (i->tier != current_tier) - { - current_tier = i->tier; - trackers.list().push_back(tier); - tier.list().clear(); - } - tier.list().push_back(entry(i->url)); - } - trackers.list().push_back(tier); - dict["announce-list"] = trackers; - } - - if (!m_comment.empty()) - dict["comment"] = m_comment; - - dict["creation date"] = - (m_creation_date - pt::ptime(gr::date(1970, gr::Jan, 1))).total_seconds(); - - if (!m_created_by.empty()) - dict["created by"] = m_created_by; - - if (!m_url_seeds.empty()) - { - if (m_url_seeds.size() == 1) - { - dict["url-list"] = m_url_seeds.front(); - } - else - { - entry& list = dict["url-list"]; - for (std::vector::const_iterator i - = m_url_seeds.begin(); i != m_url_seeds.end(); ++i) - { - list.list().push_back(entry(*i)); - } - } - } - - dict["info"] = create_info_metadata(); - - entry const& info_section = dict["info"]; - std::vector buf; - bencode(std::back_inserter(buf), info_section); - m_info_hash = hasher(&buf[0], buf.size()).final(); - - return dict; - } - - void torrent_info::set_hash(int index, const sha1_hash& h) - { - assert(index >= 0); - assert(index < (int)m_piece_hash.size()); - m_piece_hash[index] = h; - } - - void torrent_info::convert_file_names() - { - assert(false); - } - - void torrent_info::seed_free() - { - std::vector().swap(m_url_seeds); - nodes_t().swap(m_nodes); - std::vector().swap(m_piece_hash); -#ifndef NDEBUG - m_half_metadata = true; -#endif - } - -// ------- start deprecation ------- - - void torrent_info::print(std::ostream& os) const - { - os << "trackers:\n"; - for (std::vector::const_iterator i = trackers().begin(); - i != trackers().end(); ++i) - { - os << i->tier << ": " << i->url << "\n"; - } - if (!m_comment.empty()) - os << "comment: " << m_comment << "\n"; -// if (m_creation_date != pt::ptime(gr::date(pt::not_a_date_time))) -// os << "creation date: " << to_simple_string(m_creation_date) << "\n"; - os << "private: " << (m_private?"yes":"no") << "\n"; - os << "number of pieces: " << num_pieces() << "\n"; - os << "piece length: " << piece_length() << "\n"; - os << "files:\n"; - for (file_iterator i = begin_files(); i != end_files(); ++i) - os << " " << std::setw(11) << i->size << " " << i->path.string() << "\n"; - } - -// ------- end deprecation ------- - - size_type torrent_info::piece_size(int index) const - { - assert(index >= 0 && index < num_pieces()); - if (index == num_pieces()-1) - { - size_type size = total_size() - - (num_pieces() - 1) * piece_length(); - assert(size > 0); - assert(size <= piece_length()); - return size; - } - else - return piece_length(); - } - - void torrent_info::add_node(std::pair const& node) - { - m_nodes.push_back(node); - } - - std::vector torrent_info::map_block(int piece, size_type offset - , int size) const - { - assert(num_files() > 0); - std::vector ret; - - size_type start = piece * (size_type)m_piece_length + offset; - assert(start + size <= m_total_size); - - // find the file iterator and file offset - // TODO: make a vector that can map piece -> file index in O(1) - size_type file_offset = start; - std::vector::const_iterator file_iter; - - int counter = 0; - for (file_iter = begin_files();; ++counter, ++file_iter) - { - assert(file_iter != end_files()); - if (file_offset < file_iter->size) - { - file_slice f; - f.file_index = counter; - f.offset = file_offset; - f.size = (std::min)(file_iter->size - file_offset, (size_type)size); - size -= f.size; - file_offset += f.size; - ret.push_back(f); - } - - assert(size >= 0); - if (size <= 0) break; - - file_offset -= file_iter->size; - } - return ret; - } - - peer_request torrent_info::map_file(int file_index, size_type file_offset - , int size) const - { - assert(file_index < (int)m_files.size()); - assert(file_index >= 0); - size_type offset = file_offset + m_files[file_index].offset; - - peer_request ret; - ret.piece = offset / piece_length(); - ret.start = offset - ret.piece * piece_length(); - ret.length = size; - return ret; - } - -} diff --git a/libtorrent/src/tracker_manager.cpp b/libtorrent/src/tracker_manager.cpp deleted file mode 100644 index 7ee8c57ba..000000000 --- a/libtorrent/src/tracker_manager.cpp +++ /dev/null @@ -1,599 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "zlib.h" - -#include - -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/udp_tracker_connection.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/peer_connection.hpp" - -using namespace libtorrent; -using boost::tuples::make_tuple; -using boost::tuples::tuple; -using boost::bind; - -namespace -{ - enum - { - minimum_tracker_response_length = 3, - http_buffer_size = 2048 - }; - - - enum - { - FTEXT = 0x01, - FHCRC = 0x02, - FEXTRA = 0x04, - FNAME = 0x08, - FCOMMENT = 0x10, - FRESERVED = 0xe0, - - GZIP_MAGIC0 = 0x1f, - GZIP_MAGIC1 = 0x8b - }; - -} - -namespace libtorrent -{ - // returns -1 if gzip header is invalid or the header size in bytes - int gzip_header(const char* buf, int size) - { - assert(buf != 0); - assert(size > 0); - - const unsigned char* buffer = reinterpret_cast(buf); - const int total_size = size; - - // The zip header cannot be shorter than 10 bytes - if (size < 10) return -1; - - // check the magic header of gzip - if ((buffer[0] != GZIP_MAGIC0) || (buffer[1] != GZIP_MAGIC1)) return -1; - - int method = buffer[2]; - int flags = buffer[3]; - - // check for reserved flag and make sure it's compressed with the correct metod - if (method != Z_DEFLATED || (flags & FRESERVED) != 0) return -1; - - // skip time, xflags, OS code - size -= 10; - buffer += 10; - - if (flags & FEXTRA) - { - int extra_len; - - if (size < 2) return -1; - - extra_len = (buffer[1] << 8) | buffer[0]; - - if (size < (extra_len+2)) return -1; - size -= (extra_len + 2); - buffer += (extra_len + 2); - } - - if (flags & FNAME) - { - while (size && *buffer) - { - --size; - ++buffer; - } - if (!size || *buffer) return -1; - - --size; - ++buffer; - } - - if (flags & FCOMMENT) - { - while (size && *buffer) - { - --size; - ++buffer; - } - if (!size || *buffer) return -1; - - --size; - ++buffer; - } - - if (flags & FHCRC) - { - if (size < 2) return -1; - - size -= 2; - buffer += 2; - } - - return total_size - size; - } - - bool inflate_gzip( - std::vector& buffer - , tracker_request const& req - , request_callback* requester - , int maximum_tracker_response_length) - { - assert(maximum_tracker_response_length > 0); - - int header_len = gzip_header(&buffer[0], (int)buffer.size()); - if (header_len < 0) - { - requester->tracker_request_error(req, 200, "invalid gzip header in tracker response"); - return true; - } - - // start off wth one kilobyte and grow - // if needed - std::vector inflate_buffer(1024); - - // initialize the zlib-stream - z_stream str; - - // subtract 8 from the end of the buffer since that's CRC32 and input size - // and those belong to the gzip file - str.avail_in = (int)buffer.size() - header_len - 8; - str.next_in = reinterpret_cast(&buffer[header_len]); - str.next_out = reinterpret_cast(&inflate_buffer[0]); - str.avail_out = (int)inflate_buffer.size(); - str.zalloc = Z_NULL; - str.zfree = Z_NULL; - str.opaque = 0; - // -15 is really important. It will make inflate() not look for a zlib header - // and just deflate the buffer - if (inflateInit2(&str, -15) != Z_OK) - { - requester->tracker_request_error(req, 200, "gzip out of memory"); - return true; - } - - // inflate and grow inflate_buffer as needed - int ret = inflate(&str, Z_SYNC_FLUSH); - while (ret == Z_OK) - { - if (str.avail_out == 0) - { - if (inflate_buffer.size() >= (unsigned)maximum_tracker_response_length) - { - inflateEnd(&str); - requester->tracker_request_error(req, 200 - , "tracker response too large"); - return true; - } - int new_size = (int)inflate_buffer.size() * 2; - if (new_size > maximum_tracker_response_length) new_size = maximum_tracker_response_length; - int old_size = (int)inflate_buffer.size(); - - inflate_buffer.resize(new_size); - str.next_out = reinterpret_cast(&inflate_buffer[old_size]); - str.avail_out = new_size - old_size; - } - - ret = inflate(&str, Z_SYNC_FLUSH); - } - - inflate_buffer.resize(inflate_buffer.size() - str.avail_out); - inflateEnd(&str); - - if (ret != Z_STREAM_END) - { - requester->tracker_request_error(req, 200, "gzip error"); - return true; - } - - // commit the resulting buffer - std::swap(buffer, inflate_buffer); - return false; - } - - std::string base64encode(const std::string& s) - { - static const char base64_table[] = - { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', - '4', '5', '6', '7', '8', '9', '+', '/' - }; - - unsigned char inbuf[3]; - unsigned char outbuf[4]; - - std::string ret; - for (std::string::const_iterator i = s.begin(); i != s.end();) - { - // available input is 1,2 or 3 bytes - // since we read 3 bytes at a time at most - int available_input = std::min(3, (int)std::distance(i, s.end())); - - // clear input buffer - std::fill(inbuf, inbuf+3, 0); - - // read a chunk of input into inbuf - for (int j = 0; j < available_input; ++j) - { - inbuf[j] = *i; - ++i; - } - - // encode inbuf to outbuf - outbuf[0] = (inbuf[0] & 0xfc) >> 2; - outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf [1] & 0xf0) >> 4); - outbuf[2] = ((inbuf[1] & 0x0f) << 2) | ((inbuf [2] & 0xc0) >> 6); - outbuf[3] = inbuf[2] & 0x3f; - - // write output - for (int j = 0; j < available_input+1; ++j) - { - ret += base64_table[outbuf[j]]; - } - - // write pad - for (int j = 0; j < 3 - available_input; ++j) - { - ret += '='; - } - } - return ret; - } - - void intrusive_ptr_add_ref(timeout_handler const* c) - { - assert(c != 0); - assert(c->m_refs >= 0); - timeout_handler::mutex_t::scoped_lock l(c->m_mutex); - ++c->m_refs; - } - - void intrusive_ptr_release(timeout_handler const* c) - { - assert(c != 0); - assert(c->m_refs > 0); - timeout_handler::mutex_t::scoped_lock l(c->m_mutex); - --c->m_refs; - if (c->m_refs == 0) - { - l.unlock(); - delete c; - } - } - - - timeout_handler::timeout_handler(asio::strand& str) - : m_strand(str) - , m_start_time(time_now()) - , m_read_time(time_now()) - , m_timeout(str.io_service()) - , m_completion_timeout(0) - , m_read_timeout(0) - , m_refs(0) - {} - - void timeout_handler::set_timeout(int completion_timeout, int read_timeout) - { - m_completion_timeout = completion_timeout; - m_read_timeout = read_timeout; - m_start_time = time_now(); - m_read_time = time_now(); - - m_timeout.expires_at(std::min( - m_read_time + seconds(m_read_timeout) - , m_start_time + seconds(m_completion_timeout))); - m_timeout.async_wait(m_strand.wrap(bind( - &timeout_handler::timeout_callback, self(), _1))); - } - - void timeout_handler::restart_read_timeout() - { - m_read_time = time_now(); - } - - void timeout_handler::cancel() - { - m_completion_timeout = 0; - m_timeout.cancel(); - } - - void timeout_handler::timeout_callback(asio::error_code const& error) try - { - if (error) return; - if (m_completion_timeout == 0) return; - - ptime now(time_now()); - time_duration receive_timeout = now - m_read_time; - time_duration completion_timeout = now - m_start_time; - - if (m_read_timeout - < total_seconds(receive_timeout) - || m_completion_timeout - < total_seconds(completion_timeout)) - { - on_timeout(); - return; - } - - m_timeout.expires_at(std::min( - m_read_time + seconds(m_read_timeout) - , m_start_time + seconds(m_completion_timeout))); - m_timeout.async_wait(m_strand.wrap( - bind(&timeout_handler::timeout_callback, self(), _1))); - } - catch (std::exception& e) - { - assert(false); - } - - tracker_connection::tracker_connection( - tracker_manager& man - , tracker_request req - , asio::strand& str - , address bind_interface_ - , boost::weak_ptr r) - : timeout_handler(str) - , m_requester(r) - , m_bind_interface(bind_interface_) - , m_man(man) - , m_req(req) - {} - - request_callback& tracker_connection::requester() - { - boost::shared_ptr r = m_requester.lock(); - assert(r); - return *r; - } - - void tracker_connection::fail(int code, char const* msg) - { - if (has_requester()) requester().tracker_request_error( - m_req, code, msg); - close(); - } - - void tracker_connection::fail_timeout() - { - if (has_requester()) requester().tracker_request_timed_out(m_req); - close(); - } - - void tracker_connection::close() - { - cancel(); - m_man.remove_request(this); - } - - void tracker_manager::remove_request(tracker_connection const* c) - { - mutex_t::scoped_lock l(m_mutex); - - tracker_connections_t::iterator i = std::find(m_connections.begin() - , m_connections.end(), boost::intrusive_ptr(c)); - if (i == m_connections.end()) return; - - m_connections.erase(i); - } - - // returns protocol, auth, hostname, port, path - tuple - parse_url_components(std::string url) - { - std::string hostname; // hostname only - std::string auth; // user:pass - std::string protocol; // should be http - int port = 80; - - // PARSE URL - std::string::iterator start = url.begin(); - // remove white spaces in front of the url - while (start != url.end() && (*start == ' ' || *start == '\t')) - ++start; - std::string::iterator end - = std::find(url.begin(), url.end(), ':'); - protocol.assign(start, end); - - if (end == url.end()) throw std::runtime_error("invalid url"); - ++end; - if (end == url.end()) throw std::runtime_error("invalid url"); - if (*end != '/') throw std::runtime_error("invalid url"); - ++end; - if (end == url.end()) throw std::runtime_error("invalid url"); - if (*end != '/') throw std::runtime_error("invalid url"); - ++end; - start = end; - - std::string::iterator at = std::find(start, url.end(), '@'); - std::string::iterator colon = std::find(start, url.end(), ':'); - end = std::find(start, url.end(), '/'); - - if (at != url.end() - && colon != url.end() - && colon < at - && at < end) - { - auth.assign(start, at); - start = at; - ++start; - } - - std::string::iterator port_pos - = std::find(start, url.end(), ':'); - - if (port_pos < end) - { - hostname.assign(start, port_pos); - ++port_pos; - try - { - port = boost::lexical_cast(std::string(port_pos, end)); - } - catch(boost::bad_lexical_cast&) - { - throw std::runtime_error("invalid url: \"" + url - + "\", port number expected"); - } - } - else - { - hostname.assign(start, end); - } - - start = end; - return make_tuple(protocol, auth, hostname, port - , std::string(start, url.end())); - } - - void tracker_manager::queue_request( - asio::strand& str - , connection_queue& cc - , tracker_request req - , std::string const& auth - , address bind_infc - , boost::weak_ptr c) - { - mutex_t::scoped_lock l(m_mutex); - assert(req.num_want >= 0); - if (req.event == tracker_request::stopped) - req.num_want = 0; - - assert(!m_abort || req.event == tracker_request::stopped); - if (m_abort && req.event != tracker_request::stopped) - return; - - try - { - std::string protocol; - std::string hostname; - int port; - std::string request_string; - - using boost::tuples::ignore; - // TODO: should auth be used here? - boost::tie(protocol, ignore, hostname, port, request_string) - = parse_url_components(req.url); - - boost::intrusive_ptr con; - - if (protocol == "http") - { - con = new http_tracker_connection( - str - , cc - , *this - , req - , hostname - , port - , request_string - , bind_infc - , c - , m_settings - , m_proxy - , auth); - } - else if (protocol == "udp") - { - con = new udp_tracker_connection( - str - , *this - , req - , hostname - , port - , bind_infc - , c - , m_settings); - } - else - { - throw std::runtime_error("unkown protocol in tracker url"); - } - - m_connections.push_back(con); - - if (con->has_requester()) con->requester().m_manager = this; - } - catch (std::exception& e) - { - if (boost::shared_ptr r = c.lock()) - r->tracker_request_error(req, -1, e.what()); - } - } - - void tracker_manager::abort_all_requests() - { - // removes all connections from m_connections - // except those with a requester == 0 (since those are - // 'event=stopped'-requests) - mutex_t::scoped_lock l(m_mutex); - - m_abort = true; - tracker_connections_t keep_connections; - - for (tracker_connections_t::const_iterator i = - m_connections.begin(); i != m_connections.end(); ++i) - { - tracker_request const& req = (*i)->tracker_req(); - if (req.event == tracker_request::stopped) - keep_connections.push_back(*i); - } - - std::swap(m_connections, keep_connections); - } - - bool tracker_manager::empty() const - { - mutex_t::scoped_lock l(m_mutex); - return m_connections.empty(); - } - -} diff --git a/libtorrent/src/udp_tracker_connection.cpp b/libtorrent/src/udp_tracker_connection.cpp deleted file mode 100644 index d992ca050..000000000 --- a/libtorrent/src/udp_tracker_connection.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include - -#include "zlib.h" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/tracker_manager.hpp" -#include "libtorrent/udp_tracker_connection.hpp" -#include "libtorrent/io.hpp" - -namespace -{ - enum - { - udp_connection_retries = 4, - udp_announce_retries = 15, - udp_connect_timeout = 15, - udp_announce_timeout = 10, - udp_buffer_size = 2048 - }; -} - -using boost::bind; -using boost::lexical_cast; - -namespace libtorrent -{ - - udp_tracker_connection::udp_tracker_connection( - asio::strand& str - , tracker_manager& man - , tracker_request const& req - , std::string const& hostname - , unsigned short port - , address bind_infc - , boost::weak_ptr c - , session_settings const& stn) - : tracker_connection(man, req, str, bind_infc, c) - , m_man(man) - , m_strand(str) - , m_name_lookup(m_strand.io_service()) - , m_transaction_id(0) - , m_connection_id(0) - , m_settings(stn) - , m_attempts(0) - { - udp::resolver::query q(hostname, boost::lexical_cast(port)); - m_name_lookup.async_resolve(q - , m_strand.wrap(boost::bind( - &udp_tracker_connection::name_lookup, self(), _1, _2))); - set_timeout(m_settings.tracker_completion_timeout - , m_settings.tracker_receive_timeout); - } - - void udp_tracker_connection::name_lookup(asio::error_code const& error - , udp::resolver::iterator i) try - { - if (error == asio::error::operation_aborted) return; - if (!m_socket) return; // the operation was aborted - if (error || i == udp::resolver::iterator()) - { - fail(-1, error.message().c_str()); - return; - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) requester().debug_log("udp tracker name lookup successful"); -#endif - restart_read_timeout(); - - // look for an address that has the same kind as the one - // we're listening on. To make sure the tracker get our - // correct listening address. - udp::resolver::iterator target = i; - udp::resolver::iterator end; - udp::endpoint target_address = *i; - for (; target != end && target->endpoint().address().is_v4() - != bind_interface().is_v4(); ++target); - if (target == end) - { - assert(target_address.address().is_v4() != bind_interface().is_v4()); - if (has_requester()) - { - std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6"; - std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6"; - requester().tracker_warning("the tracker only resolves to an " - + tracker_address_type + " address, and you're listening on an " - + bind_address_type + " socket. This may prevent you from receiving incoming connections."); - } - } - else - { - target_address = *target; - } - - if (has_requester()) requester().m_tracker_address = tcp::endpoint(target_address.address(), target_address.port()); - m_target = target_address; - m_socket.reset(new datagram_socket(m_name_lookup.io_service())); - m_socket->open(target_address.protocol()); - m_socket->bind(udp::endpoint(bind_interface(), 0)); - m_socket->connect(target_address); - send_udp_connect(); - } - catch (std::exception& e) - { - fail(-1, e.what()); - }; - - void udp_tracker_connection::on_timeout() - { - m_socket.reset(); - m_name_lookup.cancel(); - fail_timeout(); - } - - void udp_tracker_connection::send_udp_connect() - { -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) - { - requester().debug_log("==> UDP_TRACKER_CONNECT [" - + lexical_cast(tracker_req().info_hash) + "]"); - } -#endif - if (!m_socket) return; // the operation was aborted - - char send_buf[16]; - char* ptr = send_buf; - - if (m_transaction_id == 0) - m_transaction_id = rand() ^ (rand() << 16); - - // connection_id - detail::write_uint32(0x417, ptr); - detail::write_uint32(0x27101980, ptr); - // action (connect) - detail::write_int32(action_connect, ptr); - // transaction_id - detail::write_int32(m_transaction_id, ptr); - - m_socket->send(asio::buffer((void*)send_buf, 16), 0); - ++m_attempts; - m_buffer.resize(udp_buffer_size); - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender - , boost::bind(&udp_tracker_connection::connect_response, self(), _1, _2)); - } - - void udp_tracker_connection::connect_response(asio::error_code const& error - , std::size_t bytes_transferred) try - { - if (error == asio::error::operation_aborted) return; - if (!m_socket) return; // the operation was aborted - if (error) - { - fail(-1, error.message().c_str()); - return; - } - - if (m_target != m_sender) - { - // this packet was not received from the tracker - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender - , boost::bind(&udp_tracker_connection::connect_response, self(), _1, _2)); - return; - } - - if (bytes_transferred >= udp_buffer_size) - { - fail(-1, "udp response too big"); - return; - } - - if (bytes_transferred < 8) - { - fail(-1, "got a message with size < 8"); - return; - } - - restart_read_timeout(); - - const char* ptr = &m_buffer[0]; - int action = detail::read_int32(ptr); - int transaction = detail::read_int32(ptr); - - if (action == action_error) - { - fail(-1, std::string(ptr, bytes_transferred - 8).c_str()); - return; - } - - if (action != action_connect) - { - fail(-1, "invalid action in connect reply"); - return; - } - - if (m_transaction_id != transaction) - { - fail(-1, "incorrect transaction id"); - return; - } - - if (bytes_transferred < 16) - { - fail(-1, "udp_tracker_connection: " - "got a message with size < 16"); - return; - } - // reset transaction - m_transaction_id = 0; - m_attempts = 0; - m_connection_id = detail::read_int64(ptr); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) - { - requester().debug_log("<== UDP_TRACKER_CONNECT_RESPONSE [" - + lexical_cast(m_connection_id) + "]"); - } -#endif - - if (tracker_req().kind == tracker_request::announce_request) - send_udp_announce(); - else if (tracker_req().kind == tracker_request::scrape_request) - send_udp_scrape(); - } - catch (std::exception& e) - { - fail(-1, e.what()); - } - - void udp_tracker_connection::send_udp_announce() - { - if (m_transaction_id == 0) - m_transaction_id = rand() ^ (rand() << 16); - - if (!m_socket) return; // the operation was aborted - - std::vector buf; - std::back_insert_iterator > out(buf); - - tracker_request const& req = tracker_req(); - - // connection_id - detail::write_int64(m_connection_id, out); - // action (announce) - detail::write_int32(action_announce, out); - // transaction_id - detail::write_int32(m_transaction_id, out); - // info_hash - std::copy(req.info_hash.begin(), req.info_hash.end(), out); - // peer_id - std::copy(req.pid.begin(), req.pid.end(), out); - // downloaded - detail::write_int64(req.downloaded, out); - // left - detail::write_int64(req.left, out); - // uploaded - detail::write_int64(req.uploaded, out); - // event - detail::write_int32(req.event, out); - // ip address - detail::write_int32(0, out); - // key - detail::write_int32(req.key, out); - // num_want - detail::write_int32(req.num_want, out); - // port - detail::write_uint16(req.listen_port, out); - // extensions - detail::write_uint16(0, out); - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) - { - requester().debug_log("==> UDP_TRACKER_ANNOUNCE [" - + lexical_cast(req.info_hash) + "]"); - } -#endif - - m_socket->send(asio::buffer(buf), 0); - ++m_attempts; - - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender - , bind(&udp_tracker_connection::announce_response, self(), _1, _2)); - } - - void udp_tracker_connection::send_udp_scrape() - { - if (m_transaction_id == 0) - m_transaction_id = rand() ^ (rand() << 16); - - if (!m_socket) return; // the operation was aborted - - std::vector buf; - std::back_insert_iterator > out(buf); - - // connection_id - detail::write_int64(m_connection_id, out); - // action (scrape) - detail::write_int32(action_scrape, out); - // transaction_id - detail::write_int32(m_transaction_id, out); - // info_hash - std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end(), out); - - m_socket->send(asio::buffer(&buf[0], buf.size()), 0); - ++m_attempts; - - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender - , bind(&udp_tracker_connection::scrape_response, self(), _1, _2)); - } - - void udp_tracker_connection::announce_response(asio::error_code const& error - , std::size_t bytes_transferred) try - { - if (error == asio::error::operation_aborted) return; - if (!m_socket) return; // the operation was aborted - if (error) - { - fail(-1, error.message().c_str()); - return; - } - - if (m_target != m_sender) - { - // this packet was not received from the tracker - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender - , bind(&udp_tracker_connection::connect_response, self(), _1, _2)); - return; - } - - if (bytes_transferred >= udp_buffer_size) - { - fail(-1, "udp response too big"); - return; - } - - if (bytes_transferred < 8) - { - fail(-1, "got a message with size < 8"); - return; - } - - restart_read_timeout(); - char* buf = &m_buffer[0]; - int action = detail::read_int32(buf); - int transaction = detail::read_int32(buf); - - if (transaction != m_transaction_id) - { - fail(-1, "incorrect transaction id"); - return; - } - - if (action == action_error) - { - fail(-1, std::string(buf, bytes_transferred - 8).c_str()); - return; - } - - if (action != action_announce) - { - fail(-1, "invalid action in announce response"); - return; - } - - if (bytes_transferred < 20) - { - fail(-1, "got a message with size < 20"); - return; - } - - int interval = detail::read_int32(buf); - int incomplete = detail::read_int32(buf); - int complete = detail::read_int32(buf); - int num_peers = (bytes_transferred - 20) / 6; - if ((bytes_transferred - 20) % 6 != 0) - { - fail(-1, "invalid udp tracker response length"); - return; - } - -#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) - if (has_requester()) - { - requester().debug_log("<== UDP_TRACKER_ANNOUNCE_RESPONSE"); - } -#endif - - if (!has_requester()) - { - m_man.remove_request(this); - return; - } - - std::vector peer_list; - for (int i = 0; i < num_peers; ++i) - { - peer_entry e; - std::stringstream s; - s << (int)detail::read_uint8(buf) << "."; - s << (int)detail::read_uint8(buf) << "."; - s << (int)detail::read_uint8(buf) << "."; - s << (int)detail::read_uint8(buf); - e.ip = s.str(); - e.port = detail::read_uint16(buf); - e.pid.clear(); - peer_list.push_back(e); - } - - requester().tracker_response(tracker_req(), peer_list, interval - , complete, incomplete); - - m_man.remove_request(this); - return; - } - catch (std::exception& e) - { - fail(-1, e.what()); - }; // msvc 7.1 seems to require this - - void udp_tracker_connection::scrape_response(asio::error_code const& error - , std::size_t bytes_transferred) try - { - if (error == asio::error::operation_aborted) return; - if (!m_socket) return; // the operation was aborted - if (error) - { - fail(-1, error.message().c_str()); - return; - } - - if (m_target != m_sender) - { - // this packet was not received from the tracker - m_socket->async_receive_from(asio::buffer(m_buffer), m_sender - , bind(&udp_tracker_connection::connect_response, self(), _1, _2)); - return; - } - - if (bytes_transferred >= udp_buffer_size) - { - fail(-1, "udp response too big"); - return; - } - - if (bytes_transferred < 8) - { - fail(-1, "got a message with size < 8"); - return; - } - - restart_read_timeout(); - char* buf = &m_buffer[0]; - int action = detail::read_int32(buf); - int transaction = detail::read_int32(buf); - - if (transaction != m_transaction_id) - { - fail(-1, "incorrect transaction id"); - return; - } - - if (action == action_error) - { - fail(-1, std::string(buf, bytes_transferred - 8).c_str()); - return; - } - - if (action != action_scrape) - { - fail(-1, "invalid action in announce response"); - return; - } - - if (bytes_transferred < 20) - { - fail(-1, "got a message with size < 20"); - return; - } - - int complete = detail::read_int32(buf); - /*int downloaded = */detail::read_int32(buf); - int incomplete = detail::read_int32(buf); - - if (!has_requester()) - { - m_man.remove_request(this); - return; - } - - std::vector peer_list; - requester().tracker_response(tracker_req(), peer_list, 0 - , complete, incomplete); - - m_man.remove_request(this); - } - catch (std::exception& e) - { - fail(-1, e.what()); - } - -} - diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp deleted file mode 100644 index c60725e9d..000000000 --- a/libtorrent/src/upnp.cpp +++ /dev/null @@ -1,1038 +0,0 @@ -/* - -Copyright (c) 2007, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include "libtorrent/socket.hpp" -#include "libtorrent/upnp.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/http_tracker_connection.hpp" -#include "libtorrent/xml_parse.hpp" -#include "libtorrent/connection_queue.hpp" - -#include -#include -#include -#include -#include -#include - -#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defined(TORRENT_UPNP_LOGGING) -#define TORRENT_UPNP_LOGGING -#endif - -using boost::bind; -using namespace libtorrent; - -address_v4 upnp::upnp_multicast_address; -udp::endpoint upnp::upnp_multicast_endpoint; - -namespace libtorrent -{ - bool is_local(address const& a) - { - if (a.is_v6()) return false; - address_v4 a4 = a.to_v4(); - return ((a4.to_ulong() & 0xff000000) == 0x0a000000 - || (a4.to_ulong() & 0xfff00000) == 0xac100000 - || (a4.to_ulong() & 0xffff0000) == 0xc0a80000); - } - - address_v4 guess_local_address(asio::io_service& ios) - { - // make a best guess of the interface we're using and its IP - udp::resolver r(ios); - udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(), "0")); - for (;i != udp::resolver_iterator(); ++i) - { - // ignore the loopback - if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue; - // ignore addresses that are not on a local network - if (!is_local(i->endpoint().address())) continue; - // ignore non-IPv4 addresses - if (i->endpoint().address().is_v4()) break; - } - if (i == udp::resolver_iterator()) return address_v4::any(); - return i->endpoint().address().to_v4(); - } -} - -upnp::upnp(io_service& ios, connection_queue& cc - , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb) - : m_udp_local_port(0) - , m_tcp_local_port(0) - , m_user_agent(user_agent) - , m_callback(cb) - , m_retry_count(0) - , m_socket(ios) - , m_broadcast_timer(ios) - , m_refresh_timer(ios) - , m_strand(ios) - , m_disabled(false) - , m_closing(false) - , m_cc(cc) -{ - // UPnP multicast address and port - upnp_multicast_address = address_v4::from_string("239.255.255.250"); - upnp_multicast_endpoint = udp::endpoint(upnp_multicast_address, 1900); - -#ifdef TORRENT_UPNP_LOGGING - m_log.open("upnp.log", std::ios::in | std::ios::out | std::ios::trunc); -#endif - rebind(listen_interface); -} - -upnp::~upnp() -{ -} - -void upnp::rebind(address const& listen_interface) try -{ - address_v4 bind_to = address_v4::any(); - if (listen_interface.is_v4() && listen_interface != address_v4::any()) - { - m_local_ip = listen_interface.to_v4(); - bind_to = listen_interface.to_v4(); - if (!is_local(m_local_ip)) - { - // the local address seems to be an external - // internet address. Assume it is not behind a NAT - throw std::runtime_error("local IP is not on a local network"); - } - } - else - { - m_local_ip = guess_local_address(m_socket.io_service()); - bind_to = address_v4::any(); - } - - if (!is_local(m_local_ip)) - { - throw std::runtime_error("local host is probably not on a NATed " - "network. disabling UPnP"); - } - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " local ip: " << m_local_ip.to_string() - << " bind to: " << bind_to.to_string() << std::endl; -#endif - - // the local interface hasn't changed - if (m_socket.is_open() - && m_socket.local_endpoint().address() == m_local_ip) - return; - - m_socket.close(); - - using namespace asio::ip::multicast; - - m_socket.open(udp::v4()); - m_socket.set_option(datagram_socket::reuse_address(true)); - m_socket.bind(udp::endpoint(bind_to, 0)); - - m_socket.set_option(join_group(upnp_multicast_address)); - m_socket.set_option(outbound_interface(bind_to)); - m_socket.set_option(hops(255)); - m_disabled = false; - - m_retry_count = 0; - discover_device(); -} -catch (std::exception& e) -{ - disable(); - std::stringstream msg; - msg << "UPnP portmapping disabled: " << e.what(); - m_callback(0, 0, msg.str()); -}; - -void upnp::discover_device() try -{ - const char msearch[] = - "M-SEARCH * HTTP/1.1\r\n" - "HOST: 239.255.255.250:1900\r\n" - "ST:upnp:rootdevice\r\n" - "MAN:\"ssdp:discover\"\r\n" - "MX:3\r\n" - "\r\n\r\n"; - - m_socket.async_receive_from(asio::buffer(m_receive_buffer - , sizeof(m_receive_buffer)), m_remote, m_strand.wrap(bind( - &upnp::on_reply, this, _1, _2))); - - asio::error_code ec; -#ifdef TORRENT_DEBUG_UPNP - // simulate packet loss - if (m_retry_count & 1) -#endif - m_socket.send_to(asio::buffer(msearch, sizeof(msearch) - 1) - , upnp_multicast_endpoint, 0, ec); - - if (ec) - { - disable(); - return; - } - - ++m_retry_count; - m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); - m_broadcast_timer.async_wait(m_strand.wrap(bind(&upnp::resend_request - , this, _1))); - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> Broadcasting search for rootdevice" << std::endl; -#endif -} -catch (std::exception&) -{ - disable(); -} - -void upnp::set_mappings(int tcp, int udp) -{ -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** set mappings " << tcp << " " << udp; - if (m_disabled) m_log << " DISABLED"; - m_log << std::endl; -#endif - - if (m_disabled) return; - if (udp != 0) m_udp_local_port = udp; - if (tcp != 0) m_tcp_local_port = tcp; - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - rootdevice& d = const_cast(*i); - if (d.mapping[0].local_port != m_tcp_local_port) - { - if (d.mapping[0].external_port == 0) - d.mapping[0].external_port = m_tcp_local_port; - d.mapping[0].local_port = m_tcp_local_port; - d.mapping[0].need_update = true; - } - if (d.mapping[1].local_port != m_udp_local_port) - { - if (d.mapping[1].external_port == 0) - d.mapping[1].external_port = m_udp_local_port; - d.mapping[1].local_port = m_udp_local_port; - d.mapping[1].need_update = true; - } - if (d.service_namespace - && (d.mapping[0].need_update || d.mapping[1].need_update)) - map_port(d, 0); - } -} - -void upnp::resend_request(asio::error_code const& e) -#ifndef NDEBUG -try -#endif -{ - if (e) return; - if (m_retry_count < 9 - && (m_devices.empty() || m_retry_count < 4)) - { - discover_device(); - return; - } - - if (m_devices.empty()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** Got no response in 9 retries. Giving up, " - "disabling UPnP." << std::endl; -#endif - disable(); - return; - } - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - if (i->control_url.empty() && !i->upnp_connection && !i->disabled) - { - // we don't have a WANIP or WANPPP url for this device, - // ask for it - rootdevice& d = const_cast(*i); - try - { - d.upnp_connection.reset(new http_connection(m_socket.io_service() - , m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, this, _1, _2 - , boost::ref(d))))); - d.upnp_connection->get(d.url); - } - catch (std::exception& e) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** Connection failed to: " << d.url - << " " << e.what() << std::endl; -#endif - d.disabled = true; - } - } - } -} -#ifndef NDEBUG -catch (std::exception&) -{ - assert(false); -} -#endif - -void upnp::on_reply(asio::error_code const& e - , std::size_t bytes_transferred) -#ifndef NDEBUG -try -#endif -{ - using namespace libtorrent::detail; - if (e) return; - - // parse out the url for the device - -/* - the response looks like this: - - HTTP/1.1 200 OK - ST:upnp:rootdevice - USN:uuid:000f-66d6-7296000099dc::upnp:rootdevice - Location: http://192.168.1.1:5431/dyndev/uuid:000f-66d6-7296000099dc - Server: Custom/1.0 UPnP/1.0 Proc/Ver - EXT: - Cache-Control:max-age=180 - DATE: Fri, 02 Jan 1970 08:10:38 GMT -*/ - http_parser p; - try - { - p.incoming(buffer::const_interval(m_receive_buffer - , m_receive_buffer + bytes_transferred)); - } - catch (std::exception& e) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Rootdevice responded with incorrect HTTP packet: " - << e.what() << ". Ignoring device" << std::endl; -#endif - return; - } - - if (p.status_code() != 200) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Rootdevice responded with HTTP status: " << p.status_code() - << ". Ignoring device" << std::endl; -#endif - return; - } - - if (!p.header_finished()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Rootdevice responded with incomplete HTTP " - "packet. Ignoring device" << std::endl; -#endif - return; - } - - std::string url = p.header("location"); - if (url.empty()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Rootdevice response is missing a location header. " - "Ignoring device" << std::endl; -#endif - return; - } - - rootdevice d; - d.url = url; - - std::set::iterator i = m_devices.find(d); - - if (i == m_devices.end()) - { - - std::string protocol; - std::string auth; - // we don't have this device in our list. Add it - boost::tie(protocol, auth, d.hostname, d.port, d.path) - = parse_url_components(d.url); - - // ignore the auth here. It will be re-parsed - // by the http connection later - - if (protocol != "http") - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Rootdevice uses unsupported protocol: '" << protocol - << "'. Ignoring device" << std::endl; -#endif - return; - } - - if (d.port == 0) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Rootdevice responded with a url with port 0. " - "Ignoring device" << std::endl; -#endif - return; - } -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Found rootdevice: " << d.url << std::endl; -#endif - - if (m_tcp_local_port != 0) - { - d.mapping[0].need_update = true; - d.mapping[0].local_port = m_tcp_local_port; -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** Mapping 0 will be updated" << std::endl; -#endif - } - if (m_udp_local_port != 0) - { - d.mapping[1].need_update = true; - d.mapping[1].local_port = m_udp_local_port; -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** Mapping 1 will be updated" << std::endl; -#endif - } - boost::tie(i, boost::tuples::ignore) = m_devices.insert(d); - } - - - // since we're using udp, send the query 4 times - // just to make sure we find all devices - if (m_retry_count >= 4 && !m_devices.empty()) - { - m_broadcast_timer.cancel(); - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - if (i->control_url.empty() && !i->upnp_connection && !i->disabled) - { - // we don't have a WANIP or WANPPP url for this device, - // ask for it - rootdevice& d = const_cast(*i); - try - { - d.upnp_connection.reset(new http_connection(m_socket.io_service() - , m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, this, _1, _2 - , boost::ref(d))))); - d.upnp_connection->get(d.url); - } - catch (std::exception& e) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " *** Connection failed to: " << d.url - << " " << e.what() << std::endl; -#endif - d.disabled = true; - } - } - } - } -} -#ifndef NDEBUG -catch (std::exception&) -{ - assert(false); -}; -#endif - -void upnp::post(rootdevice& d, std::stringstream const& soap - , std::string const& soap_action) -{ - std::stringstream header; - - header << "POST " << d.control_url << " HTTP/1.1\r\n" - "Host: " << d.hostname << ":" << d.port << "\r\n" - "Content-Type: text/xml; charset=\"utf-8\"\r\n" - "Content-Length: " << soap.str().size() << "\r\n" - "Soapaction: \"" << d.service_namespace << "#" << soap_action << "\"\r\n\r\n" << soap.str(); - - d.upnp_connection->sendbuffer = header.str(); - d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) - , seconds(10)); -} - -void upnp::map_port(rootdevice& d, int i) -{ - if (d.upnp_connection) return; - - if (!d.mapping[i].need_update) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** mapping (" << i - << ") does not need update, skipping" << std::endl; -#endif - if (i < num_mappings - 1) - map_port(d, i + 1); - return; - } - d.mapping[i].need_update = false; - assert(!d.upnp_connection); - assert(d.service_namespace); - - d.upnp_connection.reset(new http_connection(m_socket.io_service() - , m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, this, _1, _2 - , boost::ref(d), i)))); - - std::string soap_action = "AddPortMapping"; - - std::stringstream soap; - - soap << "\n" - "" - ""; - - soap << "" - "" << d.mapping[i].external_port << "" - "" << (d.mapping[i].protocol ? "UDP" : "TCP") << "" - "" << d.mapping[i].local_port << "" - "" << m_local_ip.to_string() << "" - "1" - "" << m_user_agent << "" - "" << d.lease_duration << ""; - soap << ""; - - post(d, soap, soap_action); -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> AddPortMapping: " << soap.str() << std::endl; -#endif - -} - -// requires the mutex to be locked -void upnp::unmap_port(rootdevice& d, int i) -{ - if (d.mapping[i].external_port == 0) - { - if (i < num_mappings - 1) - { - unmap_port(d, i + 1); - } - else - { - m_devices.erase(d); - } - return; - } - d.upnp_connection.reset(new http_connection(m_socket.io_service() - , m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, this, _1, _2 - , boost::ref(d), i)))); - - std::string soap_action = "DeletePortMapping"; - - std::stringstream soap; - - soap << "\n" - "" - ""; - - soap << "" - "" << d.mapping[i].external_port << "" - "" << (d.mapping[i].protocol ? "UDP" : "TCP") << ""; - soap << ""; - - post(d, soap, soap_action); -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> DeletePortMapping: " << soap.str() << std::endl; -#endif -} - -namespace -{ - struct parse_state - { - parse_state(): found_service(false), exit(false) {} - void reset(char const* st) - { - found_service = false; - exit = false; - service_type = st; - } - bool found_service; - bool exit; - std::string top_tag; - std::string control_url; - char const* service_type; - }; - - void find_control_url(int type, char const* string, parse_state& state) - { - if (state.exit) return; - - if (type == xml_start_tag) - { - if ((!state.top_tag.empty() && state.top_tag == "service") - || !strcmp(string, "service")) - { - state.top_tag = string; - } - } - else if (type == xml_end_tag) - { - if (!strcmp(string, "service")) - { - state.top_tag.clear(); - if (state.found_service) state.exit = true; - } - else if (!state.top_tag.empty() && state.top_tag != "service") - state.top_tag = "service"; - } - else if (type == xml_string) - { - if (state.top_tag == "serviceType") - { - if (!strcmp(string, state.service_type)) - state.found_service = true; - } - else if (state.top_tag == "controlURL") - { - state.control_url = string; - if (state.found_service) state.exit = true; - } - } - } - -} - -void upnp::on_upnp_xml(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d) try -{ - if (d.upnp_connection) - { - d.upnp_connection->close(); - d.upnp_connection.reset(); - } - - if (e) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== error while fetching control url: " << e.message() << std::endl; -#endif - return; - } - - if (!p.header_finished()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== incomplete http message" << std::endl; -#endif - return; - } - - parse_state s; - s.reset("urn:schemas-upnp-org:service:WANIPConnection:1"); - xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , m_strand.wrap(bind(&find_control_url, _1, _2, boost::ref(s)))); - if (s.found_service) - { - d.service_namespace = s.service_type; - } - else - { - // we didn't find the WAN IP connection, look for - // a PPP connection - s.reset("urn:schemas-upnp-org:service:WANPPPConnection:1"); - xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , m_strand.wrap(bind(&find_control_url, _1, _2, boost::ref(s)))); - if (s.found_service) - { - d.service_namespace = s.service_type; - } - else - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Rootdevice response, did not find a port mapping interface" << std::endl; -#endif - return; - } - } - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== Rootdevice response, found control URL: " << s.control_url - << " namespace: " << d.service_namespace << std::endl; -#endif - - d.control_url = s.control_url; - - map_port(d, 0); -} -catch (std::exception&) -{ - disable(); -}; - -void upnp::disable() -{ - m_disabled = true; - m_devices.clear(); - m_broadcast_timer.cancel(); - m_refresh_timer.cancel(); - m_socket.close(); -} - -namespace -{ - struct error_code_parse_state - { - error_code_parse_state(): in_error_code(false), exit(false), error_code(-1) {} - bool in_error_code; - bool exit; - int error_code; - }; - - void find_error_code(int type, char const* string, error_code_parse_state& state) - { - if (state.exit) return; - if (type == xml_start_tag && !strcmp("errorCode", string)) - { - state.in_error_code = true; - } - else if (type == xml_string && state.in_error_code) - { - state.error_code = std::atoi(string); - state.exit = true; - } - } -} - -namespace -{ - struct error_code_t - { - int code; - char const* msg; - }; - - error_code_t error_codes[] = - { - {402, "Invalid Arguments"} - , {501, "Action Failed"} - , {714, "The specified value does not exist in the array"} - , {715, "The source IP address cannot be wild-carded"} - , {716, "The external port cannot be wild-carded"} - , {718, "The port mapping entry specified conflicts with " - "a mapping assigned previously to another client"} - , {724, "Internal and External port values must be the same"} - , {725, "The NAT implementation only supports permanent " - "lease times on port mappings"} - , {726, "RemoteHost must be a wildcard and cannot be a " - "specific IP address or DNS name"} - , {727, "ExternalPort must be a wildcard and cannot be a specific port "} - }; - -} - -void upnp::on_upnp_map_response(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d, int mapping) try -{ - if (d.upnp_connection) - { - d.upnp_connection->close(); - d.upnp_connection.reset(); - } - - if (e) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== error while adding portmap: " << e.message() << std::endl; -#endif - m_devices.erase(d); - return; - } - - if (m_closing) return; - -// error code response may look like this: -// -// -// -// s:Client -// UPnPError -// -// -// 402 -// Invalid Args -// -// -// -// -// - - if (!p.header_finished()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== incomplete http message" << std::endl; -#endif - m_devices.erase(d); - return; - } - - error_code_parse_state s; - xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , m_strand.wrap(bind(&find_error_code, _1, _2, boost::ref(s)))); - -#ifdef TORRENT_UPNP_LOGGING - if (s.error_code != -1) - { - m_log << time_now_string() - << " <== got error message: " << s.error_code << std::endl; - } -#endif - - if (s.error_code == 725) - { - // only permanent leases supported - d.lease_duration = 0; - d.mapping[mapping].need_update = true; - map_port(d, mapping); - return; - } - else if (s.error_code == 718) - { - // conflict in mapping, try next external port - ++d.mapping[mapping].external_port; - d.mapping[mapping].need_update = true; - map_port(d, mapping); - return; - } - else if (s.error_code != -1) - { - int num_errors = sizeof(error_codes) / sizeof(error_codes[0]); - error_code_t* end = error_codes + num_errors; - error_code_t tmp = {s.error_code, 0}; - error_code_t* e = std::lower_bound(error_codes, end, tmp - , bind(&error_code_t::code, _1) < bind(&error_code_t::code, _2)); - std::string error_string = "UPnP mapping error "; - error_string += boost::lexical_cast(s.error_code); - if (e != end && e->code == s.error_code) - { - error_string += ": "; - error_string += e->msg; - } - m_callback(0, 0, error_string); - } - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== map response: " << std::string(p.get_body().begin, p.get_body().end) - << std::endl; -#endif - - if (s.error_code == -1) - { - int tcp = 0; - int udp = 0; - - if (mapping == 0) - tcp = d.mapping[mapping].external_port; - else - udp = d.mapping[mapping].external_port; - - m_callback(tcp, udp, ""); - if (d.lease_duration > 0) - { - d.mapping[mapping].expires = time_now() - + seconds(int(d.lease_duration * 0.75f)); - ptime next_expire = m_refresh_timer.expires_at(); - if (next_expire < time_now() - || next_expire > d.mapping[mapping].expires) - { - m_refresh_timer.expires_at(d.mapping[mapping].expires); - m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, this, _1))); - } - } - else - { - d.mapping[mapping].expires = max_time(); - } - } - - for (int i = 0; i < num_mappings; ++i) - { - if (d.mapping[i].need_update) - { - map_port(d, i); - return; - } - } -} -catch (std::exception&) -{ - disable(); -}; - -void upnp::on_upnp_unmap_response(asio::error_code const& e - , libtorrent::http_parser const& p, rootdevice& d, int mapping) try -{ - if (d.upnp_connection) - { - d.upnp_connection->close(); - d.upnp_connection.reset(); - } - - if (e) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== error while deleting portmap: " << e.message() << std::endl; -#endif - } - - if (!p.header_finished()) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== incomplete http message" << std::endl; -#endif - return; - } - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " <== unmap response: " << std::string(p.get_body().begin, p.get_body().end) - << std::endl; -#endif - - // ignore errors and continue with the next mapping for this device - if (mapping < num_mappings - 1) - { - unmap_port(d, mapping + 1); - return; - } - - // the main thread is likely to be waiting for - // all the unmap operations to complete - m_devices.erase(d); -} -catch (std::exception&) -{ - disable(); -}; - -void upnp::on_expire(asio::error_code const& e) try -{ - if (e) return; - - ptime now = time_now(); - ptime next_expire = max_time(); - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end; ++i) - { - rootdevice& d = const_cast(*i); - for (int m = 0; m < num_mappings; ++m) - { - if (d.mapping[m].expires != max_time()) - continue; - - if (d.mapping[m].expires < now) - { - d.mapping[m].expires = max_time(); - map_port(d, m); - } - else if (d.mapping[m].expires < next_expire) - { - next_expire = d.mapping[m].expires; - } - } - } - if (next_expire != max_time()) - { - m_refresh_timer.expires_at(next_expire); - m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, this, _1))); - } -} -catch (std::exception&) -{ - disable(); -}; - -void upnp::close() -{ - m_refresh_timer.cancel(); - m_broadcast_timer.cancel(); - m_closing = true; - m_socket.close(); - - if (m_disabled) - { - m_devices.clear(); - return; - } - - for (std::set::iterator i = m_devices.begin() - , end(m_devices.end()); i != end;) - { - rootdevice& d = const_cast(*i); - if (d.control_url.empty()) - { - m_devices.erase(i++); - continue; - } - ++i; - unmap_port(d, 0); - } -} - diff --git a/libtorrent/src/ut_pex.cpp b/libtorrent/src/ut_pex.cpp deleted file mode 100644 index 586cf7ccb..000000000 --- a/libtorrent/src/ut_pex.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - -Copyright (c) 2006, MassaRoddel, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#ifdef _MSC_VER -#pragma warning(push, 1) -#endif - -#include - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#include "libtorrent/peer_connection.hpp" -#include "libtorrent/bt_peer_connection.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/torrent.hpp" -#include "libtorrent/extensions.hpp" - -#include "libtorrent/extensions/ut_pex.hpp" - -namespace libtorrent { namespace -{ - const char extension_name[] = "ut_pex"; - - enum - { - extension_index = 1, - max_peer_entries = 100 - }; - - bool send_peer(peer_connection const& p) - { - // don't send out peers that we haven't connected to - // (that have connected to us) - if (!p.is_local()) return false; - // don't send out peers that we haven't successfully connected to - if (p.is_connecting()) return false; - // ut pex does not support IPv6 - if (!p.remote().address().is_v4()) return false; - return true; - } - - struct ut_pex_plugin: torrent_plugin - { - ut_pex_plugin(torrent& t): m_torrent(t), m_1_minute(0) {} - - virtual boost::shared_ptr new_connection(peer_connection* pc); - - std::vector& get_ut_pex_msg() - { - return m_ut_pex_msg; - } - - // the second tick of the torrent - // each minute the new lists of "added" + "added.f" and "dropped" - // are calculated here and the pex message is created - // each peer connection will use this message - // max_peer_entries limits the packet size - virtual void tick() - { - if (++m_1_minute < 60) return; - - m_1_minute = 0; - - entry pex; - std::string& pla = pex["added"].string(); - std::string& pld = pex["dropped"].string(); - std::string& plf = pex["added.f"].string(); - std::back_insert_iterator pla_out(pla); - std::back_insert_iterator pld_out(pld); - std::back_insert_iterator plf_out(plf); - - std::set dropped; - m_old_peers.swap(dropped); - - int num_added = 0; - for (torrent::peer_iterator i = m_torrent.begin() - , end(m_torrent.end()); i != end; ++i) - { - if (!send_peer(*i->second)) continue; - - m_old_peers.insert(i->first); - - std::set::iterator di = dropped.find(i->first); - if (di == dropped.end()) - { - // don't write too big of a package - if (num_added >= max_peer_entries) continue; - - // i->first was added since the last time - detail::write_endpoint(i->first, pla_out); - // no supported flags to set yet - // 0x01 - peer supports encryption - // 0x02 - peer is a seed - int flags = i->second->is_seed() ? 2 : 0; - detail::write_uint8(flags, plf_out); - ++num_added; - } - else - { - // this was in the previous message - // so, it wasn't dropped - dropped.erase(di); - } - } - - for (std::set::const_iterator i = dropped.begin() - , end(dropped.end());i != end; ++i) - { - if (!i->address().is_v4()) continue; - detail::write_endpoint(*i, pld_out); - } - - m_ut_pex_msg.clear(); - bencode(std::back_inserter(m_ut_pex_msg), pex); - } - - private: - torrent& m_torrent; - - std::set m_old_peers; - int m_1_minute; - std::vector m_ut_pex_msg; - }; - - - struct ut_pex_peer_plugin : peer_plugin - { - ut_pex_peer_plugin(torrent& t, peer_connection& pc, ut_pex_plugin& tp) - : m_torrent(t) - , m_pc(pc) - , m_tp(tp) - , m_1_minute(0) - , m_message_index(0) - , m_first_time(true) - {} - - virtual void add_handshake(entry& h) - { - entry& messages = h["m"]; - messages[extension_name] = extension_index; - } - - virtual bool on_extension_handshake(entry const& h) - { - entry const& messages = h["m"]; - - if (entry const* index = messages.find_key(extension_name)) - { - m_message_index = index->integer(); - return true; - } - else - { - m_message_index = 0; - return false; - } - } - - virtual bool on_extended(int length, int msg, buffer::const_interval body) - try - { - if (msg != extension_index) return false; - if (m_message_index == 0) return false; - - if (length > 500 * 1024) - throw protocol_error("ut peer exchange message larger than 500 kB"); - - if (body.left() < length) return true; - - entry pex_msg = bdecode(body.begin, body.end); - std::string const& peers = pex_msg["added"].string(); - std::string const& peer_flags = pex_msg["added.f"].string(); - - int num_peers = peers.length() / 6; - char const* in = peers.c_str(); - char const* fin = peer_flags.c_str(); - - if (int(peer_flags.size()) != num_peers) - return true; - - peer_id pid(0); - policy& p = m_torrent.get_policy(); - for (int i = 0; i < num_peers; ++i) - { - tcp::endpoint adr = detail::read_v4_endpoint(in); - char flags = detail::read_uint8(fin); - p.peer_from_tracker(adr, pid, peer_info::pex, flags); - } - return true; - } - catch (std::exception&) - { - return true; - } - - // the peers second tick - // every minute we send a pex message - virtual void tick() - { - if (!m_message_index) return; // no handshake yet - if (++m_1_minute <= 60) return; - - if (m_first_time) - { - send_ut_peer_list(); - m_first_time = false; - } - else - { - send_ut_peer_diff(); - } - m_1_minute = 0; - } - - private: - - void send_ut_peer_diff() - { - std::vector const& pex_msg = m_tp.get_ut_pex_msg(); - - buffer::interval i = m_pc.allocate_send_buffer(6 + pex_msg.size()); - - detail::write_uint32(1 + 1 + pex_msg.size(), i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - std::copy(pex_msg.begin(), pex_msg.end(), i.begin); - i.begin += pex_msg.size(); - - assert(i.begin == i.end); - m_pc.setup_send(); - } - - void send_ut_peer_list() - { - entry pex; - // leave the dropped string empty - pex["dropped"].string(); - std::string& pla = pex["added"].string(); - std::string& plf = pex["added.f"].string(); - std::back_insert_iterator pla_out(pla); - std::back_insert_iterator plf_out(plf); - - int num_added = 0; - for (torrent::peer_iterator i = m_torrent.begin() - , end(m_torrent.end()); i != end; ++i) - { - if (!send_peer(*i->second)) continue; - - // don't write too big of a package - if (num_added >= max_peer_entries) continue; - - // i->first was added since the last time - detail::write_endpoint(i->first, pla_out); - // no supported flags to set yet - // 0x01 - peer supports encryption - // 0x02 - peer is a seed - int flags = i->second->is_seed() ? 2 : 0; - detail::write_uint8(flags, plf_out); - ++num_added; - } - std::vector pex_msg; - bencode(std::back_inserter(pex_msg), pex); - - buffer::interval i = m_pc.allocate_send_buffer(6 + pex_msg.size()); - - detail::write_uint32(1 + 1 + pex_msg.size(), i.begin); - detail::write_uint8(bt_peer_connection::msg_extended, i.begin); - detail::write_uint8(m_message_index, i.begin); - std::copy(pex_msg.begin(), pex_msg.end(), i.begin); - i.begin += pex_msg.size(); - - assert(i.begin == i.end); - m_pc.setup_send(); - } - - torrent& m_torrent; - peer_connection& m_pc; - ut_pex_plugin& m_tp; - int m_1_minute; - int m_message_index; - - // this is initialized to true, and set to - // false after the first pex message has been sent. - // it is used to know if a diff message or a full - // message should be sent. - bool m_first_time; - }; - - boost::shared_ptr ut_pex_plugin::new_connection(peer_connection* pc) - { - bt_peer_connection* c = dynamic_cast(pc); - if (!c) return boost::shared_ptr(); - return boost::shared_ptr(new ut_pex_peer_plugin(m_torrent - , *pc, *this)); - } -}} - -namespace libtorrent -{ - - boost::shared_ptr create_ut_pex_plugin(torrent* t) - { - if (t->torrent_file().priv()) - { - return boost::shared_ptr(); - } - return boost::shared_ptr(new ut_pex_plugin(*t)); - } - -} - - diff --git a/libtorrent/src/web_peer_connection.cpp b/libtorrent/src/web_peer_connection.cpp deleted file mode 100644 index bbe7c6e66..000000000 --- a/libtorrent/src/web_peer_connection.cpp +++ /dev/null @@ -1,692 +0,0 @@ -/* - -Copyright (c) 2003, Arvid Norberg -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of the author nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include "libtorrent/pch.hpp" - -#include -#include -#include -#include -#include -#include - -#include "libtorrent/web_peer_connection.hpp" -#include "libtorrent/session.hpp" -#include "libtorrent/identify_client.hpp" -#include "libtorrent/entry.hpp" -#include "libtorrent/bencode.hpp" -#include "libtorrent/alert_types.hpp" -#include "libtorrent/invariant_check.hpp" -#include "libtorrent/io.hpp" -#include "libtorrent/version.hpp" -#include "libtorrent/aux_/session_impl.hpp" - -using boost::bind; -using boost::shared_ptr; -using libtorrent::aux::session_impl; - -namespace libtorrent -{ - web_peer_connection::web_peer_connection( - session_impl& ses - , boost::weak_ptr t - , boost::shared_ptr s - , tcp::endpoint const& remote - , std::string const& url - , policy::peer* peerinfo) - : peer_connection(ses, t, s, remote, peerinfo) - , m_url(url) - , m_first_request(true) - { - INVARIANT_CHECK; - - // we always prefer downloading entire - // pieces from web seeds - prefer_whole_pieces(true); - // we want large blocks as well, so - // we can request more bytes at once - request_large_blocks(true); - // we only want left-over bandwidth - set_non_prioritized(true); - shared_ptr tor = t.lock(); - assert(tor); - int blocks_per_piece = tor->torrent_file().piece_length() / tor->block_size(); - - // multiply with the blocks per piece since that many requests are - // merged into one http request - m_max_out_request_queue = ses.settings().urlseed_pipeline_size - * blocks_per_piece; - - // since this is a web seed, change the timeout - // according to the settings. - set_timeout(ses.settings().urlseed_timeout); -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << "*** web_peer_connection\n"; -#endif - - std::string protocol; - boost::tie(protocol, m_auth, m_host, m_port, m_path) - = parse_url_components(url); - - if (!m_auth.empty()) - m_auth = base64encode(m_auth); - - m_server_string = "URL seed @ "; - m_server_string += m_host; - } - - web_peer_connection::~web_peer_connection() - {} - - boost::optional - web_peer_connection::downloading_piece_progress() const - { - if (m_requests.empty()) - return boost::optional(); - - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - piece_block_progress ret; - - ret.piece_index = m_requests.front().piece; - if (!m_piece.empty()) - { - ret.bytes_downloaded = int(m_piece.size()); - } - else - { - if (!m_parser.header_finished()) - { - ret.bytes_downloaded = 0; - } - else - { - int receive_buffer_size = receive_buffer().left() - m_parser.body_start(); - ret.bytes_downloaded = receive_buffer_size % t->block_size(); - } - } - ret.block_index = (m_requests.front().start + ret.bytes_downloaded) / t->block_size(); - ret.full_block_bytes = t->block_size(); - const int last_piece = t->torrent_file().num_pieces() - 1; - if (ret.piece_index == last_piece && ret.block_index - == t->torrent_file().piece_size(last_piece) / t->block_size()) - ret.full_block_bytes = t->torrent_file().piece_size(last_piece) % t->block_size(); - return ret; - } - - void web_peer_connection::on_connected() - { - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - // this is always a seed - incoming_bitfield(std::vector( - t->torrent_file().num_pieces(), true)); - // it is always possible to request pieces - incoming_unchoke(); - - reset_recv_buffer(t->block_size() + 1024); - } - - void web_peer_connection::write_request(peer_request const& r) - { - INVARIANT_CHECK; - - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - assert(t->valid_metadata()); - - bool single_file_request = false; - if (!m_path.empty() && m_path[m_path.size() - 1] != '/') - single_file_request = true; - - torrent_info const& info = t->torrent_file(); - - std::string request; - request.reserve(400); - - int size = r.length; - const int block_size = t->block_size(); - while (size > 0) - { - int request_size = std::min(block_size, size); - peer_request pr = {r.piece, r.start + r.length - size - , request_size}; - m_requests.push_back(pr); - size -= request_size; - } - - proxy_settings const& ps = m_ses.web_seed_proxy(); - bool using_proxy = ps.type == proxy_settings::http - || ps.type == proxy_settings::http_pw; - - if (single_file_request) - { - request += "GET "; - // do not encode single file paths, they are - // assumed to be encoded in the torrent file - request += using_proxy ? m_url : m_path; - request += " HTTP/1.1\r\n"; - request += "Host: "; - request += m_host; - if (m_first_request) - { - request += "\r\nUser-Agent: "; - request += m_ses.settings().user_agent; - } - if (!m_auth.empty()) - { - request += "\r\nAuthorization: Basic "; - request += m_auth; - } - if (ps.type == proxy_settings::http_pw) - { - request += "\r\nProxy-Authorization: Basic "; - request += base64encode(ps.username + ":" + ps.password); - } - if (using_proxy) - { - request += "\r\nProxy-Connection: keep-alive"; - } - request += "\r\nRange: bytes="; - request += boost::lexical_cast(r.piece - * info.piece_length() + r.start); - request += "-"; - request += boost::lexical_cast(r.piece - * info.piece_length() + r.start + r.length - 1); - if (m_first_request || using_proxy) - request += "\r\nConnection: keep-alive"; - request += "\r\n\r\n"; - m_first_request = false; - m_file_requests.push_back(0); - } - else - { - std::vector files = info.map_block(r.piece, r.start - , r.length); - - for (std::vector::iterator i = files.begin(); - i != files.end(); ++i) - { - file_slice const& f = *i; - - request += "GET "; - if (using_proxy) - { - request += m_url; - std::string path = info.file_at(f.file_index).path.string(); - request += escape_path(path.c_str(), path.length()); - } - else - { - std::string path = m_path; - path += info.file_at(f.file_index).path.string(); - request += escape_path(path.c_str(), path.length()); - } - request += " HTTP/1.1\r\n"; - request += "Host: "; - request += m_host; - if (m_first_request) - { - request += "\r\nUser-Agent: "; - request += m_ses.settings().user_agent; - } - if (!m_auth.empty()) - { - request += "\r\nAuthorization: Basic "; - request += m_auth; - } - if (ps.type == proxy_settings::http_pw) - { - request += "\r\nProxy-Authorization: Basic "; - request += base64encode(ps.username + ":" + ps.password); - } - if (using_proxy) - { - request += "\r\nProxy-Connection: keep-alive"; - } - request += "\r\nRange: bytes="; - request += boost::lexical_cast(f.offset); - request += "-"; - request += boost::lexical_cast(f.offset + f.size - 1); - if (m_first_request || using_proxy) - request += "\r\nConnection: keep-alive"; - request += "\r\n\r\n"; - m_first_request = false; - assert(f.file_index >= 0); - m_file_requests.push_back(f.file_index); - } - } - -#ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << request << "\n"; -#endif - - send_buffer(request.c_str(), request.c_str() + request.size()); - } - - // -------------------------- - // RECEIVE DATA - // -------------------------- - - namespace - { - bool range_contains(peer_request const& range, peer_request const& req) - { - return range.start <= req.start - && range.start + range.length >= req.start + req.length; - } - } - - // throws exception when the client should be disconnected - void web_peer_connection::on_receive(asio::error_code const& error - , std::size_t bytes_transferred) - { - INVARIANT_CHECK; - - if (error) return; - - boost::shared_ptr t = associated_torrent().lock(); - assert(t); - - incoming_piece_fragment(); - - for (;;) - { - buffer::const_interval recv_buffer = receive_buffer(); - - int payload; - int protocol; - bool header_finished = m_parser.header_finished(); - if (!header_finished) - { - boost::tie(payload, protocol) = m_parser.incoming(recv_buffer); - m_statistics.received_bytes(payload, protocol); - - assert(recv_buffer.left() == 0 || *recv_buffer.begin == 'H'); - - assert(recv_buffer.left() <= packet_size()); - - // this means the entire status line hasn't been received yet - if (m_parser.status_code() == -1) break; - - // if the status code is not one of the accepted ones, abort - if (m_parser.status_code() != 206 // partial content - && m_parser.status_code() != 200 // OK - && !(m_parser.status_code() >= 300 // redirect - && m_parser.status_code() < 400)) - { - // we should not try this server again. - t->remove_url_seed(m_url); - std::string error_msg = boost::lexical_cast(m_parser.status_code()) - + " " + m_parser.message(); - if (m_ses.m_alerts.should_post(alert::warning)) - { - session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); - m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url() - , error_msg)); - } - throw std::runtime_error(error_msg); - } - if (!m_parser.header_finished()) break; - - m_body_start = m_parser.body_start(); - m_received_body = 0; - } - else - { - m_statistics.received_bytes(bytes_transferred, 0); - } - - // we just completed reading the header - if (!header_finished) - { - if (m_parser.status_code() >= 300 && m_parser.status_code() < 400) - { - // this means we got a redirection request - // look for the location header - std::string location = m_parser.header("location"); - - if (location.empty()) - { - // we should not try this server again. - t->remove_url_seed(m_url); - throw std::runtime_error("got HTTP redirection status without location header"); - } - - bool single_file_request = false; - if (!m_path.empty() && m_path[m_path.size() - 1] != '/') - single_file_request = true; - - // add the redirected url and remove the current one - if (!single_file_request) - { - assert(!m_file_requests.empty()); - int file_index = m_file_requests.front(); - - torrent_info const& info = t->torrent_file(); - std::string path = info.file_at(file_index).path.string(); - path = escape_path(path.c_str(), path.length()); - size_t i = location.rfind(path); - if (i == std::string::npos) - { - t->remove_url_seed(m_url); - throw std::runtime_error("got invalid HTTP redirection location (\"" + location + "\") " - "expected it to end with: " + path); - } - location.resize(i); - } - t->add_url_seed(location); - t->remove_url_seed(m_url); - throw std::runtime_error("redirecting to " + location); - } - - std::string server_version = m_parser.header("server"); - if (!server_version.empty()) - { - m_server_string = "URL seed @ "; - m_server_string += m_host; - m_server_string += " ("; - m_server_string += server_version; - m_server_string += ")"; - } - - m_body_start = m_parser.body_start(); - m_received_body = 0; - } - - recv_buffer.begin += m_body_start; - // we only received the header, no data - if (recv_buffer.left() == 0) break; - - size_type range_start; - size_type range_end; - if (m_parser.status_code() == 206) - { - std::stringstream range_str(m_parser.header("content-range")); - char dummy; - std::string bytes; - range_str >> bytes >> range_start >> dummy >> range_end; - if (!range_str) - { - // we should not try this server again. - t->remove_url_seed(m_url); - throw std::runtime_error("invalid range in HTTP response: " + range_str.str()); - } - // the http range is inclusive - range_end++; - } - else - { - range_start = 0; - range_end = m_parser.header("content-length"); - if (range_end == -1) - { - // we should not try this server again. - t->remove_url_seed(m_url); - throw std::runtime_error("no content-length in HTTP response"); - } - } - - torrent_info const& info = t->torrent_file(); - - if (m_requests.empty() || m_file_requests.empty()) - throw std::runtime_error("unexpected HTTP response"); - - int file_index = m_file_requests.front(); - peer_request in_range = info.map_file(file_index, range_start - , range_end - range_start); - - peer_request front_request = m_requests.front(); - - if (in_range.piece != front_request.piece - || in_range.start > front_request.start + int(m_piece.size())) - { - throw std::runtime_error("invalid range in HTTP response"); - } - - // skip the http header and the blocks we've already read. The - // http_body.begin is now in sync with the request at the front - // of the request queue - assert(in_range.start - int(m_piece.size()) <= front_request.start); - - // the http response body consists of 3 parts - // 1. the middle of a block or the ending of a block - // 2. a number of whole blocks - // 3. the start of a block - // in that order, these parts are parsed. - - bool range_overlaps_request = in_range.start + in_range.length - > front_request.start + int(m_piece.size()); - - // if the request is contained in the range (i.e. the entire request - // fits in the range) we should not start a partial piece, since we soon - // will receive enough to call incoming_piece() and pass the read buffer - // directly (in the next loop below). - if (range_overlaps_request && !range_contains(in_range, front_request)) - { - // the start of the next block to receive is stored - // in m_piece. We need to append the rest of that - // block from the http receive buffer and then - // (if it completed) call incoming_piece() with - // m_piece as buffer. - - int piece_size = int(m_piece.size()); - int copy_size = std::min(std::min(front_request.length - piece_size - , recv_buffer.left()), int(range_end - range_start - m_received_body)); - m_piece.resize(piece_size + copy_size); - assert(copy_size > 0); - std::memcpy(&m_piece[0] + piece_size, recv_buffer.begin, copy_size); - assert(int(m_piece.size()) <= front_request.length); - recv_buffer.begin += copy_size; - m_received_body += copy_size; - m_body_start += copy_size; - assert(m_received_body <= range_end - range_start); - assert(int(m_piece.size()) <= front_request.length); - if (int(m_piece.size()) == front_request.length) - { - // each call to incoming_piece() may result in us becoming - // a seed. If we become a seed, all seeds we're connected to - // will be disconnected, including this web seed. We need to - // check for the disconnect condition after the call. - - m_requests.pop_front(); - incoming_piece(front_request, &m_piece[0]); - if (associated_torrent().expired()) return; - cut_receive_buffer(m_body_start, t->block_size() + 1024); - m_body_start = 0; - recv_buffer = receive_buffer(); - assert(m_received_body <= range_end - range_start); - m_piece.clear(); - assert(m_piece.empty()); - } - } - - // report all received blocks to the bittorrent engine - while (!m_requests.empty() - && range_contains(in_range, m_requests.front()) - && recv_buffer.left() >= m_requests.front().length) - { - peer_request r = m_requests.front(); - m_requests.pop_front(); - assert(recv_buffer.left() >= r.length); - - incoming_piece(r, recv_buffer.begin); - if (associated_torrent().expired()) return; - m_received_body += r.length; - assert(receive_buffer().begin + m_body_start == recv_buffer.begin); - assert(m_received_body <= range_end - range_start); - cut_receive_buffer(r.length + m_body_start, t->block_size() + 1024); - m_body_start = 0; - recv_buffer = receive_buffer(); - } - - if (!m_requests.empty()) - { - range_overlaps_request = in_range.start + in_range.length - > m_requests.front().start + int(m_piece.size()); - - if (in_range.start + in_range.length < m_requests.front().start + m_requests.front().length - && (m_received_body + recv_buffer.left() >= range_end - range_start)) - { - int piece_size = int(m_piece.size()); - int copy_size = std::min(std::min(m_requests.front().length - piece_size - , recv_buffer.left()), int(range_end - range_start - m_received_body)); - assert(copy_size >= 0); - if (copy_size > 0) - { - m_piece.resize(piece_size + copy_size); - std::memcpy(&m_piece[0] + piece_size, recv_buffer.begin, copy_size); - recv_buffer.begin += copy_size; - m_received_body += copy_size; - m_body_start += copy_size; - } - assert(m_received_body == range_end - range_start); - } - } - - assert(m_received_body <= range_end - range_start); - if (m_received_body == range_end - range_start) - { - cut_receive_buffer(recv_buffer.begin - receive_buffer().begin - , t->block_size() + 1024); - recv_buffer = receive_buffer(); - m_file_requests.pop_front(); - m_parser.reset(); - m_body_start = 0; - m_received_body = 0; - continue; - } - break; - } - } - - void web_peer_connection::get_peer_info(peer_info& p) const - { - assert(!associated_torrent().expired()); - - p.down_speed = statistics().download_rate(); - p.up_speed = statistics().upload_rate(); - p.payload_down_speed = statistics().download_payload_rate(); - p.payload_up_speed = statistics().upload_payload_rate(); - p.pid = pid(); - p.ip = remote(); - -#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES - p.country[0] = m_country[0]; - p.country[1] = m_country[1]; -#endif - - p.total_download = statistics().total_payload_download(); - p.total_upload = statistics().total_payload_upload(); - - if (m_bandwidth_limit[upload_channel].throttle() == bandwidth_limit::inf) - p.upload_limit = -1; - else - p.upload_limit = m_bandwidth_limit[upload_channel].throttle(); - - if (m_bandwidth_limit[download_channel].throttle() == bandwidth_limit::inf) - p.download_limit = -1; - else - p.download_limit = m_bandwidth_limit[download_channel].throttle(); - - p.load_balancing = total_free_upload(); - - p.download_queue_length = (int)download_queue().size(); - p.upload_queue_length = (int)upload_queue().size(); - - if (boost::optional ret = downloading_piece_progress()) - { - p.downloading_piece_index = ret->piece_index; - p.downloading_block_index = ret->block_index; - p.downloading_progress = ret->bytes_downloaded; - p.downloading_total = ret->full_block_bytes; - } - else - { - p.downloading_piece_index = -1; - p.downloading_block_index = -1; - p.downloading_progress = 0; - p.downloading_total = 0; - } - - p.flags = 0; - if (is_interesting()) p.flags |= peer_info::interesting; - if (is_choked()) p.flags |= peer_info::choked; - if (is_peer_interested()) p.flags |= peer_info::remote_interested; - if (has_peer_choked()) p.flags |= peer_info::remote_choked; - if (is_local()) p.flags |= peer_info::local_connection; - if (!is_connecting() && m_server_string.empty()) - p.flags |= peer_info::handshake; - if (is_connecting() && !is_queued()) p.flags |= peer_info::connecting; - if (is_queued()) p.flags |= peer_info::queued; - - p.pieces = get_bitfield(); - p.seed = is_seed(); - - p.client = m_server_string; - p.connection_type = peer_info::web_seed; - p.source = 0; - p.failcount = 0; - } - - bool web_peer_connection::in_handshake() const - { - return m_server_string.empty(); - } - - // throws exception when the client should be disconnected - void web_peer_connection::on_sent(asio::error_code const& error - , std::size_t bytes_transferred) - { - INVARIANT_CHECK; - - if (error) return; - m_statistics.sent_bytes(0, bytes_transferred); - } - - -#ifndef NDEBUG - void web_peer_connection::check_invariant() const - { -/* - assert(m_num_pieces == std::count( - m_have_piece.begin() - , m_have_piece.end() - , true)); -*/ } -#endif - -} -