1#ifndef ANDROID_PDX_RPC_PAYLOAD_H_
2#define ANDROID_PDX_RPC_PAYLOAD_H_
3
4#include <iterator>
5
6#include <pdx/client.h>
7#include <pdx/rpc/message_buffer.h>
8#include <pdx/service.h>
9
10namespace android {
11namespace pdx {
12namespace rpc {
13
14// Implements the payload interface, required by Serialize/Deserialize, on top
15// of a thread-local MessageBuffer.
16template <typename Slot>
17class MessagePayload {
18 public:
19  using BufferType = typename MessageBuffer<Slot>::BufferType;
20  using ValueType = typename MessageBuffer<Slot>::ValueType;
21
22  // Constructs a MessagePayload with an empty TLS buffer.
23  MessagePayload()
24      : buffer_(MessageBuffer<Slot>::GetEmptyBuffer()),
25        cursor_(buffer_.begin()),
26        const_cursor_(buffer_.cbegin()) {}
27
28  // Returns a reference to the cursor iterator to be used during serialization
29  // into the underlying MessageBuffer.
30  typename BufferType::iterator& Cursor() { return cursor_; }
31
32  // Returns a reference to the const cursor iterator at the beginning of the
33  // underlying MessageBuffer.
34  typename BufferType::const_iterator& ConstCursor() { return const_cursor_; }
35
36  // Returns a const iterator marking the end of the underlying MessageBuffer.
37  typename BufferType::const_iterator ConstEnd() { return buffer_.cend(); }
38
39  // Resizes the underlying MessageBuffer and sets the cursor to the beginning.
40  void Resize(std::size_t size) {
41    buffer_.resize(size);
42    cursor_ = buffer_.begin();
43    const_cursor_ = buffer_.cbegin();
44  }
45
46  // Resets the read cursor so that data can be read from the buffer again.
47  void Rewind() { const_cursor_ = buffer_.cbegin(); }
48
49  // Adds |size| bytes to the size of the underlying MessageBuffer and positions
50  // the cursor at the beginning of the extended region.
51  void Extend(std::size_t size) {
52    const std::size_t offset = buffer_.size();
53    buffer_.resize(offset + size);
54    cursor_ = buffer_.begin() + offset;
55    const_cursor_ = buffer_.cbegin() + offset;
56  }
57
58  // Clears the underlying MessageBuffer and sets the cursor to the beginning.
59  void Clear() {
60    buffer_.clear();
61    cursor_ = buffer_.begin();
62    const_cursor_ = buffer_.cbegin();
63  }
64
65  ValueType* Data() { return buffer_.data(); }
66  const ValueType* Data() const { return buffer_.data(); }
67  std::size_t Size() const { return buffer_.size(); }
68  std::size_t Capacity() const { return buffer_.capacity(); }
69
70 private:
71  BufferType& buffer_;
72  typename BufferType::iterator cursor_;
73  typename BufferType::const_iterator const_cursor_;
74
75  MessagePayload(const MessagePayload<Slot>&) = delete;
76  void operator=(const MessagePayload<Slot>&) = delete;
77};
78
79// Implements the payload interface for service-side RPCs. Handles translating
80// between remote and local handle spaces automatically.
81template <typename Slot>
82class ServicePayload : public MessagePayload<Slot>,
83                       public MessageWriter,
84                       public MessageReader {
85 public:
86  ServicePayload(Message& message) : message_(message) {}
87
88  // MessageWriter
89  void* GetNextWriteBufferSection(size_t size) override {
90    this->Extend(size);
91    return &*this->Cursor();
92  }
93
94  OutputResourceMapper* GetOutputResourceMapper() override { return &message_; }
95
96  // MessageReader
97  BufferSection GetNextReadBufferSection() override {
98    return {&*this->ConstCursor(), &*this->ConstEnd()};
99  }
100
101  void ConsumeReadBufferSectionData(const void* new_start) override {
102    std::advance(this->ConstCursor(),
103                 PointerDistance(new_start, &*this->ConstCursor()));
104  }
105
106  InputResourceMapper* GetInputResourceMapper() override { return &message_; }
107
108 private:
109  Message& message_;
110};
111
112// Implements the payload interface for client-side RPCs. Handles gathering file
113// handles to be sent over IPC automatically.
114template <typename Slot>
115class ClientPayload : public MessagePayload<Slot>,
116                      public MessageWriter,
117                      public MessageReader {
118 public:
119  using ContainerType =
120      MessageBuffer<ThreadLocalTypeSlot<ClientPayload<Slot>>, 1024u, int>;
121  using BufferType = typename ContainerType::BufferType;
122
123  ClientPayload(Transaction& transaction) : transaction_{transaction} {}
124
125  // MessageWriter
126  void* GetNextWriteBufferSection(size_t size) override {
127    this->Extend(size);
128    return &*this->Cursor();
129  }
130
131  OutputResourceMapper* GetOutputResourceMapper() override {
132    return &transaction_;
133  }
134
135  // MessageReader
136  BufferSection GetNextReadBufferSection() override {
137    return {&*this->ConstCursor(), &*this->ConstEnd()};
138  }
139
140  void ConsumeReadBufferSectionData(const void* new_start) override {
141    std::advance(this->ConstCursor(),
142                 PointerDistance(new_start, &*this->ConstCursor()));
143  }
144
145  InputResourceMapper* GetInputResourceMapper() override {
146    return &transaction_;
147  }
148
149 private:
150  Transaction& transaction_;
151};
152
153}  // namespace rpc
154}  // namespace pdx
155}  // namespace android
156
157#endif  // ANDROID_PDX_RPC_PAYLOAD_H_
158