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 //------------------------------------------------------------------------------ |
| 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(handle_buffer, &message); |
| 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 |