void udp_socket::wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec)
{
	CHECK_MAGIC;
	using namespace libtorrent::detail;

	char header[20];
	char* h = header;

	write_uint16(0, h); // reserved
	write_uint8(0, h); // fragment
	write_uint8(ep.address().is_v4()?1:4, h); // atyp
	write_address(ep.address(), h);
	write_uint16(ep.port(), h);

	boost::array<asio::const_buffer, 2> iovec;
	iovec[0] = asio::const_buffer(header, h - header);
	iovec[1] = asio::const_buffer(p, len);

#if TORRENT_USE_IPV6
	if (m_proxy_addr.address().is_v4() && m_ipv4_sock.is_open())
#endif
		m_ipv4_sock.send_to(iovec, m_proxy_addr, 0, ec);
#if TORRENT_USE_IPV6
	else
		m_ipv6_sock.send_to(iovec, m_proxy_addr, 0, ec);
#endif
}
Example #2
0
void rpc_manager::invoke(int message_id, udp::endpoint target_addr
	, observer_ptr o)
{
	INVARIANT_CHECK;

	if (m_destructing)
	{
		o->abort();
		return;
	}

	msg m;
	m.message_id = message_id;
	m.reply = false;
	m.id = m_our_id;
	m.addr = target_addr;
	TORRENT_ASSERT(!m_transactions[m_next_transaction_id]);
#ifdef TORRENT_DEBUG
	int potential_new_id = m_next_transaction_id;
#endif
#ifndef BOOST_NO_EXCEPTIONS
	try
	{
#endif
		m.transaction_id.clear();
		std::back_insert_iterator<std::string> out(m.transaction_id);
		io::write_uint16(m_next_transaction_id, out);
		
		o->send(m);

		o->sent = time_now();
#if TORRENT_USE_IPV6
		o->target_addr = target_addr.address();
#else
		o->target_addr = target_addr.address().to_v4();
#endif
		o->port = target_addr.port();

#ifdef TORRENT_DHT_VERBOSE_LOGGING
		TORRENT_LOG(rpc) << "Invoking " << messages::ids[message_id] 
			<< " -> " << target_addr;
#endif	
		m_send(m);
		new_transaction_id(o);
#ifndef BOOST_NO_EXCEPTIONS
	}
	catch (std::exception& e)
	{
		// m_send may fail with "no route to host"
		TORRENT_ASSERT(potential_new_id == m_next_transaction_id);
		o->abort();
	}
#endif
}
Example #3
0
void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
{
	if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
	if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec);

	if (ep.address().is_v4())
	{
		m_ipv4_sock.open(udp::v4(), ec);
		if (ec) return;
		m_ipv4_sock.bind(ep, ec);
		if (ec) return;
		m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf))
			, m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2));
	}
	else
	{
		m_ipv6_sock.set_option(v6only(true), ec);
		if (ec) return;
		m_ipv6_sock.bind(ep, ec);
		if (ec) return;
		m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf))
			, m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2));
	}
	m_bind_port = ep.port();
}
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec)
{
	CHECK_MAGIC;

	TORRENT_ASSERT(is_open());

	// if the sockets are closed, the udp_socket is closing too
	if (!is_open()) return;

	if (m_tunnel_packets)
	{
		// send udp packets through SOCKS5 server
		wrap(ep, p, len, ec);
		return;	
	}

	if (m_queue_packets)
	{
		m_queue.push_back(queued_packet());
		queued_packet& qp = m_queue.back();
		qp.ep = ep;
		qp.buf.insert(qp.buf.begin(), p, p + len);
		return;
	}

#if TORRENT_USE_IPV6
	if (ep.address().is_v4() && m_ipv4_sock.is_open())
#endif
		m_ipv4_sock.send_to(asio::buffer(p, len), ep, 0, ec);
#if TORRENT_USE_IPV6
	else
		m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec);
#endif
}
Example #5
0
string EndpointToString(const udp::endpoint &endpoint)
{	
	string strIp = endpoint.address().to_string();
	unsigned int dwPort = endpoint.port();
	char szIpPort[32] = {0};
	sprintf(szIpPort, "%s:%d", strIp.c_str(), dwPort);
	return szIpPort;
}
Example #6
0
void observer::set_target(udp::endpoint const& ep)
{
	m_sent = clock_type::now();

	m_port = ep.port();
#if TORRENT_USE_IPV6
	if (ep.address().is_v6())
	{
		flags |= flag_ipv6_address;
		m_addr.v6 = ep.address().to_v6().to_bytes();
	}
	else
#endif
	{
		flags &= ~flag_ipv6_address;
		m_addr.v4 = ep.address().to_v4().to_bytes();
	}
}
Example #7
0
	broadcast_socket::broadcast_socket(io_service& ios
		, udp::endpoint const& multicast_endpoint
		, receive_handler_t const& handler
		, bool loopback)
		: m_multicast_endpoint(multicast_endpoint)
		, m_on_receive(handler)
		, m_ip_broadcast(false)
	{
		TORRENT_ASSERT(is_multicast(m_multicast_endpoint.address()));

		using namespace asio::ip::multicast;
	
		error_code ec;
		std::vector<ip_interface> interfaces = enum_net_interfaces(ios, ec);

#if TORRENT_USE_IPV6
		if (multicast_endpoint.address().is_v6())
			open_multicast_socket(ios, address_v6::any(), loopback, ec);
		else
#endif
			open_multicast_socket(ios, address_v4::any(), loopback, ec);
		
		for (std::vector<ip_interface>::const_iterator i = interfaces.begin()
			, end(interfaces.end()); i != end; ++i)
		{
			// only multicast on compatible networks
			if (i->interface_address.is_v4() != multicast_endpoint.address().is_v4()) continue;
			// ignore any loopback interface
			if (!loopback && is_loopback(i->interface_address)) continue;

			ec = error_code();
			open_multicast_socket(ios, i->interface_address, loopback, ec);
#ifndef NDEBUG
//			fprintf(stderr, "broadcast socket [ if: %s group: %s ] %s\n"
//				, i->interface_address.to_string().c_str()
//				, print_address(multicast_endpoint.address()).c_str()
//				, ec.message().c_str());
#endif
			open_unicast_socket(ios, i->interface_address
				, i->netmask.is_v4() ? i->netmask.to_v4() : address_v4());
		}
	}
