Chromium Code Reviews| 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 #include "ipc/mojo/ipc_channel_mojo_readers.h" | |
| 6 | |
| 7 #include "ipc/mojo/ipc_channel_mojo.h" | |
| 8 #include "mojo/embedder/embedder.h" | |
| 9 | |
| 10 #if defined(OS_POSIX) && !defined(OS_NACL) | |
| 11 #include "ipc/file_descriptor_set_posix.h" | |
| 12 #endif | |
| 13 | |
| 14 namespace IPC { | |
| 15 namespace internal { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 //------------------------------------------------------------------------------ | |
|
yzshen1
2014/09/09 23:52:40
This separator seems unnecessary.
yzshen1
2014/09/10 17:31:09
?
yzshen1
2014/09/10 18:06:16
This is a very trivial suggestion. But if you don'
Hajime Morrita
2014/09/10 20:29:53
Oops again. I overlooked this one. I'm sorry about
| |
| 20 | |
| 21 // TODO(morrita): This should be built using higher-level Mojo construct | |
| 22 // for clarity and extensibility. | |
| 23 class HelloMessage { | |
| 24 public: | |
| 25 static Pickle CreateRequest(int32 pid) { | |
| 26 Pickle request; | |
| 27 request.WriteString(kHelloRequestMagic); | |
| 28 request.WriteInt(pid); | |
| 29 return request; | |
| 30 } | |
| 31 | |
| 32 static bool ReadRequest(Pickle& pickle, int32* pid) { | |
| 33 PickleIterator iter(pickle); | |
| 34 std::string hello; | |
| 35 if (!iter.ReadString(&hello)) { | |
| 36 DLOG(WARNING) << "Failed to Read magic string."; | |
| 37 return false; | |
| 38 } | |
| 39 | |
| 40 if (hello != kHelloRequestMagic) { | |
| 41 DLOG(WARNING) << "Magic mismatch:" << hello; | |
| 42 return false; | |
| 43 } | |
| 44 | |
| 45 int read_pid; | |
| 46 if (!iter.ReadInt(&read_pid)) { | |
| 47 DLOG(WARNING) << "Failed to Read PID."; | |
| 48 return false; | |
| 49 } | |
| 50 | |
| 51 *pid = read_pid; | |
| 52 return true; | |
| 53 } | |
| 54 | |
| 55 static Pickle CreateResponse(int32 pid) { | |
| 56 Pickle request; | |
| 57 request.WriteString(kHelloResponseMagic); | |
| 58 request.WriteInt(pid); | |
| 59 return request; | |
| 60 } | |
| 61 | |
| 62 static bool ReadResponse(Pickle& pickle, int32* pid) { | |
| 63 PickleIterator iter(pickle); | |
| 64 std::string hello; | |
| 65 if (!iter.ReadString(&hello)) { | |
| 66 DLOG(WARNING) << "Failed to read magic string."; | |
| 67 return false; | |
| 68 } | |
| 69 | |
| 70 if (hello != kHelloResponseMagic) { | |
| 71 DLOG(WARNING) << "Magic mismatch:" << hello; | |
| 72 return false; | |
| 73 } | |
| 74 | |
| 75 int read_pid; | |
| 76 if (!iter.ReadInt(&read_pid)) { | |
| 77 DLOG(WARNING) << "Failed to read PID."; | |
| 78 return false; | |
| 79 } | |
| 80 | |
| 81 *pid = read_pid; | |
| 82 return true; | |
| 83 } | |
| 84 | |
| 85 private: | |
| 86 static const char* kHelloRequestMagic; | |
| 87 static const char* kHelloResponseMagic; | |
| 88 }; | |
| 89 | |
| 90 const char* HelloMessage::kHelloRequestMagic = "MREQ"; | |
| 91 const char* HelloMessage::kHelloResponseMagic = "MRES"; | |
| 92 | |
| 93 } // namespace | |
| 94 | |
| 95 //------------------------------------------------------------------------------ | |
| 96 | |
| 97 MessageReader::MessageReader(mojo::ScopedMessagePipeHandle pipe, | |
| 98 ChannelMojo* owner) | |
| 99 : internal::MessagePipeReader(pipe.Pass()), owner_(owner) { | |
| 100 } | |
| 101 | |
| 102 void MessageReader::OnMessageReceived() { | |
| 103 Message message(data_buffer().empty() ? "" : &data_buffer()[0], | |
| 104 static_cast<uint32>(data_buffer().size())); | |
| 105 | |
| 106 std::vector<MojoHandle> handle_buffer; | |
| 107 TakeHandleBuffer(&handle_buffer); | |
| 108 #if defined(OS_POSIX) && !defined(OS_NACL) | |
| 109 MojoResult write_result = | |
| 110 ChannelMojo::WriteToFileDescriptorSet(message, handle_buffer); | |
| 111 if (write_result != MOJO_RESULT_OK) { | |
| 112 CloseWithError(write_result); | |
| 113 return; | |
| 114 } | |
| 115 #else | |
| 116 DCHECK(handle_buffer.empty()); | |
| 117 #endif | |
| 118 | |
| 119 message.TraceMessageEnd(); | |
| 120 owner_->OnMessageReceived(message); | |
| 121 } | |
| 122 | |
| 123 void MessageReader::OnPipeClosed() { | |
| 124 if (!owner_) | |
| 125 return; | |
| 126 owner_->OnPipeClosed(this); | |
| 127 owner_ = NULL; | |
| 128 } | |
| 129 | |
| 130 void MessageReader::OnPipeError(MojoResult error) { | |
| 131 if (!owner_) | |
| 132 return; | |
| 133 owner_->OnPipeError(this); | |
| 134 } | |
| 135 | |
| 136 bool MessageReader::Send(scoped_ptr<Message> message) { | |
| 137 DCHECK(IsValid()); | |
| 138 | |
| 139 message->TraceMessageBegin(); | |
| 140 std::vector<MojoHandle> handles; | |
| 141 #if defined(OS_POSIX) && !defined(OS_NACL) | |
| 142 MojoResult read_result = | |
| 143 ChannelMojo::ReadFromFileDescriptorSet(*message, handles); | |
| 144 if (read_result != MOJO_RESULT_OK) { | |
| 145 std::for_each(handles.begin(), handles.end(), &MojoClose); | |
| 146 CloseWithError(read_result); | |
| 147 return false; | |
| 148 } | |
| 149 #endif | |
| 150 MojoResult write_result = | |
| 151 MojoWriteMessage(handle(), | |
| 152 message->data(), | |
| 153 static_cast<uint32>(message->size()), | |
| 154 handles.empty() ? NULL : &handles[0], | |
| 155 static_cast<uint32>(handles.size()), | |
| 156 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
| 157 if (MOJO_RESULT_OK != write_result) { | |
| 158 std::for_each(handles.begin(), handles.end(), &MojoClose); | |
| 159 CloseWithError(write_result); | |
| 160 return false; | |
| 161 } | |
| 162 | |
| 163 return true; | |
| 164 } | |
| 165 | |
| 166 //------------------------------------------------------------------------------ | |
| 167 | |
| 168 ControlReader::ControlReader(mojo::ScopedMessagePipeHandle pipe, | |
| 169 ChannelMojo* owner) | |
| 170 : internal::MessagePipeReader(pipe.Pass()), owner_(owner) { | |
| 171 } | |
| 172 | |
| 173 void ControlReader::OnPipeClosed() { | |
| 174 if (!owner_) | |
| 175 return; | |
| 176 owner_->OnPipeClosed(this); | |
| 177 owner_ = NULL; | |
| 178 } | |
| 179 | |
| 180 void ControlReader::OnPipeError(MojoResult error) { | |
| 181 if (!owner_) | |
| 182 return; | |
| 183 owner_->OnPipeError(this); | |
| 184 } | |
| 185 | |
| 186 bool ControlReader::Connect() { | |
| 187 return true; | |
| 188 } | |
| 189 | |
| 190 //------------------------------------------------------------------------------ | |
| 191 | |
| 192 ServerControlReader::ServerControlReader(mojo::ScopedMessagePipeHandle pipe, | |
| 193 ChannelMojo* owner) | |
| 194 : ControlReader(pipe.Pass(), owner) { | |
| 195 } | |
| 196 | |
| 197 ServerControlReader::~ServerControlReader() { | |
| 198 } | |
| 199 | |
| 200 bool ServerControlReader::Connect() { | |
| 201 MojoResult result = SendHelloRequest(); | |
| 202 if (result != MOJO_RESULT_OK) { | |
| 203 CloseWithError(result); | |
| 204 return false; | |
| 205 } | |
| 206 | |
| 207 return true; | |
| 208 } | |
| 209 | |
| 210 MojoResult ServerControlReader::SendHelloRequest() { | |
| 211 DCHECK(IsValid()); | |
| 212 DCHECK(!message_pipe_.is_valid()); | |
| 213 | |
| 214 mojo::ScopedMessagePipeHandle self; | |
| 215 mojo::ScopedMessagePipeHandle peer; | |
| 216 MojoResult create_result = | |
| 217 mojo::CreateMessagePipe(NULL, &message_pipe_, &peer); | |
| 218 if (MOJO_RESULT_OK != create_result) { | |
| 219 DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result; | |
| 220 return create_result; | |
| 221 } | |
| 222 | |
| 223 MojoHandle peer_to_send = peer.get().value(); | |
| 224 Pickle request = HelloMessage::CreateRequest(owner_->GetSelfPID()); | |
| 225 MojoResult write_result = | |
| 226 MojoWriteMessage(handle(), | |
| 227 request.data(), | |
| 228 static_cast<uint32>(request.size()), | |
| 229 &peer_to_send, | |
| 230 1, | |
| 231 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
| 232 if (MOJO_RESULT_OK != write_result) { | |
| 233 DLOG(WARNING) << "Writing Hello request failed: " << create_result; | |
| 234 return write_result; | |
| 235 } | |
| 236 | |
| 237 // |peer| is sent and no longer owned by |this|. | |
| 238 (void)peer.release(); | |
| 239 return MOJO_RESULT_OK; | |
| 240 } | |
| 241 | |
| 242 MojoResult ServerControlReader::RespondHelloResponse() { | |
| 243 Pickle request(data_buffer().empty() ? "" : &data_buffer()[0], | |
| 244 static_cast<uint32>(data_buffer().size())); | |
| 245 | |
| 246 int32 read_pid = 0; | |
| 247 if (!HelloMessage::ReadResponse(request, &read_pid)) { | |
| 248 DLOG(ERROR) << "Failed to parse Hello response."; | |
| 249 return MOJO_RESULT_UNKNOWN; | |
| 250 } | |
| 251 | |
| 252 base::ProcessId pid = static_cast<base::ProcessId>(read_pid); | |
| 253 owner_->set_peer_pid(pid); | |
| 254 owner_->OnConnected(message_pipe_.Pass()); | |
| 255 return MOJO_RESULT_OK; | |
| 256 } | |
| 257 | |
| 258 void ServerControlReader::OnMessageReceived() { | |
| 259 MojoResult result = RespondHelloResponse(); | |
| 260 if (result != MOJO_RESULT_OK) | |
| 261 CloseWithError(result); | |
| 262 } | |
| 263 | |
| 264 //------------------------------------------------------------------------------ | |
| 265 | |
| 266 ClientControlReader::ClientControlReader(mojo::ScopedMessagePipeHandle pipe, | |
| 267 ChannelMojo* owner) | |
| 268 : ControlReader(pipe.Pass(), owner) { | |
| 269 } | |
| 270 | |
| 271 MojoResult ClientControlReader::RespondHelloRequest( | |
| 272 MojoHandle message_channel) { | |
| 273 DCHECK(IsValid()); | |
| 274 | |
| 275 mojo::ScopedMessagePipeHandle received_pipe( | |
| 276 (mojo::MessagePipeHandle(message_channel))); | |
| 277 | |
| 278 int32 read_request = 0; | |
| 279 Pickle request(data_buffer().empty() ? "" : &data_buffer()[0], | |
| 280 static_cast<uint32>(data_buffer().size())); | |
| 281 if (!HelloMessage::ReadRequest(request, &read_request)) { | |
| 282 DLOG(ERROR) << "Hello request has wrong magic."; | |
| 283 return MOJO_RESULT_UNKNOWN; | |
| 284 } | |
| 285 | |
| 286 base::ProcessId pid = read_request; | |
| 287 Pickle response = HelloMessage::CreateResponse(owner_->GetSelfPID()); | |
| 288 MojoResult write_result = | |
| 289 MojoWriteMessage(handle(), | |
| 290 response.data(), | |
| 291 static_cast<uint32>(response.size()), | |
| 292 NULL, | |
| 293 0, | |
| 294 MOJO_WRITE_MESSAGE_FLAG_NONE); | |
| 295 if (MOJO_RESULT_OK != write_result) { | |
| 296 DLOG(ERROR) << "Writing Hello response failed: " << write_result; | |
| 297 return write_result; | |
| 298 } | |
| 299 | |
| 300 owner_->set_peer_pid(pid); | |
| 301 owner_->OnConnected(received_pipe.Pass()); | |
| 302 return MOJO_RESULT_OK; | |
| 303 } | |
| 304 | |
| 305 void ClientControlReader::OnMessageReceived() { | |
| 306 std::vector<MojoHandle> handle_buffer; | |
| 307 TakeHandleBuffer(&handle_buffer); | |
| 308 if (handle_buffer.size() != 1) { | |
| 309 DLOG(ERROR) << "Hello request doesn't contains required handle: " | |
| 310 << handle_buffer.size(); | |
| 311 CloseWithError(MOJO_RESULT_UNKNOWN); | |
| 312 return; | |
| 313 } | |
| 314 | |
| 315 MojoResult result = RespondHelloRequest(handle_buffer[0]); | |
| 316 if (result != MOJO_RESULT_OK) { | |
| 317 DLOG(ERROR) << "Failed to respond Hello request. Closing: " << result; | |
| 318 CloseWithError(result); | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 } // namespace internal | |
| 323 } // namespace IPC | |
| OLD | NEW |