OLD | NEW |
(Empty) | |
| 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 sandobx-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( |
| 83 scoped_ptr<std::vector<scoped_refptr<Dispatcher> > > dispatchers, |
| 84 Channel* channel); |
| 85 ~TransportData(); |
| 86 |
| 87 const void* buffer() const { return buffer_.get(); } |
| 88 size_t buffer_size() const { return buffer_size_; } |
| 89 |
| 90 // Gets attached platform-specific handles; this may return null if there are |
| 91 // none. Note that the caller may mutate the set of platform-specific handles. |
| 92 std::vector<embedder::PlatformHandle>* platform_handles() { |
| 93 return platform_handles_.get(); |
| 94 } |
| 95 |
| 96 // Returns true if there are platform-specific handles attached. |
| 97 bool has_platform_handles() const { |
| 98 return platform_handles_ && !platform_handles_->empty(); |
| 99 } |
| 100 |
| 101 // Receive-side functions: |
| 102 |
| 103 // Checks if the given buffer (from the "wire") looks like a valid |
| 104 // |TransportData| buffer. (Should only be called if |buffer_size| is |
| 105 // nonzero.) Returns null if valid, and a pointer to a human-readable error |
| 106 // message (for debug/logging purposes) on error. Note: This checks the |
| 107 // validity of the handle table entries (i.e., does range checking), but does |
| 108 // not check that the validity of the actual serialized dispatcher |
| 109 // information. |
| 110 static const char* ValidateBuffer(const void* buffer, size_t buffer_size); |
| 111 |
| 112 // Deserializes dispatchers from the given (serialized) transport data buffer |
| 113 // (typically from a |MessageInTransit::View|). |buffer| should be non-null |
| 114 // and |buffer_size| should be nonzero. |
| 115 static scoped_ptr<std::vector<scoped_refptr<Dispatcher> > > |
| 116 DeserializeDispatchersFromBuffer(const void* buffer, |
| 117 size_t buffer_size, |
| 118 Channel* channel); |
| 119 |
| 120 private: |
| 121 // To allow us to make compile-assertions about |Header|, etc. in the .cc |
| 122 // file. |
| 123 struct PrivateStructForCompileAsserts; |
| 124 |
| 125 // Header for the "secondary buffer"/"transport data". Must be a multiple of |
| 126 // |MessageInTransit::kMessageAlignment| in size. Must be POD. |
| 127 struct Header { |
| 128 uint32_t num_handles; |
| 129 // TODO(vtl): Not used yet: |
| 130 uint32_t platform_handle_table_offset; |
| 131 uint32_t num_platform_handles; |
| 132 uint32_t unused; |
| 133 }; |
| 134 |
| 135 struct HandleTableEntry { |
| 136 int32_t type; // From |Dispatcher::Type| (|kTypeUnknown| for "invalid"). |
| 137 uint32_t offset; // Relative to the start of the "secondary buffer". |
| 138 uint32_t size; // (Not including any padding.) |
| 139 uint32_t unused; |
| 140 }; |
| 141 |
| 142 // The maximum possible size of a valid transport data buffer. |
| 143 static const size_t kMaxBufferSize; |
| 144 |
| 145 // The maximum total number of platform handles that may be attached. |
| 146 static const size_t kMaxPlatformHandles; |
| 147 |
| 148 size_t buffer_size_; |
| 149 scoped_ptr<char, base::AlignedFreeDeleter> buffer_; // Never null. |
| 150 |
| 151 // Any platform-specific handles attached to this message (for inter-process |
| 152 // transport). The vector (if any) owns the handles that it contains (and is |
| 153 // responsible for closing them). |
| 154 // TODO(vtl): With C++11, change it to a vector of |ScopedPlatformHandles|. |
| 155 scoped_ptr<std::vector<embedder::PlatformHandle> > platform_handles_; |
| 156 |
| 157 DISALLOW_COPY_AND_ASSIGN(TransportData); |
| 158 }; |
| 159 |
| 160 } // namespace system |
| 161 } // namespace mojo |
| 162 |
| 163 #endif // MOJO_SYSTEM_TRANSPORT_DATA_H_ |
OLD | NEW |