Example #8
0
	node_entry(node_id const& id_, udp::endpoint ep, int roundtriptime = 0xffff, bool pinged = false)
		: addr(ep.address())
		, port(ep.port())
		, timeout_count(pinged ? 0 : 0xffff)
		, rtt(roundtriptime)
		, id(id_)
	{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
		first_seen = time_now();
#endif
	}
Example #9
0
	node_entry(udp::endpoint ep)
		: addr(ep.address())
		, port(ep.port())
		, timeout_count(0xffff)
		, rtt(0xffff)
		, id(0)
	{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
		first_seen = time_now();
#endif
	}
Example #10
0
bool CUDPSocket::SendData(udp::endpoint&  ep, char* msg, int size, string& errInfo, unsigned long iProxyIp /*= 0*/, unsigned short iProxyPort /*= 0*/)
{
	if(ep.address().to_v4().to_string().empty())
		return false;

	if(ep.address().to_v4().to_string()=="255.255.255.255")
		return false;

	if(ep.port() <=0 || ep.port() >65535)
		return false;


	if(msg == NULL)
		return true;

    try
    {
        int ret = this->m_mySocket.send_to(boost::asio::buffer((const void*)msg, size), ep);
        if (ret < size)
        {
            return false;
        }
    }
    catch (const boost::system::error_code& err)
    {
        ostringstream oss;
        oss << "严重错误 CUDPSocket error_code2 " << err.value();
        make_log_func_(oss.str());
        return false;
    }
    catch (...)
    {
        ostringstream oss;
        oss << "严重错误...";
        make_log_func_(oss.str());
        return false;
    }


	return true;
}
Example #11
0
	node_entry::node_entry(udp::endpoint ep)
		: last_queried(min_time())
		, id(0)
		, a(ep.address().to_v4().to_bytes())
		, p(ep.port())
		, rtt(0xffff)
		, timeout_count(0xff)
	{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
		first_seen = aux::time_now();
#endif
	}
void DatagramTransceiver::sendMessage(const QString &msg, const udp::endpoint& remote_endpoint)
{
   bool write_in_progress = m_write_msgs.empty() == false;

   MessageToSend* struct_msg = new MessageToSend;
   struct_msg->destination_endpoint.address(remote_endpoint.address());
   struct_msg->destination_endpoint.port(remote_endpoint.port());
   struct_msg->msg = msg;

    m_write_msgs.push_back(struct_msg);

    if (write_in_progress == false) doSend();
}
Example #13
0
	node_entry::node_entry(node_id const& id_, udp::endpoint ep
		, int roundtriptime
		, bool pinged)
		: last_queried(pinged ? aux::time_now() : min_time())
		, id(id_)
		, a(ep.address().to_v4().to_bytes())
		, p(ep.port())
		, rtt(roundtriptime & 0xffff)
		, timeout_count(pinged ? 0 : 0xff)
	{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
		first_seen = aux::time_now();
#endif
	}
Example #14
0
void observer::set_target(udp::endpoint const& ep)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
	// use high resolution timers for logging
	m_sent = time_now_hires();
#else
	m_sent = time_now();
#endif

	m_port = ep.port();
#if TORRENT_USE_IPV6
	if (ep.address().is_v6())
	{
		flags |= flag_ipv6_address;
		m_addr.v6 = ep.address().to_v6().to_bytes();
	}
	else
#endif
	{
		flags &= ~flag_ipv6_address;
		m_addr.v4 = ep.address().to_v4().to_bytes();
	}
}
Example #15
0
void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
{
	CHECK_MAGIC;
	TORRENT_ASSERT(is_single_thread());

	TORRENT_ASSERT(m_abort == false);
	if (m_abort)
	{
		ec = boost::asio::error::operation_aborted;
		return;
	}

	if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
#if TORRENT_USE_IPV6
	if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec);
