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