1 // 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_MESSAGE_H_
6 #define LIB_FIDL_CPP_MESSAGE_H_
7 
8 #include <lib/fidl/coding.h>
9 #include <lib/fidl/cpp/message_part.h>
10 #include <zircon/fidl.h>
11 
12 namespace fidl {
13 
14 // A FIDL message.
15 //
16 // A FIDL message has two parts: the bytes and the handles. The bytes are
17 // divided into a header (of type fidl_message_header_t) and a payload, which
18 // follows the header.
19 //
20 // A Message object does not own the storage for the message parts.
21 class Message {
22 public:
23     // Creates a message without any storage.
24     Message();
25 
26     // Creates a message whose storage is backed by |bytes| and |handles|.
27     //
28     // The constructed |Message| object does not take ownership of the given
29     // storage, although does take ownership of zircon handles contained withing
30     // handles.
31     Message(BytePart bytes, HandlePart handles);
32 
33     ~Message();
34 
35     Message(const Message& other) = delete;
36     Message& operator=(const Message& other) = delete;
37 
38     Message(Message&& other);
39     Message& operator=(Message&& other);
40 
41     // Whether the message has enough bytes to contain a fidl_message_header_t.
has_header()42     bool has_header() const {
43         return bytes_.actual() >= sizeof(fidl_message_header_t);
44     }
45 
46     // The header at the start of the message.
47     //
48     // Valid only if has_header().
header()49     const fidl_message_header_t& header() const {
50         return *reinterpret_cast<fidl_message_header_t*>(bytes_.data());
51     }
header()52     fidl_message_header_t& header() {
53         return *reinterpret_cast<fidl_message_header_t*>(bytes_.data());
54     }
55 
56     // The transaction ID in the message header.
57     //
58     // Valid only if has_header().
txid()59     zx_txid_t txid() const { return header().txid; }
set_txid(zx_txid_t txid)60     void set_txid(zx_txid_t txid) { header().txid = txid; }
61 
62     // The flags in the message header.
63     //
64     // Valid only if has_header().
flags()65     uint32_t flags() const { return header().flags; }
66 
67     // The flags in the message header.
68     //
69     // Valid only if has_header().
ordinal()70     uint32_t ordinal() const { return header().ordinal; }
71 
72     // The message payload that follows the header.
73     //
74     // Valid only if has_header().
payload()75     BytePart payload() const {
76         constexpr uint32_t n = sizeof(fidl_message_header_t);
77         return BytePart(bytes_.data() + n, bytes_.capacity() - n, bytes_.actual() - n);
78     }
79 
80     // The message bytes interpreted as the given type.
81     template <typename T>
GetBytesAs()82     T* GetBytesAs() const {
83         return reinterpret_cast<T*>(bytes_.data());
84     }
85 
86     // The message payload that follows the header interpreted as the given type.
87     //
88     // Valid only if has_header().
89     template <typename T>
GetPayloadAs()90     T* GetPayloadAs() const {
91         return reinterpret_cast<T*>(bytes_.data() + sizeof(fidl_message_header_t));
92     }
93 
94     // The storage for the bytes of the message.
bytes()95     BytePart& bytes() { return bytes_; }
bytes()96     const BytePart& bytes() const { return bytes_; }
set_bytes(BytePart bytes)97     void set_bytes(BytePart bytes) { bytes_ = static_cast<BytePart&&>(bytes); }
98 
99     // The storage for the handles of the message.
100     //
101     // When the message is encoded, the handle values are stored in this part of
102     // the message. When the message is decoded, this part of the message is
103     // empty and the handle values are stored in the bytes().
handles()104     HandlePart& handles() { return handles_; }
handles()105     const HandlePart& handles() const { return handles_; }
106 
107     // Encodes the message in-place.
108     //
109     // The message must previously have been in a decoded state, for example,
110     // either by being built in a decoded state using a |Builder| or having been
111     // decoded using the |Decode| method.
112     zx_status_t Encode(const fidl_type_t* type, const char** error_msg_out);
113 
114     // Decodes the message in-place.
115     //
116     // The message must previously have been in an encoded state, for example,
117     // either by being read from a zx_channel_t or having been encoded using the
118     // |Encode| method.
119     zx_status_t Decode(const fidl_type_t* type, const char** error_msg_out);
120 
121     // Validates the message in-place.
122     //
123     // The message must already be in an encoded state, for example, either by
124     // being read from a zx_channel_t or having been created in that state.
125     //
126     // Does not modify the message.
127     zx_status_t Validate(const fidl_type_t* type, const char** error_msg_out) const;
128 
129     // Read a message from the given channel.
130     //
131     // The bytes read from the channel are stored in bytes() and the handles
132     // read from the channel are stored in handles(). Existing data in these
133     // buffers is overwritten.
134     zx_status_t Read(zx_handle_t channel, uint32_t flags);
135 
136     // Writes a message to the given channel.
137     //
138     // The bytes stored in bytes() are written to the channel and the handles
139     // stored in handles() are written to the channel.
140     //
141     // If this method returns ZX_OK, handles() will be empty because they were
142     // consumed by this operation.
143     zx_status_t Write(zx_handle_t channel, uint32_t flags);
144 
145     // Issues a synchronous send and receive transaction on the given channel.
146     //
147     // The bytes stored in bytes() are written to the channel and the handles
148     // stored in handles() are written to the channel. The bytes read from the
149     // channel are stored in response->bytes() and the handles read from the
150     // channel are stored in response->handles().
151     //
152     // If this method returns ZX_OK, handles() will be empty because they were
153     // consumed by this operation.
154     zx_status_t Call(zx_handle_t channel, uint32_t flags, zx_time_t deadline,
155                      Message* response);
156 
157     // Stop tracking the handles in stored in handles(), without closing them.
158     //
159     // Typically, these handles will be extracted during decode or the
160     // message's destructor, so this function will be unnecessary. However,
161     // for clients of ulib/fidl which decode message manually, this function
162     // is necessary to prevent extracted handles from being closed.
163     void ClearHandlesUnsafe();
164 
165 private:
166     BytePart bytes_;
167     HandlePart handles_;
168 };
169 
170 } // namespace fidl
171 
172 #endif // LIB_FIDL_CPP_MESSAGE_H_
173