Beispiel #1
0
void connection::handle_write(const error_code& e, reply *rep)
{
    //如果连接已经断开 则放弃写回
    if(stopped())return;
    string mess_r = "Client[" + address_ + ":" + port_ + "] request file " + request_.uri;
    //记录 请求信息
    log->record(mess_r);
    if (!e)
    {
        // Initiate graceful connection closure.
        //error_code ignored_ec;
        //socket_.shutdown(asio::ip::tcp::socket::shutdown_both, ignored_ec);
	
	    string mess_s;
	    if(rep->status == reply::ok){
		    mess_s = "Successfully send file " + request_.uri + " with " + boost::lexical_cast<std::string>(rep->content.size())+ " bytes to clien[" +\
					 address_ + ":" + port_ + "]";
	    }else{
		    mess_s = "Failed to send file " + request_.uri + " to client[" + address_ + ":" + port_ + "] due to " + rep->to_string(rep->status);
	    }
	    log->record(mess_s);
        connection::start_read();
    }else{
  	    string mess_f = "Failed to send file " + request_.uri + " to client[" + address_ + ":" + port_  + "] due to error " + e.message() ;
	    log->record(mess_f);
    }
    //connection::start_read();
    // No new asynchronous operations are started. This means that all shared_ptr
    // references to the connection object will disappear and the object will be
    // destroyed automatically after this handler returns. The connection class's
    // destructor closes the socket.
}
Beispiel #2
0
void natpmp::on_reply(error_code const& e
	, std::size_t bytes_transferred)
{
	mutex::scoped_lock l(m_mutex);

#if defined TORRENT_ASIO_DEBUGGING
	complete_async("natpmp::on_reply");
#endif

	using namespace libtorrent::detail;
	if (e)
	{
		char msg[200];
		snprintf(msg, sizeof(msg), "error on receiving reply: %s"
			, convert_from_native(e.message()).c_str());
		log(msg, l);
		return;
	}

#if defined TORRENT_ASIO_DEBUGGING
	add_outstanding_async("natpmp::on_reply");
#endif
	// make a copy of the response packet buffer
	// to avoid overwriting it in the next receive call
	char msg_buf[16];
	memcpy(msg_buf, m_response_buffer, bytes_transferred);

	m_socket.async_receive_from(asio::buffer(&m_response_buffer, 16)
		, m_remote, boost::bind(&natpmp::on_reply, self(), _1, _2));

	// simulate packet loss
/*
	if ((random() % 2) == 0)
	{
		log(" simulating drop", l);
		return;
	}
*/
	if (m_remote != m_nat_endpoint)
	{
		char msg[200];
		snprintf(msg, sizeof(msg), "received packet from wrong IP: %s"
			, print_endpoint(m_remote).c_str());
		log(msg, l);
		return;
	}

	error_code ec;
	m_send_timer.cancel(ec);

	if (bytes_transferred < 12)
	{
		char msg[200];
		snprintf(msg, sizeof(msg), "received packet of invalid size: %d", int(bytes_transferred));
		log(msg, l);
		return;
	}

	char* in = msg_buf;
	int version = read_uint8(in);
	int cmd = read_uint8(in);
	int result = read_uint16(in);
	int time = read_uint32(in);

	if (cmd == 128)
	{
		// public IP request response
		m_external_ip = read_v4_address(in);

		char msg[200];
		snprintf(msg, sizeof(msg), "<== public IP address [ %s ]", print_address(m_external_ip).c_str());
		log(msg, l);
		return;

	}

	if (bytes_transferred < 16)
	{
		char msg[200];
		snprintf(msg, sizeof(msg), "received packet of invalid size: %d", int(bytes_transferred));
		log(msg, l);
		return;
	}

	int private_port = read_uint16(in);
	int public_port = read_uint16(in);
	int lifetime = read_uint32(in);

	(void)time; // to remove warning

	int protocol = (cmd - 128 == 1)?udp:tcp;

	char msg[200];
	int num_chars = snprintf(msg, sizeof(msg), "<== port map ["
		" protocol: %s local: %u external: %u ttl: %u ]"
		, (cmd - 128 == 1 ? "udp" : "tcp")
		, private_port, public_port, lifetime);

	if (version != 0)
	{
		snprintf(msg + num_chars, sizeof(msg) - num_chars, "unexpected version: %u"
			, version);
		log(msg, l);
	}

	mapping_t* m = 0;
	int index = -1;
	for (std::vector<mapping_t>::iterator i = m_mappings.begin()
		, end(m_mappings.end()); i != end; ++i)
	{
		if (private_port != i->local_port) continue;
		if (protocol != i->protocol) continue;
		if (!i->map_sent) continue;
		if (!i->outstanding_request) continue;
		m = &*i;
		index = i - m_mappings.begin();
		break;
	}

	if (m == 0)
	{
		snprintf(msg + num_chars, sizeof(msg) - num_chars, " not found in map table");
		log(msg, l);
		return;
	}
	m->outstanding_request = false;

	log(msg, l);

	if (public_port == 0 || lifetime == 0)
	{
		// this means the mapping was
		// successfully closed
		m->protocol = none;
	}
	else
	{
		m->expires = aux::time_now() + seconds(int(lifetime * 0.7f));
		m->external_port = public_port;
	}

	if (result != 0)
	{
		int errors[] =
		{
			errors::unsupported_protocol_version,
			errors::natpmp_not_authorized,
			errors::network_failure,
			errors::no_resources,
			errors::unsupported_opcode,
		};
		int ev = errors::no_error;
		if (result >= 1 && result <= 5) ev = errors[result - 1];

		m->expires = aux::time_now() + hours(2);
		l.unlock();
		m_callback(index, address(), 0, error_code(ev, get_libtorrent_category()));
		l.lock();
	}
	else if (m->action == mapping_t::action_add)
	{
		l.unlock();
		m_callback(index, m_external_ip, m->external_port,
			error_code(errors::no_error, get_libtorrent_category()));
		l.lock();
	}

	if (m_abort) return;

	m_currently_mapping = -1;
	m->action = mapping_t::action_none;
	m_send_timer.cancel(ec);
	update_expiration_timer(l);
	try_next_mapping(index, l);
}
Beispiel #3
0
 void on_disconnected(error_code const& ec)      
 {
     LogInfo("Client " << " disconnected with error: " << ec.message() );
 }
