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(); }
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)); }
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)); }
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); }
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); }
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(); }
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; }