From 07bcb3545a343e0e049df9b87171c5df4c8ac585 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Fri, 12 Jun 2009 16:40:38 +0000 Subject: [PATCH] converted a whole lot of error strings into error_codes. Documented some previously undocumented alerts as well as all the error codes --- docs/manual.rst | 554 +++++++++++++++++++---- include/libtorrent/alert_types.hpp | 135 ++++-- include/libtorrent/aux_/session_impl.hpp | 7 +- include/libtorrent/error_code.hpp | 88 ++++ include/libtorrent/natpmp.hpp | 12 +- include/libtorrent/parse_url.hpp | 5 +- include/libtorrent/peer_connection.hpp | 2 +- include/libtorrent/torrent.hpp | 2 +- include/libtorrent/upnp.hpp | 44 +- src/bt_peer_connection.cpp | 119 +++-- src/error_code.cpp | 90 +++- src/http_connection.cpp | 25 +- src/http_seed_connection.cpp | 24 +- src/lt_trackers.cpp | 2 +- src/metadata_transfer.cpp | 16 +- src/natpmp.cpp | 41 +- src/parse_url.cpp | 17 +- src/peer_connection.cpp | 97 ++-- src/policy.cpp | 23 +- src/session_impl.cpp | 43 +- src/smart_ban.cpp | 6 +- src/torrent.cpp | 132 +++--- src/udp_tracker_connection.cpp | 10 +- src/upnp.cpp | 92 ++-- src/ut_metadata.cpp | 8 +- src/ut_pex.cpp | 4 +- src/web_peer_connection.cpp | 33 +- test/test_primitives.cpp | 26 +- 28 files changed, 1181 insertions(+), 476 deletions(-) diff --git a/docs/manual.rst b/docs/manual.rst index d984a2e3a..b8c137d08 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -4640,6 +4640,7 @@ the index returned from add_mapping_. ``type`` is 0 for NAT-PMP and 1 for UPnP. +``error`` tells you what failed. :: struct portmap_error_alert: alert @@ -4647,6 +4648,7 @@ the index returned from add_mapping_. // ... int mapping; int type; + error_code error; }; portmap_alert @@ -4906,6 +4908,21 @@ to the torrent which got the failed piece and the index of the piece itself from }; +peer_alert +---------- + +The peer alert is a base class for alerts that refer to a specific peer. It includes all +the information to identify the peer. i.e. ``ip`` and ``peer-id``. + +:: + + struct peer_alert: torrent_alert + { + // ... + tcp::endpoint ip; + peer_id pid; + }; + peer_ban_alert -------------- @@ -4914,10 +4931,37 @@ to us. ``ip`` is the endpoint to the peer that was banned. :: - struct peer_ban_alert: torrent_alert + struct peer_ban_alert: peer_alert + { + // ... + }; + + +peer_snubbed_alert +------------------ + +This alert is generated when a peer is snubbed, when it stops sending data when we request +it. + +:: + + struct peer_snubbed_alert: peer_alert + { + // ... + }; + + +peer_unsnubbed_alert +-------------------- + +This alert is generated when a peer is unsnubbed. Essentially when it was snubbed for stalling +sending data, and now it started sending data again. + +:: + + struct peer_unsnubbed_alert: peer_alert { // ... - asio::ip::tcp::endpoint ip; }; @@ -4927,13 +4971,44 @@ peer_error_alert This alert is generated when a peer sends invalid data over the peer-peer protocol. The peer will be disconnected, but you get its ip address from the alert, to identify it. +The ``error_code`` tells you what error caused this alert. + :: - struct peer_error_alert: torrent_alert + struct peer_error_alert: peer_alert { // ... - asio::ip::tcp::endpoint ip; - peer_id id; + error_code error; + }; + + +peer_connected_alert +-------------------- + +This alert is generated when a peer is connected. + +:: + + struct peer_connected_alert: peer_alert + { + // ... + }; + + +peer_disconnected_alert +----------------------- + +This alert is generated when a peer is disconnected for any reason (other than the ones +covered by ``peer_error_alert``). + +The ``error_code`` tells you what error caused peer to disconnect. + +:: + + struct peer_disconnected_alert: peer_alert + { + // ... + error_code error; }; @@ -4946,20 +5021,10 @@ request from the peer. :: - struct invalid_request_alert: torrent_alert + struct invalid_request_alert: peer_alert { - invalid_request_alert( - peer_request const& r - , torrent_handle const& h - , asio::ip::tcp::endpoint const& send - , peer_id const& pid - , std::string const& msg); - - virtual std::auto_ptr clone() const; - - asio::ip::tcp::endpoint ip; + // ... peer_request request; - peer_id id; }; @@ -4976,6 +5041,97 @@ The ``peer_request`` contains the values the client sent in its ``request`` mess the index of the piece it want data from, ``start`` is the offset within the piece where the data should be read, and ``length`` is the amount of data it wants. +request_dropped_alert +--------------------- + +This alert is generated when a peer rejects or ignores a piece request. + +:: + + struct request_dropped_alert: peer_alert + { + // ... + int block_index; + int piece_index; + }; + + +block_timeout_alert +------------------- + +This alert is generated when a block request times out. + +:: + + struct block_timeout_alert: peer_alert + { + // ... + int block_index; + int piece_index; + }; + + +block_finished_alert +-------------------- + +This alert is generated when a block request receives a response. + +:: + + struct block_finished_alert: peer_alert + { + // ... + int block_index; + int piece_index; + }; + + +block_downloading_alert +----------------------- + +This alert is generated when a block request is sent to a peer. + +:: + + struct block_downloading_alert: peer_alert + { + // ... + int block_index; + int piece_index; + }; + + +unwanted_block_alert +-------------------- + +This alert is generated when a block is received that was not requested or +whose request timed out. + +:: + + struct unwanted_block_alert: peer_alert + { + // ... + int block_index; + int piece_index; + }; + + +torrent_delete_failed_alert +--------------------------- + +This alert is generated when a request to delete the files of a torrent fails. + +The ``error_code`` tells you why it failed. + +:: + + struct torrent_delete_failed_alert: torrent_alert + { + // ... + error_code error; + }; + torrent_finished_alert ---------------------- @@ -5053,7 +5209,7 @@ fastresume_rejected_alert ------------------------- This alert is generated when a fastresume file has been passed to ``add_torrent`` but the -files on disk did not match the fastresume file. The string explains the reason why the +files on disk did not match the fastresume file. The ``error_code`` explains the reason why the resume file was rejected. :: @@ -5061,7 +5217,7 @@ resume file was rejected. struct fastresume_rejected_alert: torrent_alert { // ... - std::string msg; + error_code error; }; @@ -5148,14 +5304,14 @@ save_resume_data_failed_alert ----------------------------- This alert is generated instead of ``save_resume_data_alert`` if there was an error -generating the resume data. ``msg`` describes what went wrong. +generating the resume data. ``error`` describes what went wrong. :: struct save_resume_data_failed_alert: torrent_alert { // ... - std::string msg; + error_code error; }; dht_announce_alert @@ -5268,71 +5424,303 @@ libtorrent uses boost.system's ``error_code`` class to represent errors. libtorr its own error category (``libtorrent::libtorrent_category``) whith the following error codes: -====== ============================ ================================================================= -code symbol description -====== ============================ ================================================================= -0 no_error Not an error ------- ---------------------------- ----------------------------------------------------------------- -1 file_collision Two torrents has files which end up overwriting each other ------- ---------------------------- ----------------------------------------------------------------- -2 failed_hash_check A piece did not match its piece hash ------- ---------------------------- ----------------------------------------------------------------- -3 torrent_is_no_dict The .torrent file does not contain a bencoded dictionary at - its top level ------- ---------------------------- ----------------------------------------------------------------- -4 torrent_missing_info The .torrent file does not have an ``info`` dictionary ------- ---------------------------- ----------------------------------------------------------------- -5 torrent_info_no_dict The .torrent file's ``info`` entry is not a dictionary ------- ---------------------------- ----------------------------------------------------------------- -6 torrent_missing_piece_length The .torrent file does not have a ``piece length`` entry ------- ---------------------------- ----------------------------------------------------------------- -7 torrent_missing_name The .torrent file does not have a ``name`` entry ------- ---------------------------- ----------------------------------------------------------------- -8 torrent_invalid_name The .torrent file's name entry is invalid ------- ---------------------------- ----------------------------------------------------------------- -9 torrent_invalid_length The length of a file, or of the whole .torrent file is invalid. - Either negative or not an integer ------- ---------------------------- ----------------------------------------------------------------- -10 torrent_file_parse_failed Failed to parse a file entry in the .torrent ------- ---------------------------- ----------------------------------------------------------------- -11 torrent_missing_pieces The ``pieces`` field is missing or invalid in the .torrent file ------- ---------------------------- ----------------------------------------------------------------- -12 torrent_invalid_hashes The ``pieces`` string has incorrect length ------- ---------------------------- ----------------------------------------------------------------- -13 too_many_pieces_in_torrent The .torrent file has more pieces than is supported by libtorrent ------- ---------------------------- ----------------------------------------------------------------- -14 invalid_swarm_metadata The metadata (.torrent file) that was received from the swarm - matched the info-hash, but failed to be parsed ------- ---------------------------- ----------------------------------------------------------------- -15 invalid_bencoding The file or buffer is not correctly bencoded ------- ---------------------------- ----------------------------------------------------------------- -16 no_files_in_torrent The .torrent file does not contain any files ------- ---------------------------- ----------------------------------------------------------------- -17 invalid_escaped_string The string was not properly url-encoded as expected ------- ---------------------------- ----------------------------------------------------------------- -18 session_is_closing Operation is not permitted since the session is shutting down ------- ---------------------------- ----------------------------------------------------------------- -19 duplicate_torrent There's already a torrent with that info-hash added to the - session ------- ---------------------------- ----------------------------------------------------------------- -20 invalid_torrent_handle The supplied torrent_handle is not referring to a valid torrent ------- ---------------------------- ----------------------------------------------------------------- -21 invalid_entry_type The type requested from the entry did not match its type ------- ---------------------------- ----------------------------------------------------------------- -22 missing_info_hash_in_uri The specified URI does not contain a valid info-hash ------- ---------------------------- ----------------------------------------------------------------- -23 file_too_short One of the files in the torrent was unexpectadly small. This - might be caused by files being changed by an external process ------- ---------------------------- ----------------------------------------------------------------- -24 unsupported_url_protocol The URL used an unknown protocol. Currently ``http`` and - ``https`` (if built with openssl support) are recognized. For - trackers ``udp`` is recognized as well. ------- ---------------------------- ----------------------------------------------------------------- -25 url_parse_error The URL did not conform to URL syntax and failed to be parsed -====== ============================ ================================================================= +====== ========================================= ================================================================= +code symbol description +====== ========================================= ================================================================= +0 no_error Not an error +------ ----------------------------------------- ----------------------------------------------------------------- +1 file_collision Two torrents has files which end up overwriting each other +------ ----------------------------------------- ----------------------------------------------------------------- +2 failed_hash_check A piece did not match its piece hash +------ ----------------------------------------- ----------------------------------------------------------------- +3 torrent_is_no_dict The .torrent file does not contain a bencoded dictionary at + its top level +------ ----------------------------------------- ----------------------------------------------------------------- +4 torrent_missing_info The .torrent file does not have an ``info`` dictionary +------ ----------------------------------------- ----------------------------------------------------------------- +5 torrent_info_no_dict The .torrent file's ``info`` entry is not a dictionary +------ ----------------------------------------- ----------------------------------------------------------------- +6 torrent_missing_piece_length The .torrent file does not have a ``piece length`` entry +------ ----------------------------------------- ----------------------------------------------------------------- +7 torrent_missing_name The .torrent file does not have a ``name`` entry +------ ----------------------------------------- ----------------------------------------------------------------- +8 torrent_invalid_name The .torrent file's name entry is invalid +------ ----------------------------------------- ----------------------------------------------------------------- +9 torrent_invalid_length The length of a file, or of the whole .torrent file is invalid. + Either negative or not an integer +------ ----------------------------------------- ----------------------------------------------------------------- +10 torrent_file_parse_failed Failed to parse a file entry in the .torrent +------ ----------------------------------------- ----------------------------------------------------------------- +11 torrent_missing_pieces The ``pieces`` field is missing or invalid in the .torrent file +------ ----------------------------------------- ----------------------------------------------------------------- +12 torrent_invalid_hashes The ``pieces`` string has incorrect length +------ ----------------------------------------- ----------------------------------------------------------------- +13 too_many_pieces_in_torrent The .torrent file has more pieces than is supported by libtorrent +------ ----------------------------------------- ----------------------------------------------------------------- +14 invalid_swarm_metadata The metadata (.torrent file) that was received from the swarm + matched the info-hash, but failed to be parsed +------ ----------------------------------------- ----------------------------------------------------------------- +15 invalid_bencoding The file or buffer is not correctly bencoded +------ ----------------------------------------- ----------------------------------------------------------------- +16 no_files_in_torrent The .torrent file does not contain any files +------ ----------------------------------------- ----------------------------------------------------------------- +17 invalid_escaped_string The string was not properly url-encoded as expected +------ ----------------------------------------- ----------------------------------------------------------------- +18 session_is_closing Operation is not permitted since the session is shutting down +------ ----------------------------------------- ----------------------------------------------------------------- +19 duplicate_torrent There's already a torrent with that info-hash added to the + session +------ ----------------------------------------- ----------------------------------------------------------------- +20 invalid_torrent_handle The supplied torrent_handle is not referring to a valid torrent +------ ----------------------------------------- ----------------------------------------------------------------- +21 invalid_entry_type The type requested from the entry did not match its type +------ ----------------------------------------- ----------------------------------------------------------------- +22 missing_info_hash_in_uri The specified URI does not contain a valid info-hash +------ ----------------------------------------- ----------------------------------------------------------------- +23 file_too_short One of the files in the torrent was unexpectadly small. This + might be caused by files being changed by an external process +------ ----------------------------------------- ----------------------------------------------------------------- +24 unsupported_url_protocol The URL used an unknown protocol. Currently ``http`` and + ``https`` (if built with openssl support) are recognized. For + trackers ``udp`` is recognized as well. +------ ----------------------------------------- ----------------------------------------------------------------- +25 url_parse_error The URL did not conform to URL syntax and failed to be parsed +------ ----------------------------------------- ----------------------------------------------------------------- +26 peer_sent_empty_piece The peer sent a 'piece' message of length 0 +------ ----------------------------------------- ----------------------------------------------------------------- +27 parse_failed A bencoded structure was currupt and failed to be parsed +------ ----------------------------------------- ----------------------------------------------------------------- +28 invalid_file_tag The fast resume file was missing or had an invalid file version + tag +------ ----------------------------------------- ----------------------------------------------------------------- +29 missing_info_hash The fast resume file was missing or had an invalid info-hash +------ ----------------------------------------- ----------------------------------------------------------------- +30 mismatching_info_hash The info-hash in the resume file did not match the torrent +------ ----------------------------------------- ----------------------------------------------------------------- +31 invalid_hostname The URL contained an invalid hostname +------ ----------------------------------------- ----------------------------------------------------------------- +32 invalid_port The URL had an invalid port +------ ----------------------------------------- ----------------------------------------------------------------- +33 port_blocked The port is blocked by the port-filter, and prevented the + connection +------ ----------------------------------------- ----------------------------------------------------------------- +34 expected_close_bracket_in_address The IPv6 address was expected to end with ']' +------ ----------------------------------------- ----------------------------------------------------------------- +35 destructing_torrent The torrent is being destructed, preventing the operation to + succeed +------ ----------------------------------------- ----------------------------------------------------------------- +36 timed_out The connection timed out +------ ----------------------------------------- ----------------------------------------------------------------- +37 upload_upload_connection The peer is upload only, and we are upload only. There's no point + in keeping the connection +------ ----------------------------------------- ----------------------------------------------------------------- +38 uninteresting_upload_peer The peer is upload only, and we're not interested in it. There's + no point in keeping the connection +------ ----------------------------------------- ----------------------------------------------------------------- +39 invalid_info_hash The peer sent an unknown info-hash +------ ----------------------------------------- ----------------------------------------------------------------- +40 torrent_paused The torrent is paused, preventing the operation from succeeding +------ ----------------------------------------- ----------------------------------------------------------------- +41 invalid_have The peer sent an invalid have message, either wrong size or + referring to a piece that doesn't exist in the torrent +------ ----------------------------------------- ----------------------------------------------------------------- +42 invalid_bitfield_size The bitfield message had the incorrect size +------ ----------------------------------------- ----------------------------------------------------------------- +43 too_many_requests_when_choked The peer kept requesting pieces after it was choked, possible + abuse attempt. +------ ----------------------------------------- ----------------------------------------------------------------- +44 invalid_piece The peer sent a piece message that does not correspond to a + piece request sent by the client +------ ----------------------------------------- ----------------------------------------------------------------- +45 no_memory memory allocation failed +------ ----------------------------------------- ----------------------------------------------------------------- +46 torrent_aborted The torrent is aborted, preventing the operation to succeed +------ ----------------------------------------- ----------------------------------------------------------------- +47 self_connection The peer is a connection to ourself, no point in keeping it +------ ----------------------------------------- ----------------------------------------------------------------- +48 invalid_piece_size The peer sent a piece message with invalid size, either negative + or greater than one block +------ ----------------------------------------- ----------------------------------------------------------------- +49 timed_out_no_interest The peer has not been interesting or interested in us for too + long, no point in keeping it around +------ ----------------------------------------- ----------------------------------------------------------------- +50 timed_out_inactivity The peer has not said anything in a long time, possibly dead +------ ----------------------------------------- ----------------------------------------------------------------- +51 timed_out_no_handshake The peer did not send a handshake within a reasonable amount of + time, it might not be a bittorrent peer +------ ----------------------------------------- ----------------------------------------------------------------- +52 timed_out_no_request The peer has been unchoked for too long without requesting any + data. It might be lying about its interest in us +------ ----------------------------------------- ----------------------------------------------------------------- +53 invalid_choke The peer sent an invalid choke message +------ ----------------------------------------- ----------------------------------------------------------------- +54 invalid_unchoke The peer send an invalid unchoke message +------ ----------------------------------------- ----------------------------------------------------------------- +55 invalid_interested The peer sent an invalid interested message +------ ----------------------------------------- ----------------------------------------------------------------- +56 invalid_not_interested The peer sent an invalid not-interested message +------ ----------------------------------------- ----------------------------------------------------------------- +57 invalid_request The peer sent an invalid piece request message +------ ----------------------------------------- ----------------------------------------------------------------- +58 invalid_hash_list The peer sent an invalid hash-list message (this is part of the + merkle-torrent extension) +------ ----------------------------------------- ----------------------------------------------------------------- +59 invalid_hash_piece The peer sent an invalid hash-piece message (this is part of the + merkle-torrent extension) +------ ----------------------------------------- ----------------------------------------------------------------- +60 invalid_cancel The peer sent an invalid cancel message +------ ----------------------------------------- ----------------------------------------------------------------- +61 invalid_dht_port The peer sent an invalid DHT port-message +------ ----------------------------------------- ----------------------------------------------------------------- +62 invalid_suggest The peer sent an invalid suggest piece-message +------ ----------------------------------------- ----------------------------------------------------------------- +63 invalid_have_all The peer sent an invalid have all-message +------ ----------------------------------------- ----------------------------------------------------------------- +64 invalid_have_none The peer sent an invalid have none-message +------ ----------------------------------------- ----------------------------------------------------------------- +65 invalid_reject The peer sent an invalid reject message +------ ----------------------------------------- ----------------------------------------------------------------- +66 invalid_allow_fast The peer sent an invalid allow fast-message +------ ----------------------------------------- ----------------------------------------------------------------- +67 invalid_extended The peer sent an invalid extesion message ID +------ ----------------------------------------- ----------------------------------------------------------------- +68 invalid_message The peer sent an invalid message ID +------ ----------------------------------------- ----------------------------------------------------------------- +69 sync_hash_not_found The synchronization hash was not found in the encrypted handshake +------ ----------------------------------------- ----------------------------------------------------------------- +70 invalid_encryption_constant The encryption constant in the handshake is invalid +------ ----------------------------------------- ----------------------------------------------------------------- +71 no_plaintext_mode The peer does not support plaintext, which is the selected mode +------ ----------------------------------------- ----------------------------------------------------------------- +72 no_rc4_mode The peer does not support rc4, which is the selected mode +------ ----------------------------------------- ----------------------------------------------------------------- +73 unsupported_encryption_mode The peer does not support any of the encryption modes that the + client supports +------ ----------------------------------------- ----------------------------------------------------------------- +74 unsupported_encryption_mode_selected The peer selected an encryption mode that the client did not + advertise and does not support +------ ----------------------------------------- ----------------------------------------------------------------- +75 invalid_pad_size The pad size used in the encryption handshake is of invalid size +------ ----------------------------------------- ----------------------------------------------------------------- +76 invalid_encrypt_handshake The encryption handshake is invalid +------ ----------------------------------------- ----------------------------------------------------------------- +77 no_incoming_encrypted The client is set to not support incoming encrypted connections + and this is an encrypted connection +------ ----------------------------------------- ----------------------------------------------------------------- +78 no_incoming_regular The client is set to not support incoming regular bittorrent + connections, and this is a regular connection +------ ----------------------------------------- ----------------------------------------------------------------- +79 duplicate_peer_id The client is already connected to this peer-ID +------ ----------------------------------------- ----------------------------------------------------------------- +80 torrent_removed Torrent was removed +------ ----------------------------------------- ----------------------------------------------------------------- +81 packet_too_large The packet size exceeded the upper sanity check-limit +------ ----------------------------------------- ----------------------------------------------------------------- +82 http_parse_error Failed to parse HTTP response +------ ----------------------------------------- ----------------------------------------------------------------- +83 http_error The web server responded with an error +------ ----------------------------------------- ----------------------------------------------------------------- +84 missing_location The web server response is missing a location header +------ ----------------------------------------- ----------------------------------------------------------------- +85 invalid_redirection The web seed redirected to a path that no longer matches the + .torrent directory structure +------ ----------------------------------------- ----------------------------------------------------------------- +86 redirecting The connection was closed becaused it redirected to a different + URL +------ ----------------------------------------- ----------------------------------------------------------------- +87 invalid_range The HTTP range header is invalid +------ ----------------------------------------- ----------------------------------------------------------------- +88 no_content_length The HTTP response did not have a content length +------ ----------------------------------------- ----------------------------------------------------------------- +89 banned_by_ip_filter The IP is blocked by the IP filter +------ ----------------------------------------- ----------------------------------------------------------------- +90 too_many_connections At the connection limit +------ ----------------------------------------- ----------------------------------------------------------------- +91 peer_banned The peer is marked as banned +------ ----------------------------------------- ----------------------------------------------------------------- +92 stopping_torrent The torrent is stopping, causing the operation to fail +------ ----------------------------------------- ----------------------------------------------------------------- +93 too_many_corrupt_pieces The peer has sent too many corrupt pieces and is banned +------ ----------------------------------------- ----------------------------------------------------------------- +94 torrent_not_ready The torrent is not ready to receive peers +------ ----------------------------------------- ----------------------------------------------------------------- +95 peer_not_constructed The peer is not completely constructed yet +------ ----------------------------------------- ----------------------------------------------------------------- +96 session_closing The session is closing, causing the operation to fail +------ ----------------------------------------- ----------------------------------------------------------------- +97 optimistic_disconnect The peer was disconnected in order to leave room for a + potentially better peer +------ ----------------------------------------- ----------------------------------------------------------------- +98 torrent_finished The torrent is finished +------ ----------------------------------------- ----------------------------------------------------------------- +99 no_router No UPnP router found +------ ----------------------------------------- ----------------------------------------------------------------- +100 metadata_too_large The metadata message says the metadata exceeds the limit +------ ----------------------------------------- ----------------------------------------------------------------- +101 invalid_metadata_request The peer sent an invalid metadata request message +------ ----------------------------------------- ----------------------------------------------------------------- +102 invalid_metadata_size The peer advertised an invalid metadata size +------ ----------------------------------------- ----------------------------------------------------------------- +103 invalid_metadata_offset The peer sent a message with an invalid metadata offset +------ ----------------------------------------- ----------------------------------------------------------------- +104 invalid_metadata_message The peer sent an invalid metadata message +------ ----------------------------------------- ----------------------------------------------------------------- +105 pex_message_too_large The peer sent a peer exchange message that was too large +------ ----------------------------------------- ----------------------------------------------------------------- +106 invalid_pex_message The peer sent an invalid peer exchange message +------ ----------------------------------------- ----------------------------------------------------------------- +107 invalid_lt_tracker_message The peer sent an invalid tracker exchange message +------ ----------------------------------------- ----------------------------------------------------------------- +108 unsupported_protocol_version The NAT-PMP router responded with an unsupported protocol version +------ ----------------------------------------- ----------------------------------------------------------------- +109 natpmp_not_authorized You are not authorized to map ports on this NAT-PMP router +------ ----------------------------------------- ----------------------------------------------------------------- +110 network_failure The NAT-PMP router failed because of a network failure +------ ----------------------------------------- ----------------------------------------------------------------- +111 no_resources The NAT-PMP router failed because of lack of resources +------ ----------------------------------------- ----------------------------------------------------------------- +112 unsupported_opcode The NAT-PMP router failed because an unsupported opcode was sent +====== ========================================= ================================================================= The names of these error codes are declared in then ``libtorrent::errors`` namespace. +There is also another error category, ``libtorrent::upnp_category``, defining errors +retrned by UPnP routers. Here's a (possibly incomplete) list of UPnP error codes: + +====== ========================================= ==================================================== +code symbol description +====== ========================================= ==================================================== +0 no_error No error +------ ----------------------------------------- ---------------------------------------------------- +402 invalid_argument One of the arguments in the request is invalid +------ ----------------------------------------- ---------------------------------------------------- +501 action_failed The request failed +------ ----------------------------------------- ---------------------------------------------------- +714 value_not_in_array The specified value does not exist in the array +------ ----------------------------------------- ---------------------------------------------------- +715 source_ip_cannot_be_wildcarded The source IP address cannot be wild-carded, but + must be fully specified +------ ----------------------------------------- ---------------------------------------------------- +716 external_port_cannot_be_wildcarded The external port cannot be wildcarded, but must + be specified +------ ----------------------------------------- ---------------------------------------------------- +718 port_mapping_conflict The port mapping entry specified conflicts with a + mapping assigned previously to another client +------ ----------------------------------------- ---------------------------------------------------- +724 internal_port_must_match_external Internal and external port value must be the same +------ ----------------------------------------- ---------------------------------------------------- +725 only_permanent_leases_supported The NAT implementation only supports permanent + lease times on port mappings +------ ----------------------------------------- ---------------------------------------------------- +726 remote_host_must_be_wildcard RemoteHost must be a wildcard and cannot be a + specific IP addres or DNS name +------ ----------------------------------------- ---------------------------------------------------- +727 external_port_must_be_wildcard ExternalPort must be a wildcard and cannot be a + specific port +====== ========================================= ==================================================== + +The UPnP errors are declared in the ``libtorrent::upnp_errors`` namespace. + translating error codes ----------------------- diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 447429ae8..8fbdf6fee 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -256,6 +256,19 @@ namespace libtorrent struct TORRENT_EXPORT tracker_error_alert: tracker_alert { + tracker_error_alert(torrent_handle const& h + , int times + , int status + , std::string const& url_ + , error_code const& e) + : tracker_alert(h, url_) + , times_in_row(times) + , status_code(status) + , msg(e.message()) + { + TORRENT_ASSERT(!url.empty()); + } + tracker_error_alert(torrent_handle const& h , int times , int status @@ -265,7 +278,9 @@ namespace libtorrent , times_in_row(times) , status_code(status) , msg(msg_) - { TORRENT_ASSERT(!url.empty()); } + { + TORRENT_ASSERT(!url.empty()); + } virtual std::auto_ptr clone() const { return std::auto_ptr(new tracker_error_alert(*this)); } @@ -276,7 +291,8 @@ namespace libtorrent { char ret[400]; snprintf(ret, sizeof(ret), "%s (%d) %s (%d)" - , torrent_alert::message().c_str(), status_code, msg.c_str(), times_in_row); + , torrent_alert::message().c_str(), status_code + , msg.c_str(), times_in_row); return ret; } @@ -335,6 +351,13 @@ namespace libtorrent struct TORRENT_EXPORT scrape_failed_alert: tracker_alert { + scrape_failed_alert(torrent_handle const& h + , std::string const& url_ + , error_code const& e) + : tracker_alert(h, url_) + , msg(e.message()) + { TORRENT_ASSERT(!url.empty()); } + scrape_failed_alert(torrent_handle const& h , std::string const& url_ , std::string const& msg_) @@ -497,10 +520,14 @@ namespace libtorrent struct TORRENT_EXPORT peer_error_alert: peer_alert { peer_error_alert(torrent_handle const& h, tcp::endpoint const& ip - , peer_id const& pid, std::string const& msg_) + , peer_id const& pid, error_code const& e) : peer_alert(h, ip, pid) - , msg(msg_) - {} + , error(e) + { +#ifndef TORRENT_NO_DEPRECATE + msg = error.message(); +#endif + } virtual std::auto_ptr clone() const { return std::auto_ptr(new peer_error_alert(*this)); } @@ -510,10 +537,14 @@ namespace libtorrent virtual std::string message() const { error_code ec; - return peer_alert::message() + " peer error: " + msg; + return peer_alert::message() + " peer error: " + error.message(); } + error_code error; + +#ifndef TORRENT_NO_DEPRECATE std::string msg; +#endif }; struct TORRENT_EXPORT peer_connect_alert: peer_alert @@ -537,10 +568,14 @@ namespace libtorrent struct TORRENT_EXPORT peer_disconnected_alert: peer_alert { peer_disconnected_alert(torrent_handle const& h, tcp::endpoint const& ip - , peer_id const& pid, std::string const& msg_) + , peer_id const& pid, error_code const& e) : peer_alert(h, ip, pid) - , msg(msg_) - {} + , error(e) + { +#ifndef TORRENT_NO_DEPRECATE + msg = error.message(); +#endif + } virtual std::auto_ptr clone() const { return std::auto_ptr(new peer_disconnected_alert(*this)); } @@ -549,10 +584,14 @@ namespace libtorrent virtual int category() const { return static_category; } virtual std::string message() const { - return peer_alert::message() + " disconnecting: " + msg; + return peer_alert::message() + " disconnecting: " + error.message(); } + error_code error; + +#ifndef TORRENT_NO_DEPRECATE std::string msg; +#endif }; struct TORRENT_EXPORT invalid_request_alert: peer_alert @@ -813,12 +852,20 @@ namespace libtorrent struct TORRENT_EXPORT torrent_delete_failed_alert: torrent_alert { - torrent_delete_failed_alert(torrent_handle const& h, std::string msg_) + torrent_delete_failed_alert(torrent_handle const& h, error_code const& e) : torrent_alert(h) - , msg(msg_) - {} + , error(e) + { +#ifndef TORRENT_NO_DEPRECATE + msg = error.message(); +#endif + } + error_code error; + +#ifndef TORRENT_NO_DEPRECATE std::string msg; +#endif virtual std::auto_ptr clone() const { return std::auto_ptr(new torrent_delete_failed_alert(*this)); } @@ -829,7 +876,7 @@ namespace libtorrent virtual std::string message() const { return torrent_alert::message() + " torrent deletion failed: " - + msg; + + error.message(); } }; @@ -857,12 +904,20 @@ namespace libtorrent struct TORRENT_EXPORT save_resume_data_failed_alert: torrent_alert { save_resume_data_failed_alert(torrent_handle const& h - , std::string const& msg_) + , error_code const& e) : torrent_alert(h) - , msg(msg_) - {} + , error(e) + { +#ifndef TORRENT_NO_DEPRECATE + msg = error.message(); +#endif + } + error_code error; + +#ifndef TORRENT_NO_DEPRECATE std::string msg; +#endif virtual std::auto_ptr clone() const { return std::auto_ptr(new save_resume_data_failed_alert(*this)); } @@ -873,7 +928,7 @@ namespace libtorrent virtual std::string message() const { return torrent_alert::message() + " resume data was not generated: " - + msg; + + error.message(); } }; @@ -932,8 +987,17 @@ namespace libtorrent { url_seed_alert( torrent_handle const& h - , const std::string& url_ - , const std::string& msg_) + , std::string const& url_ + , error_code const& e) + : torrent_alert(h) + , url(url_) + , msg(e.message()) + {} + + url_seed_alert( + torrent_handle const& h + , std::string const& url_ + , std::string const& msg_) : torrent_alert(h) , url(url_) , msg(msg_) @@ -1118,13 +1182,20 @@ namespace libtorrent struct TORRENT_EXPORT portmap_error_alert: alert { - portmap_error_alert(int i, int t, const std::string& msg_) - : mapping(i), type(t), msg(msg_) - {} + portmap_error_alert(int i, int t, error_code const& e) + : mapping(i), type(t), error(e) + { +#ifndef TORRENT_NO_DEPRECATE + msg = error.message(); +#endif + } int mapping; int type; + error_code error; +#ifndef TORRENT_NO_DEPRECATE std::string msg; +#endif virtual std::auto_ptr clone() const { return std::auto_ptr(new portmap_error_alert(*this)); } @@ -1136,7 +1207,7 @@ namespace libtorrent { static char const* type_str[] = {"NAT-PMP", "UPnP"}; return std::string("could not map port using ") + type_str[type] - + ": " + msg; + + ": " + error.message(); } }; @@ -1191,12 +1262,20 @@ namespace libtorrent struct TORRENT_EXPORT fastresume_rejected_alert: torrent_alert { fastresume_rejected_alert(torrent_handle const& h - , std::string const& msg_) + , error_code const& e) : torrent_alert(h) - , msg(msg_) - {} + , error(e) + { +#ifndef TORRENT_NO_DEPRECATE + msg = error.message(); +#endif + } + error_code error; + +#ifndef TORRENT_NO_DEPRECATE std::string msg; +#endif virtual std::auto_ptr clone() const { return std::auto_ptr(new fastresume_rejected_alert(*this)); } @@ -1206,7 +1285,7 @@ namespace libtorrent virtual int category() const { return static_category; } virtual std::string message() const { - return torrent_alert::message() + " fast resume rejected: " + msg; + return torrent_alert::message() + " fast resume rejected: " + error.message(); } }; diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index f23f21aad..b9cfda8f8 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -167,8 +167,7 @@ namespace libtorrent boost::weak_ptr find_torrent(const sha1_hash& info_hash); peer_id const& get_peer_id() const { return m_peer_id; } - void close_connection(peer_connection const* p - , char const* message); + void close_connection(peer_connection const* p, error_code const& ec); void set_settings(session_settings const& s); session_settings const& settings() const { return m_settings; } @@ -191,9 +190,11 @@ namespace libtorrent pe_settings const& get_pe_settings() const { return m_pe_settings; } #endif + void on_port_map_log(char const* msg, int map_transport); + // called when a port mapping is successful, or a router returns // a failure to map a port - void on_port_mapping(int mapping, int port, std::string const& errmsg + void on_port_mapping(int mapping, int port, error_code const& ec , int nat_transport); bool is_aborted() const { return m_abort; } diff --git a/include/libtorrent/error_code.hpp b/include/libtorrent/error_code.hpp index 53a17738b..c52abe5ee 100644 --- a/include/libtorrent/error_code.hpp +++ b/include/libtorrent/error_code.hpp @@ -77,6 +77,94 @@ namespace libtorrent file_too_short, unsupported_url_protocol, url_parse_error, + peer_sent_empty_piece, + parse_failed, + invalid_file_tag, + missing_info_hash, + mismatching_info_hash, + invalid_hostname, + invalid_port, + port_blocked, + expected_close_bracket_in_address, + destructing_torrent, + timed_out, + upload_upload_connection, + uninteresting_upload_peer, + invalid_info_hash, + torrent_paused, + invalid_have, + invalid_bitfield_size, + too_many_requests_when_choked, + invalid_piece, + no_memory, + torrent_aborted, + self_connection, + invalid_piece_size, + timed_out_no_interest, + timed_out_inactivity, + timed_out_no_handshake, + timed_out_no_request, + invalid_choke, + invalid_unchoke, + invalid_interested, + invalid_not_interested, + invalid_request, + invalid_hash_list, + invalid_hash_piece, + invalid_cancel, + invalid_dht_port, + invalid_suggest, + invalid_have_all, + invalid_have_none, + invalid_reject, + invalid_allow_fast, + invalid_extended, + invalid_message, + sync_hash_not_found, + invalid_encryption_constant, + no_plaintext_mode, + no_rc4_mode, + unsupported_encryption_mode, + unsupported_encryption_mode_selected, + invalid_pad_size, + invalid_encrypt_handshake, + no_incoming_encrypted, + no_incoming_regular, + duplicate_peer_id, + torrent_removed, + packet_too_large, + http_parse_error, + http_error, + missing_location, + invalid_redirection, + redirecting, + invalid_range, + no_content_length, + banned_by_ip_filter, + too_many_connections, + peer_banned, + stopping_torrent, + too_many_corrupt_pieces, + torrent_not_ready, + peer_not_constructed, + session_closing, + optimistic_disconnect, + torrent_finished, + no_router, + metadata_too_large, + invalid_metadata_request, + invalid_metadata_size, + invalid_metadata_offset, + invalid_metadata_message, + pex_message_too_large, + invalid_pex_message, + invalid_lt_tracker_message, + + unsupported_protocol_version, + natpmp_not_authorized, + network_failure, + no_resources, + unsupported_opcode, }; } diff --git a/include/libtorrent/natpmp.hpp b/include/libtorrent/natpmp.hpp index aa9d0b275..2ad31b5cd 100644 --- a/include/libtorrent/natpmp.hpp +++ b/include/libtorrent/natpmp.hpp @@ -45,12 +45,15 @@ namespace libtorrent // int: port mapping index // int: external port // std::string: error message -typedef boost::function portmap_callback_t; +typedef boost::function portmap_callback_t; +typedef boost::function log_callback_t; class TORRENT_EXPORT natpmp : public intrusive_ptr_base { public: - natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb); + natpmp(io_service& ios, address const& listen_interface + , portmap_callback_t const& cb + , log_callback_t const& lcb); void rebind(address const& listen_interface); @@ -74,8 +77,8 @@ private: void update_expiration_timer(); void mapping_expired(error_code const& e, int i); - void log(std::string const& msg); - void disable(char const* message); + void log(char const* msg); + void disable(error_code const& ec); struct mapping_t { @@ -111,6 +114,7 @@ private: }; portmap_callback_t m_callback; + log_callback_t m_log_callback; std::vector m_mappings; diff --git a/include/libtorrent/parse_url.hpp b/include/libtorrent/parse_url.hpp index 18a6ddf90..8b2698069 100644 --- a/include/libtorrent/parse_url.hpp +++ b/include/libtorrent/parse_url.hpp @@ -45,13 +45,14 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "libtorrent/config.hpp" +#include "libtorrent/error_code.hpp" namespace libtorrent { TORRENT_EXPORT boost::tuple - parse_url_components(std::string url); + , std::string, int, std::string> + parse_url_components(std::string url, error_code& ec); } diff --git a/include/libtorrent/peer_connection.hpp b/include/libtorrent/peer_connection.hpp index 929a51ee7..f0dcd4efc 100644 --- a/include/libtorrent/peer_connection.hpp +++ b/include/libtorrent/peer_connection.hpp @@ -309,7 +309,7 @@ namespace libtorrent void on_timeout(); // this will cause this peer_connection to be disconnected. - void disconnect(char const* message, int error = 0); + void disconnect(error_code const& ec, int error = 0); bool is_disconnecting() const { return m_disconnecting; } // this is called when the connection attempt has succeeded diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index ef1fc2dd2..e3356ba10 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -496,7 +496,7 @@ namespace libtorrent int block_size() const { TORRENT_ASSERT(m_block_size > 0); return m_block_size; } peer_request to_req(piece_block const& p); - void disconnect_all(); + void disconnect_all(error_code const& ec); int disconnect_peers(int num); // this is called wheh the torrent has completed diff --git a/include/libtorrent/upnp.hpp b/include/libtorrent/upnp.hpp index a7b80de89..fc869defc 100644 --- a/include/libtorrent/upnp.hpp +++ b/include/libtorrent/upnp.hpp @@ -54,20 +54,55 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { + namespace upnp_errors + { + enum error_code_enum + { + no_error = 0, + invalid_argument = 402, + action_failed = 501, + value_not_in_array = 714, + source_ip_cannot_be_wildcarded = 715, + external_port_cannot_be_wildcarded = 716, + port_mapping_conflict = 718, + internal_port_must_match_external = 724, + only_permanent_leases_supported = 725, + remote_host_must_be_wildcard = 726, + external_port_must_be_wildcard = 727, + }; + } + +#if BOOST_VERSION < 103500 + extern asio::error::error_category upnp_category; +#else + + struct TORRENT_EXPORT upnp_error_category : boost::system::error_category + { + virtual const char* name() const; + virtual std::string message(int ev) const; + virtual boost::system::error_condition default_error_condition(int ev) const + { return boost::system::error_condition(ev, *this); } + }; + + extern TORRENT_EXPORT upnp_error_category upnp_category; +#endif + // int: port-mapping index // int: external port // std::string: error message // an empty string as error means success // a port-mapping index of -1 means it's // an informational log message -typedef boost::function portmap_callback_t; +typedef boost::function portmap_callback_t; +typedef boost::function log_callback_t; class TORRENT_EXPORT upnp : public intrusive_ptr_base { public: upnp(io_service& ios, connection_queue& cc , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb, bool ignore_nonrouters, void* state = 0); + , portmap_callback_t const& cb, log_callback_t const& lcb + , bool ignore_nonrouters, void* state = 0); ~upnp(); void* drain_state(); @@ -114,9 +149,9 @@ private: , int mapping, http_connection& c); void on_expire(error_code const& e); - void disable(char const* msg); + void disable(error_code const& ec); void return_error(int mapping, int code); - void log(std::string const&); + void log(char const* msg); void delete_port_mapping(rootdevice& d, int i); void create_port_mapping(http_connection& c, rootdevice& d, int i); @@ -245,6 +280,7 @@ private: std::set m_devices; portmap_callback_t m_callback; + log_callback_t m_log_callback; // current retry count int m_retry_count; diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index 7e3d2502d..d2b562687 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -390,7 +390,7 @@ namespace libtorrent m_dh_key_exchange.reset(new (std::nothrow) dh_key_exchange); if (!m_dh_key_exchange || !m_dh_key_exchange->good()) { - disconnect("out of memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return; } @@ -403,7 +403,7 @@ namespace libtorrent buffer::interval send_buf = allocate_send_buffer(dh_key_len + pad_size); if (send_buf.begin == 0) { - disconnect("out of memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return; } @@ -621,7 +621,7 @@ namespace libtorrent m_RC4_handler.reset(new (std::nothrow) RC4_handler(local_key, remote_key)); if (!m_RC4_handler) { - disconnect("no memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return; } @@ -884,7 +884,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (packet_size() != 1) { - disconnect("'choke' message size != 1", 2); + disconnect(error_code(errors::invalid_choke, libtorrent_category), 2); return; } if (!packet_finished()) return; @@ -919,7 +919,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (packet_size() != 1) { - disconnect("'unchoke' message size != 1", 2); + disconnect(error_code(errors::invalid_unchoke, libtorrent_category), 2); return; } if (!packet_finished()) return; @@ -939,7 +939,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (packet_size() != 1) { - disconnect("'interested' message size != 1", 2); + disconnect(error_code(errors::invalid_interested, libtorrent_category), 2); return; } if (!packet_finished()) return; @@ -959,7 +959,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (packet_size() != 1) { - disconnect("'not interested' message size != 1", 2); + disconnect(error_code(errors::invalid_not_interested, libtorrent_category), 2); return; } if (!packet_finished()) return; @@ -979,7 +979,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (packet_size() != 5) { - disconnect("'have' message size != 5", 2); + disconnect(error_code(errors::invalid_have, libtorrent_category), 2); return; } if (!packet_finished()) return; @@ -1011,10 +1011,7 @@ namespace libtorrent if (t->valid_metadata() && packet_size() - 1 != (t->torrent_file().num_pieces() + 7) / 8) { - char msg[200]; - snprintf(msg, 200, "got bitfield with invalid size: %d bytes. expected: %d bytes" - , int(packet_size()-1), int((t->torrent_file().num_pieces() + 7) / 8)); - disconnect(msg, 2); + disconnect(error_code(errors::invalid_bitfield_size, libtorrent_category), 2); return; } @@ -1041,7 +1038,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (packet_size() != 13) { - disconnect("'request' message size != 13", 2); + disconnect(error_code(errors::invalid_request, libtorrent_category), 2); return; } if (!packet_finished()) return; @@ -1096,7 +1093,7 @@ namespace libtorrent if (list_size > packet_size() - 13) { - disconnect("invalid hash list in hash piece message"); + disconnect(error_code(errors::invalid_hash_list, libtorrent_category), 2); return; } @@ -1194,7 +1191,7 @@ namespace libtorrent lazy_entry hash_list; if (lazy_bdecode(recv_buffer.begin + 13, recv_buffer.end + 13 + list_size, hash_list) != 0) { - disconnect("invalid bencoding in hashpiece message"); + disconnect(error_code(errors::invalid_hash_piece, libtorrent_category), 2); return; } @@ -1202,7 +1199,7 @@ namespace libtorrent // [ [node-index, hash], [node-index, hash], ... ] if (hash_list.type() != lazy_entry::list_t) { - disconnect("invalid hash-list in hashpiece message"); + disconnect(error_code(errors::invalid_hash_list, libtorrent_category), 2); return; } @@ -1228,7 +1225,7 @@ namespace libtorrent #endif if (!nodes.empty() && !t->add_merkle_nodes(nodes, p.piece)) { - disconnect("invalid hashes in hashpiece message"); + disconnect(error_code(errors::invalid_hash_piece, libtorrent_category), 2); return; } } @@ -1249,7 +1246,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (packet_size() != 13) { - disconnect("'cancel' message size != 13", 2); + disconnect(error_code(errors::invalid_cancel, libtorrent_category), 2); return; } if (!packet_finished()) return; @@ -1277,12 +1274,12 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (!m_supports_dht_port) { - disconnect("got 'dht_port' message from peer that doesn't support it", 2); + disconnect(error_code(errors::invalid_dht_port, libtorrent_category), 2); return; } if (packet_size() != 3) { - disconnect("'dht_port' message size != 3", 2); + disconnect(error_code(errors::invalid_dht_port, libtorrent_category), 2); return; } if (!packet_finished()) return; @@ -1302,7 +1299,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (!m_supports_fast) { - disconnect("got 'suggest_piece' without FAST excension support", 2); + disconnect(error_code(errors::invalid_suggest, libtorrent_category), 2); return; } @@ -1322,7 +1319,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (!m_supports_fast) { - disconnect("got 'have_all' without FAST extension support", 2); + disconnect(error_code(errors::invalid_have_all, libtorrent_category), 2); return; } incoming_have_all(); @@ -1335,7 +1332,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (!m_supports_fast) { - disconnect("got 'have_none' without FAST extension support", 2); + disconnect(error_code(errors::invalid_have_none, libtorrent_category), 2); return; } incoming_have_none(); @@ -1348,7 +1345,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (!m_supports_fast) { - disconnect("got 'reject_request' without FAST extension support", 2); + disconnect(error_code(errors::invalid_reject, libtorrent_category), 2); return; } @@ -1372,7 +1369,7 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (!m_supports_fast) { - disconnect("got 'allowed_fast' without FAST extension support", 2); + disconnect(error_code(errors::invalid_allow_fast, libtorrent_category), 2); return; } @@ -1396,13 +1393,13 @@ namespace libtorrent m_statistics.received_bytes(0, received); if (packet_size() < 2) { - disconnect("'extended' message smaller than 2 bytes", 2); + disconnect(error_code(errors::invalid_extended, libtorrent_category), 2); return; } if (associated_torrent().expired()) { - disconnect("'extended' message sent before proper handshake", 2); + disconnect(error_code(errors::invalid_extended, libtorrent_category), 2); return; } @@ -1430,9 +1427,7 @@ namespace libtorrent } #endif - char msg[200]; - snprintf(msg, 200, "unknown extended message id: %d", extended_id); - disconnect(msg, 2); + disconnect(error_code(errors::invalid_message, libtorrent_category), 2); return; } @@ -1518,7 +1513,7 @@ namespace libtorrent // if we're finished and this peer is uploading only // disconnect it if (t->is_finished() && upload_only()) - disconnect("upload to upload connection, closing"); + disconnect(error_code(errors::upload_upload_connection, libtorrent_category)); } bool bt_peer_connection::dispatch_message(int received) @@ -1555,9 +1550,7 @@ namespace libtorrent #endif m_statistics.received_bytes(0, received); - char msg[200]; - snprintf(msg, 200, "unknown message message id: %d size: %d", packet_type, packet_size()); - disconnect(msg, 2); + disconnect(error_code(errors::invalid_message, libtorrent_category)); return packet_finished(); } @@ -2046,7 +2039,7 @@ namespace libtorrent // read dh key, generate shared secret if (m_dh_key_exchange->compute_secret(recv_buffer.begin) == -1) { - disconnect("out of memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return; } @@ -2103,7 +2096,7 @@ namespace libtorrent m_statistics.received_bytes(0, bytes_transferred); if (packet_finished()) - disconnect("sync hash not found", 2); + disconnect(error_code(errors::sync_hash_not_found, libtorrent_category), 2); return; } @@ -2120,7 +2113,7 @@ namespace libtorrent if (!m_sync_hash) { m_statistics.received_bytes(0, bytes_transferred); - disconnect("no memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return; } } @@ -2137,7 +2130,7 @@ namespace libtorrent m_sync_bytes_read += bytes_processed; if (m_sync_bytes_read >= 512) { - disconnect("sync hash not found within 532 bytes", 2); + disconnect(error_code(errors::sync_hash_not_found, libtorrent_category), 2); return; } @@ -2211,7 +2204,7 @@ namespace libtorrent if (!m_RC4_handler.get()) { - disconnect("invalid streamkey identifier (info hash) in encrypted handshake", 2); + disconnect(error_code(errors::invalid_info_hash, libtorrent_category), 2); return; } @@ -2223,7 +2216,7 @@ namespace libtorrent const char sh_vc[] = {0,0,0,0, 0,0,0,0}; if (!std::equal(sh_vc, sh_vc+8, recv_buffer.begin + 20)) { - disconnect("unable to verify constant", 2); + disconnect(error_code(errors::invalid_encryption_constant, libtorrent_category), 2); return; } @@ -2246,7 +2239,7 @@ namespace libtorrent { m_statistics.received_bytes(0, bytes_transferred); if (packet_finished()) - disconnect("sync verification constant not found", 2); + disconnect(error_code(errors::invalid_encryption_constant, libtorrent_category), 2); return; } @@ -2258,7 +2251,7 @@ namespace libtorrent m_sync_vc.reset(new (std::nothrow) char[8]); if (!m_sync_vc) { - disconnect("no memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return; } std::fill(m_sync_vc.get(), m_sync_vc.get() + 8, 0); @@ -2278,7 +2271,7 @@ namespace libtorrent if (m_sync_bytes_read >= 512) { - disconnect("sync verification constant not found within 520 bytes", 2); + disconnect(error_code(errors::invalid_encryption_constant, libtorrent_category), 2); return; } @@ -2348,7 +2341,7 @@ namespace libtorrent case pe_settings::plaintext: if (!(crypto_field & 0x01)) { - disconnect("plaintext not provided", 1); + disconnect(error_code(errors::no_plaintext_mode, libtorrent_category), 1); return; } crypto_select = 0x01; @@ -2356,7 +2349,7 @@ namespace libtorrent case pe_settings::rc4: if (!(crypto_field & 0x02)) { - disconnect("rc4 not provided", 1); + disconnect(error_code(errors::no_rc4_mode, libtorrent_category), 1); return; } crypto_select = 0x02; @@ -2378,7 +2371,7 @@ namespace libtorrent } if (!crypto_select) { - disconnect("rc4/plaintext not provided", 1); + disconnect(error_code(errors::unsupported_encryption_mode, libtorrent_category), 1); return; } break; @@ -2396,7 +2389,8 @@ namespace libtorrent { if (allowed_enc_level == pe_settings::plaintext) { - disconnect("rc4 selected by peer when not provided", 2); + disconnect(error_code(errors::unsupported_encryption_mode_selected + , libtorrent_category), 2); return; } m_rc4_encrypted = true; @@ -2405,14 +2399,16 @@ namespace libtorrent { if (allowed_enc_level == pe_settings::rc4) { - disconnect("plaintext selected by peer when not provided", 2); + disconnect(error_code(errors::unsupported_encryption_mode_selected + , libtorrent_category), 2); return; } m_rc4_encrypted = false; } else { - disconnect("unsupported crypto method selected by peer", 2); + disconnect(error_code(errors::unsupported_encryption_mode_selected + , libtorrent_category), 2); return; } } @@ -2420,7 +2416,7 @@ namespace libtorrent int len_pad = detail::read_int16(recv_buffer.begin); if (len_pad < 0 || len_pad > 512) { - disconnect("invalid pad length", 2); + disconnect(error_code(errors::invalid_pad_size, libtorrent_category), 2); return; } @@ -2460,7 +2456,7 @@ namespace libtorrent if (len_ia < 0) { - disconnect("invalid len_ia in handshake", 2); + disconnect(error_code(errors::invalid_encrypt_handshake, libtorrent_category), 2); return; } @@ -2579,7 +2575,7 @@ namespace libtorrent #ifndef TORRENT_DISABLE_ENCRYPTION if (!is_local() && m_ses.get_pe_settings().in_enc_policy == pe_settings::disabled) { - disconnect("encrypted incoming connections disabled"); + disconnect(error_code(errors::no_incoming_encrypted, libtorrent_category)); return; } @@ -2598,7 +2594,7 @@ namespace libtorrent TORRENT_ASSERT((!is_local() && m_encrypted) || is_local()); #endif // #ifndef TORRENT_DISABLE_ENCRYPTION - disconnect("incorrect protocol identifier", 2); + disconnect(error_code(errors::invalid_info_hash, libtorrent_category), 2); return; } @@ -2609,7 +2605,7 @@ namespace libtorrent (m_ses.get_pe_settings().in_enc_policy == pe_settings::forced) && !m_encrypted) { - disconnect("non encrypted incoming connections disabled"); + disconnect(error_code(errors::no_incoming_regular, libtorrent_category)); return; } #endif @@ -2684,7 +2680,7 @@ namespace libtorrent #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << " received invalid info_hash\n"; #endif - disconnect("invalid info-hash in handshake", 2); + disconnect(error_code(errors::invalid_info_hash, libtorrent_category), 2); return; } @@ -2763,11 +2759,12 @@ namespace libtorrent // if not, we should close the outgoing one. if (pid < m_ses.get_peer_id() && is_local()) { - (*i)->connection->disconnect("duplicate peer-id, connection closed"); + (*i)->connection->disconnect(error_code(errors::duplicate_peer_id + , libtorrent_category)); } else { - disconnect("duplicate peer-id, connection closed"); + disconnect(error_code(errors::duplicate_peer_id, libtorrent_category)); return; } } @@ -2778,7 +2775,7 @@ namespace libtorrent if (pid == m_ses.get_peer_id()) { if (peer_info_struct()) peer_info_struct()->banned = true; - disconnect("closing connection to ourself", 1); + disconnect(error_code(errors::self_connection, libtorrent_category), 1); return; } @@ -2869,9 +2866,7 @@ namespace libtorrent { m_statistics.received_bytes(0, bytes_transferred); // packet too large - char msg[200]; - printf("packet > 1 MB (%u bytes)", (unsigned int)packet_size); - disconnect(msg, 2); + disconnect(error_code(errors::packet_too_large, libtorrent_category), 2); return; } @@ -2903,7 +2898,7 @@ namespace libtorrent if (!t) { m_statistics.received_bytes(0, bytes_transferred); - disconnect("torrent removed", 1); + disconnect(error_code(errors::torrent_removed, libtorrent_category), 1); return; } #ifdef TORRENT_DEBUG diff --git a/src/error_code.cpp b/src/error_code.cpp index 4566195a2..5d826d91b 100644 --- a/src/error_code.cpp +++ b/src/error_code.cpp @@ -73,6 +73,94 @@ namespace libtorrent "file too short", "unsupported URL protocol", "failed to parse URL", + "peer sent 0 length piece", + "parse failed", + "invalid file format tag", + "missing info-hash", + "mismatching info-hash", + "invalid hostname", + "invalid port", + "port blocked by port-filter", + "expected closing ] for address", + "destructing torrent", + "timed out", + "upload to uplaod connection", + "uninteresting upload-only peer", + "invalid info-hash", + "torrent paused", + "'have'-message with higher index than the number of pieces", + "bitfield of invalid size", + "too many piece requests while choked", + "invalid piece packet", + "out of memory", + "torrent aborted", + "connected to ourselves", + "invalid piece size", + "timed out: no interest", + "timed out: inactivity", + "timed out: no handshake", + "timed out: no request", + "invalid choke message", + "invalid unchoke message", + "invalid interested message", + "invalid not-interested message", + "invalid request message", + "invalid hash list", + "invalid hash piece message", + "invalid cancel message", + "invalid dht-port message", + "invalid suggest piece message", + "invalid have-all message", + "invalid have-none message", + "invalid reject message", + "invalid allow-fast message", + "invalid extended message", + "invalid message", + "sync hash not found", + "unable to verify encryption constant", + "plaintext mode not provided", + "rc4 mode not provided", + "unsupported encryption mode", + "peer selected unsupported encryption mode", + "invalid encryption pad size", + "invalid encryption handshake", + "incoming encrypted connections disabled", + "incoming regular connections disabled", + "duplicate peer-id", + "torrent removed", + "packet too large", + "failed to parse HTTP response", + "HTTP error", + "missing location header", + "invalid redirection", + "redirecting", + "invalid HTTP range", + "missing content-length", + "banned by IP filter", + "too many connections", + "peer banned", + "stopping torrent", + "too many corrupt pieces", + "torrent is not ready to accept peers", + "peer is not properly constructed", + "session is closing", + "optimistic disconnect", + "torrent finished", + "no router found", + "metadata too large", + "invalid metadata request", + "invalid metadata size", + "invalid metadata offset", + "invalid metadata message", + "pex message too large", + "invalid pex message", + "invalid lt_tracker message", + + "unsupported protocol version", + "not authorized to create port map (enable NAT-PMP on your router)", + "network failure", + "out of resources", + "unsupported opcode", }; if (ev < 0 || ev >= sizeof(msgs)/sizeof(msgs[0])) return "Unknown error"; @@ -83,7 +171,7 @@ namespace libtorrent #else - ::asio::error::error_category libtorrent_category = asio::error::error_category(20); + ::asio::error::error_category libtorrent_category(20); #endif diff --git a/src/http_connection.cpp b/src/http_connection.cpp index a5010319a..8b898fdee 100644 --- a/src/http_connection.cpp +++ b/src/http_connection.cpp @@ -57,11 +57,11 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri std::string auth; std::string hostname; std::string path; - char const* error; + error_code ec; int port; - boost::tie(protocol, auth, hostname, port, path, error) - = parse_url_components(url); + boost::tie(protocol, auth, hostname, port, path) + = parse_url_components(url, ec); int default_port = protocol == "https" ? 443 : 80; @@ -77,9 +77,8 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri return; } - if (error) + if (ec) { - error_code ec(errors::url_parse_error, libtorrent_category); m_resolver.get_io_service().post(boost::bind(&http_connection::callback , this, ec, (char*)0, 0)); return; @@ -89,15 +88,6 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri bool ssl = false; if (protocol == "https") ssl = true; -#ifndef TORRENT_USE_OPENSSL - if (ssl) - { - error_code ec(errors::unsupported_url_protocol, libtorrent_category); - m_resolver.get_io_service().post(boost::bind(&http_connection::callback - , this, ec, (char*)0, 0)); - return; - } -#endif char request[2048]; char* end = request + sizeof(request); @@ -500,10 +490,9 @@ void http_connection::on_read(error_code const& e error_code ec; m_sock.close(ec); using boost::tuples::ignore; - char const* error; - boost::tie(ignore, ignore, ignore, ignore, ignore, error) - = parse_url_components(location); - if (error == 0) + boost::tie(ignore, ignore, ignore, ignore, ignore) + = parse_url_components(location, ec); + if (!ec) { get(location, m_timeout, m_priority, &m_proxy, m_redirects - 1); } diff --git a/src/http_seed_connection.cpp b/src/http_seed_connection.cpp index 5561c3c54..48395247b 100644 --- a/src/http_seed_connection.cpp +++ b/src/http_seed_connection.cpp @@ -94,10 +94,10 @@ namespace libtorrent #endif std::string protocol; - char const* error; - boost::tie(protocol, m_auth, m_host, m_port, m_path, error) - = parse_url_components(url); - TORRENT_ASSERT(error == 0); + error_code ec; + boost::tie(protocol, m_auth, m_host, m_port, m_path) + = parse_url_components(url, ec); + TORRENT_ASSERT(!ec); if (!m_auth.empty()) m_auth = base64encode(m_auth); @@ -271,7 +271,7 @@ namespace libtorrent TORRENT_ASSERT(!m_requests.empty()); if (m_requests.empty()) { - disconnect("unexpected HTTP response", 2); + disconnect(error_code(errors::http_error, libtorrent_category), 2); return; } @@ -290,7 +290,7 @@ namespace libtorrent if (error) { - disconnect("failed to parse HTTP response", 2); + disconnect(error_code(errors::http_parse_error, libtorrent_category), 2); return; } @@ -320,7 +320,7 @@ namespace libtorrent m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url() , error_msg)); } - disconnect(error_msg.c_str(), 1); + disconnect(error_code(errors::http_error, libtorrent_category), 1); return; } if (!m_parser.header_finished()) @@ -344,16 +344,14 @@ namespace libtorrent { // we should not try this server again. t->remove_web_seed(m_url, web_seed_entry::http_seed); - disconnect("got HTTP redirection status without location header", 2); + disconnect(error_code(errors::missing_location, libtorrent_category), 2); return; } // add the redirected url and remove the current one t->add_web_seed(location, web_seed_entry::http_seed); t->remove_web_seed(m_url, web_seed_entry::http_seed); - char msg[200]; - snprintf(msg, 200, "redirecting to \"%s\"", location.c_str()); - disconnect(msg, 2); + disconnect(error_code(errors::redirecting, libtorrent_category), 2); return; } @@ -372,7 +370,7 @@ namespace libtorrent { // we should not try this server again. t->remove_web_seed(m_url, web_seed_entry::http_seed); - disconnect("no content-length in HTTP response", 2); + disconnect(error_code(errors::no_content_length, libtorrent_category), 2); return; } if (payload > m_response_left) payload = m_response_left; @@ -408,7 +406,7 @@ namespace libtorrent // temporarily unavailable, retry later t->retry_web_seed(m_url, web_seed_entry::http_seed, retry_time); t->remove_web_seed(m_url, web_seed_entry::http_seed); - disconnect("503 retrying later", 1); + disconnect(error_code(errors::http_error, libtorrent_category), 1); return; } diff --git a/src/lt_trackers.cpp b/src/lt_trackers.cpp index 1c0214027..68f66efc8 100644 --- a/src/lt_trackers.cpp +++ b/src/lt_trackers.cpp @@ -194,7 +194,7 @@ namespace libtorrent { namespace int ret = lazy_bdecode(body.begin, body.end, msg); if (ret != 0 || msg.type() != lazy_entry::dict_t) { - m_pc.disconnect("invalid bencoding in lt_tracker message", 2); + m_pc.disconnect(error_code(errors::invalid_lt_tracker_message, libtorrent_category), 2); return true; } diff --git a/src/metadata_transfer.cpp b/src/metadata_transfer.cpp index 274a6f374..6cb052c8b 100644 --- a/src/metadata_transfer.cpp +++ b/src/metadata_transfer.cpp @@ -367,7 +367,7 @@ namespace libtorrent { namespace if (length > 500 * 1024) { - m_pc.disconnect("LT_metadata message larger than 500 kB"); + m_pc.disconnect(error_code(errors::metadata_too_large, libtorrent_category), 2); return true; } @@ -392,7 +392,7 @@ namespace libtorrent { namespace if (length != 3) { // invalid metadata request - m_pc.disconnect("invalid metadata request"); + m_pc.disconnect(error_code(errors::invalid_metadata_request, libtorrent_category), 2); return true; } @@ -417,22 +417,22 @@ namespace libtorrent { namespace if (total_size > 500 * 1024) { - m_pc.disconnect("metadata size larger than 500 kB"); + m_pc.disconnect(error_code(errors::metadata_too_large, libtorrent_category), 2); return true; } if (total_size <= 0) { - m_pc.disconnect("invalid metadata size"); + m_pc.disconnect(error_code(errors::invalid_metadata_size, libtorrent_category), 2); return true; } if (offset > total_size || offset < 0) { - m_pc.disconnect("invalid metadata offset"); + m_pc.disconnect(error_code(errors::invalid_metadata_offset, libtorrent_category), 2); return true; } if (offset + data_size > total_size) { - m_pc.disconnect("invalid metadata message"); + m_pc.disconnect(error_code(errors::invalid_metadata_message, libtorrent_category), 2); return true; } @@ -460,9 +460,7 @@ namespace libtorrent { namespace break; default: { - char msg[200]; - snprintf(msg, sizeof(msg), "unknown metadata extension message: %u", type); - m_pc.disconnect(msg, 2); + m_pc.disconnect(error_code(errors::invalid_metadata_message, libtorrent_category), 2); } } return true; diff --git a/src/natpmp.cpp b/src/natpmp.cpp index a822d1eb4..6a57d49f1 100644 --- a/src/natpmp.cpp +++ b/src/natpmp.cpp @@ -49,8 +49,10 @@ POSSIBILITY OF SUCH DAMAGE. using boost::bind; using namespace libtorrent; -natpmp::natpmp(io_service& ios, address const& listen_interface, portmap_callback_t const& cb) +natpmp::natpmp(io_service& ios, address const& listen_interface + , portmap_callback_t const& cb, log_callback_t const& lcb) : m_callback(cb) + , m_log_callback(lcb) , m_currently_mapping(-1) , m_retry_count(0) , m_socket(ios) @@ -74,7 +76,7 @@ void natpmp::rebind(address const& listen_interface) char msg[200]; snprintf(msg, sizeof(msg), "failed to find default route: %s", ec.message().c_str()); log(msg); - disable(msg); + disable(ec); return; } @@ -92,13 +94,13 @@ void natpmp::rebind(address const& listen_interface) m_socket.open(udp::v4(), ec); if (ec) { - disable(ec.message().c_str()); + disable(ec); return; } m_socket.bind(udp::endpoint(address_v4::any(), 0), ec); if (ec) { - disable(ec.message().c_str()); + disable(ec); return; } @@ -128,12 +130,12 @@ bool natpmp::get_mapping(int index, int& local_port, int& external_port, int& pr return true; } -void natpmp::log(std::string const& msg) +void natpmp::log(char const* msg) { - m_callback(-1, 0, msg); + m_log_callback(msg); } -void natpmp::disable(char const* message) +void natpmp::disable(error_code const& ec) { m_disabled = true; @@ -142,7 +144,7 @@ void natpmp::disable(char const* message) { if (i->protocol == none) continue; i->protocol = none; - m_callback(i - m_mappings.begin(), 0, message); + m_callback(i - m_mappings.begin(), 0, ec); } close(); } @@ -437,26 +439,23 @@ void natpmp::on_reply(error_code const& e if (result != 0) { - char msg[200]; - char const* errors[] = + int errors[] = { - "Unsupported protocol version", - "Not authorized to create port map (enable NAT-PMP on your router)", - "Network failure", - "Out of resources", - "Unsupported opcode" + errors::unsupported_protocol_version, + errors::natpmp_not_authorized, + errors::network_failure, + errors::no_resources, + errors::unsupported_opcode, }; - char const* error_msg = ""; - if (result >= 1 && result <= 5) error_msg = errors[result - 1]; + int ev = errors::no_error; + if (result >= 1 && result <= 5) ev = errors[result - 1]; - snprintf(msg, sizeof(msg), "NAT router reports error (%u) %s" - , result, error_msg); m->expires = time_now() + hours(2); - m_callback(index, 0, msg); + m_callback(index, 0, error_code(ev, libtorrent_category)); } else if (m->action == mapping_t::action_add) { - m_callback(index, m->external_port, ""); + m_callback(index, m->external_port, error_code(errors::no_error, libtorrent_category)); } m_currently_mapping = -1; diff --git a/src/parse_url.cpp b/src/parse_url.cpp index c7e412c95..927e3f747 100644 --- a/src/parse_url.cpp +++ b/src/parse_url.cpp @@ -36,14 +36,13 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - // returns protocol, auth, hostname, port, path, error - boost::tuple - parse_url_components(std::string url) + // returns protocol, auth, hostname, port, path + boost::tuple + parse_url_components(std::string url, error_code& ec) { std::string hostname; // hostname only std::string auth; // user:pass std::string protocol; // http or https for instance - char const* error = 0; int port = 80; std::string::iterator at; @@ -63,19 +62,19 @@ namespace libtorrent if (end == url.end()) { - error = "no protocol in url"; + ec = error_code(errors::unsupported_url_protocol, libtorrent_category); goto exit; } ++end; if (end == url.end() || *end != '/') { - error = "incomplete protocol"; + ec = error_code(errors::unsupported_url_protocol, libtorrent_category); goto exit; } ++end; if (end == url.end() || *end != '/') { - error = "incomplete protocol"; + ec = error_code(errors::unsupported_url_protocol, libtorrent_category); goto exit; } ++end; @@ -101,7 +100,7 @@ namespace libtorrent port_pos = std::find(start, url.end(), ']'); if (port_pos == url.end()) { - error = "expected closing ']' for address"; + ec = error_code(errors::expected_close_bracket_in_address, libtorrent_category); goto exit; } port_pos = std::find(port_pos, url.end(), ':'); @@ -125,7 +124,7 @@ namespace libtorrent start = end; exit: return boost::make_tuple(protocol, auth, hostname, port - , std::string(start, url.end()), error); + , std::string(start, url.end())); } } diff --git a/src/peer_connection.cpp b/src/peer_connection.cpp index a41722ccb..38ea04102 100644 --- a/src/peer_connection.cpp +++ b/src/peer_connection.cpp @@ -373,13 +373,13 @@ namespace libtorrent m_socket->io_control(ioc, ec); if (ec) { - disconnect(ec.message().c_str()); + disconnect(ec); return; } m_remote = m_socket->remote_endpoint(ec); if (ec) { - disconnect(ec.message().c_str()); + disconnect(ec); return; } if (m_remote.address().is_v4()) @@ -561,7 +561,8 @@ namespace libtorrent } if (interesting) t->get_policy().peer_is_interesting(*this); - else if (upload_only()) disconnect("upload to upload connections"); + else if (upload_only()) disconnect(error_code( + errors::upload_upload_connection, libtorrent_category)); } void peer_connection::init() @@ -918,7 +919,7 @@ namespace libtorrent (*m_logger) << " " << i->second->torrent_file().info_hash() << "\n"; } #endif - disconnect("got invalid info-hash", 2); + disconnect(error_code(errors::invalid_info_hash, libtorrent_category), 2); return; } @@ -929,7 +930,7 @@ namespace libtorrent #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << " rejected connection to paused torrent\n"; #endif - disconnect("connection rejected bacause torrent is paused"); + disconnect(error_code(errors::torrent_paused, libtorrent_category), 2); return; } @@ -1300,7 +1301,7 @@ namespace libtorrent // if we got an invalid message, abort if (index >= int(m_have_piece.size()) || index < 0) { - disconnect("got 'have'-message with higher index than the number of pieces", 2); + disconnect(error_code(errors::invalid_have, libtorrent_category), 2); return; } @@ -1422,10 +1423,7 @@ namespace libtorrent if (t->valid_metadata() && (bits.size() + 7) / 8 != (m_have_piece.size() + 7) / 8) { - char msg[200]; - snprintf(msg, 200, "got bitfield with invalid size: %d bytes. expected: %d bytes" - , int((bits.size() + 7) / 8), int((m_have_piece.size() + 7) / 8)); - disconnect(msg, 2); + disconnect(error_code(errors::invalid_bitfield_size, libtorrent_category), 2); return; } @@ -1494,7 +1492,8 @@ namespace libtorrent m_num_pieces = num_pieces; if (interesting) t->get_policy().peer_is_interesting(*this); - else if (upload_only()) disconnect("upload to upload connections"); + else if (upload_only()) disconnect(error_code( + errors::upload_upload_connection, libtorrent_category)); } void peer_connection::disconnect_if_redundant() @@ -1505,7 +1504,7 @@ namespace libtorrent TORRENT_ASSERT(t); if (m_upload_only && t->is_finished()) { - disconnect("seed to seed"); + disconnect(error_code(errors::upload_upload_connection, libtorrent_category)); return; } @@ -1514,7 +1513,7 @@ namespace libtorrent && m_bitfield_received && t->are_files_checked()) { - disconnect("uninteresting upload-only peer"); + disconnect(error_code(errors::uninteresting_upload_peer, libtorrent_category)); return; } } @@ -1655,7 +1654,7 @@ namespace libtorrent if (m_choke_rejects > m_ses.settings().max_rejects) { - disconnect("too many piece requests while choked"); + disconnect(error_code(errors::too_many_requests_when_choked, libtorrent_category)); return; } else if ((m_choke_rejects & 0xf) == 0) @@ -1742,7 +1741,7 @@ namespace libtorrent "start: " << r.start << " | " "length: " << r.length << " ]\n"; #endif - disconnect("got invalid piece packet", 2); + disconnect(error_code(errors::invalid_piece, libtorrent_category), 2); return; } @@ -1813,7 +1812,7 @@ namespace libtorrent char* buffer = m_ses.allocate_disk_buffer("receive buffer"); if (buffer == 0) { - disconnect("out of memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return; } disk_buffer_holder holder(m_ses, buffer); @@ -1883,7 +1882,7 @@ namespace libtorrent if (t->alerts().should_post()) { t->alerts().post_alert(peer_error_alert(t->get_handle(), m_remote - , m_peer_id, "peer sent 0 length piece")); + , m_peer_id, error_code(errors::peer_sent_empty_piece, libtorrent_category))); } // This is used as a reject-request by bitcomet incoming_reject_request(p); @@ -2098,7 +2097,7 @@ namespace libtorrent { if (!t) { - disconnect(j.str.c_str()); + disconnect(j.error); return; } @@ -2721,13 +2720,13 @@ namespace libtorrent (*m_ses.m_logger) << time_now_string() << " CONNECTION TIMED OUT: " << m_remote.address().to_string(ec) << "\n"; #endif - disconnect("timed out: connect", 1); + disconnect(error_code(errors::timed_out, libtorrent_category), 1); } // the error argument defaults to 0, which means deliberate disconnect // 1 means unexpected disconnect/error // 2 protocol error (client sent something invalid) - void peer_connection::disconnect(char const* message, int error) + void peer_connection::disconnect(error_code const& ec, int error) { #ifdef TORRENT_DEBUG m_disconnect_started = true; @@ -2737,13 +2736,13 @@ namespace libtorrent switch (error) { case 0: - (*m_logger) << "*** CONNECTION CLOSED " << message << "\n"; + (*m_logger) << "*** CONNECTION CLOSED " << ec.message() << "\n"; break; case 1: - (*m_logger) << "*** CONNECTION FAILED " << message << "\n"; + (*m_logger) << "*** CONNECTION FAILED " << ec.message() << "\n"; break; case 2: - (*m_logger) << "*** PEER ERROR " << message << "\n"; + (*m_logger) << "*** PEER ERROR " << ec.message() << "\n"; break; } #endif @@ -2765,17 +2764,17 @@ namespace libtorrent torrent_handle handle; if (t) handle = t->get_handle(); - if (message) + if (ec) { if (error > 1 && m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - peer_error_alert(handle, remote(), pid(), message)); + peer_error_alert(handle, remote(), pid(), ec)); } else if (error <= 1 && m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - peer_disconnected_alert(handle, remote(), pid(), message)); + peer_disconnected_alert(handle, remote(), pid(), ec)); } } @@ -2814,9 +2813,9 @@ namespace libtorrent #endif m_disconnecting = true; - error_code ec; - m_socket->close(ec); - m_ses.close_connection(this, message); + error_code e; + m_socket->close(e); + m_ses.close_connection(this, ec); // we should only disconnect while we still have // at least one reference left to the connection @@ -3009,14 +3008,14 @@ namespace libtorrent if (disk_buffer_size > 16 * 1024) { - disconnect("invalid piece size", 2); + disconnect(error_code(errors::invalid_piece_size, libtorrent_category), 2); return false; } m_disk_recv_buffer.reset(m_ses.allocate_disk_buffer("receive buffer")); if (!m_disk_recv_buffer) { - disconnect("out of memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return false; } m_disk_recv_buffer_size = disk_buffer_size; @@ -3139,7 +3138,7 @@ namespace libtorrent { m_ses.m_half_open.done(m_connection_ticket); m_connecting = false; - disconnect("torrent aborted"); + disconnect(error_code(errors::torrent_aborted, libtorrent_category)); return; } @@ -3164,7 +3163,7 @@ namespace libtorrent (*m_logger) << time_now_string() << " *** LAST ACTIVITY [ " << total_seconds(d) << " seconds ago ] ***\n"; #endif - disconnect("timed out: inactivity"); + disconnect(error_code(errors::timed_out_inactivity, libtorrent_category)); return; } @@ -3177,7 +3176,7 @@ namespace libtorrent (*m_logger) << time_now_string() << " *** NO HANDSHAKE [ waited " << total_seconds(d) << " seconds ] ***\n"; #endif - disconnect("timed out: no handshake"); + disconnect(error_code(errors::timed_out_no_handshake, libtorrent_category)); return; } @@ -3196,7 +3195,7 @@ namespace libtorrent (*m_logger) << time_now_string() << " *** NO REQUEST [ t: " << total_seconds(d) << " ] ***\n"; #endif - disconnect("timed out: no request when unchoked"); + disconnect(error_code(errors::timed_out_no_request, libtorrent_category)); return; } @@ -3225,7 +3224,7 @@ namespace libtorrent "t1: " << total_seconds(d1) << " | " "t2: " << total_seconds(d2) << " ] ***\n"; #endif - disconnect("timed out: no interest"); + disconnect(error_code(errors::timed_out_no_interest, libtorrent_category)); return; } @@ -3515,7 +3514,7 @@ namespace libtorrent { if (!t) { - disconnect(j.str.c_str()); + disconnect(j.error); return; } @@ -3887,7 +3886,7 @@ namespace libtorrent std::pair buffer = m_ses.allocate_buffer(size); if (buffer.first == 0) { - disconnect("out of memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return; } TORRENT_ASSERT(buffer.second >= size); @@ -3912,7 +3911,7 @@ namespace libtorrent std::pair buffer = m_ses.allocate_buffer(size); if (buffer.first == 0) { - disconnect("out of memory"); + disconnect(error_code(errors::no_memory, libtorrent_category)); return buffer::interval(0, 0); } TORRENT_ASSERT(buffer.second >= size); @@ -3975,7 +3974,7 @@ namespace libtorrent #endif m_statistics.trancieve_ip_packet(bytes_in_loop, m_remote.address().is_v6()); on_receive(error, bytes_transferred); - disconnect(error.message().c_str()); + disconnect(error); return; } @@ -4079,7 +4078,7 @@ namespace libtorrent if (ec && ec != asio::error::would_block) { m_statistics.trancieve_ip_packet(bytes_in_loop, m_remote.address().is_v6()); - disconnect(ec.message().c_str()); + disconnect(ec); return; } if (ec == asio::error::would_block) break; @@ -4142,14 +4141,14 @@ namespace libtorrent if (!t) { - disconnect("torrent aborted"); + disconnect(error_code(errors::torrent_aborted, libtorrent_category)); return; } m_socket->open(m_remote.protocol(), ec); if (ec) { - disconnect(ec.message().c_str()); + disconnect(ec); return; } @@ -4159,7 +4158,7 @@ namespace libtorrent m_socket->io_control(ioc, ec); if (ec) { - disconnect(ec.message().c_str()); + disconnect(ec); return; } @@ -4171,7 +4170,7 @@ namespace libtorrent m_socket->set_option(socket_acceptor::reuse_address(true), ec); if (ec) { - disconnect(ec.message().c_str()); + disconnect(ec); return; } bind_interface.port(m_ses.next_port()); @@ -4190,7 +4189,7 @@ namespace libtorrent m_socket->bind(bind_interface, ec); if (ec) { - disconnect(ec.message().c_str()); + disconnect(ec); return; } m_socket->async_connect(m_remote @@ -4227,7 +4226,7 @@ namespace libtorrent (*m_ses.m_logger) << time_now_string() << " CONNECTION FAILED: " << m_remote.address().to_string(ec) << ": " << e.message() << "\n"; #endif - disconnect(e.message().c_str(), 1); + disconnect(e, 1); return; } @@ -4249,7 +4248,7 @@ namespace libtorrent // if the remote endpoint is the same as the local endpoint, we're connected // to ourselves if (m_peer_info) m_peer_info->banned = true; - disconnect("connected to ourselves", 1); + disconnect(error_code(errors::self_connection, libtorrent_category), 1); return; } @@ -4310,7 +4309,7 @@ namespace libtorrent #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n"; #endif - disconnect(error.message().c_str()); + disconnect(error); return; } if (m_disconnecting) return; diff --git a/src/policy.cpp b/src/policy.cpp index 97f7a1652..c432fd563 100644 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -369,7 +369,7 @@ namespace libtorrent if ((*i)->connection) { - (*i)->connection->disconnect("peer banned by IP filter"); + (*i)->connection->disconnect(error_code(errors::banned_by_ip_filter, libtorrent_category)); if (ses.m_alerts.should_post()) ses.m_alerts.post_alert(peer_blocked_alert((*i)->address())); TORRENT_ASSERT((*i)->connection == 0 @@ -681,7 +681,7 @@ namespace libtorrent && ses.num_connections() >= ses.max_connections() && c.remote().address() != m_torrent->current_tracker().address()) { - c.disconnect("too many connections, refusing incoming connection"); + c.disconnect(error_code(errors::too_many_connections, libtorrent_category)); return false; } @@ -720,7 +720,7 @@ namespace libtorrent if (i->banned) { - c.disconnect("ip address banned, closing"); + c.disconnect(error_code(errors::peer_banned, libtorrent_category)); return false; } @@ -739,14 +739,14 @@ namespace libtorrent if (ec1) { - c.disconnect(ec1.message().c_str()); + c.disconnect(ec1); return false; } if (self_connection) { - c.disconnect("connected to ourselves", 1); - i->connection->disconnect("connected to ourselves", 1); + c.disconnect(error_code(errors::self_connection, libtorrent_category), 1); + i->connection->disconnect(error_code(errors::self_connection, libtorrent_category), 1); return false; } @@ -755,11 +755,11 @@ namespace libtorrent // or the current one is already connected if (ec2) { - i->connection->disconnect(ec2.message().c_str()); + i->connection->disconnect(ec2); } else if (!i->connection->is_connecting() || c.is_local()) { - c.disconnect("duplicate connection, closing"); + c.disconnect(error_code(errors::duplicate_peer_id, libtorrent_category)); return false; } else @@ -769,8 +769,7 @@ namespace libtorrent " is connecting and this connection is incoming. closing existing " "connection in favour of this one"); #endif - i->connection->disconnect("incoming duplicate connection " - "with higher priority, closing"); + i->connection->disconnect(error_code(errors::duplicate_peer_id, libtorrent_category)); } } @@ -786,7 +785,7 @@ namespace libtorrent if (int(m_peers.size()) >= m_torrent->settings().max_peerlist_size) { - c.disconnect("peer list size exceeded, refusing incoming connection"); + c.disconnect(error_code(errors::too_many_connections, libtorrent_category)); return false; } @@ -858,7 +857,7 @@ namespace libtorrent policy::peer& pp = **i; if (pp.connection) { - p->connection->disconnect("duplicate connection"); + p->connection->disconnect(error_code(errors::duplicate_peer_id, libtorrent_category)); return false; } erase_peer(i); diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 7728fcb1d..9f0ee983a 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -590,7 +590,7 @@ namespace aux { #ifdef TORRENT_DEBUG int conn = m_connections.size(); #endif - (*m_connections.begin())->disconnect("stopping torrent"); + (*m_connections.begin())->disconnect(error_code(errors::stopping_torrent, libtorrent_category)); TORRENT_ASSERT(conn == int(m_connections.size()) + 1); } @@ -1089,7 +1089,7 @@ namespace aux { } void session_impl::close_connection(peer_connection const* p - , char const* message) + , error_code const& ec) { // too expensive // INVARIANT_CHECK; @@ -1102,7 +1102,7 @@ namespace aux { #if defined(TORRENT_LOGGING) (*m_logger) << time_now_string() << " CLOSING CONNECTION " - << p->remote() << " : " << message << "\n"; + << p->remote() << " : " << ec.message() << "\n"; #endif TORRENT_ASSERT(p->is_disconnecting()); @@ -1303,7 +1303,7 @@ namespace aux { // are ticked through the torrents' second_tick if (!p->associated_torrent().expired()) continue; if (m_last_tick - p->connected_time() > seconds(m_settings.handshake_timeout)) - p->disconnect("timeout: incoming connection"); + p->disconnect(error_code(errors::timed_out, libtorrent_category)); } // -------------------------------------------------------------- @@ -2318,22 +2318,25 @@ namespace aux { t->get_policy().add_peer(peer, peer_id(0), peer_info::lsd, 0); } - void session_impl::on_port_mapping(int mapping, int port - , std::string const& errmsg, int map_transport) + void session_impl::on_port_map_log( + char const* msg, int map_transport) { TORRENT_ASSERT(map_transport >= 0 && map_transport <= 1); // log message - if (mapping == -1) - { #ifdef TORRENT_UPNP_LOGGING - char const* transport_names[] = {"NAT-PMP", "UPnP"}; - m_upnp_log << time_now_string() << " " - << transport_names[map_transport] << ": " << errmsg; + char const* transport_names[] = {"NAT-PMP", "UPnP"}; + m_upnp_log << time_now_string() << " " + << transport_names[map_transport] << ": " << msg; #endif - if (m_alerts.should_post()) - m_alerts.post_alert(portmap_log_alert(map_transport, errmsg)); - return; - } + if (m_alerts.should_post()) + m_alerts.post_alert(portmap_log_alert(map_transport, msg)); + } + + void session_impl::on_port_mapping(int mapping, int port + , error_code const& ec, int map_transport) + { + mutex_t::scoped_lock l(m_mutex); + TORRENT_ASSERT(map_transport >= 0 && map_transport <= 1); #ifndef TORRENT_DISABLE_DHT if (mapping == m_udp_mapping[map_transport] && port != 0) @@ -2357,11 +2360,11 @@ namespace aux { return; } - if (!errmsg.empty()) + if (ec) { if (m_alerts.should_post()) m_alerts.post_alert(portmap_error_alert(mapping - , map_transport, errmsg)); + , map_transport, ec)); } else { @@ -2787,7 +2790,9 @@ namespace aux { m_natpmp = new natpmp(m_io_service , m_listen_interface.address() , bind(&session_impl::on_port_mapping - , this, _1, _2, _3, 0)); + , this, _1, _2, _3, 0) + , bind(&session_impl::on_port_map_log + , this, _1, 0)); if (m_listen_interface.port() > 0) { @@ -2814,6 +2819,8 @@ namespace aux { , m_settings.user_agent , bind(&session_impl::on_port_mapping , this, _1, _2, _3, 1) + , bind(&session_impl::on_port_map_log + , this, _1, 0) , m_settings.upnp_ignore_nonrouters); m_upnp->discover_device(); diff --git a/src/smart_ban.cpp b/src/smart_ban.cpp index d7d3c2e41..d5e853c3d 100644 --- a/src/smart_ban.cpp +++ b/src/smart_ban.cpp @@ -214,7 +214,8 @@ namespace libtorrent { namespace << " | ip: " << p->ip() << " ]\n"; #endif p->banned = true; - if (p->connection) p->connection->disconnect("banning peer for sending bad data"); + if (p->connection) p->connection->disconnect( + error_code(errors::peer_banned, libtorrent_category)); } // we already have this exact entry in the map // we don't have to insert it @@ -276,7 +277,8 @@ namespace libtorrent { namespace << " | ip: " << p->ip() << " ]\n"; #endif p->banned = true; - if (p->connection) p->connection->disconnect("banning peer for sending bad data"); + if (p->connection) p->connection->disconnect( + error_code(errors::peer_banned, libtorrent_category)); } torrent& m_torrent; diff --git a/src/torrent.cpp b/src/torrent.cpp index b5f821331..d99ddf661 100644 --- a/src/torrent.cpp +++ b/src/torrent.cpp @@ -245,10 +245,11 @@ namespace libtorrent std::vector().swap(m_resume_data); if (m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), "parse failed")); + error_code ec(errors::parse_failed, libtorrent_category); + m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), ec)); #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING (*m_ses.m_logger) << "fastresume data for " - << torrent_file().name() << " rejected: parse failed\n"; + << torrent_file().name() << " rejected: " << ec.message() << "\n"; #endif } } @@ -314,7 +315,7 @@ namespace libtorrent TORRENT_ASSERT(m_abort); if (!m_connections.empty()) - disconnect_all(); + disconnect_all(error_code(errors::torrent_aborted, libtorrent_category)); } void torrent::read_piece(int piece) @@ -372,7 +373,7 @@ namespace libtorrent { if (alerts().should_post()) alerts().post_alert(file_error_alert(j.error_file, get_handle(), j.error)); - if (c) c->disconnect("no memory"); + if (c) c->disconnect(error_code(errors::no_memory, libtorrent_category)); return; } @@ -621,28 +622,29 @@ namespace libtorrent if (m_resume_entry.type() == lazy_entry::dict_t) { - char const* error = 0; + int ev = 0; if (m_resume_entry.dict_find_string_value("file-format") != "libtorrent resume file") - error = "invalid file format tag"; + ev = errors::invalid_file_tag; std::string info_hash = m_resume_entry.dict_find_string_value("info-hash"); - if (!error && info_hash.empty()) - error = "missing info-hash"; + if (!ev && info_hash.empty()) + ev = errors::missing_info_hash; - if (!error && sha1_hash(info_hash) != m_torrent_file->info_hash()) - error = "mismatching info-hash"; + if (!ev && sha1_hash(info_hash) != m_torrent_file->info_hash()) + ev = errors::mismatching_info_hash; - if (error && m_ses.m_alerts.should_post()) + if (ev && m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), error)); + m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle() + , error_code(ev, libtorrent_category))); } - if (error) + if (ev) { #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING (*m_ses.m_logger) << "fastresume data for " << torrent_file().name() << " rejected: " - << error << "\n"; + << error_code(ev, libtorrent_category).message() << "\n"; #endif std::vector().swap(m_resume_data); lazy_entry().swap(m_resume_entry); @@ -786,12 +788,12 @@ namespace libtorrent if (fastresume_rejected && m_ses.m_alerts.should_post()) { - m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), j.str)); + m_ses.m_alerts.post_alert(fastresume_rejected_alert(get_handle(), j.error)); } #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING (*m_ses.m_logger) << "fastresume data for " << torrent_file().name() << " rejected: " - << j.str << "\n"; + << j.error.message() << "\n"; #endif if (ret == 0) @@ -894,7 +896,7 @@ namespace libtorrent clear_error(); - disconnect_all(); + disconnect_all(error_code(errors::stopping_torrent, libtorrent_category)); m_owning_storage->async_release_files(); if (!m_picker) m_picker.reset(new piece_picker()); @@ -1927,7 +1929,8 @@ namespace libtorrent (*p->connection->m_logger) << "*** BANNING PEER [ " << p->ip() << " ] 'too many corrupt pieces'\n"; #endif - p->connection->disconnect("too many corrupt pieces, banning peer"); + p->connection->disconnect(error_code(errors::too_many_corrupt_pieces + , libtorrent_category)); } } } @@ -2010,7 +2013,7 @@ namespace libtorrent // disconnect all peers and close all // files belonging to the torrents - disconnect_all(); + disconnect_all(error_code(errors::torrent_aborted, libtorrent_category)); if (m_owning_storage.get()) { m_storage->async_release_files( @@ -2102,7 +2105,7 @@ namespace libtorrent if (ret != 0) { if (alerts().should_post()) - alerts().post_alert(torrent_delete_failed_alert(get_handle(), j.str)); + alerts().post_alert(torrent_delete_failed_alert(get_handle(), j.error)); } else { @@ -2129,7 +2132,7 @@ namespace libtorrent if (!j.resume_data && alerts().should_post()) { - alerts().post_alert(save_resume_data_failed_alert(get_handle(), j.str)); + alerts().post_alert(save_resume_data_failed_alert(get_handle(), j.error)); return; } @@ -2611,16 +2614,17 @@ namespace libtorrent // now, look for trackers with the same hostname // that is has higher priority than this one // if we find one, swap with the udp-tracker + error_code ec; std::string udp_hostname; using boost::tuples::ignore; - boost::tie(ignore, ignore, udp_hostname, ignore, ignore, ignore) - = parse_url_components(i->url); + boost::tie(ignore, ignore, udp_hostname, ignore, ignore) + = parse_url_components(i->url, ec); for (std::vector::iterator j = m_trackers.begin(); j != i; ++j) { std::string hostname; - boost::tie(ignore, ignore, hostname, ignore, ignore, ignore) - = parse_url_components(j->url); + boost::tie(ignore, ignore, hostname, ignore, ignore) + = parse_url_components(j->url, ec); if (hostname != udp_hostname) continue; if (j->url.substr(0, 6) == "udp://") continue; using std::swap; @@ -2749,14 +2753,14 @@ namespace libtorrent std::string hostname; int port; std::string path; - char const* error; - boost::tie(protocol, auth, hostname, port, path, error) - = parse_url_components(web.url); + error_code ec; + boost::tie(protocol, auth, hostname, port, path) + = parse_url_components(web.url, ec); - if (error) + if (ec) { #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING - (*m_ses.m_logger) << time_now_string() << " failed to parse web seed url: " << error << "\n"; + (*m_ses.m_logger) << time_now_string() << " failed to parse web seed url: " << ec.message() << "\n"; #endif // never try it again m_web_seeds.erase(web); @@ -2772,7 +2776,8 @@ namespace libtorrent if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), web.url, "unknown protocol")); + url_seed_alert(get_handle(), web.url, error_code( + errors::unsupported_url_protocol, libtorrent_category))); } // never try it again m_web_seeds.erase(web); @@ -2784,7 +2789,8 @@ namespace libtorrent if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), web.url, "invalid hostname")); + url_seed_alert(get_handle(), web.url, error_code( + errors::invalid_hostname, libtorrent_category))); } // never try it again m_web_seeds.erase(web); @@ -2796,7 +2802,8 @@ namespace libtorrent if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), web.url, "invalid port")); + url_seed_alert(get_handle(), web.url, error_code( + errors::invalid_port, libtorrent_category))); } // never try it again m_web_seeds.erase(web); @@ -2820,7 +2827,8 @@ namespace libtorrent if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), web.url, "port blocked by port-filter")); + url_seed_alert(get_handle(), web.url, error_code( + errors::port_blocked, libtorrent_category))); } // never try it again m_web_seeds.erase(web); @@ -2853,7 +2861,7 @@ namespace libtorrent if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), web.url, e.message())); + url_seed_alert(get_handle(), web.url, e)); } // the name lookup failed for the http host. Don't try @@ -2869,16 +2877,16 @@ namespace libtorrent using boost::tuples::ignore; std::string hostname; int port; - char const* error; - boost::tie(ignore, ignore, hostname, port, ignore, error) - = parse_url_components(web.url); + error_code ec; + boost::tie(ignore, ignore, hostname, port, ignore) + = parse_url_components(web.url, ec); - if (error) + if (ec) { if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), web.url, error)); + url_seed_alert(get_handle(), web.url, ec)); } m_web_seeds.erase(web); return; @@ -2916,13 +2924,11 @@ namespace libtorrent { if (m_ses.m_alerts.should_post()) { - char msg[400]; - snprintf(msg, sizeof(msg), "HTTP seed hostname lookup failed: %s", e.message().c_str()); - m_ses.m_alerts.post_alert( - url_seed_alert(get_handle(), web.url, msg)); + m_ses.m_alerts.post_alert(url_seed_alert(get_handle(), web.url, e)); } #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING - (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << web.url << "\n"; + (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << web.url + << " " << e.message() << "\n"; #endif // unavailable, retry in 30 minutes @@ -3003,7 +3009,7 @@ namespace libtorrent #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING (*m_ses.m_logger) << " ** HOSTNAME LOOKUP FAILED!**: " << e.what() << "\n"; #endif - c->disconnect(e.what(), 1); + c->disconnect(error_code(errors::no_error, libtorrent_category), 1); } #endif } @@ -3719,7 +3725,7 @@ namespace libtorrent std::set::iterator i = m_connections.find(boost::get_pointer(c)); if (i != m_connections.end()) m_connections.erase(i); - c->disconnect(e.what()); + c->disconnect(error_code(errors::no_error, libtorrent_category), 1); return false; } #endif @@ -3788,25 +3794,25 @@ namespace libtorrent || m_state == torrent_status::checking_resume_data) && valid_metadata()) { - p->disconnect("torrent is not ready to accept peers"); + p->disconnect(error_code(errors::torrent_not_ready, libtorrent_category)); return false; } if (m_ses.m_connections.find(p) == m_ses.m_connections.end()) { - p->disconnect("peer is not properly constructed"); + p->disconnect(error_code(errors::peer_not_constructed, libtorrent_category)); return false; } if (m_ses.is_aborted()) { - p->disconnect("session is closing"); + p->disconnect(error_code(errors::session_closing, libtorrent_category)); return false; } if (int(m_connections.size()) >= m_max_connections) { - p->disconnect("reached connection limit"); + p->disconnect(error_code(errors::too_many_connections, libtorrent_category)); return false; } @@ -3832,7 +3838,7 @@ namespace libtorrent (*m_ses.m_logger) << time_now_string() << " CLOSING CONNECTION " << p->remote() << " policy::new_connection threw: " << e.what() << "\n"; #endif - p->disconnect(e.what()); + p->disconnect(error_code(errors::no_error, libtorrent_category)); return false; } #endif @@ -3861,7 +3867,7 @@ namespace libtorrent && !m_abort; } - void torrent::disconnect_all() + void torrent::disconnect_all(error_code const& ec) { // doesn't work with the m_paused -> m_num_peers == 0 condition // INVARIANT_CHECK; @@ -3883,7 +3889,7 @@ namespace libtorrent if (p->is_disconnecting()) m_connections.erase(m_connections.begin()); else - p->disconnect(m_abort?"stopping torrent":"pausing torrent"); + p->disconnect(ec); TORRENT_ASSERT(m_connections.size() <= size); } } @@ -3950,7 +3956,7 @@ namespace libtorrent peer_connection* p = *i; ++ret; - p->disconnect("optimistic disconnect"); + p->disconnect(error_code(errors::optimistic_disconnect, libtorrent_category)); } return ret; @@ -4002,7 +4008,8 @@ namespace libtorrent } } std::for_each(seeds.begin(), seeds.end() - , bind(&peer_connection::disconnect, _1, "torrent finished, disconnecting seed", 0)); + , bind(&peer_connection::disconnect, _1, error_code(errors::torrent_finished + , libtorrent_category), 0)); if (m_abort) return; @@ -4538,7 +4545,7 @@ namespace libtorrent } #endif - disconnect_all(); + disconnect_all(error_code(errors::torrent_removed, libtorrent_category)); stop_announcing(); if (m_owning_storage.get()) @@ -4671,7 +4678,7 @@ namespace libtorrent if (alerts().should_post()) { alerts().post_alert(save_resume_data_failed_alert(get_handle() - , "save resume data failed, torrent is being destructed")); + , error_code(errors::destructing_torrent, libtorrent_category))); } return; } @@ -4767,7 +4774,7 @@ namespace libtorrent alerts().post_alert(torrent_paused_alert(get_handle())); } - disconnect_all(); + disconnect_all(error_code(errors::torrent_paused, libtorrent_category)); stop_announcing(); } @@ -5032,7 +5039,7 @@ namespace libtorrent #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING (*p->m_logger) << "**ERROR**: " << e.what() << "\n"; #endif - p->disconnect(e.what(), 1); + p->disconnect(error_code(errors::no_error, libtorrent_category), 1); } #endif } @@ -5587,7 +5594,8 @@ namespace libtorrent if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert(tracker_error_alert(get_handle() - , ae?ae->fails:0, 0, r.url, "tracker timed out")); + , ae?ae->fails:0, 0, r.url + , error_code(errors::timed_out, libtorrent_category))); } } else if (r.kind == tracker_request::scrape_request) @@ -5595,7 +5603,7 @@ namespace libtorrent if (m_ses.m_alerts.should_post()) { m_ses.m_alerts.post_alert(scrape_failed_alert(get_handle() - , r.url, "tracker timed out")); + , r.url, error_code(errors::timed_out, libtorrent_category))); } } update_tracker_timer(); diff --git a/src/udp_tracker_connection.cpp b/src/udp_tracker_connection.cpp index 3a86e1259..c55798455 100644 --- a/src/udp_tracker_connection.cpp +++ b/src/udp_tracker_connection.cpp @@ -95,15 +95,15 @@ namespace libtorrent { std::string hostname; int port; - char const* error; + error_code ec; using boost::tuples::ignore; - boost::tie(ignore, ignore, hostname, port, ignore, error) - = parse_url_components(tracker_req().url); + boost::tie(ignore, ignore, hostname, port, ignore) + = parse_url_components(tracker_req().url, ec); - if (error) + if (ec) { - fail(-1, error); + fail(-1, ec.message().c_str()); return; } diff --git a/src/upnp.cpp b/src/upnp.cpp index ecc1fcef5..a53002eac 100644 --- a/src/upnp.cpp +++ b/src/upnp.cpp @@ -60,9 +60,11 @@ static error_code ec; upnp::upnp(io_service& ios, connection_queue& cc , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb, bool ignore_nonrouters, void* state) + , portmap_callback_t const& cb, log_callback_t const& lcb + , bool ignore_nonrouters, void* state) : m_user_agent(user_agent) , m_callback(cb) + , m_log_callback(lcb) , m_retry_count(0) , m_io_service(ios) , m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250", ec), 1900) @@ -110,9 +112,9 @@ void upnp::discover_device() discover_device_impl(); } -void upnp::log(std::string const& msg) +void upnp::log(char const* msg) { - m_callback(-1, 0, msg); + m_log_callback(msg); } void upnp::discover_device_impl() @@ -137,7 +139,7 @@ void upnp::discover_device_impl() char msg[200]; snprintf(msg, sizeof(msg), "broadcast failed: %s. Aborting.", ec.message().c_str()); log(msg); - disable(ec.message().c_str()); + disable(ec); return; } @@ -256,7 +258,7 @@ void upnp::resend_request(error_code const& e) if (m_devices.empty()) { - disable("no UPnP router found (no response)"); + disable(error_code(errors::no_router, libtorrent_category)); return; } @@ -452,16 +454,16 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer std::string protocol; std::string auth; - char const* error; + error_code ec; // we don't have this device in our list. Add it - boost::tie(protocol, auth, d.hostname, d.port, d.path, error) - = parse_url_components(d.url); + boost::tie(protocol, auth, d.hostname, d.port, d.path) + = parse_url_components(d.url, ec); - if (error) + if (ec) { char msg[200]; snprintf(msg, sizeof(msg), "invalid URL %s from %s: %s" - , d.url.c_str(), print_endpoint(from).c_str(), error); + , d.url.c_str(), print_endpoint(from).c_str(), ec.message().c_str()); log(msg); return; } @@ -916,11 +918,11 @@ void upnp::on_upnp_xml(error_code const& e std::string protocol; std::string auth; - char const* error; + error_code ec; if (!d.control_url.empty() && d.control_url[0] == '/') { - boost::tie(protocol, auth, d.hostname, d.port, d.path, error) - = parse_url_components(d.url); + boost::tie(protocol, auth, d.hostname, d.port, d.path) + = parse_url_components(d.url, ec); d.control_url = protocol + "://" + d.hostname + ":" + to_string(d.port).elems + s.control_url; } @@ -932,14 +934,14 @@ void upnp::on_upnp_xml(error_code const& e , s.url_base.c_str(), d.url.c_str()); log(msg); - boost::tie(protocol, auth, d.hostname, d.port, d.path, error) - = parse_url_components(d.control_url); + boost::tie(protocol, auth, d.hostname, d.port, d.path) + = parse_url_components(d.control_url, ec); - if (error) + if (ec) { char msg[200]; snprintf(msg, sizeof(msg), "failed to parse URL '%s': %s" - , d.control_url.c_str(), error); + , d.control_url.c_str(), ec.message().c_str()); log(msg); d.disabled = true; return; @@ -948,7 +950,7 @@ void upnp::on_upnp_xml(error_code const& e if (num_mappings() > 0) update_map(d, 0); } -void upnp::disable(char const* msg) +void upnp::disable(error_code const& ec) { m_disabled = true; @@ -958,16 +960,16 @@ void upnp::disable(char const* msg) { if (i->protocol == none) continue; i->protocol = none; - m_callback(i - m_mappings.begin(), 0, msg); + m_callback(i - m_mappings.begin(), 0, ec); } // we cannot clear the devices since there // might be outstanding requests relying on // the device entry being present when they // complete - error_code ec; - m_broadcast_timer.cancel(ec); - m_refresh_timer.cancel(ec); + error_code e; + m_broadcast_timer.cancel(e); + m_refresh_timer.cancel(e); m_socket.close(); } @@ -994,10 +996,7 @@ namespace state.exit = true; } } -} -namespace -{ struct error_code_t { int code; @@ -1006,7 +1005,8 @@ namespace error_code_t error_codes[] = { - {402, "Invalid Arguments"} + {0, "no error"} + , {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"} @@ -1023,6 +1023,42 @@ namespace } +#if BOOST_VERSION >= 103500 + + +const char* upnp_error_category::name() const +{ + return "UPnP error"; +} + +std::string upnp_error_category::message(int ev) const +{ + int num_errors = sizeof(error_codes) / sizeof(error_codes[0]); + error_code_t* end = error_codes + num_errors; + error_code_t tmp = {ev, 0}; + error_code_t* e = std::lower_bound(error_codes, end, tmp + , bind(&error_code_t::code, _1) < bind(&error_code_t::code, _2)); + if (e != end && e->code == ev) + { + return e->msg; + } + return "unknown UPnP error"; +} + +namespace libtorrent +{ + TORRENT_EXPORT upnp_error_category upnp_category; +} + +#else + +namespace libtorrent +{ + TORRENT_EXPORT ::asio::error::error_category upnp_category(21); +} + +#endif + void upnp::on_upnp_map_response(error_code const& e , libtorrent::http_parser const& p, rootdevice& d, int mapping , http_connection& c) @@ -1134,7 +1170,7 @@ void upnp::on_upnp_map_response(error_code const& e if (s.error_code == -1) { - m_callback(mapping, m.external_port, ""); + m_callback(mapping, m.external_port, error_code()); if (d.lease_duration > 0) { m.expires = time_now() @@ -1172,7 +1208,7 @@ void upnp::return_error(int mapping, int code) error_string += ": "; error_string += e->msg; } - m_callback(mapping, 0, error_string); + m_callback(mapping, 0, error_code(code, upnp_category)); } void upnp::on_upnp_unmap_response(error_code const& e diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index ca791a0fc..8c513c16a 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -284,7 +284,7 @@ namespace libtorrent { namespace if (length > 17 * 1024) { - m_pc.disconnect("ut_metadata message larger than 17 kB", 2); + m_pc.disconnect(error_code(errors::invalid_metadata_message, libtorrent_category), 2); return true; } @@ -294,7 +294,7 @@ namespace libtorrent { namespace entry msg = bdecode(body.begin, body.end, len); if (msg.type() == entry::undefined_t) { - m_pc.disconnect("invalid bencoding in ut_metadata message", 2); + m_pc.disconnect(error_code(errors::invalid_metadata_message, libtorrent_category), 2); return true; } @@ -345,9 +345,7 @@ namespace libtorrent { namespace break; default: { - char msg[200]; - snprintf(msg, sizeof(msg), "unknown ut_metadata extension message: %u", type); - m_pc.disconnect(msg, 2); + m_pc.disconnect(error_code(errors::invalid_metadata_message, libtorrent_category), 2); } } return true; diff --git a/src/ut_pex.cpp b/src/ut_pex.cpp index e2e79f9cc..d897f3f5d 100644 --- a/src/ut_pex.cpp +++ b/src/ut_pex.cpp @@ -232,7 +232,7 @@ namespace libtorrent { namespace if (length > 500 * 1024) { - m_pc.disconnect("peer exchange message larger than 500 kB", 2); + m_pc.disconnect(error_code(errors::pex_message_too_large, libtorrent_category), 2); return true; } @@ -242,7 +242,7 @@ namespace libtorrent { namespace int ret = lazy_bdecode(body.begin, body.end, pex_msg); if (ret != 0 || pex_msg.type() != lazy_entry::dict_t) { - m_pc.disconnect("invalid bencoding in ut_metadata message", 2); + m_pc.disconnect(error_code(errors::invalid_pex_message, libtorrent_category), 2); return true; } diff --git a/src/web_peer_connection.cpp b/src/web_peer_connection.cpp index 0f45a92d5..6986e0818 100644 --- a/src/web_peer_connection.cpp +++ b/src/web_peer_connection.cpp @@ -98,10 +98,10 @@ namespace libtorrent #endif std::string protocol; - char const* error; - boost::tie(protocol, m_auth, m_host, m_port, m_path, error) - = parse_url_components(url); - TORRENT_ASSERT(error == 0); + error_code ec; + boost::tie(protocol, m_auth, m_host, m_port, m_path) + = parse_url_components(url, ec); + TORRENT_ASSERT(!ec); if (!m_auth.empty()) m_auth = base64encode(m_auth); @@ -350,7 +350,7 @@ namespace libtorrent #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << "*** " << std::string(recv_buffer.begin, recv_buffer.end) << "\n"; #endif - disconnect("failed to parse HTTP response", 2); + disconnect(error_code(errors::http_parse_error, libtorrent_category), 2); return; } @@ -386,7 +386,7 @@ namespace libtorrent , error_msg)); } m_statistics.received_bytes(0, bytes_transferred); - disconnect(error_msg.c_str(), 1); + disconnect(error_code(errors::http_error, libtorrent_category), 1); return; } if (!m_parser.header_finished()) @@ -422,7 +422,7 @@ namespace libtorrent { // we should not try this server again. t->remove_web_seed(m_url, web_seed_entry::url_seed); - disconnect("got HTTP redirection status without location header", 2); + disconnect(error_code(errors::missing_location, libtorrent_category), 2); return; } @@ -444,19 +444,14 @@ namespace libtorrent if (i == std::string::npos) { t->remove_web_seed(m_url, web_seed_entry::url_seed); - char msg[200]; - snprintf(msg, 200, "got invalid HTTP redirection location (\"%s\") " - "expected it to end with: %s", location.c_str(), path.c_str()); - disconnect(msg, 2); + disconnect(error_code(errors::invalid_redirection, libtorrent_category), 2); return; } location.resize(i); } t->add_web_seed(location, web_seed_entry::url_seed); t->remove_web_seed(m_url, web_seed_entry::url_seed); - char msg[200]; - snprintf(msg, 200, "redirecting to \"%s\"", location.c_str()); - disconnect(msg, 2); + disconnect(error_code(errors::redirecting, libtorrent_category), 2); return; } @@ -490,9 +485,7 @@ namespace libtorrent m_statistics.received_bytes(0, bytes_transferred); // we should not try this server again. t->remove_web_seed(m_url, web_seed_entry::url_seed); - char msg[200]; - snprintf(msg, 200, "invalid range in HTTP response"); - disconnect(msg, 2); + disconnect(error_code(errors::invalid_range, libtorrent_category)); return; } // the http range is inclusive @@ -507,7 +500,7 @@ namespace libtorrent m_statistics.received_bytes(0, bytes_transferred); // we should not try this server again. t->remove_web_seed(m_url, web_seed_entry::url_seed); - disconnect("no content-length in HTTP response", 2); + disconnect(error_code(errors::no_content_length, libtorrent_category), 2); return; } } @@ -515,7 +508,7 @@ namespace libtorrent if (m_requests.empty() || m_file_requests.empty()) { m_statistics.received_bytes(0, bytes_transferred); - disconnect("unexpected HTTP response", 2); + disconnect(error_code(errors::http_error, libtorrent_category), 2); return; } @@ -568,7 +561,7 @@ namespace libtorrent m_statistics.received_bytes(0, bytes_transferred); // this means the end of the incoming request ends _before_ the // first expected byte (fs + m_piece.size()) - disconnect("invalid range in HTTP response", 2); + disconnect(error_code(errors::invalid_range, libtorrent_category), 2); return; } diff --git a/test/test_primitives.cpp b/test/test_primitives.cpp index 8a598b75c..cca90dc46 100644 --- a/test/test_primitives.cpp +++ b/test/test_primitives.cpp @@ -428,23 +428,24 @@ int test_main() // test url parsing - TEST_CHECK(parse_url_components("http://foo:bar@host.com:80/path/to/file") - == make_tuple("http", "foo:bar", "host.com", 80, "/path/to/file", (char const*)0)); + error_code ec; + TEST_CHECK(parse_url_components("http://foo:bar@host.com:80/path/to/file", ec) + == make_tuple("http", "foo:bar", "host.com", 80, "/path/to/file")); - TEST_CHECK(parse_url_components("http://host.com/path/to/file") - == make_tuple("http", "", "host.com", 80, "/path/to/file", (char const*)0)); + TEST_CHECK(parse_url_components("http://host.com/path/to/file", ec) + == make_tuple("http", "", "host.com", 80, "/path/to/file")); - TEST_CHECK(parse_url_components("ftp://host.com:21/path/to/file") - == make_tuple("ftp", "", "host.com", 21, "/path/to/file", (char const*)0)); + TEST_CHECK(parse_url_components("ftp://host.com:21/path/to/file", ec) + == make_tuple("ftp", "", "host.com", 21, "/path/to/file")); - TEST_CHECK(parse_url_components("http://host.com/path?foo:bar@foo:") - == make_tuple("http", "", "host.com", 80, "/path?foo:bar@foo:", (char const*)0)); + TEST_CHECK(parse_url_components("http://host.com/path?foo:bar@foo:", ec) + == make_tuple("http", "", "host.com", 80, "/path?foo:bar@foo:")); - TEST_CHECK(parse_url_components("http://192.168.0.1/path/to/file") - == make_tuple("http", "", "192.168.0.1", 80, "/path/to/file", (char const*)0)); + TEST_CHECK(parse_url_components("http://192.168.0.1/path/to/file", ec) + == make_tuple("http", "", "192.168.0.1", 80, "/path/to/file")); - TEST_CHECK(parse_url_components("http://[::1]/path/to/file") - == make_tuple("http", "", "[::1]", 80, "/path/to/file", (char const*)0)); + TEST_CHECK(parse_url_components("http://[::1]/path/to/file", ec) + == make_tuple("http", "", "[::1]", 80, "/path/to/file")); // base64 test vectors from http://www.faqs.org/rfcs/rfc4648.html @@ -669,7 +670,6 @@ int test_main() // test network functions - error_code ec; TEST_CHECK(is_local(address::from_string("192.168.0.1", ec))); TEST_CHECK(is_local(address::from_string("10.1.1.56", ec))); TEST_CHECK(!is_local(address::from_string("14.14.251.63", ec)));