OLD | NEW |
| (Empty) |
1 // Copyright 2013 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/message_pipe_dispatcher.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "mojo/edk/system/configuration.h" | |
9 #include "mojo/edk/system/local_message_pipe_endpoint.h" | |
10 #include "mojo/edk/system/memory.h" | |
11 #include "mojo/edk/system/message_pipe.h" | |
12 #include "mojo/edk/system/options_validation.h" | |
13 #include "mojo/edk/system/proxy_message_pipe_endpoint.h" | |
14 | |
15 namespace mojo { | |
16 namespace system { | |
17 | |
18 const unsigned kInvalidPort = static_cast<unsigned>(-1); | |
19 | |
20 // MessagePipeDispatcher ------------------------------------------------------- | |
21 | |
22 // static | |
23 const MojoCreateMessagePipeOptions | |
24 MessagePipeDispatcher::kDefaultCreateOptions = { | |
25 static_cast<uint32_t>(sizeof(MojoCreateMessagePipeOptions)), | |
26 MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE}; | |
27 | |
28 MessagePipeDispatcher::MessagePipeDispatcher( | |
29 const MojoCreateMessagePipeOptions& /*validated_options*/) | |
30 : port_(kInvalidPort) { | |
31 } | |
32 | |
33 // static | |
34 MojoResult MessagePipeDispatcher::ValidateCreateOptions( | |
35 UserPointer<const MojoCreateMessagePipeOptions> in_options, | |
36 MojoCreateMessagePipeOptions* out_options) { | |
37 const MojoCreateMessagePipeOptionsFlags kKnownFlags = | |
38 MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE; | |
39 | |
40 *out_options = kDefaultCreateOptions; | |
41 if (in_options.IsNull()) | |
42 return MOJO_RESULT_OK; | |
43 | |
44 UserOptionsReader<MojoCreateMessagePipeOptions> reader(in_options); | |
45 if (!reader.is_valid()) | |
46 return MOJO_RESULT_INVALID_ARGUMENT; | |
47 | |
48 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateMessagePipeOptions, flags, reader)) | |
49 return MOJO_RESULT_OK; | |
50 if ((reader.options().flags & ~kKnownFlags)) | |
51 return MOJO_RESULT_UNIMPLEMENTED; | |
52 out_options->flags = reader.options().flags; | |
53 | |
54 // Checks for fields beyond |flags|: | |
55 | |
56 // (Nothing here yet.) | |
57 | |
58 return MOJO_RESULT_OK; | |
59 } | |
60 | |
61 void MessagePipeDispatcher::Init(scoped_refptr<MessagePipe> message_pipe, | |
62 unsigned port) { | |
63 DCHECK(message_pipe); | |
64 DCHECK(port == 0 || port == 1); | |
65 | |
66 message_pipe_ = message_pipe; | |
67 port_ = port; | |
68 } | |
69 | |
70 Dispatcher::Type MessagePipeDispatcher::GetType() const { | |
71 return kTypeMessagePipe; | |
72 } | |
73 | |
74 // static | |
75 scoped_refptr<MessagePipeDispatcher> | |
76 MessagePipeDispatcher::CreateRemoteMessagePipe( | |
77 scoped_refptr<ChannelEndpoint>* channel_endpoint) { | |
78 scoped_refptr<MessagePipe> message_pipe( | |
79 MessagePipe::CreateLocalProxy(channel_endpoint)); | |
80 scoped_refptr<MessagePipeDispatcher> dispatcher( | |
81 new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions)); | |
82 dispatcher->Init(message_pipe, 0); | |
83 return dispatcher; | |
84 } | |
85 | |
86 // static | |
87 scoped_refptr<MessagePipeDispatcher> MessagePipeDispatcher::Deserialize( | |
88 Channel* channel, | |
89 const void* source, | |
90 size_t size) { | |
91 unsigned port = kInvalidPort; | |
92 scoped_refptr<MessagePipe> message_pipe; | |
93 if (!MessagePipe::Deserialize(channel, source, size, &message_pipe, &port)) | |
94 return nullptr; | |
95 DCHECK(message_pipe); | |
96 DCHECK(port == 0 || port == 1); | |
97 | |
98 scoped_refptr<MessagePipeDispatcher> dispatcher( | |
99 new MessagePipeDispatcher(MessagePipeDispatcher::kDefaultCreateOptions)); | |
100 dispatcher->Init(message_pipe, port); | |
101 return dispatcher; | |
102 } | |
103 | |
104 MessagePipeDispatcher::~MessagePipeDispatcher() { | |
105 // |Close()|/|CloseImplNoLock()| should have taken care of the pipe. | |
106 DCHECK(!message_pipe_); | |
107 } | |
108 | |
109 MessagePipe* MessagePipeDispatcher::GetMessagePipeNoLock() const { | |
110 lock().AssertAcquired(); | |
111 return message_pipe_.get(); | |
112 } | |
113 | |
114 unsigned MessagePipeDispatcher::GetPortNoLock() const { | |
115 lock().AssertAcquired(); | |
116 return port_; | |
117 } | |
118 | |
119 void MessagePipeDispatcher::CancelAllAwakablesNoLock() { | |
120 lock().AssertAcquired(); | |
121 message_pipe_->CancelAllAwakables(port_); | |
122 } | |
123 | |
124 void MessagePipeDispatcher::CloseImplNoLock() { | |
125 lock().AssertAcquired(); | |
126 message_pipe_->Close(port_); | |
127 message_pipe_ = nullptr; | |
128 port_ = kInvalidPort; | |
129 } | |
130 | |
131 scoped_refptr<Dispatcher> | |
132 MessagePipeDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { | |
133 lock().AssertAcquired(); | |
134 | |
135 // TODO(vtl): Currently, there are no options, so we just use | |
136 // |kDefaultCreateOptions|. Eventually, we'll have to duplicate the options | |
137 // too. | |
138 scoped_refptr<MessagePipeDispatcher> rv = | |
139 new MessagePipeDispatcher(kDefaultCreateOptions); | |
140 rv->Init(message_pipe_, port_); | |
141 message_pipe_ = nullptr; | |
142 port_ = kInvalidPort; | |
143 return scoped_refptr<Dispatcher>(rv.get()); | |
144 } | |
145 | |
146 MojoResult MessagePipeDispatcher::WriteMessageImplNoLock( | |
147 UserPointer<const void> bytes, | |
148 uint32_t num_bytes, | |
149 std::vector<DispatcherTransport>* transports, | |
150 MojoWriteMessageFlags flags) { | |
151 DCHECK(!transports || | |
152 (transports->size() > 0 && | |
153 transports->size() <= GetConfiguration().max_message_num_handles)); | |
154 | |
155 lock().AssertAcquired(); | |
156 | |
157 if (num_bytes > GetConfiguration().max_message_num_bytes) | |
158 return MOJO_RESULT_RESOURCE_EXHAUSTED; | |
159 | |
160 return message_pipe_->WriteMessage(port_, bytes, num_bytes, transports, | |
161 flags); | |
162 } | |
163 | |
164 MojoResult MessagePipeDispatcher::ReadMessageImplNoLock( | |
165 UserPointer<void> bytes, | |
166 UserPointer<uint32_t> num_bytes, | |
167 DispatcherVector* dispatchers, | |
168 uint32_t* num_dispatchers, | |
169 MojoReadMessageFlags flags) { | |
170 lock().AssertAcquired(); | |
171 return message_pipe_->ReadMessage(port_, bytes, num_bytes, dispatchers, | |
172 num_dispatchers, flags); | |
173 } | |
174 | |
175 HandleSignalsState MessagePipeDispatcher::GetHandleSignalsStateImplNoLock() | |
176 const { | |
177 lock().AssertAcquired(); | |
178 return message_pipe_->GetHandleSignalsState(port_); | |
179 } | |
180 | |
181 MojoResult MessagePipeDispatcher::AddAwakableImplNoLock( | |
182 Awakable* awakable, | |
183 MojoHandleSignals signals, | |
184 uint32_t context, | |
185 HandleSignalsState* signals_state) { | |
186 lock().AssertAcquired(); | |
187 return message_pipe_->AddAwakable(port_, awakable, signals, context, | |
188 signals_state); | |
189 } | |
190 | |
191 void MessagePipeDispatcher::RemoveAwakableImplNoLock( | |
192 Awakable* awakable, | |
193 HandleSignalsState* signals_state) { | |
194 lock().AssertAcquired(); | |
195 message_pipe_->RemoveAwakable(port_, awakable, signals_state); | |
196 } | |
197 | |
198 void MessagePipeDispatcher::StartSerializeImplNoLock( | |
199 Channel* channel, | |
200 size_t* max_size, | |
201 size_t* max_platform_handles) { | |
202 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | |
203 return message_pipe_->StartSerialize(port_, channel, max_size, | |
204 max_platform_handles); | |
205 } | |
206 | |
207 bool MessagePipeDispatcher::EndSerializeAndCloseImplNoLock( | |
208 Channel* channel, | |
209 void* destination, | |
210 size_t* actual_size, | |
211 embedder::PlatformHandleVector* platform_handles) { | |
212 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | |
213 | |
214 bool rv = message_pipe_->EndSerialize(port_, channel, destination, | |
215 actual_size, platform_handles); | |
216 message_pipe_ = nullptr; | |
217 port_ = kInvalidPort; | |
218 return rv; | |
219 } | |
220 | |
221 // MessagePipeDispatcherTransport ---------------------------------------------- | |
222 | |
223 MessagePipeDispatcherTransport::MessagePipeDispatcherTransport( | |
224 DispatcherTransport transport) | |
225 : DispatcherTransport(transport) { | |
226 DCHECK_EQ(message_pipe_dispatcher()->GetType(), Dispatcher::kTypeMessagePipe); | |
227 } | |
228 | |
229 } // namespace system | |
230 } // namespace mojo | |
OLD | NEW |