| // 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_ |