Beispiel #4
0
void natpmp::on_reply(error_code const& e
	, std::size_t bytes_transferred)
{
	TORRENT_ASSERT(is_single_thread());

	COMPLETE_ASYNC("natpmp::on_reply");

	using namespace libtorrent::detail;
	if (e)
	{
#ifndef TORRENT_DISABLE_LOGGING
		log("error on receiving reply: %s"
			, convert_from_native(e.message()).c_str());
#endif
		return;
	}

	ADD_OUTSTANDING_ASYNC("natpmp::on_reply");
	// make a copy of the response packet buffer
	// to avoid overwriting it in the next receive call
	char msg_buf[sizeof(m_response_buffer)];
	memcpy(msg_buf, m_response_buffer, bytes_transferred);

	m_socket.async_receive_from(boost::asio::buffer(&m_response_buffer[0]
		, sizeof(m_response_buffer))
		, m_remote, std::bind(&natpmp::on_reply, self(), _1, _2));

	if (m_remote != m_nat_endpoint)
	{
#ifndef TORRENT_DISABLE_LOGGING
		log("received packet from wrong IP: %s"
			, print_endpoint(m_remote).c_str());
#endif
		return;
	}

	error_code ec;
	m_send_timer.cancel(ec);

	if (bytes_transferred < 12)
	{
#ifndef TORRENT_DISABLE_LOGGING
		log("received packet of invalid size: %d", int(bytes_transferred));
#endif
		return;
	}

	char* in = msg_buf;
	int version = read_uint8(in);
	int cmd = read_uint8(in);
	int result = read_uint16(in);
	int time = read_uint32(in);
	TORRENT_UNUSED(version);
	TORRENT_UNUSED(time);

	if (cmd == 128)
	{
		// public IP request response
		m_external_ip = read_v4_address(in);

#ifndef TORRENT_DISABLE_LOGGING
		log("<== public IP address [ %s ]", print_address(m_external_ip).c_str());
#endif
		return;

	}

	if (bytes_transferred != 16)
	{
#ifndef TORRENT_DISABLE_LOGGING
		log("received packet of invalid size: %d", int(bytes_transferred));
#endif
		return;
	}

	int const private_port = read_uint16(in);
	int const public_port = read_uint16(in);
	int const lifetime = read_uint32(in);

	int const protocol = (cmd - 128 == 1)?udp:tcp;

#ifndef TORRENT_DISABLE_LOGGING
	char msg[200];
	int num_chars = std::snprintf(msg, sizeof(msg), "<== port map ["
		" protocol: %s local: %u external: %u ttl: %u ]"
		, (cmd - 128 == 1 ? "udp" : "tcp")
		, private_port, public_port, lifetime);

	if (version != 0)
	{
		std::snprintf(msg + num_chars, sizeof(msg) - num_chars, "unexpected version: %u"
			, version);
		log("%s", msg);
	}
#endif

	mapping_t* m = nullptr;
	int index = -1;
	for (std::vector<mapping_t>::iterator i = m_mappings.begin()
		, end(m_mappings.end()); i != end; ++i)
	{
		if (private_port != i->local_port) continue;
		if (protocol != i->protocol) continue;
		if (!i->map_sent) continue;
		if (!i->outstanding_request) continue;
		m = &*i;
		index = i - m_mappings.begin();
		break;
	}

	if (m == nullptr)
	{
#ifndef TORRENT_DISABLE_LOGGING
		snprintf(msg + num_chars, sizeof(msg) - num_chars, " not found in map table");
		log("%s", msg);
#endif
		return;
	}
	m->outstanding_request = false;

#ifndef TORRENT_DISABLE_LOGGING
	log("%s", msg);
#endif

	if (public_port == 0 || lifetime == 0)
	{
		// this means the mapping was
		// successfully closed
		m->protocol = none;
	}
	else
	{
		m->expires = aux::time_now() + seconds(int(lifetime * 0.7f));
		m->external_port = public_port;
	}

	if (result != 0)
	{
		int errors[] =
		{
			errors::unsupported_protocol_version,
			errors::natpmp_not_authorized,
			errors::network_failure,
			errors::no_resources,
			errors::unsupported_opcode,
		};
		int ev = errors::no_error;
		if (result >= 1 && result <= 5) ev = errors[result - 1];

		m->expires = aux::time_now() + hours(2);
		int const proto = m->protocol;
		m_callback(index, address(), 0, proto
			, error_code(ev, get_libtorrent_category()));
	}
	else if (m->action == mapping_t::action_add)
	{
		int const proto = m->protocol;
		m_callback(index, m_external_ip, m->external_port, proto
			, error_code(errors::no_error, get_libtorrent_category()));
	}

	if (m_abort) return;

	m_currently_mapping = -1;
	m->action = mapping_t::action_none;
	m_send_timer.cancel(ec);
	update_expiration_timer();
	try_next_mapping(index);
}
Beispiel #5
0
	void udp_tracker_connection::name_lookup(error_code const& error
		, udp::resolver::iterator i)
	{
		if (error == asio::error::operation_aborted) return;
		if (error || i == udp::resolver::iterator())
		{
			fail(-1, error.message().c_str());
			return;
		}

		boost::shared_ptr<request_callback> cb = requester();
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
		if (cb) cb->debug_log("*** UDP_TRACKER [ name lookup successful ]");
#endif
		restart_read_timeout();
		
		// look for an address that has the same kind as the one
		// we're listening on. To make sure the tracker get our
		// correct listening address.

		std::transform(i, udp::resolver::iterator(), std::back_inserter(m_endpoints)
			, boost::bind(&udp::resolver::iterator::value_type::endpoint, _1));

		// remove endpoints that are filtered by the IP filter
		for (std::list<udp::endpoint>::iterator i = m_endpoints.begin();
			i != m_endpoints.end();)
		{
			if (m_ses.m_ip_filter.access(i->address()) == ip_filter::blocked) 
				i = m_endpoints.erase(i);
			else
				++i;
		}

		if (m_endpoints.empty())
		{
			fail(-1, "blocked by IP filter");
			return;
		}
		
		std::list<udp::endpoint>::iterator iter = m_endpoints.begin();
		m_target = *iter;

		if (bind_interface() != address_v4::any())
		{
			// find first endpoint that matches our bind interface type
			for (; iter != m_endpoints.end() && iter->address().is_v4()
				!= bind_interface().is_v4(); ++iter);

			if (iter == m_endpoints.end())
			{
				TORRENT_ASSERT(m_target.address().is_v4() != bind_interface().is_v4());
				if (cb)
				{
					char const* tracker_address_type = m_target.address().is_v4() ? "IPv4" : "IPv6";
					char const* bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
					char msg[200];
					snprintf(msg, sizeof(msg)
						, "the tracker only resolves to an %s  address, and you're "
						"listening on an %s socket. This may prevent you from receiving "
						"incoming connections."
						, tracker_address_type, bind_address_type);

					cb->tracker_warning(tracker_req(), msg);
				}
			}
			else
			{
				m_target = *iter;
			}
		}

		if (cb) cb->m_tracker_address = tcp::endpoint(m_target.address(), m_target.port());

		if (bind_interface() != address_v4::any())
		{
			error_code ec;
			m_socket.bind(udp::endpoint(bind_interface(), 0), ec);
			if (ec)
			{
				fail(-1, ec.message().c_str());
				return;
			}
		}
		send_udp_connect();
	}