#endif

	if (ep.address().is_v4())
	{
		m_ipv4_sock.open(udp::v4(), ec);
		if (ec) return;
		m_ipv4_sock.bind(ep, ec);
		if (ec) return;
		udp::socket::non_blocking_io ioc(true);
		m_ipv4_sock.io_control(ioc, ec);
		if (ec) return;
		setup_read(&m_ipv4_sock);
	}
#if TORRENT_USE_IPV6
	else
	{
#ifdef IPV6_V6ONLY
		m_ipv6_sock.set_option(v6only(true), ec);
		if (ec) return;
#endif
		m_ipv6_sock.bind(ep, ec);
		if (ec) return;
		udp::socket::non_blocking_io ioc(true);
		m_ipv6_sock.io_control(ioc, ec);
		if (ec) return;
		setup_read(&m_ipv6_sock);
	}
#endif
#ifdef TORRENT_DEBUG
	m_started = true;
#endif
	m_bind_port = ep.port();
}
Example #16
0
void udp_socket::send(udp::endpoint const& ep, char const* p, int len, error_code& ec)
{
	if (ec == asio::error::operation_aborted) return;

	if (m_tunnel_packets)
	{
		// send udp packets through SOCKS5 server
		wrap(ep, p, len, ec);
		return;	
	}

	if (ep.address().is_v4() && m_ipv4_sock.is_open())
		m_ipv4_sock.send_to(asio::buffer(p, len), ep, 0, ec);
	else
		m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec);
}
void udp_socket::bind(udp::endpoint const& ep, error_code& ec)
{
	CHECK_MAGIC;
	mutex_t::scoped_lock l(m_mutex);	

	TORRENT_ASSERT(m_abort == false);
	if (m_abort) return;

	if (m_ipv4_sock.is_open()) m_ipv4_sock.close(ec);
#if TORRENT_USE_IPV6
	if (m_ipv6_sock.is_open()) m_ipv6_sock.close(ec);
#endif

	if (ep.address().is_v4())
	{
		m_ipv4_sock.open(udp::v4(), ec);
		if (ec) return;
		m_ipv4_sock.bind(ep, ec);
		if (ec) return;

		if (m_v4_outstanding == 0)
		{
			++m_v4_outstanding;
			m_ipv4_sock.async_receive_from(asio::buffer(m_v4_buf, sizeof(m_v4_buf))
				, m_v4_ep, boost::bind(&udp_socket::on_read, this, &m_ipv4_sock, _1, _2));
		}
	}
#if TORRENT_USE_IPV6
	else
	{
		m_ipv6_sock.set_option(v6only(true), ec);
		if (ec) return;
		m_ipv6_sock.bind(ep, ec);
		if (ec) return;
		if (m_v6_outstanding == 0)
		{
			++m_v6_outstanding;
			m_ipv6_sock.async_receive_from(asio::buffer(m_v6_buf, sizeof(m_v6_buf))
				, m_v6_ep, boost::bind(&udp_socket::on_read, this, &m_ipv6_sock, _1, _2));
		}
	}
#endif
#ifdef TORRENT_DEBUG
	m_started = true;
#endif
	m_bind_port = ep.port();
}
Example #18
0
//==============================================================================
//	Handle Connection (uglysolution.com)
//	- Checks if the connection already exists. If it exists, restart timeout timer.
//	  Else, add new connection.
//==============================================================================
boost::shared_ptr<Connection> ConnectionHandler::handleConnection( udp::endpoint& _endpoint )
{
    unsigned int connection_size = m_connections.size();

    // Check if the connection already exists
    for( unsigned int i = 0; i < connection_size; i++ )
    {
        if( m_connections[i]->endpoint.address().to_string().compare(_endpoint.address().to_string()) == 0 && m_connections[i]->endpoint.port() == _endpoint.port() )
        {
            boost::shared_ptr<Connection> connection = m_connections[i];
            connection->timout_timer.expires_from_now( boost::posix_time::seconds(TIMEOUT) );
            connection->timout_timer.async_wait( boost::bind(&ConnectionHandler::timeout, this, connection, boost::asio::placeholders::error) );
            return m_connections[i];
        }
    }

    // Check if connection size is greater than the allowed amount of connections
    if( connection_size >= MAX_CONNECTIONS )
        return boost::shared_ptr<Connection>();

    // Find an connection ID
    m_id_counter++;
    for( unsigned int i = 0; i < m_connections.size(); i++ )
    {
        if( m_connections[i]->connection_id == m_id_counter )
        {
            m_id_counter++;
            i = 0;
        }
    }

    // Add the connection and start the timers
    boost::shared_ptr<Connection> new_connection( new Connection(m_id_counter, _endpoint, (*m_io_service)) );
    new_connection->ack_timer.async_wait( boost::bind(&ConnectionHandler::requestAck, this, new_connection, boost::asio::placeholders::error) );
    new_connection->timout_timer.async_wait( boost::bind(&ConnectionHandler::timeout, this, new_connection, boost::asio::placeholders::error) );
    m_connections.push_back( new_connection );

    // temp solution
    if( m_network_handler->isServer() )
        new_connection->sync_timer.async_wait( boost::bind(&ConnectionHandler::syncClock, this, new_connection, boost::asio::placeholders::error) );

    return m_connections.back();
}
Example #19
0
bool dht_tracker::send_packet(entry& e, udp::endpoint const& addr)
{
    static char const version_str[] = {'L', 'T'
                                       , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR
                                      };
    e["v"] = std::string(version_str, version_str + 4);

    m_send_buf.clear();
    bencode(std::back_inserter(m_send_buf), e);

    // update the quota. We won't prevent the packet to be sent if we exceed
    // the quota, we'll just (potentially) block the next incoming request.

    m_send_quota -= int(m_send_buf.size());

    error_code ec;
    m_send_fun(addr, m_send_buf, ec, 0);
    if (ec)
    {
        m_counters.inc_stats_counter(counters::dht_messages_out_dropped);
#ifndef TORRENT_DISABLE_LOGGING
        m_log->log_packet(dht_logger::outgoing_message, m_send_buf, addr);
#endif
        return false;
    }

    m_counters.inc_stats_counter(counters::dht_bytes_out, m_send_buf.size());
    // account for IP and UDP overhead
    m_counters.inc_stats_counter(counters::sent_ip_overhead_bytes
                                 , addr.address().is_v6() ? 48 : 28);
    m_counters.inc_stats_counter(counters::dht_messages_out);
#ifndef TORRENT_DISABLE_LOGGING
    m_log->log_packet(dht_logger::outgoing_message, m_send_buf, addr);
#endif
    return true;
}
Example #20
0
tuple endpoint_to_tuple(udp::endpoint const& ep)
{
    return boost::python::make_tuple(ep.address().to_string(), ep.port());
}
Example #21
0
void udp_socket::send(udp::endpoint const& ep, char const* p, int len
	, error_code& ec, int flags)
{
	CHECK_MAGIC;

	TORRENT_ASSERT(is_single_thread());

	// if the sockets are closed, the udp_socket is closing too
	if (!is_open())
	{
		ec = error_code(boost::system::errc::bad_file_descriptor, boost::system::generic_category());
		return;
	}

	if (!(flags & peer_connection) || m_proxy_settings.proxy_peer_connections)
	{
		if (m_tunnel_packets)
		{
			// send udp packets through SOCKS5 server
			wrap(ep, p, len, ec);
			return;	
		}

		if (m_queue_packets)
		{
			if (m_queue.size() > 1000) return;

			m_queue.push_back(queued_packet());
			queued_packet& qp = m_queue.back();
			qp.ep = ep;
			qp.hostname = 0;
			qp.flags = flags;
			qp.buf.insert(qp.buf.begin(), p, p + len);
			return;
		}
	}

	if (m_force_proxy) return;

#if TORRENT_USE_IPV6
	if (ep.address().is_v6() && m_ipv6_sock.is_open())
		m_ipv6_sock.send_to(asio::buffer(p, len), ep, 0, ec);
	else
#endif
		m_ipv4_sock.send_to(asio::buffer(p, len), ep, 0, ec);

	if (ec == error::would_block || ec == error::try_again)
	{
#if TORRENT_USE_IPV6
		if (ep.address().is_v6() && m_ipv6_sock.is_open())
		{
			if (!m_v6_write_subscribed)
			{
				m_ipv6_sock.async_send(asio::null_buffers()
					, boost::bind(&udp_socket::on_writable, this, _1, &m_ipv6_sock));
				m_v6_write_subscribed = true;
			}
		}
		else
#endif
		{
			if (!m_v4_write_subscribed)
			{
				m_ipv4_sock.async_send(asio::null_buffers()
					, boost::bind(&udp_socket::on_writable, this, _1, &m_ipv4_sock));
				m_v4_write_subscribed = true;
			}
		}
	}
}
uint64_t endpoint_to_i(const udp::endpoint& ep)
{
    uint64_t addr_i = ep.address().to_v4().to_ulong();
    uint32_t port = ep.port();
    return (addr_i << 32) + port;
}
Example #23
0
void upnp::on_reply(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	mutex_t::scoped_lock l(m_mutex);

	using namespace libtorrent::detail;

	// parse out the url for the device

/*
	the response looks like this:

	HTTP/1.1 200 OK
	ST:upnp:rootdevice
	USN:uuid:000f-66d6-7296000099dc::upnp:rootdevice
	Location: http://192.168.1.1:5431/dyndev/uuid:000f-66d6-7296000099dc
	Server: Custom/1.0 UPnP/1.0 Proc/Ver
	EXT:
	Cache-Control:max-age=180
	DATE: Fri, 02 Jan 1970 08:10:38 GMT

	a notification looks like this:

	NOTIFY * HTTP/1.1
	Host:239.255.255.250:1900
	NT:urn:schemas-upnp-org:device:MediaServer:1
	NTS:ssdp:alive
	Location:http://10.0.3.169:2869/upnphost/udhisapi.dll?content=uuid:c17f0c32-d19b-4938-ae94-65f945c3a26e
	USN:uuid:c17f0c32-d19b-4938-ae94-65f945c3a26e::urn:schemas-upnp-org:device:MediaServer:1
	Cache-Control:max-age=900
	Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0

*/
	error_code ec;
	if (!in_local_network(m_io_service, from.address(), ec))
	{
		if (ec)
		{
			char msg[200];
			snprintf(msg, sizeof(msg), "when receiving response from: %s: %s"
				, print_endpoint(from).c_str(), ec.message().c_str());
			log(msg);
		}
		else
		{
			char msg[200];
			int num_chars = snprintf(msg, sizeof(msg)
				, "ignoring response from: %s. IP is not on local network. "
				, print_endpoint(from).c_str());
			log(msg);

			std::vector<ip_interface> net = enum_net_interfaces(m_io_service, ec);
			for (std::vector<ip_interface>::const_iterator i = net.begin()
				, end(net.end()); i != end; ++i)
			{
				num_chars += snprintf(msg + num_chars, sizeof(msg) - num_chars, "(%s,%s) "
					, print_address(i->interface_address).c_str(), print_address(i->netmask).c_str());
			}
			log(msg);
		}
		return;
	} 

	if (m_ignore_non_routers)
	{
		std::vector<ip_route> routes = enum_routes(m_io_service, ec);
		if (std::find_if(routes.begin(), routes.end()
			, bind(&ip_route::gateway, _1) == from.address()) == routes.end())
		{
			// this upnp device is filtered because it's not in the
			// list of configured routers
			if (ec)
			{
				char msg[200];
				snprintf(msg, sizeof(msg), "when receiving response from: %s: %s"
					, print_endpoint(from).c_str(), ec.message().c_str());
				log(msg);
			}
			else
			{
				char msg[200];
				int num_chars = snprintf(msg, sizeof(msg), "ignoring response from: %s: IP is not a router. "
					, print_endpoint(from).c_str());
				for (std::vector<ip_route>::const_iterator i = routes.begin()
					, end(routes.end()); i != end; ++i)
				{
					num_chars += snprintf(msg + num_chars, sizeof(msg) - num_chars, "(%s,%s) "
						, print_address(i->gateway).c_str(), print_address(i->netmask).c_str());
				}
				log(msg);
			}
			return;
		}
	}

	http_parser p;
	bool error = false;
	p.incoming(buffer::const_interval(buffer
		, buffer + bytes_transferred), error);
	if (error)
	{
		char msg[200];
		snprintf(msg, sizeof(msg), "received malformed HTTP from: %s"
			, print_endpoint(from).c_str());
		log(msg);
		return;
	}

	if (p.status_code() != 200 && p.method() != "notify")
	{
		if (p.method().empty())
		{
			char msg[200];
			snprintf(msg, sizeof(msg), "HTTP status %u from %s"
				, p.status_code(), print_endpoint(from).c_str());
			log(msg);
		}
		else
		{
			char msg[200];
			snprintf(msg, sizeof(msg), "HTTP method %s from %s"
				, p.method().c_str(), print_endpoint(from).c_str());
			log(msg);
		}
		return;
	}

	if (!p.header_finished())
	{
		char msg[200];
		snprintf(msg, sizeof(msg), "incomplete HTTP packet from %s"
			, print_endpoint(from).c_str());
		log(msg);
		return;
	}

	std::string url = p.header("location");
	if (url.empty())
	{
		char msg[200];
		snprintf(msg, sizeof(msg), "missing location header from %s"
			, print_endpoint(from).c_str());
		log(msg);
		return;
	}

	rootdevice d;
	d.url = url;

	std::set<rootdevice>::iterator i = m_devices.find(d);

	if (i == m_devices.end())
	{

		std::string protocol;
		std::string auth;
		char const* error;
		// 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);

		if (error)
		{
			char msg[200];
			snprintf(msg, sizeof(msg), "invalid URL %s from %s: %s"
				, d.url.c_str(), print_endpoint(from).c_str(), error);
			log(msg);
			return;
		}

		// ignore the auth here. It will be re-parsed
		// by the http connection later

		if (protocol != "http")
		{
			char msg[200];
			snprintf(msg, sizeof(msg), "unsupported protocol %s from %s"
				, protocol.c_str(), print_endpoint(from).c_str());
			log(msg);
			return;
		}

		if (d.port == 0)
		{
			char msg[200];
			snprintf(msg, sizeof(msg), "URL with port 0 from %s"
				, print_endpoint(from).c_str());
			log(msg);
			return;
		}

		char msg[200];
		snprintf(msg, sizeof(msg), "found rootdevice: %s (%d)"
			, d.url.c_str(), int(m_devices.size()));
		log(msg);

		if (m_devices.size() >= 50)
		{
			char msg[200];
			snprintf(msg, sizeof(msg), "too many rootdevices: (%d). Ignoring %s"
				, int(m_devices.size()), d.url.c_str());
			log(msg);
			return;
		}

		TORRENT_ASSERT(d.mapping.empty());
		for (std::vector<global_mapping_t>::iterator j = m_mappings.begin()
			, end(m_mappings.end()); j != end; ++j)
		{
			mapping_t m;
			m.action = mapping_t::action_add;
			m.local_port = j->local_port;
			m.external_port = j->external_port;
			m.protocol = j->protocol;
			d.mapping.push_back(m);
		}
		boost::tie(i, boost::tuples::ignore) = m_devices.insert(d);
	}


	if (!m_devices.empty())
	{
		for (std::set<rootdevice>::iterator i = m_devices.begin()
			, end(m_devices.end()); i != end; ++i)
		{
			if (i->control_url.empty() && !i->upnp_connection && !i->disabled)
			{
				// we don't have a WANIP or WANPPP url for this device,
				// ask for it
				rootdevice& d = const_cast<rootdevice&>(*i);
				TORRENT_ASSERT(d.magic == 1337);
#ifndef BOOST_NO_EXCEPTIONS
				try
				{
#endif
					char msg[200];
					snprintf(msg, sizeof(msg), "connecting to: %s"
						, d.url.c_str());
					log(msg);

					if (d.upnp_connection) d.upnp_connection->close();
					d.upnp_connection.reset(new http_connection(m_io_service
						, m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
						, boost::ref(d), _5)));
					d.upnp_connection->get(d.url, seconds(30), 1);
#ifndef BOOST_NO_EXCEPTIONS
				}
				catch (std::exception& e)
				{
					(void)e;

					char msg[200];
					snprintf(msg, sizeof(msg), "connection failed to: %s %s"
						, d.url.c_str(), e.what());
					log(msg);
					d.disabled = true;
				}
#endif
			}
		}
	}
}
	bool utp_socket_manager::incoming_packet(std::weak_ptr<utp_socket_interface> socket
		, udp::endpoint const& ep, span<char const> p)
	{
//		UTP_LOGV("incoming packet size:%d\n", size);

		if (p.size() < sizeof(utp_header)) return false;

		utp_header const* ph = reinterpret_cast<utp_header const*>(p.data());

//		UTP_LOGV("incoming packet version:%d\n", int(ph->get_version()));

		if (ph->get_version() != 1) return false;

		const time_point receive_time = clock_type::now();

		// parse out connection ID and look for existing
		// connections. If found, forward to the utp_stream.
		std::uint16_t id = ph->connection_id;

		// first test to see if it's the same socket as last time
		// in most cases it is
		if (m_last_socket
			&& utp_match(m_last_socket, ep, id))
		{
			return utp_incoming_packet(m_last_socket, p, ep, receive_time);
		}

		std::pair<socket_map_t::iterator, socket_map_t::iterator> r =
			m_utp_sockets.equal_range(id);

		for (; r.first != r.second; ++r.first)
		{
			if (!utp_match(r.first->second, ep, id)) continue;
			bool ret = utp_incoming_packet(r.first->second, p, ep, receive_time);
			if (ret) m_last_socket = r.first->second;
			return ret;
		}

//		UTP_LOGV("incoming packet id:%d source:%s\n", id, print_endpoint(ep).c_str());

		if (!m_sett.get_bool(settings_pack::enable_incoming_utp))
			return false;

		// if not found, see if it's a SYN packet, if it is,
		// create a new utp_stream
		if (ph->get_type() == ST_SYN)
		{
			// possible SYN flood. Just ignore
			if (int(m_utp_sockets.size()) > m_sett.get_int(settings_pack::connections_limit) * 2)
				return false;

//			UTP_LOGV("not found, new connection id:%d\n", m_new_connection);

			std::shared_ptr<socket_type> c(new (std::nothrow) socket_type(m_ios));
			if (!c) return false;

			TORRENT_ASSERT(m_new_connection == -1);
			// create the new socket with this ID
			m_new_connection = id;

			instantiate_connection(m_ios, aux::proxy_settings(), *c
				, m_ssl_context, this, true, false);

			utp_stream* str = nullptr;
#ifdef TORRENT_USE_OPENSSL
			if (is_ssl(*c))
				str = &c->get<ssl_stream<utp_stream>>()->next_layer();
			else
#endif
				str = c->get<utp_stream>();

			TORRENT_ASSERT(str);
			int link_mtu, utp_mtu;
			mtu_for_dest(ep.address(), link_mtu, utp_mtu);
			utp_init_mtu(str->get_impl(), link_mtu, utp_mtu);
			utp_init_socket(str->get_impl(), socket);
			bool ret = utp_incoming_packet(str->get_impl(), p, ep, receive_time);
			if (!ret) return false;
			m_cb(c);
			// the connection most likely changed its connection ID here
			// we need to move it to the correct ID
			return true;
		}

		if (ph->get_type() == ST_RESET) return false;

		// #error send reset

		return false;
	}
