Skip to content

Commit

Permalink
Fixes #39
Browse files Browse the repository at this point in the history
Made some requestors.
  • Loading branch information
John-LittleBearLabs committed Nov 15, 2023
1 parent ca50166 commit 7041b31
Show file tree
Hide file tree
Showing 64 changed files with 2,244 additions and 347 deletions.
2 changes: 1 addition & 1 deletion cmake/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def electron_version(self, branch='main'):
def unavailable(self):
avail = list(map(as_int, self.available()))
version_set = {}
fuzz = 115
fuzz = 59876
def check(version, version_set, s):
i = as_int(version)
by = (fuzz,0)
Expand Down
63 changes: 63 additions & 0 deletions component/block_http_request.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "block_http_request.h"

#include <services/network/public/cpp/resource_request.h>
#include <services/network/public/cpp/simple_url_loader.h>
#include <services/network/public/mojom/url_response_head.mojom.h>

using Self = ipfs::BlockHttpRequest;

namespace {
constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("ipfs_gateway_request", R"(
semantics {
sender: "IPFS component"
description:
"Sends a request to an IPFS gateway."
trigger:
"Processing of an ipfs:// or ipns:// URL."
data: "None"
destination: WEBSITE
}
policy {
cookies_allowed: NO
setting: "EnableIpfs"
}
)");
}

Self::BlockHttpRequest(ipfs::HttpRequestDescription req_inf,
HttpCompleteCallback cb,
raw_ptr<network::mojom::URLLoaderFactory> loader_factory)
: callback_{cb} {
auto req = std::make_unique<network::ResourceRequest>();
req->url = GURL{req_inf.url};
req->priority = net::HIGHEST; // TODO
if (!req_inf.accept.empty()) {
req->headers.SetHeader("Accept", req_inf.accept);
}
using L = network::SimpleURLLoader;
loader_ = L::Create(std::move(req), kTrafficAnnotation, FROM_HERE);
loader_->SetTimeoutDuration(base::Seconds(req_inf.timeout_seconds));
loader_->SetAllowHttpErrorResults(true);
auto bound = base::BindOnce(&Self::OnResponse, base::Unretained(this));
DCHECK(loader_factory);
loader_->DownloadToString(loader_factory, std::move(bound),
gw::BLOCK_RESPONSE_BUFFER_SIZE);
}
Self::~BlockHttpRequest() noexcept {}
void Self::OnResponse(std::unique_ptr<std::string> body) {
auto const* head = loader_->ResponseInfo();
auto status_text = head->headers->GetStatusText();
LOG(INFO) << "Handling body of size " << body->size() << " and status of "
<< status_text;
int status = std::atoi(status_text.c_str());
auto hdrs = [head](std::string_view k) {
std::string val;
head->headers->EnumerateHeader(nullptr, k, &val);
return val;
};
callback_(status, *body, hdrs);
}
void Self::self_ownership(std::unique_ptr<BlockHttpRequest>& p) {
self_.swap(p);
}
38 changes: 38 additions & 0 deletions component/block_http_request.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#ifndef IPFS_BLOCK_HTTP_REQUEST_H_
#define IPFS_BLOCK_HTTP_REQUEST_H_

#include <ipfs_client/gw/gateway_request.h>

#include <ipfs_client/context_api.h>

namespace network {
struct ResourceRequest;
class SimpleURLLoader;
} // namespace network
namespace network::mojom {
class URLLoaderFactory;
}

namespace ipfs {
class BlockHttpRequest {
// TODO ween oneself off of SimpleURLLoader
// std::array<char, gw::BLOCK_RESPONSE_BUFFER_SIZE> buffer_;
std::unique_ptr<BlockHttpRequest> self_;
std::unique_ptr<network::SimpleURLLoader> loader_;

public:
using HttpCompleteCallback = ipfs::ContextApi::HttpCompleteCallback;
BlockHttpRequest(ipfs::HttpRequestDescription,
HttpCompleteCallback,
raw_ptr<network::mojom::URLLoaderFactory>);
~BlockHttpRequest() noexcept;
void self_ownership(std::unique_ptr<BlockHttpRequest>&);

private:
HttpCompleteCallback callback_;

void OnResponse(std::unique_ptr<std::string> body);
};
} // namespace ipfs