Beispiel #6
0
	void udp_tracker_connection::on_receive(error_code const& e
		, udp::endpoint const& ep, char const* buf, int size)
	{
		// ignore resposes before we've sent any requests
		if (m_state == action_error) return;

		if (!m_socket.is_open()) return; // the operation was aborted

		// ignore packet not sent from the tracker
		if (m_target != ep) return;
		
		received_bytes(size + 28); // assuming UDP/IP header
		if (e) fail(-1, e.message().c_str());

#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
		boost::shared_ptr<request_callback> cb = requester();
		if (cb)
		{
			char msg[200];
			snprintf(msg, 200, "<== UDP_TRACKER_PACKET [ size: %d ]", size);
			cb->debug_log(msg);
		}
#endif

		// ignore packets smaller than 8 bytes
		if (size < 8) return;

		restart_read_timeout();

		const char* ptr = buf;
		int action = detail::read_int32(ptr);
		int transaction = detail::read_int32(ptr);

#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
		if (cb)
		{
			char msg[200];
			snprintf(msg, 200, "*** UDP_TRACKER_PACKET [ action: %d ]", action);
			cb->debug_log(msg);
		}
#endif

		// ignore packets with incorrect transaction id
		if (m_transaction_id != transaction) return;

		if (action == action_error)
		{
			fail(-1, std::string(ptr, size - 8).c_str());
			return;
		}

		// ignore packets that's not a response to our message
		if (action != m_state) return;

#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING
		if (cb)
		{
			char msg[200];
			snprintf(msg, 200, "*** UDP_TRACKER_RESPONSE [ cid: %x%x ]"
				, int(m_connection_id >> 32), int(m_connection_id & 0xffffffff));
			cb->debug_log(msg);
		}
#endif

		switch (m_state)
		{
			case action_connect:
				on_connect_response(buf, size);
				break;
			case action_announce:
				on_announce_response(buf, size);
				break;
			case action_scrape:
				on_scrape_response(buf, size);
				break;
			default: break;
		}
	}
