| // 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. | |
| #ifndef LIB_FIDL_CPP_INTERFACE_REQUEST_H_ | |
| #define LIB_FIDL_CPP_INTERFACE_REQUEST_H_ | |
| #include <lib/fidl/epitaph.h> | |
| #include <lib/fit/function.h> | |
| #include <lib/zx/channel.h> | |
| #include <cstddef> | |
| #include <utility> | |
| #include "lib/fidl/cpp/clone.h" | |
| #include "lib/fidl/cpp/coding_traits.h" | |
| namespace fidl { | |
| class Builder; | |
| // The server endpoint of a FIDL channel. | |
| // | |
| // The remote end of the channel expects this end of the channel to speak the | |
| // protocol associated with |Interface|. This type is the dual of | |
| // |InterfaceHandle|. | |
| // | |
| // An |InterfaceRequest| does not have thread affinity and can therefore be | |
| // transferred to another thread or another process. To bind an implementation | |
| // of |Interface| to this |InterfaceRequest|, use a |Binding| object. | |
| // | |
| // Typically, |InterfaceRequest| objects are created by a prospective client of | |
| // |Interface|, which then sends the |InterfaceRequest| to another process to | |
| // request that the remote process implement the |Interface|. This pattern | |
| // enables *pipelined* operation, in which the client can start calling methods | |
| // on an associated |InterfacePtr| immediately, before the |InterfaceRequest| | |
| // has reached the remote process and been bound to an implementation. These | |
| // method calls are buffered by the underlying channel until they are read by | |
| // the remote process. | |
| // | |
| // Example: | |
| // | |
| // #include "foo.fidl.h" | |
| // | |
| // class FooImpl : public Foo { | |
| // public: | |
| // explicit FooImpl(InterfaceRequest<Foo> request) | |
| // : binding_(this, std::move(request)) {} | |
| // | |
| // // Foo implementation here. | |
| // | |
| // private: | |
| // Binding<Foo> binding_; | |
| // }; | |
| // | |
| // After the |InterfaceRequest| has been bound to an implementation, the | |
| // implementation will receive method calls from the remote endpoint of the | |
| // channel on the thread to which the |InterfaceRequest| was bound. | |
| // | |
| // See also: | |
| // | |
| // * |InterfaceHandle|, which is the client analog of an |InterfaceRequest|. | |
| template <typename Interface> | |
| class InterfaceRequest final { | |
| public: | |
| // Creates an |InterfaceHandle| whose underlying channel is invalid. | |
| // | |
| // Some protocols contain messages that permit such |InterfaceRequest| | |
| // objects, which indicate that the client is not interested in the server | |
| // providing an implementation of |Interface|. | |
| InterfaceRequest() = default; | |
| // Creates an |InterfaceHandle| that wraps the given |channel|. | |
| explicit InterfaceRequest(zx::channel channel) : channel_(std::move(channel)) {} | |
| InterfaceRequest(const InterfaceRequest& other) = delete; | |
| InterfaceRequest& operator=(const InterfaceRequest& other) = delete; | |
| InterfaceRequest(InterfaceRequest&& other) : channel_(std::move(other.channel_)) {} | |
| InterfaceRequest& operator=(InterfaceRequest&& other) { | |
| channel_ = std::move(other.channel_); | |
| return *this; | |
| } | |
| // Implicit conversion from nullptr to an |InterfaceRequest| with an | |
| // invalid |channel|. | |
| InterfaceRequest(std::nullptr_t) {} | |
| // Whether the underlying channel is valid. | |
| bool is_valid() const { return !!channel_; } | |
| explicit operator bool() const { return is_valid(); } | |
| // Transfers ownership of the underlying channel to the caller. | |
| zx::channel TakeChannel() { return std::move(channel_); } | |
| // The underlying channel. | |
| const zx::channel& channel() const { return channel_; } | |
| void set_channel(zx::channel channel) { channel_ = std::move(channel); } | |
| void Encode(Encoder* encoder, size_t offset) { encoder->EncodeHandle(&channel_, offset); } | |
| static void Decode(Decoder* decoder, InterfaceRequest<Interface>* value, size_t offset) { | |
| decoder->DecodeHandle(&value->channel_, offset); | |
| } | |
| // Sends an Epitaph over the bound channel corresponding to the error passed | |
| // as a parameter, closes the channel, and unbinds it. An Epitaph is the last | |
| // message sent over a channel before a close operation; for the purposes of | |
| // this function, it can be thought of as a return code. See the FIDL | |
| // language spec for more information about Epitaphs. | |
| // | |
| // The return value can be any of the return values of zx_channel_write. | |
| zx_status_t Close(zx_status_t epitaph_value) { | |
| return is_valid() ? fidl_epitaph_write(TakeChannel().get(), epitaph_value) : ZX_ERR_BAD_STATE; | |
| } | |
| private: | |
| zx::channel channel_; | |
| }; | |
| // A |InterfaceRequestHandler<Interface>| is simply a function that | |
| // handles an interface request for |Interface|. If it determines that the | |
| // request should be "accepted", then it should "connect" ("take ownership | |
| // of") request. Otherwise, it can simply drop |request| (as implied by the | |
| // interface). | |
| template <typename Interface> | |
| using InterfaceRequestHandler = fit::function<void(fidl::InterfaceRequest<Interface> request)>; | |
| // Equality. | |
| template <typename T> | |
| struct Equality<InterfaceRequest<T>> { | |
| bool operator()(const InterfaceRequest<T>& lhs, const InterfaceRequest<T>& rhs) const { | |
| return lhs.channel() == rhs.channel(); | |
| } | |
| }; | |
| template <typename T> | |
| struct CodingTraits<InterfaceRequest<T>> | |
| : public EncodableCodingTraits<InterfaceRequest<T>, sizeof(zx_handle_t)> {}; | |
| template <typename T> | |
| inline zx_status_t Clone(const InterfaceRequest<T>& value, InterfaceRequest<T>* result) { | |
| if (!value) { | |
| *result = InterfaceRequest<T>(); | |
| return ZX_OK; | |
| } | |
| return ZX_ERR_ACCESS_DENIED; | |
| } | |
| } // namespace fidl | |
| #endif // LIB_FIDL_CPP_INTERFACE_REQUEST_H_ |