blob: e89e8bc85eb86f952bc70d2f7fd61742da7314a8 [file] [log] [blame]
// Copyright 2014 The Chromium 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 <memory>
#include "examples/echo/echo.mojom.h"
#include "mojo/common/binding_set.h"
#include "mojo/public/c/system/main.h"
#include "mojo/public/cpp/application/application_impl_base.h"
#include "mojo/public/cpp/application/run_application.h"
#include "mojo/public/cpp/application/service_provider_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace mojo {
namespace examples {
// This file demonstrates three ways to implement a simple Mojo server. Because
// there's no state that's saved per-pipe, all three servers appear to the
// client to do exactly the same thing.
//
// To choose one of the them, update MojoMain() at the end of this file.
// 1. MultiServer - creates a new object for each connection. Cleans up by using
// StrongBinding.
// 2. SingletonServer -- all requests are handled by one object. Connections are
// tracked using BindingSet.
// 3. OneAtATimeServer -- each request "replaces" any previous request. Any old
// interface pipe is closed and the new interface pipe is bound.
// EchoImpl defines our implementation of the Echo interface.
// It is used by all three server variants.
class EchoImpl : public Echo {
public:
void EchoString(const mojo::String& value,
const Callback<void(mojo::String)>& callback) override {
callback.Run(value);
}
};
// StrongBindingEchoImpl inherits from EchoImpl and adds the StrongBinding<>
// class so instances will delete themselves when the message pipe is closed.
// This simplifies lifetime management. This class is only used by MultiServer.
class StrongBindingEchoImpl : public EchoImpl {
public:
explicit StrongBindingEchoImpl(InterfaceRequest<Echo> handle)
: strong_binding_(this, handle.Pass()) {}
private:
mojo::StrongBinding<Echo> strong_binding_;
};
// MultiServer creates a new object to handle each message pipe.
class MultiServer : public mojo::ApplicationImplBase {
public:
MultiServer() {}
// From ApplicationImplBase
bool OnAcceptConnection(ServiceProviderImpl* service_provider_impl) override {
service_provider_impl->AddService<Echo>(
[](const mojo::ConnectionContext& connection_context,
mojo::InterfaceRequest<Echo> echo_request) {
// This object will be deleted automatically because of the use of
// StrongBinding<> for the declaration of |strong_binding_|.
new StrongBindingEchoImpl(echo_request.Pass());
});
return true;
}
};
// SingletonServer uses the same object to handle all message pipes. Useful
// for stateless operation.
class SingletonServer : public mojo::ApplicationImplBase {
public:
SingletonServer() {}
// From ApplicationImplBase
bool OnAcceptConnection(ServiceProviderImpl* service_provider_impl) override {
service_provider_impl->AddService<Echo>(
[this](const mojo::ConnectionContext& connection_context,
mojo::InterfaceRequest<Echo> echo_request) {
// All channels will connect to this singleton object, so just
// add the binding to our collection.
bindings_.AddBinding(&echo_impl_, echo_request.Pass());
});
return true;
}
private:
EchoImpl echo_impl_;
mojo::BindingSet<Echo> bindings_;
};
// OneAtATimeServer works with only one pipe at a time. When a new pipe tries
// to bind, the previous pipe is closed. This would seem to be useful when
// clients are expected to make a single call and then go away, but in fact it's
// not reliable. There's a race condition because a second client could bind
// to the server before the first client called EchoString(). Therefore, this
// is an example of how not to write your code.
class OneAtATimeServer : public mojo::ApplicationImplBase {
public:
OneAtATimeServer() : binding_(&echo_impl_) {}
// From ApplicationImplBase
bool OnAcceptConnection(ServiceProviderImpl* service_provider_impl) override {
service_provider_impl->AddService<Echo>(
[this](const mojo::ConnectionContext& connection_context,
mojo::InterfaceRequest<Echo> echo_request) {
binding_.Bind(echo_request.Pass());
});
return true;
}
private:
EchoImpl echo_impl_;
mojo::Binding<Echo> binding_;
};
} // namespace examples
} // namespace mojo
MojoResult MojoMain(MojoHandle application_request) {
// Uncomment one of the three servers at a time to see it work:
mojo::examples::MultiServer server_app;
// mojo::examples::SingletonServer server_app;
// mojo::examples::OneAtATimeServer server_app;
return mojo::RunApplication(application_request, &server_app);
}