Beispiel #7
0
static bool error(error_code ec) {
  if (!ec)
    return false;
  errs() << "LLVMSymbolizer: error reading file: " << ec.message() << ".\n";
  return true;
}
void TAsyncCommonSocketChannel::handleResolve(const error_code& err,
        tcp::resolver::iterator epItr, const ReturnCallback& cb) {
    if (err) {
        cb(::boost::make_shared<TTransportException>("TAsyncCommonSocketChannel error in handling resolve: " + err.message()));
    } else {
        //attempt a connection on the first endpoint resolved
        connectToResolvedEndpoint(epItr, cb);
    }
}
	void http_seed_connection::on_receive(error_code const& error
		, std::size_t bytes_transferred)
	{
		INVARIANT_CHECK;

		if (error)
		{
			m_statistics.received_bytes(0, bytes_transferred);
#ifdef TORRENT_VERBOSE_LOGGING
			peer_log("*** http_seed_connection error: %s", error.message().c_str());
#endif
			return;
		}

		boost::shared_ptr<torrent> t = associated_torrent().lock();
		TORRENT_ASSERT(t);

		for (;;)
		{
			buffer::const_interval recv_buffer = receive_buffer();

			if (bytes_transferred == 0) break;
			TORRENT_ASSERT(recv_buffer.left() > 0);

			TORRENT_ASSERT(!m_requests.empty());
			if (m_requests.empty())
			{
				m_statistics.received_bytes(0, bytes_transferred);
				disconnect(errors::http_error, 2);
				return;
			}

			peer_request front_request = m_requests.front();

			bool header_finished = m_parser.header_finished();
			if (!header_finished)
			{
				bool parse_error = false;
				int protocol = 0;
				int payload = 0;
				boost::tie(payload, protocol) = m_parser.incoming(recv_buffer, parse_error);
				m_statistics.received_bytes(0, protocol);
				bytes_transferred -= protocol;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
				if (payload > front_request.length) payload = front_request.length;
#endif

				if (parse_error)
				{
					m_statistics.received_bytes(0, bytes_transferred);
					disconnect(errors::http_parse_error, 2);
					return;
				}

				TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
			
				TORRENT_ASSERT(recv_buffer.left() <= packet_size());
				
				// this means the entire status line hasn't been received yet
				if (m_parser.status_code() == -1)
				{
					TORRENT_ASSERT(payload == 0);
					TORRENT_ASSERT(bytes_transferred == 0);
					break;
				}

				// if the status code is not one of the accepted ones, abort
				if (!is_ok_status(m_parser.status_code()))
				{
					int retry_time = atoi(m_parser.header("retry-after").c_str());
					if (retry_time <= 0) retry_time = 5 * 60;
					// temporarily unavailable, retry later
					t->retry_web_seed(this, retry_time);

					std::string error_msg = to_string(m_parser.status_code()).elems
						+ (" " + m_parser.message());
					if (m_ses.m_alerts.should_post<url_seed_alert>())
					{
						m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url()
							, error_msg));
					}
					m_statistics.received_bytes(0, bytes_transferred);
					disconnect(error_code(m_parser.status_code(), get_http_category()), 1);
					return;
				}
				if (!m_parser.header_finished())
				{
					TORRENT_ASSERT(payload == 0);
					TORRENT_ASSERT(bytes_transferred == 0);
					break;
				}
			}

			// we just completed reading the header
			if (!header_finished)
			{
				if (is_redirect(m_parser.status_code()))
				{
					// this means we got a redirection request
					// look for the location header
					std::string location = m_parser.header("location");
					m_statistics.received_bytes(0, bytes_transferred);

					if (location.empty())
					{
						// we should not try this server again.
						t->remove_web_seed(this);
						disconnect(errors::missing_location, 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(this);
					disconnect(errors::redirecting, 2);
					return;
				}

				std::string const& server_version = m_parser.header("server");
				if (!server_version.empty())
				{
					m_server_string = "URL seed @ ";
					m_server_string += m_host;
					m_server_string += " (";
					m_server_string += server_version;
					m_server_string += ")";
				}

				m_response_left = atol(m_parser.header("content-length").c_str());
				if (m_response_left == -1)
				{
					m_statistics.received_bytes(0, bytes_transferred);
					// we should not try this server again.
					t->remove_web_seed(this);
					disconnect(errors::no_content_length, 2);
					return;
				}
				if (m_response_left != front_request.length)
				{
					m_statistics.received_bytes(0, bytes_transferred);
					// we should not try this server again.
					t->remove_web_seed(this);
					disconnect(errors::invalid_range, 2);
					return;
				}
				m_body_start = m_parser.body_start();
			}

			recv_buffer.begin += m_body_start;

			// =========================
			// === CHUNKED ENCODING  ===
			// =========================
			while (m_parser.chunked_encoding()
				&& m_chunk_pos >= 0
				&& m_chunk_pos < recv_buffer.left())
			{
				int header_size = 0;
				size_type chunk_size = 0;
				buffer::const_interval chunk_start = recv_buffer;
				chunk_start.begin += m_chunk_pos;
				TORRENT_ASSERT(chunk_start.begin[0] == '\r' || is_hex(chunk_start.begin, 1));
				bool ret = m_parser.parse_chunk_header(chunk_start, &chunk_size, &header_size);
				if (!ret)
				{
					TORRENT_ASSERT(bytes_transferred >= size_t(chunk_start.left() - m_partial_chunk_header));
					bytes_transferred -= chunk_start.left() - m_partial_chunk_header;
					m_statistics.received_bytes(0, chunk_start.left() - m_partial_chunk_header);
					m_partial_chunk_header = chunk_start.left();
					if (bytes_transferred == 0) return;
					break;
				}
				else
				{
#ifdef TORRENT_VERBOSE_LOGGING
					peer_log("*** parsed chunk: %d header_size: %d", chunk_size, header_size);
#endif
					TORRENT_ASSERT(bytes_transferred >= size_t(header_size - m_partial_chunk_header));
					bytes_transferred -= header_size - m_partial_chunk_header;

					m_statistics.received_bytes(0, header_size - m_partial_chunk_header);
					m_partial_chunk_header = 0;
					TORRENT_ASSERT(chunk_size != 0 || chunk_start.left() <= header_size || chunk_start.begin[header_size] == 'H');
					// cut out the chunk header from the receive buffer
					TORRENT_ASSERT(m_chunk_pos + m_body_start < INT_MAX);
					cut_receive_buffer(header_size, t->block_size() + 1024, int(m_chunk_pos + m_body_start));
					recv_buffer = receive_buffer();
					recv_buffer.begin += m_body_start;
					m_chunk_pos += chunk_size;
					if (chunk_size == 0)
					{
						TORRENT_ASSERT(receive_buffer().left() < m_chunk_pos + m_body_start + 1
							|| receive_buffer()[int(m_chunk_pos + m_body_start)] == 'H'
							|| (m_parser.chunked_encoding() && receive_buffer()[int(m_chunk_pos + m_body_start)] == '\r'));
						m_chunk_pos = -1;
					}
				}
			}

			int payload = bytes_transferred;
			if (payload > m_response_left) payload = int(m_response_left);
			if (payload > front_request.length) payload = front_request.length;
			m_statistics.received_bytes(payload, 0);
			incoming_piece_fragment(payload);
			m_response_left -= payload;

			if (m_parser.status_code() == 503)
			{
				if (!m_parser.finished()) return;

				int retry_time = atol(std::string(recv_buffer.begin, recv_buffer.end).c_str());
				if (retry_time <= 0) retry_time = 60;
#ifdef TORRENT_VERBOSE_LOGGING
				peer_log("*** retrying in %d seconds", retry_time);
#endif

				m_statistics.received_bytes(0, bytes_transferred);
				// temporarily unavailable, retry later
				t->retry_web_seed(this, retry_time);
				disconnect(error_code(m_parser.status_code(), get_http_category()), 1);
				return;
			}


			// we only received the header, no data
			if (recv_buffer.left() == 0) break;

			if (recv_buffer.left() < front_request.length) break;

			// if the response is chunked, we need to receive the last
			// terminating chunk and the tail headers before we can proceed
			if (m_parser.chunked_encoding() && m_chunk_pos >= 0) break;

			m_requests.pop_front();
			incoming_piece(front_request, recv_buffer.begin);
			if (associated_torrent().expired()) return;

			int size_to_cut = m_body_start + front_request.length;
			TORRENT_ASSERT(receive_buffer().left() < size_to_cut + 1
				|| receive_buffer()[size_to_cut] == 'H'
				|| (m_parser.chunked_encoding() && receive_buffer()[size_to_cut] == '\r'));

			cut_receive_buffer(size_to_cut, t->block_size() + 1024);
			if (m_response_left == 0) m_chunk_pos = 0;
			else m_chunk_pos -= front_request.length;
			bytes_transferred -= payload;
			m_body_start = 0;
			if (m_response_left > 0) continue;
			TORRENT_ASSERT(m_response_left == 0);
			m_parser.reset();
		}
	}
