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