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 #pragma once
6 
7 #include <lib/zx/channel.h>
8 #include <zircon/fidl.h>
9 
10 namespace devmgr {
11 
12 // Manages state of a FIDL transaction so we can reply to the correct message.
13 // FidlTxn must not outlive the channel it is given
14 class FidlTxn {
15 public:
FidlTxn(zx::unowned_channel channel,uint32_t txid)16     FidlTxn(zx::unowned_channel channel, uint32_t txid) : channel_(channel), txid_(txid) { }
FidlTxn(const zx::channel & channel,uint32_t txid)17     FidlTxn(const zx::channel& channel, uint32_t txid) : channel_(channel), txid_(txid) { }
18 
19     FidlTxn& operator=(const FidlTxn&) = delete;
20     FidlTxn(const FidlTxn&) = delete;
21 
22     FidlTxn& operator=(FidlTxn&&) = delete;
23     FidlTxn(FidlTxn&&) = delete;
24 
Reply(const fidl_msg_t * msg)25     zx_status_t Reply(const fidl_msg_t* msg) {
26         auto hdr = static_cast<fidl_message_header_t*>(msg->bytes);
27         hdr->txid = txid_;
28         return channel_->write(0, msg->bytes, msg->num_bytes,
29                                msg->handles, msg->num_handles);
30     }
31 
FidlReply(fidl_txn_t * reply,const fidl_msg_t * msg)32     static zx_status_t FidlReply(fidl_txn_t* reply, const fidl_msg_t* msg) {
33         static_assert(offsetof(FidlTxn, txn_) == 0);
34         return reinterpret_cast<FidlTxn*>(reply)->Reply(msg);
35     }
36 
fidl_txn()37     fidl_txn_t* fidl_txn() { return &txn_; }
38 
39 private:
40     // Due to the implementation of FidlReply, it is important that this be the
41     // first member variable.
42     fidl_txn_t txn_ = { .reply = FidlTxn::FidlReply };
43 
44     // Reply channel
45     const zx::unowned_channel channel_;
46 
47     // Transaction id of the message we're replying to
48     const uint32_t txid_;
49 };
50 
51 } // namespace devmgr
52