Beispiel #10
0
	void on_udp_receive(error_code const& ec, size_t bytes_transferred, udp::endpoint* from, char* buffer, int size)
	{
		if (ec)
		{
			fprintf(stderr, "%s: UDP tracker, read failed: %s\n", time_now_string(), ec.message().c_str());
			return;
		}

		if (bytes_transferred < 16)
		{
			fprintf(stderr, "%s: UDP message too short (from: %s)\n", time_now_string(), print_endpoint(*from).c_str());
			return;
		}

		fprintf(stderr, "%s: UDP message %d bytes\n", time_now_string(), int(bytes_transferred));

		char* ptr = buffer;
		detail::read_uint64(ptr);
		boost::uint32_t action = detail::read_uint32(ptr);
		boost::uint32_t transaction_id = detail::read_uint32(ptr);

		error_code e;

		switch (action)
		{
			case 0: // connect

				fprintf(stderr, "%s: UDP connect from %s\n", time_now_string()
					, print_endpoint(*from).c_str());
				ptr = buffer;
				detail::write_uint32(0, ptr); // action = connect
				detail::write_uint32(transaction_id, ptr); // transaction_id
				detail::write_uint64(10, ptr); // connection_id
				m_socket.send_to(asio::buffer(buffer, 16), *from, 0, e);
				if (e) fprintf(stderr, "%s: UDP send_to failed. ERROR: %s\n"
					, time_now_string(), e.message().c_str());
				else fprintf(stderr, "%s: UDP sent response to: %s\n"
					, time_now_string(), print_endpoint(*from).c_str());
				break;

			case 1: // announce

				++m_udp_announces;
				fprintf(stderr, "%s: UDP announce [%d]\n", time_now_string()
					, int(m_udp_announces));
				ptr = buffer;
				detail::write_uint32(1, ptr); // action = announce
				detail::write_uint32(transaction_id, ptr); // transaction_id
				detail::write_uint32(1800, ptr); // interval
				detail::write_uint32(1, ptr); // incomplete
				detail::write_uint32(1, ptr); // complete
				// 0 peers
				m_socket.send_to(asio::buffer(buffer, 20), *from, 0, e);
				if (e) fprintf(stderr, "%s: UDP send_to failed. ERROR: %s\n"
					, time_now_string(), e.message().c_str());
				else fprintf(stderr, "%s: UDP sent response to: %s\n"
					, time_now_string(), print_endpoint(*from).c_str());
				break;
			case 2:
				// ignore scrapes
				fprintf(stderr, "%s: UDP scrape (ignored)\n", time_now_string());
				break;
			default:
				fprintf(stderr, "%s: UDP unknown message: %d\n", time_now_string()
					, action);
				break;
		}

		m_socket.async_receive_from(
			asio::buffer(buffer, size), *from, 0
			, boost::bind(&udp_tracker::on_udp_receive, this, _1, _2, from, buffer, size));
	}