Example #25
0
void lsd::on_announce(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;

	http_parser p;

	bool error = false;
	p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred)
		, error);

	if (!p.header_finished() || error)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (m_log) fprintf(m_log, "%s <== announce: incomplete HTTP message\n", time_now_string());
#endif
		return;
	}

	if (p.method() != "bt-search")
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (m_log) fprintf(m_log, "%s <== announce: invalid HTTP method: %s\n"
			, time_now_string(), p.method().c_str());
#endif
		return;
	}

	std::string const& port_str = p.header("port");
	if (port_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		if (m_log) fprintf(m_log, "%s <== announce: invalid BT-SEARCH, missing port\n"
			, time_now_string());
#endif
		return;
	}

	int port = std::atoi(port_str.c_str());

	typedef std::multimap<std::string, std::string> headers_t;
	headers_t const& headers = p.headers();

	headers_t::const_iterator cookie_iter = headers.find("cookie");
	if (cookie_iter != headers.end())
	{
		// we expect it to be hexadecimal
		// if it isn't, it's not our cookie anyway
		boost::int32_t cookie = strtol(cookie_iter->second.c_str(), NULL, 16);
		if (cookie == m_cookie)
		{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
			if (m_log) fprintf(m_log, "%s <== announce: ignoring packet (cookie matched our own): %x == %x\n"
				, time_now_string(), cookie, m_cookie);
#endif
			return;
		}
	}

	std::pair<headers_t::const_iterator, headers_t::const_iterator> ihs
		= headers.equal_range("infohash");

	for (headers_t::const_iterator i = ihs.first; i != ihs.second; ++i)
	{
		std::string const& ih_str = i->second;
		if (ih_str.size() != 40)
		{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
			if (m_log) fprintf(m_log, "%s <== announce: invalid BT-SEARCH, invalid infohash: %s\n"
				, time_now_string(), ih_str.c_str());
#endif
			continue;
		}

		sha1_hash ih(0);
		from_hex(ih_str.c_str(), 40, (char*)&ih[0]);

		if (!ih.is_all_zeros() && port != 0)
		{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
			if (m_log) fprintf(m_log, "%s *** incoming local announce %s:%d ih: %s\n"
				, time_now_string(), print_address(from.address()).c_str()
				, port, ih_str.c_str());
#endif
			// we got an announce, pass it on through the callback
			TORRENT_TRY {
				m_callback(tcp::endpoint(from.address(), port), ih);
			} TORRENT_CATCH(std::exception&) {}
		}
	}
}
Example #26
0
bool dht_tracker::incoming_packet(udp::endpoint const& ep
                                  , span<char const> const buf)
{
    int const buf_size = int(buf.size());
    if (buf_size <= 20
            || buf.front() != 'd'
            || buf.back() != 'e') return false;

    m_counters.inc_stats_counter(counters::dht_bytes_in, buf_size);
    // account for IP and UDP overhead
    m_counters.inc_stats_counter(counters::recv_ip_overhead_bytes
                                 , ep.address().is_v6() ? 48 : 28);
    m_counters.inc_stats_counter(counters::dht_messages_in);

    if (m_settings.ignore_dark_internet && ep.address().is_v4())
    {
        address_v4::bytes_type b = ep.address().to_v4().to_bytes();

        // these are class A networks not available to the public
        // if we receive messages from here, that seems suspicious
        static std::uint8_t const class_a[] = { 3, 6, 7, 9, 11, 19, 21, 22, 25
                                                , 26, 28, 29, 30, 33, 34, 48, 51, 56
                                              };

        if (std::find(std::begin(class_a), std::end(class_a), b[0]) != std::end(class_a))
        {
            m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
            return true;
        }
    }

    if (!m_blocker.incoming(ep.address(), clock_type::now(), m_log))
    {
        m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
        return true;
    }

    TORRENT_ASSERT(buf_size > 0);

    int pos;
    error_code err;
    int ret = bdecode(buf.data(), buf.data() + buf_size, m_msg, err, &pos, 10, 500);
    if (ret != 0)
    {
        m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
#ifndef TORRENT_DISABLE_LOGGING
        m_log->log_packet(dht_logger::incoming_message, buf, ep);
#endif
        return false;
    }

    if (m_msg.type() != bdecode_node::dict_t)
    {
        m_counters.inc_stats_counter(counters::dht_messages_in_dropped);
#ifndef TORRENT_DISABLE_LOGGING
        m_log->log_packet(dht_logger::incoming_message, buf, ep);
#endif
        // it's not a good idea to send a response to an invalid messages
        return false;
    }

#ifndef TORRENT_DISABLE_LOGGING
    m_log->log_packet(dht_logger::incoming_message, buf, ep);
#endif

    libtorrent::dht::msg m(m_msg, ep);
    m_dht.incoming(m);
#if TORRENT_USE_IPV6
    m_dht6.incoming(m);
#endif
    return true;
}
Example #27
0
	inline std::string print_endpoint(udp::endpoint const& ep)
	{
		return print_endpoint(tcp::endpoint(ep.address(), ep.port()));
	}
