Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / system / transport_data.h
1 // Copyright 2014 The Chromium 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 MOJO_SYSTEM_TRANSPORT_DATA_H_
6 #define MOJO_SYSTEM_TRANSPORT_DATA_H_
7
8 #include <stdint.h>
9
10 #include <vector>
11
12 #include "base/macros.h"
13 #include "base/memory/aligned_memory.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "mojo/embedder/platform_handle.h"
16 #include "mojo/system/dispatcher.h"
17 #include "mojo/system/system_impl_export.h"
18
19 namespace mojo {
20 namespace system {
21
22 // This class is used by |MessageInTransit| to represent handles (|Dispatcher|s)
23 // in various stages of serialization.
24 //
25 // The stages are:
26 //   - Before reaching |TransportData|: Turn |DispatcherTransport|s into
27 //     |Dispatcher|s that are "owned" by (and attached to) a |MessageInTransit|.
28 //     This invalidates the handles in the space of the sending application
29 //     (and, e.g., if another thread is waiting on such a handle, it'll be
30 //     notified of this invalidation).
31 //   - Serialize these dispatchers into the |TransportData|: First, for each
32 //     attached dispatcher, there's an entry in the |TransportData|'s "handle
33 //     table", which points to a segment of (dispatcher-type-dependent) data.
34 //   - During the serialization of the dispatchers, |PlatformHandle|s may be
35 //     detached from the dispatchers and attached to the |TransportData|.
36 //   - Before sending the |MessageInTransit|, including its main buffer and the
37 //     |TransportData|'s buffer, the |Channel| sends any |PlatformHandle|s (in a
38 //     platform-, and possibly sandbox-situation-, specific way) first. In doing
39 //     so, it appends a "platform handle table" to the |TransportData|
40 //     containing information about how to deserialize these |PlatformHandle|s.
41 //   - Finally, at this point, to send the |MessageInTransit|, there only
42 //     remains "inert" data: the |MessageInTransit|'s main buffer and data from
43 //     the |TransportData|, consisting of the "handle table" (one entry for each
44 //     attached dispatcher), dispatcher-type-specific data (one segment for each
45 //     entry in the "handle table"), and the "platform handle table" (one entry
46 //     for each attached |PlatformHandle|).
47 //
48 // To receive a message (|MessageInTransit|), the "reverse" happens:
49 //   - On POSIX, receive and buffer |PlatformHandle|s (i.e., FDs), which were
50 //     sent before the "inert" data.
51 //   - Receive the "inert" data from the |MessageInTransit|. Examine its
52 //     "platform handle table". On POSIX, match its entries with the buffered
53 //     |PlatformHandle|s, which were previously received. On Windows, do what's
54 //     necessary to obtain |PlatformHandle|s (e.g.: i. if the sender is fully
55 //     trusted and able to duplicate handle into the receiver, then just pick
56 //     out the |HANDLE| value; ii. if the receiver is fully trusted and able to
57 //     duplicate handles from the receiver, do the |DuplicateHandle()|; iii.
58 //     otherwise, talk to a broker to get handles). Reattach all the
59 //     |PlatformHandle|s to the |MessageInTransit|.
60 //   - For each entry in the "handle table", use serialized dispatcher data to
61 //     reconstitute a dispatcher, taking ownership of associated
62 //     |PlatformHandle|s (and detaching them). Attach these dispatchers to the
63 //     |MessageInTransit|.
64 //   - At this point, the |MessageInTransit| consists of its main buffer
65 //     (primarily the data payload) and the attached dispatchers; the
66 //     |TransportData| can be discarded.
67 //   - When |MojoReadMessage()| is to give data to the application, attach the
68 //     dispatchers to the (global, "core") handle table, getting handles; give
69 //     the application the data payload and these handles.
70 //
71 // TODO(vtl): Everything above involving |PlatformHandle|s.
72 class MOJO_SYSTEM_IMPL_EXPORT TransportData {
73  public:
74   // The maximum size of a single serialized dispatcher. This must be a multiple
75   // of |kMessageAlignment|.
76   static const size_t kMaxSerializedDispatcherSize = 10000;
77
78   // The maximum number of platform handles to attach for a single serialized
79   // dispatcher.
80   static const size_t kMaxSerializedDispatcherPlatformHandles = 2;
81
82   TransportData(scoped_ptr<DispatcherVector> dispatchers, Channel* channel);
83   ~TransportData();
84
85   const void* buffer() const { return buffer_.get(); }
86   void* buffer() { return buffer_.get(); }
87   size_t buffer_size() const { return buffer_size_; }
88
89   uint32_t platform_handle_table_offset() const {
90     return header()->platform_handle_table_offset;
91   }
92
93   // Gets attached platform-specific handles; this may return null if there are
94   // none. Note that the caller may mutate the set of platform-specific handles.
95   const std::vector<embedder::PlatformHandle>* platform_handles() const {
96     return platform_handles_.get();
97   }
98   std::vector<embedder::PlatformHandle>* platform_handles() {
99     return platform_handles_.get();
100   }
101
102   // Receive-side functions:
103
104   // Checks if the given buffer (from the "wire") looks like a valid
105   // |TransportData| buffer. (Should only be called if |buffer_size| is
106   // nonzero.) Returns null if valid, and a pointer to a human-readable error
107   // message (for debug/logging purposes) on error. Note: This checks the
108   // validity of the handle table entries (i.e., does range checking), but does
109   // not check that the validity of the actual serialized dispatcher
110   // information.
111   static const char* ValidateBuffer(const void* buffer, size_t buffer_size);
112
113   // Deserializes dispatchers from the given (serialized) transport data buffer
114   // (typically from a |MessageInTransit::View|). |buffer| should be non-null
115   // and |buffer_size| should be nonzero.
116   static scoped_ptr<DispatcherVector> DeserializeDispatchersFromBuffer(
117       const void* buffer,
118       size_t buffer_size,
119       Channel* channel);
120
121  private:
122   // To allow us to make compile-assertions about |Header|, etc. in the .cc
123   // file.
124   struct PrivateStructForCompileAsserts;
125
126   // Header for the "secondary buffer"/"transport data". Must be a multiple of
127   // |MessageInTransit::kMessageAlignment| in size. Must be POD.
128   struct Header {
129     uint32_t num_handles;
130     // TODO(vtl): Not used yet:
131     uint32_t platform_handle_table_offset;
132     uint32_t num_platform_handles;
133     uint32_t unused;
134   };
135
136   struct HandleTableEntry {
137     int32_t type;  // From |Dispatcher::Type| (|kTypeUnknown| for "invalid").
138     uint32_t offset;  // Relative to the start of the "secondary buffer".
139     uint32_t size;  // (Not including any padding.)
140     uint32_t unused;
141   };
142
143   // The maximum possible size of a valid transport data buffer.
144   static const size_t kMaxBufferSize;
145
146   // The maximum total number of platform handles that may be attached.
147   static const size_t kMaxPlatformHandles;
148
149   const Header* header() const {
150     return reinterpret_cast<const Header*>(buffer_.get());
151   }
152
153   size_t buffer_size_;
154   scoped_ptr<char, base::AlignedFreeDeleter> buffer_;  // Never null.
155
156   // Any platform-specific handles attached to this message (for inter-process
157   // transport). The vector (if any) owns the handles that it contains (and is
158   // responsible for closing them).
159   // TODO(vtl): With C++11, change it to a vector of |ScopedPlatformHandles|.
160   scoped_ptr<std::vector<embedder::PlatformHandle> > platform_handles_;
161
162   DISALLOW_COPY_AND_ASSIGN(TransportData);
163 };
164
165 }  // namespace system
166 }  // namespace mojo
167
168 #endif  // MOJO_SYSTEM_TRANSPORT_DATA_H_