blob: 56de9a25681b2bef40d87e694bb4597e2aa68720 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fuchsia/overnet/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/task.h>
#include "fuchsia_port.h"
#include "garnet/lib/overnet/router_endpoint.h"
#include "lib/component/cpp/startup_context.h"
#include "mdns.h"
namespace overnetstack {
class FuchsiaTimer final : public overnet::Timer {
public:
overnet::TimeStamp Now() override {
return ToTimeStamp(async::Now(dispatcher_));
}
private:
async_dispatcher_t* dispatcher_ = async_get_default_dispatcher();
struct Task : public async_task_t {
overnet::Timeout* timeout;
};
static void TaskHandler(async_dispatcher_t* async, async_task_t* task,
zx_status_t status) {
FireTimeout(static_cast<Task*>(task)->timeout, ToOvernetStatus(status));
}
void InitTimeout(overnet::Timeout* timeout,
overnet::TimeStamp when) override {
auto* async_timeout = TimeoutStorage<Task>(timeout);
async_timeout->state = {ASYNC_STATE_INIT};
async_timeout->handler = TaskHandler;
async_timeout->deadline = FromTimeStamp(when).get();
async_timeout->timeout = timeout;
if (async_post_task(dispatcher_, async_timeout) != ZX_OK) {
FireTimeout(timeout, overnet::Status::Cancelled());
}
}
void CancelTimeout(overnet::Timeout* timeout,
overnet::Status status) override {
if (async_cancel_task(dispatcher_, TimeoutStorage<Task>(timeout)) ==
ZX_OK) {
FireTimeout(timeout, overnet::Status::Cancelled());
}
}
};
class FuchsiaLog final : public overnet::TraceSinkInterface {
public:
void Done() override {}
void Trace(overnet::TraceOutput output) override {
auto severity = [sev = output.severity] {
switch (sev) {
case overnet::Severity::DEBUG:
return fxl::LOG_INFO;
case overnet::Severity::INFO:
return fxl::LOG_INFO;
case overnet::Severity::WARNING:
return fxl::LOG_WARNING;
case overnet::Severity::ERROR:
return fxl::LOG_ERROR;
}
}();
fxl::LogMessage(severity, output.file, output.line, nullptr).stream()
<< output.message;
}
};
static FuchsiaLog fuchsia_log;
static overnet::TraceSink fuchsia_trace_sink(overnet::Severity::INFO,
&fuchsia_log);
overnet::NodeId GenerateNodeId() {
uint64_t out;
zx_cprng_draw(&out, sizeof(out));
return overnet::NodeId(out);
}
class OvernetApp final : public fuchsia::overnet::Overnet {
public:
OvernetApp() : context_(component::StartupContext::CreateFromStartupInfo()) {
context_->outgoing().AddPublicService(bindings_.GetHandler(this));
}
overnet::Status Start() {
return udp_nub_.Start().Then([this]() {
mdns_advert_ =
std::make_unique<MdnsAdvertisement>(context_.get(), &udp_nub_);
RunMdnsIntroducer(context_.get(), &udp_nub_);
return overnet::Status::Ok();
});
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Method implementations
void ListPeers(ListPeersCallback callback) override {
using Peer = fuchsia::overnet::Peer;
std::vector<Peer> response;
endpoint_.ForEachPeer([&response](overnet::NodeId node) {
response.emplace_back(Peer{node.get()});
});
callback(fidl::VectorPtr<Peer>(std::move(response)));
}
private:
FuchsiaTimer timer_;
std::unique_ptr<component::StartupContext> context_;
fidl::BindingSet<fuchsia::overnet::Overnet> bindings_;
overnet::RouterEndpoint endpoint_{&timer_, fuchsia_trace_sink,
GenerateNodeId(), true};
UdpNub udp_nub_{&endpoint_, fuchsia_trace_sink};
std::unique_ptr<MdnsAdvertisement> mdns_advert_;
};
} // namespace overnetstack
int main(int argc, const char** argv) {
async::Loop loop(&kAsyncLoopConfigAttachToThread);
overnetstack::OvernetApp app;
auto status = app.Start().Then([&]() {
loop.Run();
return overnet::Status::Ok();
});
if (status.is_ok()) {
return 0;
} else {
std::cerr << "Failed to start overnetstack: " << status << "\n";
return static_cast<int>(status.code());
}
}