blob: 3ec05aca317bca4fa22966722b94a577c71a377f [file] [log] [blame]
// Copyright 2022 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.
// [START fidl_includes]
#include <fidl/fuchsia.examples/cpp/fidl.h>
// [END fidl_includes]
// [START includes]
#include <lib/async-loop/cpp/loop.h>
#include <lib/sys/component/llcpp/outgoing_directory.h>
#include <lib/syslog/cpp/macros.h>
// [END includes]
// [START server]
class EchoImpl : public fidl::Server<fuchsia_examples::Echo> {
public:
// [START bind_server]
// Bind a new implementation to a channel. The implementation deletes itself
// when the connection tears down.
static void BindSelfManagedServer(async_dispatcher_t* dispatcher,
fidl::ServerEnd<fuchsia_examples::Echo> server_end) {
std::unique_ptr impl = std::make_unique<EchoImpl>();
EchoImpl* impl_ptr = impl.get();
fidl::ServerBindingRef binding_ref = fidl::BindServer(
dispatcher, std::move(server_end), std::move(impl), std::mem_fn(&EchoImpl::OnUnbound));
impl_ptr->binding_ref_.emplace(std::move(binding_ref));
}
// [END bind_server]
// Called when the connection is torn down, shortly before the implementation is destroyed.
void OnUnbound(fidl::UnbindInfo info, fidl::ServerEnd<fuchsia_examples::Echo> server_end) {
if (info.is_peer_closed()) {
FX_LOGS(INFO) << "Client disconnected";
} else if (!info.is_user_initiated()) {
FX_LOGS(ERROR) << "Server error: " << info;
}
}
void EchoString(EchoStringRequest& request, EchoStringCompleter::Sync& completer) override {
completer.Reply({request.value()});
}
void SendString(SendStringRequest& request, SendStringCompleter::Sync& completer) override {
ZX_ASSERT(binding_ref_.has_value());
fitx::result result = fidl::SendEvent(*binding_ref_)->OnString({request.value()});
if (!result.is_ok()) {
FX_LOGS(ERROR) << "Error sending event: " << result.error_value();
}
}
private:
std::optional<fidl::ServerBindingRef<fuchsia_examples::Echo>> binding_ref_;
};
// [END server]
// [START main]
int main(int argc, const char** argv) {
// Initialize the async loop. The Echo server will use the dispatcher of this
// loop to listen for incoming requests.
async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
async_dispatcher_t* dispatcher = loop.dispatcher();
// Create an OutgoingDirectory class which will serve incoming requests.
component::OutgoingDirectory outgoing = component::OutgoingDirectory::Create(dispatcher);
zx::status result = outgoing.ServeFromStartupInfo();
if (result.is_error()) {
FX_LOGS(ERROR) << "Failed to serve outgoing directory: " << result.status_string();
return -1;
}
// Register a handler for components trying to connect to fuchsia.examples.Echo.
result = outgoing.AddProtocol<fuchsia_examples::Echo>(
[dispatcher](fidl::ServerEnd<fuchsia_examples::Echo> server_end) {
FX_LOGS(INFO) << "Incoming connection for "
<< fidl::DiscoverableProtocolName<fuchsia_examples::Echo>;
EchoImpl::BindSelfManagedServer(dispatcher, std::move(server_end));
});
if (result.is_error()) {
FX_LOGS(ERROR) << "Failed to add Echo protocol: " << result.status_string();
return -1;
}
FX_LOGS(INFO) << "Running unified C++ echo server";
loop.Run();
return 0;
}
// [END main]