#endif // IPFS_BLOCK_HTTP_REQUEST_H_
2 changes: 1 addition & 1 deletion component/cache_requestor.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "cache_requestor.h"

#include "gateway_requests.h"
#include "chromium_ipfs_context.h"
#include "inter_request_state.h"

#include <base/timer/timer.h>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
#include "gateway_requests.h"
#include "chromium_ipfs_context.h"

#include "block_http_request.h"
#include "crypto_api.h"
#include "inter_request_state.h"
#include "ipns_cbor.h"

#include <services/network/public/cpp/simple_url_loader.h>
#include "base/strings/escape.h"
#include "net/base/mime_sniffer.h"
#include "net/base/mime_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "url/gurl.h"

#include <ipfs_client/dag_block.h>
#include <ipfs_client/ipfs_request.h>
#include <ipfs_client/ipns_record.h>

#include <libp2p/multi/content_identifier_codec.hpp>
#include <libp2p/peer/peer_id.hpp>

#include <base/logging.h>

using Self = ipfs::GatewayRequests;
using Self = ipfs::ChromiumIpfsContext;

constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
net::DefineNetworkTrafficAnnotation("ipfs_gateway_request", R"(
Expand Down Expand Up @@ -207,17 +209,19 @@ bool Self::ProcessResponse(BusyGateway& gw,
auto duration = (end_time - start_time).InMillisecondsRoundedUp();
if (cid.value().content_type ==
libp2p::multi::MulticodecType::Code::LIBP2P_KEY) {
auto as_peer = libp2p::peer::PeerId::fromHash(cid.value().content_address);
if (!as_peer.has_value()) {
LOG(INFO) << cid_str
<< " has the codec of being a libp2p key, like one would "
"expect of a Peer ID, but it does not parse as a Peer ID.";
return false;
}
// auto as_peer =
// libp2p::peer::PeerId::fromHash(cid.value().content_address); if
// (!as_peer.has_value()) {
// LOG(INFO) << cid_str
// << " has the codec of being a libp2p key, like one would "
// "expect of a Peer ID, but it does not parse as a Peer
// ID.";
// return false;
// }
auto* bytes = reinterpret_cast<Byte const*>(body->data());
auto record =
ValidateIpnsRecord({bytes, body->size()}, as_peer.value(),
crypto_api::VerifySignature, ParseCborIpns);
// auto record = ValidateIpnsRecord({bytes, body->size()},
// as_peer.value(), crypto_api::VerifySignature, ParseCborIpns);
auto record = ValidateIpnsRecord({bytes, body->size()}, cid.value(), *this);
if (!record.has_value()) {
LOG(ERROR) << "IPNS record failed to validate! From: " << gw.url();
return false;
Expand Down Expand Up @@ -247,7 +251,9 @@ bool Self::ProcessResponse(BusyGateway& gw,
auto& orc = state_->orchestrator();
orc.add_node(cid_str, ipld::DagNode::fromBlock(block));
if (gw.srcreq) {
orc.build_response(gw.srcreq->dependent);
if (gw.srcreq->dependent->ready_after()) {
orc.build_response(gw.srcreq->dependent);
}
} else {
LOG(ERROR) << "This BusyGateway with response has no top-level "
"IpfsRequest associated with it "
Expand Down Expand Up @@ -291,13 +297,14 @@ std::string Self::MimeType(std::string extension,
} else {
result.clear();
}
if (net::SniffMimeType({content.data(), content.size()}, GURL{url}, result,
auto head_size = std::min(content.size(), 999'999UL);
if (net::SniffMimeType({content.data(), head_size}, GURL{url}, result,
net::ForceSniffFileUrlsForHtml::kDisabled, &result)) {
VLOG(1) << "Got " << result << " from content of " << url;
}
if (result.empty() || result == "application/octet-stream") {
// C'mon, man
net::SniffMimeTypeFromLocalData({content.data(), content.size()}, &result);
net::SniffMimeTypeFromLocalData({content.data(), head_size}, &result);
LOG(INFO) << "Falling all the way back to content type " << result;
}
return result;
Expand All @@ -319,14 +326,45 @@ void Self::RequestByCid(std::string cid,
prio, {});
sched_.IssueRequests(me);
}
void Self::SendDnsTextRequest(std::string host,
DnsTextResultsCallback res,
DnsTextCompleteCallback don) {
if (dns_reqs_.find(host) != dns_reqs_.end()) {
LOG(ERROR) << "Requested resolution of DNSLink host " << host
<< " multiple times.";
}
auto don_wrap = [don, this, host]() {
don();
LOG(INFO) << "Finished resolving " << host << " via DNSLink";
dns_reqs_.erase(host);
};
dns_reqs_[host] = std::make_unique<DnsTxtRequest>(host, res, don_wrap,
network_context_.get());
}
void Self::SendHttpRequest(HttpRequestDescription req_inf,
HttpCompleteCallback cb) const {
auto ptr = std::make_unique<BlockHttpRequest>(req_inf, cb, loader_factory_);
ptr->self_ownership(ptr);
}
auto Self::deserialize_cbor(ByteView bytes) const -> IpnsCborEntry {
return ParseCborIpns(bytes);
}
bool Self::verify_key_signature(SigningKeyType t,
ByteView signature,
ByteView data,
ByteView key_bytes) const {
return crypto_api::VerifySignature(static_cast<ipns::KeyType>(t), signature,
data, key_bytes);
}

Self::GatewayRequests(InterRequestState& state)
Self::ChromiumIpfsContext(InterRequestState& state)
: state_{state},
sched_([this]() { return state_->gateways().GenerateList(); }) {}
Self::~GatewayRequests() {
Self::~ChromiumIpfsContext() {
LOG(WARNING) << "API dtor - are all URIs loaded?";
}

Self::GatewayUrlLoader::GatewayUrlLoader(BusyGateway&& bg)
: GatewayRequest(std::move(bg)) {}
Self::GatewayUrlLoader::~GatewayUrlLoader() noexcept {}

26 changes: 20 additions & 6 deletions component/gateway_requests.h → component/chromium_ipfs_context.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#ifndef IPFS_GATEWAY_REQUESTS_H_
#define IPFS_GATEWAY_REQUESTS_H_
#ifndef IPFS_CHROMIUM_IPFS_CONTEXT_H_
#define IPFS_CHROMIUM_IPFS_CONTEXT_H_

#include "dns_txt_request.h"

#include <ipfs_client/block_storage.h>
#include <ipfs_client/context_api.h>
Expand All @@ -24,7 +26,7 @@ class InterRequestState;
class IpfsRequest;
class NetworkRequestor;

class GatewayRequests final : public ContextApi {
class ChromiumIpfsContext final : public ContextApi {
struct GatewayUrlLoader : public ipfs::GatewayRequest {
GatewayUrlLoader(BusyGateway&&);
GatewayUrlLoader(GatewayRequest&&);
Expand All @@ -33,16 +35,28 @@ class GatewayRequests final : public ContextApi {
};

raw_ptr<network::mojom::URLLoaderFactory> loader_factory_ = nullptr;
raw_ptr<network::mojom::NetworkContext> network_context_; // TODO initialize
raw_ref<InterRequestState> state_;
Scheduler sched_;
std::function<void(std::vector<std::string>)> disc_cb_;
std::map<std::string, std::unique_ptr<DnsTxtRequest>> dns_reqs_;

void Request(std::string task, std::shared_ptr<DagListener>, Priority);
std::shared_ptr<GatewayRequest> InitiateGatewayRequest(BusyGateway) override;
std::string MimeType(std::string extension,
std::string_view content,
std::string const& url) const override;
std::string UnescapeUrlComponent(std::string_view) const override;
void SendDnsTextRequest(std::string,
DnsTextResultsCallback,
DnsTextCompleteCallback) override;
void SendHttpRequest(HttpRequestDescription req_inf,
HttpCompleteCallback cb) const override;
IpnsCborEntry deserialize_cbor(ByteView) const override;
bool verify_key_signature(SigningKeyType,
ByteView signature,
ByteView data,
ByteView key_bytes) const override;

void OnResponse(std::shared_ptr<ContextApi>,
std::shared_ptr<GatewayUrlLoader>,
Expand All @@ -59,13 +73,13 @@ class GatewayRequests final : public ContextApi {
Priority);

public:
GatewayRequests(InterRequestState&);
~GatewayRequests();
ChromiumIpfsContext(InterRequestState&);
~ChromiumIpfsContext();
void SetLoaderFactory(network::mojom::URLLoaderFactory&);
Scheduler& scheduler();
void Discover(std::function<void(std::vector<std::string>)>) override;
};

} // namespace ipfs

#endif // IPFS_GATEWAY_REQUESTS_H_
#endif // IPFS_CHROMIUM_IPFS_CONTEXT_H_
37 changes: 37 additions & 0 deletions component/dns_txt_request.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "dns_txt_request.h"

#include <services/network/network_context.h>
#include <services/network/public/mojom/host_resolver.mojom.h>

namespace moj = network::mojom;
using Self = ipfs::DnsTxtRequest;

Self::DnsTxtRequest(std::string host,
ipfs::ContextApi::DnsTextResultsCallback res,
ipfs::ContextApi::DnsTextCompleteCallback don,
moj::NetworkContext* network_context)
: results_callback_{res}, completion_callback_{don} {
auto params = moj::ResolveHostParameters::New();
params->dns_query_type = net::DnsQueryType::TXT;
params->initial_priority = net::RequestPriority::HIGHEST;
params->source = net::HostResolverSource::ANY;
params->cache_usage = moj::ResolveHostParameters_CacheUsage::STALE_ALLOWED;
params->secure_dns_policy = moj::SecureDnsPolicy::ALLOW;
params->purpose = moj::ResolveHostParameters::Purpose::kUnspecified;
LOG(INFO) << "Querying DNS for TXT records on " << host;
auto hrh = moj::HostResolverHost::NewHostPortPair({host, 0});
auto nak = net::NetworkAnonymizationKey::CreateTransient();
network_context->ResolveHost(std::move(hrh), nak, std::move(params),
recv_.BindNewPipeAndPassRemote());
}
Self::~DnsTxtRequest() {}

void Self::OnTextResults(std::vector<std::string> const& results) {
results_callback_(results);
}
void Self::OnComplete(int32_t,
const ::net::ResolveErrorInfo&,
const absl::optional<::net::AddressList>&,
const absl::optional<Endpoints>&) {
completion_callback_();
}
36 changes: 36 additions & 0 deletions component/dns_txt_request.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef IPFS_DNS_TXT_REQUEST_H_
#define IPFS_DNS_TXT_REQUEST_H_

#include <ipfs_client/context_api.h>

#include <mojo/public/cpp/bindings/receiver.h>
#include <services/network/public/cpp/resolve_host_client_base.h>

namespace network::mojom {
class NetworkContext;
}

namespace ipfs {
class DnsTxtRequest final : public network::ResolveHostClientBase {
ipfs::ContextApi::DnsTextResultsCallback results_callback_;
ipfs::ContextApi::DnsTextCompleteCallback completion_callback_;
mojo::Receiver<network::mojom::ResolveHostClient> recv_{this};

using Endpoints = std::vector<::net::HostResolverEndpointResult>;
void OnTextResults(std::vector<std::string> const&) override;
void OnComplete(int32_t result,
::net::ResolveErrorInfo const&,
absl::optional<::net::AddressList> const&,
absl::optional<Endpoints> const&) override;

public:
DnsTxtRequest(std::string,
ipfs::ContextApi::DnsTextResultsCallback,
ipfs::ContextApi::DnsTextCompleteCallback,
network::mojom::NetworkContext*);
DnsTxtRequest(DnsTxtRequest&&) = delete;
~DnsTxtRequest() noexcept override;
};
} // namespace ipfs

#endif // IPFS_DNS_TXT_REQUEST_H_
Loading

0 comments on commit 7041b31

Please sign in to comment.