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 
10 namespace android {
11 namespace pdx {
12 namespace rpc {
13 
14 // Implements the payload interface, required by Serialize/Deserialize, on top
15 // of a thread-local MessageBuffer.
16 template <typename Slot>
17 class 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.
MessagePayload()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.
Cursor()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.
ConstCursor()34   typename BufferType::const_iterator& ConstCursor() { return const_cursor_; }
35 
36   // Returns a const iterator marking the end of the underlying MessageBuffer.
ConstEnd()37   typename BufferType::const_iterator ConstEnd() { return buffer_.cend(); }
38 
39   // Resizes the underlying MessageBuffer and sets the cursor to the beginning.
Resize(std::size_t size)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.
Rewind()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.
Extend(std::size_t size)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.
Clear()59   void Clear() {
60     buffer_.clear();
61     cursor_ = buffer_.begin();
62     const_cursor_ = buffer_.cbegin();
63   }
64 
Data()65   ValueType* Data() { return buffer_.data(); }
Data()66   const ValueType* Data() const { return buffer_.data(); }
Size()67   std::size_t Size() const { return buffer_.size(); }
Capacity()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.
81 template <typename Slot>
82 class ServicePayload : public MessagePayload<Slot>,
83                        public MessageWriter,
84                        public MessageReader {
85  public:
ServicePayload(Message & message)86   explicit ServicePayload(Message& message) : message_(message) {}
87 
88   // MessageWriter
GetNextWriteBufferSection(size_t size)89   void* GetNextWriteBufferSection(size_t size) override {
90     this->Extend(size);
91     return &*this->Cursor();
92   }
93 
GetOutputResourceMapper()94   OutputResourceMapper* GetOutputResourceMapper() override { return &message_; }
95 
96   // MessageReader
GetNextReadBufferSection()97   BufferSection GetNextReadBufferSection() override {
98     return {&*this->ConstCursor(), &*this->ConstEnd()};
99   }
100 
ConsumeReadBufferSectionData(const void * new_start)101   void ConsumeReadBufferSectionData(const void* new_start) override {
102     std::advance(this->ConstCursor(),
103                  PointerDistance(new_start, &*this->ConstCursor()));
104   }
105 
GetInputResourceMapper()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.
114 template <typename Slot>
115 class 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 
ClientPayload(Transaction & transaction)123   explicit ClientPayload(Transaction& transaction)
124       : transaction_{transaction} {}
125 
126   // MessageWriter
GetNextWriteBufferSection(size_t size)127   void* GetNextWriteBufferSection(size_t size) override {
128     this->Extend(size);
129     return &*this->Cursor();
130   }
131 
GetOutputResourceMapper()132   OutputResourceMapper* GetOutputResourceMapper() override {
133     return &transaction_;
134   }
135 
136   // MessageReader
GetNextReadBufferSection()137   BufferSection GetNextReadBufferSection() override {
138     return {&*this->ConstCursor(), &*this->ConstEnd()};
139   }
140 
ConsumeReadBufferSectionData(const void * new_start)141   void ConsumeReadBufferSectionData(const void* new_start) override {
142     std::advance(this->ConstCursor(),
143                  PointerDistance(new_start, &*this->ConstCursor()));
144   }
145 
GetInputResourceMapper()146   InputResourceMapper* GetInputResourceMapper() override {
147     return &transaction_;
148   }
149 
150  private:
151   Transaction& transaction_;
152 };
153 
154 }  // namespace rpc
155 }  // namespace pdx
156 }  // namespace android
157 
158 #endif  // ANDROID_PDX_RPC_PAYLOAD_H_
159