OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 #include "mojo/edk/system/data_pipe.h" | |
6 | |
7 #include <stddef.h> | |
8 #include <stdint.h> | |
9 #include <string.h> | |
10 | |
11 #include <algorithm> | |
12 #include <limits> | |
13 | |
14 #include "mojo/edk/system/configuration.h" | |
15 #include "mojo/edk/system/options_validation.h" | |
16 #include "mojo/edk/system/raw_channel.h" | |
17 #include "mojo/edk/system/transport_data.h" | |
18 | |
19 namespace mojo { | |
20 namespace edk { | |
21 | |
22 namespace { | |
23 | |
24 const uint32_t kInvalidDataPipeHandleIndex = static_cast<uint32_t>(-1); | |
25 | |
26 struct MOJO_ALIGNAS(8) SerializedDataPipeHandleDispatcher { | |
27 MOJO_ALIGNAS(4) | |
28 uint32_t platform_handle_index; // (Or |kInvalidDataPipeHandleIndex|.) | |
29 | |
30 // These are from MojoCreateDataPipeOptions | |
31 MOJO_ALIGNAS(4) MojoCreateDataPipeOptionsFlags flags; | |
32 MOJO_ALIGNAS(4) uint32_t element_num_bytes; | |
33 MOJO_ALIGNAS(4) uint32_t capacity_num_bytes; | |
34 | |
35 MOJO_ALIGNAS(4) | |
36 uint32_t shared_memory_handle_index; // (Or |kInvalidDataPipeHandleIndex|.) | |
37 MOJO_ALIGNAS(4) uint32_t shared_memory_size; | |
38 }; | |
39 | |
40 } // namespace | |
41 | |
42 MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() { | |
43 MojoCreateDataPipeOptions result = { | |
44 static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), | |
45 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, | |
46 1u, | |
47 static_cast<uint32_t>( | |
48 GetConfiguration().default_data_pipe_capacity_bytes)}; | |
49 return result; | |
50 } | |
51 | |
52 MojoResult DataPipe::ValidateCreateOptions( | |
53 const MojoCreateDataPipeOptions* in_options, | |
54 MojoCreateDataPipeOptions* out_options) { | |
55 const MojoCreateDataPipeOptionsFlags kKnownFlags = | |
56 MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | |
57 | |
58 *out_options = GetDefaultCreateOptions(); | |
59 if (!in_options) | |
60 return MOJO_RESULT_OK; | |
61 | |
62 UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options); | |
63 if (!reader.is_valid()) | |
64 return MOJO_RESULT_INVALID_ARGUMENT; | |
65 | |
66 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader)) | |
67 return MOJO_RESULT_OK; | |
68 if ((reader.options().flags & ~kKnownFlags)) | |
69 return MOJO_RESULT_UNIMPLEMENTED; | |
70 out_options->flags = reader.options().flags; | |
71 | |
72 // Checks for fields beyond |flags|: | |
73 | |
74 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes, | |
75 reader)) | |
76 return MOJO_RESULT_OK; | |
77 if (reader.options().element_num_bytes == 0) | |
78 return MOJO_RESULT_INVALID_ARGUMENT; | |
79 out_options->element_num_bytes = reader.options().element_num_bytes; | |
80 | |
81 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes, | |
82 reader) || | |
83 reader.options().capacity_num_bytes == 0) { | |
84 // Round the default capacity down to a multiple of the element size (but at | |
85 // least one element). | |
86 size_t default_data_pipe_capacity_bytes = | |
87 GetConfiguration().default_data_pipe_capacity_bytes; | |
88 out_options->capacity_num_bytes = | |
89 std::max(static_cast<uint32_t>(default_data_pipe_capacity_bytes - | |
90 (default_data_pipe_capacity_bytes % | |
91 out_options->element_num_bytes)), | |
92 out_options->element_num_bytes); | |
93 return MOJO_RESULT_OK; | |
94 } | |
95 if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0) | |
96 return MOJO_RESULT_INVALID_ARGUMENT; | |
97 if (reader.options().capacity_num_bytes > | |
98 GetConfiguration().max_data_pipe_capacity_bytes) | |
99 return MOJO_RESULT_RESOURCE_EXHAUSTED; | |
100 out_options->capacity_num_bytes = reader.options().capacity_num_bytes; | |
101 | |
102 return MOJO_RESULT_OK; | |
103 } | |
104 | |
105 void DataPipe::StartSerialize(bool have_channel_handle, | |
106 bool have_shared_memory, | |
107 size_t* max_size, | |
108 size_t* max_platform_handles) { | |
109 *max_size = sizeof(SerializedDataPipeHandleDispatcher); | |
110 *max_platform_handles = 0; | |
111 if (have_channel_handle) | |
112 (*max_platform_handles)++; | |
113 if (have_shared_memory) | |
114 (*max_platform_handles)++; | |
115 } | |
116 | |
117 void DataPipe::EndSerialize(const MojoCreateDataPipeOptions& options, | |
118 ScopedPlatformHandle channel_handle, | |
119 ScopedPlatformHandle shared_memory_handle, | |
120 size_t shared_memory_size, | |
121 void* destination, | |
122 size_t* actual_size, | |
123 PlatformHandleVector* platform_handles) { | |
124 SerializedDataPipeHandleDispatcher* serialization = | |
125 static_cast<SerializedDataPipeHandleDispatcher*>(destination); | |
126 if (channel_handle.is_valid()) { | |
127 DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max()); | |
128 serialization->platform_handle_index = | |
129 static_cast<uint32_t>(platform_handles->size()); | |
130 platform_handles->push_back(channel_handle.release()); | |
131 } else { | |
132 serialization->platform_handle_index = kInvalidDataPipeHandleIndex; | |
133 } | |
134 | |
135 serialization->flags = options.flags; | |
136 serialization->element_num_bytes = options.element_num_bytes; | |
137 serialization->capacity_num_bytes = options.capacity_num_bytes; | |
138 | |
139 serialization->shared_memory_size = static_cast<uint32_t>(shared_memory_size); | |
140 if (serialization->shared_memory_size) { | |
141 DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max()); | |
142 serialization->shared_memory_handle_index = | |
143 static_cast<uint32_t>(platform_handles->size()); | |
144 platform_handles->push_back(shared_memory_handle.release()); | |
145 } else { | |
146 serialization->shared_memory_handle_index = kInvalidDataPipeHandleIndex; | |
147 } | |
148 | |
149 *actual_size = sizeof(SerializedDataPipeHandleDispatcher); | |
150 } | |
151 | |
152 ScopedPlatformHandle DataPipe::Deserialize( | |
153 const void* source, | |
154 size_t size, | |
155 PlatformHandleVector* platform_handles, | |
156 MojoCreateDataPipeOptions* options, | |
157 ScopedPlatformHandle* shared_memory_handle, | |
158 size_t* shared_memory_size) { | |
159 if (size != sizeof(SerializedDataPipeHandleDispatcher)) { | |
160 LOG(ERROR) << "Invalid serialized data pipe dispatcher (bad size)"; | |
161 return ScopedPlatformHandle(); | |
162 } | |
163 | |
164 const SerializedDataPipeHandleDispatcher* serialization = | |
165 static_cast<const SerializedDataPipeHandleDispatcher*>(source); | |
166 size_t platform_handle_index = serialization->platform_handle_index; | |
167 | |
168 // Starts off invalid, which is what we want. | |
169 PlatformHandle platform_handle; | |
170 if (platform_handle_index != kInvalidDataPipeHandleIndex) { | |
171 if (!platform_handles || | |
172 platform_handle_index >= platform_handles->size()) { | |
173 LOG(ERROR) | |
174 << "Invalid serialized data pipe dispatcher (missing handles)"; | |
175 return ScopedPlatformHandle(); | |
176 } | |
177 | |
178 // We take ownership of the handle, so we have to invalidate the one in | |
179 // |platform_handles|. | |
180 std::swap(platform_handle, (*platform_handles)[platform_handle_index]); | |
181 } | |
182 | |
183 options->struct_size = sizeof(MojoCreateDataPipeOptions); | |
184 options->flags = serialization->flags; | |
185 options->element_num_bytes = serialization->element_num_bytes; | |
186 options->capacity_num_bytes = serialization->capacity_num_bytes; | |
187 | |
188 if (shared_memory_size) { | |
189 *shared_memory_size = serialization->shared_memory_size; | |
190 if (*shared_memory_size) { | |
191 DCHECK(serialization->shared_memory_handle_index != | |
192 kInvalidDataPipeHandleIndex); | |
193 if (!platform_handles || | |
194 serialization->shared_memory_handle_index >= | |
195 platform_handles->size()) { | |
196 LOG(ERROR) << "Invalid serialized data pipe dispatcher " | |
197 << "(missing handles)"; | |
198 return ScopedPlatformHandle(); | |
199 } | |
200 | |
201 PlatformHandle temp_shared_memory_handle; | |
202 std::swap(temp_shared_memory_handle, | |
203 (*platform_handles)[serialization->shared_memory_handle_index]); | |
204 *shared_memory_handle = | |
205 ScopedPlatformHandle(temp_shared_memory_handle); | |
206 } | |
207 } | |
208 | |
209 size -= sizeof(SerializedDataPipeHandleDispatcher); | |
210 | |
211 return ScopedPlatformHandle(platform_handle); | |
212 } | |
213 | |
214 } // namespace edk | |
215 } // namespace mojo | |
OLD | NEW |