Beispiel #1
0
    std::string address() const {
        if (endpoint_.address().is_v6()) {
            std::string result;
            result.push_back('[');
            result.append(endpoint().address().to_string());
            result.push_back(']');
            return result;
        }

        return endpoint_.address().to_string();
    }
Beispiel #2
0
 virtual request_t build_request(endpoint_type ep, error_code & ec)
 {
     request_t rc = request_t();
     if(!ep.address().is_v4())
     {
         ec = error_code(boost::asio::error::address_family_not_supported);
         return rc;
     }
     rc.detail.version = 4;
     rc.detail.command = 1;
     rc.detail.destination_port = ::htons(ep.port());
     rc.detail.destination_address = ep.address().to_v4().to_bytes();
     rc.detail.end_marker = 0;
     return rc;
 }
	void async_connect(endpoint_type const& endpoint, Handler const& handler)
	{
		// make sure we don't try to connect to INADDR_ANY. binding is fine,
		// and using a hostname is fine on SOCKS version 5.
		TORRENT_ASSERT(m_command == socks5_bind
			|| endpoint.address() != address()
			|| (!m_dst_name.empty() && m_version == 5));

		m_remote_endpoint = endpoint;

		// the connect is split up in the following steps:
		// 1. resolve name of proxy server
		// 2. connect to proxy server
		// 3. if version == 5:
		//   3.1 send SOCKS5 authentication method message
		//   3.2 read SOCKS5 authentication response
		//   3.3 send username+password
		// 4. send SOCKS command message

		// to avoid unnecessary copying of the handler,
		// store it in a shaed_ptr
		boost::shared_ptr<handler_type> h(new handler_type(handler));

		ADD_OUTSTANDING_ASYNC("socks5_stream::name_lookup");
		tcp::resolver::query q(m_hostname, to_string(m_port).elems);
		m_resolver.async_resolve(q, boost::bind(
			&socks5_stream::name_lookup, this, _1, _2, h));
	}
Beispiel #4
0
    static inline
    void
    pack(msgpack::packer<Stream>& target, const endpoint_type& source) {
        const std::string address = source.address().to_string();
        const unsigned short port = source.port();

        type_traits<tuple_type>::pack(target, tuple_type(address, port));
    }
Beispiel #5
0
    static inline
    void
    unpack(const msgpack::object& source, endpoint_type& target) {
        std::string address;
        unsigned short port;

        type_traits<tuple_type>::unpack(source, std::move(std::tie(address, port)));

        target.address(boost::asio::ip::address::from_string(address));
        target.port(port);
    }
Beispiel #6
0
	void async_connect(endpoint_type const& endpoint, Handler const& handler)
	{
		if (!endpoint.address().is_v4())
		{
			m_io_service.post(boost::bind<void>(handler, boost::asio::error::operation_not_supported, 0));
			return;
		}

		if (m_impl == 0)
		{
			m_io_service.post(boost::bind<void>(handler, boost::asio::error::not_connected, 0));
			return;
		}

		m_connect_handler = handler;
		do_connect(endpoint);
	}
Beispiel #7
0
    boost::system::error_code
    bind
        ( endpoint_type const& e )
    {
        // Only fixed port is handled right now.
        if ( e.port() != FIXED_PORT )
            return make_error_code( boost::system::errc::invalid_argument );

        // Generate our local address.
        if ( e.address().is_v4() )
            local_endpoint( generate_unique_ipv4_endpoint( e.port() ) );
        else
            local_endpoint( generate_unique_ipv6_endpoint( e.port() ) );

        add_route_to_socket( local_endpoint(), this );
        return boost::system::error_code();
    }
Beispiel #8
0
Handoff
OverlayImpl::onHandoff (std::unique_ptr <beast::asio::ssl_bundle>&& ssl_bundle,
    beast::http::message&& request,
        endpoint_type remote_endpoint)
{
    auto const id = next_id_++;
    beast::WrappedSink sink (deprecatedLogs()["Peer"], makePrefix(id));
    beast::Journal journal (sink);

    Handoff handoff;
    if (processRequest(request, handoff))
        return handoff;
    if (! isPeerUpgrade(request))
        return handoff;

    handoff.moved = true;

    if (journal.trace) journal.trace <<
        "Peer connection upgrade from " << remote_endpoint;

    error_code ec;
    auto const local_endpoint (ssl_bundle->socket.local_endpoint(ec));
    if (ec)
    {
        if (journal.trace) journal.trace <<
            remote_endpoint << " failed: " << ec.message();
        return handoff;
    }

    auto consumer = m_resourceManager.newInboundEndpoint(
        beast::IPAddressConversion::from_asio(remote_endpoint));
    if (consumer.disconnect())
        return handoff;

    auto const slot = m_peerFinder->new_inbound_slot (
        beast::IPAddressConversion::from_asio(local_endpoint),
            beast::IPAddressConversion::from_asio(remote_endpoint));

    if (slot == nullptr)
    {
        // self-connect, close
        handoff.moved = false;
        return handoff;
    }

    // TODO Validate HTTP request

    {
        auto const types = beast::rfc2616::split_commas(
            request.headers["Connect-As"]);
        if (std::find_if(types.begin(), types.end(),
                [](std::string const& s)
                {
                    return beast::ci_equal(s, "peer");
                }) == types.end())
        {
            handoff.moved = false;
            handoff.response = makeRedirectResponse(slot, request,
                remote_endpoint.address());
            handoff.keep_alive = request.keep_alive();
            return handoff;
        }
    }

    handoff.moved = true;
    bool success = true;

    protocol::TMHello hello;
    std::tie(hello, success) = parseHello (request, journal);
    if(! success)
        return handoff;

    uint256 sharedValue;
    std::tie(sharedValue, success) = makeSharedValue(
        ssl_bundle->stream.native_handle(), journal);
    if(! success)
        return handoff;

    RippleAddress publicKey;
    std::tie(publicKey, success) = verifyHello (hello,
        sharedValue, journal, getApp());
    if(! success)
        return handoff;

    std::string name;
    bool const cluster = getApp().getUNL().nodeInCluster(
        publicKey, name);
    
    auto const result = m_peerFinder->activate (slot,
        publicKey.toPublicKey(), cluster);
    if (result != PeerFinder::Result::success)
    {
        if (journal.trace) journal.trace <<
            "Peer " << remote_endpoint << " redirected, slots full";
        handoff.moved = false;
        handoff.response = makeRedirectResponse(slot, request,
            remote_endpoint.address());
        handoff.keep_alive = request.keep_alive();
        return handoff;
    }

    auto const peer = std::make_shared<PeerImp>(id,
        remote_endpoint, slot, std::move(request), hello, publicKey,
            consumer, std::move(ssl_bundle), *this);
    {
        // As we are not on the strand, run() must be called
        // while holding the lock, otherwise new I/O can be
        // queued after a call to stop().
        std::lock_guard <decltype(mutex_)> lock (mutex_);
        add(peer);
        peer->run();
    }
    handoff.moved = true;
    return handoff;
}