Example #28
0
	bool utp_socket_manager::incoming_packet(error_code const& ec, udp::endpoint const& ep
			, char const* p, int size)
	{
//		UTP_LOGV("incoming packet size:%d\n", size);

		if (size < int(sizeof(utp_header))) return false;

		utp_header const* ph = (utp_header*)p;

//		UTP_LOGV("incoming packet version:%d\n", int(ph->get_version()));

		if (ph->get_version() != 1) return false;

		const ptime receive_time = time_now_hires();
		
		// parse out connection ID and look for existing
		// connections. If found, forward to the utp_stream.
		boost::uint16_t id = ph->connection_id;

		// first test to see if it's the same socket as last time
		// in most cases it is
		if (m_last_socket
			&& utp_match(m_last_socket, ep, id))
		{
			return utp_incoming_packet(m_last_socket, p, size, ep, receive_time);
		}

		std::pair<socket_map_t::iterator, socket_map_t::iterator> r =
			m_utp_sockets.equal_range(id);

		for (; r.first != r.second; ++r.first)
		{
			if (!utp_match(r.first->second, ep, id)) continue;
			bool ret = utp_incoming_packet(r.first->second, p, size, ep, receive_time);
			if (ret) m_last_socket = r.first->second;
			return ret;
		}

//		UTP_LOGV("incoming packet id:%d source:%s\n", id, print_endpoint(ep).c_str());

		if (!m_sett.enable_incoming_utp)
			return false;

		// if not found, see if it's a SYN packet, if it is,
		// create a new utp_stream
		if (ph->get_type() == ST_SYN)
		{
			// possible SYN flood. Just ignore
			if (m_utp_sockets.size() > m_sett.connections_limit * 2)
				return false;

//			UTP_LOGV("not found, new connection id:%d\n", m_new_connection);

			boost::shared_ptr<socket_type> c(new (std::nothrow) socket_type(m_sock.get_io_service()));
			if (!c) return false;

			TORRENT_ASSERT(m_new_connection == -1);
			// create the new socket with this ID
			m_new_connection = id;

			instantiate_connection(m_sock.get_io_service(), proxy_settings(), *c, 0, this);
			utp_stream* str = c->get<utp_stream>();
			TORRENT_ASSERT(str);
			int link_mtu, utp_mtu;
			mtu_for_dest(ep.address(), link_mtu, utp_mtu);
			utp_init_mtu(str->get_impl(), link_mtu, utp_mtu);
			bool ret = utp_incoming_packet(str->get_impl(), p, size, ep, receive_time);
			if (!ret) return false;
			m_cb(c);
			// the connection most likely changed its connection ID here
			// we need to move it to the correct ID
			return true;
		}

		// #error send reset

		return false;
	}
