blob: 5272231fabab8084c84aef7197022eac43ccabc0 [file] [log] [blame]
Doug Horn1427b6a2018-12-11 13:19:16 -08001// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef LIB_FIDL_CPP_INTERNAL_MESSAGE_READER_H_
6#define LIB_FIDL_CPP_INTERNAL_MESSAGE_READER_H_
7
8#include <lib/async/wait.h>
9#include <lib/fidl/cpp/message.h>
10#include <lib/fidl/cpp/message_buffer.h>
11#include <lib/fit/function.h>
12#include <lib/zx/channel.h>
13
14#include <functional>
15#include <memory>
16#include <utility>
17
18#include "lib/fidl/cpp/internal/message_handler.h"
19
20namespace fidl {
21namespace internal {
22
23class MessageReader {
24 public:
25 explicit MessageReader(MessageHandler* message_handler = nullptr);
26 ~MessageReader();
27
28 MessageReader(const MessageReader&) = delete;
29 MessageReader& operator=(const MessageReader&) = delete;
30
31 // Binds the given channel to this |MessageReader|.
32 //
33 // The |MessageReader| will wait asynchronously for messages on this channel
34 // and dispatch them to the message handler using |dispatcher|. After this
35 // method returns, the |MessageReader| will be waiting for incomming messages.
36 //
37 // If the |MessageReader| is already bound, the |MessageReader| will first
38 // be unbound.
39 //
40 // If |dispatcher| is null, the current thread must have a default async_t.
41 zx_status_t Bind(zx::channel channel,
42 async_dispatcher_t* dispatcher = nullptr);
43
44 // Unbinds the channel from this |MessageReader|.
45 //
46 // The |MessageReader| will stop waiting for the messages on this channel.
47 //
48 // Returns the channel to which this |MessageReader| was previously bound, if
49 // any.
50 zx::channel Unbind();
51
52 // Unbinds the channel from this |MessageReader| and clears the error handler.
53 void Reset();
54
55 // Unbinds the channel from |other| and bindings it to this |MessageReader|.
56 //
57 // Also moves the error handler from |other| to this |MessageReader|.
58 //
59 // Useful for implementing move semantics for objects that have a
60 // |MessageReader|.
61 zx_status_t TakeChannelAndErrorHandlerFrom(MessageReader* other);
62
63 // Sends an epitaph with the given value, unbinds, and then closes the channel
64 // associated with this |MessageReader|.
65 //
66 // The |MessageReader| will send an Epitaph with the given error, unbind
67 // the channel, and then close it.
68 //
69 // The return value can be any of the return values of zx_channel_write.
70 zx_status_t Close(zx_status_t epitaph_value);
71
72 // Whether the |MessageReader| is currently bound.
73 //
74 // See |Bind()| and |Unbind()|.
75 bool is_bound() const { return channel_.is_valid(); }
76
77 // The channel to which this |MessageReader| is bound, if any.
78 const zx::channel& channel() const { return channel_; }
79
80 // Synchronously waits on |channel()| until either a message is available or
81 // the peer closes. If the channel is readable, reads a single message from
82 // the channel and dispatches it to the message handler.
83 //
84 // Returns |ZX_ERR_BAD_STATE| if this |MessageReader| is not bound, or if it
85 // receives a malformed Epitaph.
86 zx_status_t WaitAndDispatchOneMessageUntil(zx::time deadline);
87
88 // The given message handler is called whenever the |MessageReader| reads a
89 // message from the channel.
90 //
91 // The |Message| given to the message handler will be valid until the message
92 // handler returns.
93 //
94 // The handler should return ZX_OK if the message was handled and an error
95 // otherwise. If the handler returns ZX_OK, the |MessageReader| will continue
96 // to wait for messages.
97 //
98 // The handler can destroy the |MessageReader|, in which case the
99 // handler MUST return |ZX_ERR_STOP|. If the handler returns
100 // |ZX_ERR_SHOULD_WAIT|, the |MessageReader| will continue waiting. Other
101 // errors cause the |MessageReader| to unbind from the channel and call the
102 // error handler.
103 void set_message_handler(MessageHandler* message_handler) {
104 message_handler_ = message_handler;
105 }
106
107 // The given error handler is called whenever the |MessageReader| encounters
108 // an error on the channel.
109 //
110 // If the error is being reported because an error occurred on the local side
111 // of the channel, the zx_status_t of that error will be passed as the
112 // parameter to the handler.
113 //
114 // If an Epitaph was present on the channel, its error value will be passed as
115 // the parameter. See the FIDL language specification for more detail on
116 // Epitaphs.
117 //
118 // For example, the error handler will be called if the remote side of the
119 // channel sends an invalid message. When the error handler is called, the
120 // |Binding| will no longer be bound to the channel.
121 //
122 // The handler can destroy the |MessageReader|.
123 void set_error_handler(fit::function<void(zx_status_t)> error_handler) {
124 error_handler_ = std::move(error_handler);
125 }
126
127 private:
128 static void CallHandler(async_dispatcher_t* dispatcher, async_wait_t* wait,
129 zx_status_t status, const zx_packet_signal_t* signal);
130 void OnHandleReady(async_dispatcher_t* dispatcher, zx_status_t status,
131 const zx_packet_signal_t* signal);
132 zx_status_t ReadAndDispatchMessage(MessageBuffer* buffer);
133 void NotifyError(zx_status_t epitaph_value);
134 void Stop();
135
136 async_wait_t wait_; // Must be first.
137 zx::channel channel_;
138 async_dispatcher_t* dispatcher_;
139 bool* should_stop_; // See |Canary| in message_reader.cc.
140 MessageHandler* message_handler_;
141 fit::function<void(zx_status_t)> error_handler_;
142};
143
144} // namespace internal
145} // namespace fidl
146
147#endif // LIB_FIDL_CPP_INTERNAL_MESSAGE_READER_H_