void Client::printErrorCode(const error_code &ec, const std::string& method)
{
	warnlog << "[" << method << "] Error Code: " << ec.value() << ", message: " << ec.message();
}
Beispiel #12
0
 void handle_sent(const error_code& ec, std::size_t) {
     // here response has been sent
     if (ec) {
         std::cout << "Error sending response to " << remote_endpoint_ << ": " << ec.message() << "\n";
     }
 }
	// throws exception when the client should be disconnected
	void web_peer_connection::on_receive(error_code const& error
		, std::size_t bytes_transferred)
	{
		INVARIANT_CHECK;

		if (error)
		{
#ifdef TORRENT_VERBOSE_LOGGING
			(*m_logger) << "*** web_peer_connection error: "
				<< error.message() << "\n";
#endif
			return;
		}

		boost::shared_ptr<torrent> t = associated_torrent().lock();
		TORRENT_ASSERT(t);

		incoming_piece_fragment();

		for (;;)
		{
			buffer::const_interval recv_buffer = receive_buffer();

			int payload;
			int protocol;
			bool header_finished = m_parser.header_finished();
			if (!header_finished)
			{
				boost::tie(payload, protocol) = m_parser.incoming(recv_buffer);
				m_statistics.received_bytes(0, protocol);
				bytes_transferred -= protocol;

				TORRENT_ASSERT(recv_buffer.left() == 0 || *recv_buffer.begin == 'H');
			
				TORRENT_ASSERT(recv_buffer.left() <= packet_size());
				
				// this means the entire status line hasn't been received yet
				if (m_parser.status_code() == -1)
				{
					TORRENT_ASSERT(payload == 0);
					TORRENT_ASSERT(bytes_transferred == 0);
					break;
				}

				// if the status code is not one of the accepted ones, abort
				if (m_parser.status_code() != 206 // partial content
					&& m_parser.status_code() != 200 // OK
					&& !(m_parser.status_code() >= 300 // redirect
						&& m_parser.status_code() < 400))
				{
					if (m_parser.status_code() == 503)
					{
						// temporarily unavailable, retry later
						t->retry_url_seed(m_url);
					}
					t->remove_url_seed(m_url);
					std::string error_msg = boost::lexical_cast<std::string>(m_parser.status_code())
						+ " " + m_parser.message();
					if (m_ses.m_alerts.should_post(alert::warning))
					{
						session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
						m_ses.m_alerts.post_alert(url_seed_alert(t->get_handle(), url()
							, error_msg));
					}
					throw std::runtime_error(error_msg);
				}
				if (!m_parser.header_finished())
				{
					TORRENT_ASSERT(payload == 0);
					TORRENT_ASSERT(bytes_transferred == 0);
					break;
				}

				m_body_start = m_parser.body_start();
				m_received_body = 0;
			}

			// we just completed reading the header
			if (!header_finished)
			{
				if (m_parser.status_code() >= 300 && m_parser.status_code() < 400)
				{
					// this means we got a redirection request
					// look for the location header
					std::string location = m_parser.header("location");

					if (location.empty())
					{
						// we should not try this server again.
						t->remove_url_seed(m_url);
						throw std::runtime_error("got HTTP redirection status without location header");
					}
					
					bool single_file_request = false;
					if (!m_path.empty() && m_path[m_path.size() - 1] != '/')
						single_file_request = true;

					// add the redirected url and remove the current one
					if (!single_file_request)
					{
						TORRENT_ASSERT(!m_file_requests.empty());
						int file_index = m_file_requests.front();

						torrent_info const& info = t->torrent_file();
						std::string path = info.file_at(file_index).path.string();
						path = escape_path(path.c_str(), path.length());
						size_t i = location.rfind(path);
						if (i == std::string::npos)
						{
							t->remove_url_seed(m_url);
							throw std::runtime_error("got invalid HTTP redirection location (\"" + location + "\") "
								"expected it to end with: " + path);
						}
						location.resize(i);
					}
					t->add_url_seed(location);
					t->remove_url_seed(m_url);
					throw std::runtime_error("redirecting to " + location);
				}

				std::string const& server_version = m_parser.header("server");
				if (!server_version.empty())
				{
					m_server_string = "URL seed @ ";
					m_server_string += m_host;
					m_server_string += " (";
					m_server_string += server_version;
					m_server_string += ")";
				}

				m_body_start = m_parser.body_start();
				m_received_body = 0;
				m_range_pos = 0;
			}

			recv_buffer.begin += m_body_start;

			// we only received the header, no data
			if (recv_buffer.left() == 0) break;

			size_type range_start;
			size_type range_end;
			if (m_parser.status_code() == 206)
			{
				std::stringstream range_str(m_parser.header("content-range"));
				char dummy;
				std::string bytes;
				range_str >> bytes >> range_start >> dummy >> range_end;
				if (!range_str)
				{
					// we should not try this server again.
					t->remove_url_seed(m_url);
					throw std::runtime_error("invalid range in HTTP response: " + range_str.str());
				}
				// the http range is inclusive
				range_end++;
			}
			else
			{
Beispiel #14
0
void lsd::announce_impl(sha1_hash const& ih, int listen_port, bool broadcast
	, int retry_count)
{
#if TORRENT_USE_IPV6
	if (m_disabled && m_disabled6) return;
#else
	if (m_disabled) return;
#endif

	char ih_hex[41];
	to_hex((char const*)&ih[0], 20, ih_hex);
	char msg[200];

#ifndef TORRENT_DISABLE_LOGGING
	debug_log("==> LSD: ih: %s port: %u\n", ih_hex, listen_port);
#endif

	error_code ec;
	if (!m_disabled)
	{
		int msg_len = render_lsd_packet(msg, sizeof(msg), listen_port, ih_hex
			, m_cookie, "239.192.152.143");
		m_socket.send(msg, msg_len, ec, broadcast ? broadcast_socket::broadcast : 0);
		if (ec)
		{
			m_disabled = true;
#ifndef TORRENT_DISABLE_LOGGING
			debug_log("*** LSD: failed to send message: (%d) %s", ec.value()
				, ec.message().c_str());
#endif
		}
	}

#if TORRENT_USE_IPV6
	if (!m_disabled6)
	{
		int msg_len = render_lsd_packet(msg, sizeof(msg), listen_port, ih_hex
			, m_cookie, "[ff15::efc0:988f]");
		m_socket6.send(msg, msg_len, ec, broadcast ? broadcast_socket::broadcast : 0);
		if (ec)
		{
			m_disabled6 = true;
#ifndef TORRENT_DISABLE_LOGGING
			debug_log("*** LSD: failed to send message6: (%d) %s", ec.value()
				, ec.message().c_str());
#endif
		}
	}
#endif

	++retry_count;
	if (retry_count >= 3) return;

#if TORRENT_USE_IPV6
	if (m_disabled && m_disabled6) return;
#else
	if (m_disabled) return;
#endif

#if defined TORRENT_ASIO_DEBUGGING
	add_outstanding_async("lsd::resend_announce");
#endif
	m_broadcast_timer.expires_from_now(seconds(2 * retry_count), ec);
	m_broadcast_timer.async_wait(boost::bind(&lsd::resend_announce, self(), _1
		, ih, listen_port, retry_count));
}
Beispiel #15
0
static inline void print_error(char const * title, error_code const & ec)
{
	LOG_ERROR(title << ": " << ec.message());
}