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