15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stack> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/atomic_sequence_num.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct WaitableEventLazyInstanceTraits 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::DefaultLazyInstanceTraits<base::WaitableEvent> { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static base::WaitableEvent* New(void* instance) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use placement new to initialize our instance in our preallocated space. 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new (instance) base::WaitableEvent(true, true); 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<base::WaitableEvent, WaitableEventLazyInstanceTraits> 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dummy_event = LAZY_INSTANCE_INITIALIZER; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::StaticAtomicSequenceNumber g_next_id; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IPC { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define kSyncMessageHeaderSize 4 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncMessage::SyncMessage( 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 routing_id, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 type, 420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) PriorityValue priority, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessageReplyDeserializer* deserializer) 440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) : Message(routing_id, type, priority), 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deserializer_(deserializer), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pump_messages_event_(NULL) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_sync(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_unblock(true); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add synchronous message data before the message payload. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncHeader header; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.message_id = g_next_id.GetNext(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSyncHeader(this, header); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncMessage::~SyncMessage() { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(deserializer_.get()); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return deserializer_.release(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncMessage::EnableMessagePumping() { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!pump_messages_event_); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_pump_messages_event(dummy_event.Pointer()); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!msg.is_reply()) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetMessageId(msg) == request_id; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PickleIterator SyncMessage::GetDataIterator(const Message* msg) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PickleIterator iter(*msg); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!iter.SkipBytes(kSyncMessageHeaderSize)) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PickleIterator(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return iter; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SyncMessage::GetMessageId(const Message& msg) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!msg.is_sync() && !msg.is_reply()) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncHeader header; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadSyncHeader(msg, &header)) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header.message_id; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message* SyncMessage::GenerateReply(const Message* msg) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(msg->is_sync()); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID, 1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) msg->priority()); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reply->set_reply(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SyncHeader header; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use the same message id, but this time reply bit is set 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header.message_id = GetMessageId(*msg); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteSyncHeader(reply, header); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reply; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(msg.is_sync() || msg.is_reply()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PickleIterator iter(msg); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = msg.ReadInt(&iter, &header->message_id); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(msg->is_sync() || msg->is_reply()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(msg->payload_size() == 0); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = msg->WriteInt(header.message_id); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: if you add anything here, you need to update kSyncMessageHeaderSize. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(kSyncMessageHeaderSize == msg->payload_size()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg)); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace IPC 146