Example #29
0
void lsd::on_announce(udp::endpoint const& from, char* buffer
	, std::size_t bytes_transferred)
{
	using namespace libtorrent::detail;

	http_parser p;

	bool error = false;
	p.incoming(buffer::const_interval(buffer, buffer + bytes_transferred)
		, error);

	if (!p.header_finished() || error)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: incomplete HTTP message\n";
#endif
		return;
	}

	if (p.method() != "bt-search")
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid HTTP method: " << p.method() << std::endl;
#endif
		return;
	}

	std::string const& port_str = p.header("port");
	if (port_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing port" << std::endl;
#endif
		return;
	}

	std::string const& ih_str = p.header("infohash");
	if (ih_str.empty())
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
	m_log << time_now_string()
		<< " <== announce: invalid BT-SEARCH, missing infohash" << std::endl;
#endif
		return;
	}

	sha1_hash ih(0);
	std::istringstream ih_sstr(ih_str);
	ih_sstr >> ih;
	int port = std::atoi(port_str.c_str());

	if (!ih.is_all_zeros() && port != 0)
	{
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
		m_log << time_now_string()
			<< " *** incoming local announce " << from.address()
			<< ":" << to_string(port).elems << " ih: " << ih << std::endl;
#endif
		// we got an announce, pass it on through the callback
#ifndef BOOST_NO_EXCEPTIONS
		try {
#endif
			m_callback(tcp::endpoint(from.address(), port), ih);
#ifndef BOOST_NO_EXCEPTIONS
		}
		catch (std::exception&) {}
#endif
	}
}
Example #30
0
long UdpTransport::send_buffer(
    const udp::endpoint& target, const char* buf, size_t size)
{
  uint64_t bytes_sent = 0;

  int send_attempts = -1;
  ssize_t actual_sent = -1;

  while (actual_sent < 0 && (settings_.resend_attempts < 0 ||
                                send_attempts < settings_.resend_attempts))
  {
    if(settings_.max_send_hertz > 0)
    {
      enforcer_.sleep_until_next();
    }

    // send the fragment
    try
    {
      actual_sent = socket_.send_to(asio::buffer(buf, size), target);
    }
    catch (const boost::system::system_error& e)
    {
      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "UdpTransport::send_buffer:"
          " Error sending packet to %s:%d: %s\n",
          target.address().to_string().c_str(), (int)target.port(), e.what());

      // ensure erroneous data is not being used
      actual_sent = -1;
    }

    ++send_attempts;
    if(settings_.debug_to_kb_prefix != "")
    {
      ++sent_packets;
    }

    if(actual_sent > 0)
    {
      madara_logger_log(context_.get_logger(), logger::LOG_MAJOR,
          "UdpTransport::send_buffer: Sent %d byte packet to %s:%d\n",
          (int)actual_sent, target.address().to_string().c_str(),
          (int)target.port());

      bytes_sent += actual_sent;

      if(settings_.debug_to_kb_prefix != "")
      {
        sent_data += actual_sent;
        if(sent_data_max < actual_sent)
        {
          sent_data_max = actual_sent;
        }
        if(sent_data_min > actual_sent || sent_data_min == 0)
        {
          sent_data_min = actual_sent;
        }
      }
    }
    else
    {
      if(settings_.debug_to_kb_prefix != "")
      {
        ++failed_sends;
      }
    }
  }

  return (long)bytes_sent;
}