blob: 9e3acf8e1fae1dba5a46469dae1e77b2513cd19b [file] [log] [blame]
[email protected]76a6d452012-02-03 21:48:431// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]cd40b4a2008-12-22 23:58:525#include "build/build_config.h"
6
[email protected]800580552008-12-22 23:10:327#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:298#include <windows.h>
[email protected]800580552008-12-22 23:10:329#endif
initial.commit09911bf2008-07-26 23:55:2910#include <stack>
11
[email protected]1e9499c2010-04-06 20:33:3612#include "base/atomic_sequence_num.h"
[email protected]76a6d452012-02-03 21:48:4313#include "base/lazy_instance.h"
initial.commit09911bf2008-07-26 23:55:2914#include "base/logging.h"
[email protected]44f9c952011-01-02 06:05:3915#include "base/synchronization/waitable_event.h"
[email protected]946d1b22009-07-22 23:57:2116#include "ipc/ipc_sync_message.h"
initial.commit09911bf2008-07-26 23:55:2917
[email protected]76a6d452012-02-03 21:48:4318namespace {
19
20struct WaitableEventLazyInstanceTraits
21 : public base::DefaultLazyInstanceTraits<base::WaitableEvent> {
22 static base::WaitableEvent* New(void* instance) {
23 // Use placement new to initialize our instance in our preallocated space.
24 return new (instance) base::WaitableEvent(true, true);
25 }
26};
27
[email protected]8a8443f2012-03-13 12:07:1928base::LazyInstance<base::WaitableEvent, WaitableEventLazyInstanceTraits>
[email protected]76a6d452012-02-03 21:48:4329 dummy_event = LAZY_INSTANCE_INITIALIZER;
30
[email protected]8a8443f2012-03-13 12:07:1931base::StaticAtomicSequenceNumber g_next_id;
32
33} // namespace
[email protected]76a6d452012-02-03 21:48:4334
initial.commit09911bf2008-07-26 23:55:2935namespace IPC {
36
initial.commit09911bf2008-07-26 23:55:2937#define kSyncMessageHeaderSize 4
38
initial.commit09911bf2008-07-26 23:55:2939SyncMessage::SyncMessage(
40 int32 routing_id,
[email protected]168ae922009-12-04 18:08:4541 uint32 type,
initial.commit09911bf2008-07-26 23:55:2942 PriorityValue priority,
43 MessageReplyDeserializer* deserializer)
44 : Message(routing_id, type, priority),
[email protected]1c4947f2009-01-15 22:25:1145 deserializer_(deserializer),
46 pump_messages_event_(NULL)
[email protected]800580552008-12-22 23:10:3247 {
initial.commit09911bf2008-07-26 23:55:2948 set_sync();
49 set_unblock(true);
50
51 // Add synchronous message data before the message payload.
52 SyncHeader header;
[email protected]1e9499c2010-04-06 20:33:3653 header.message_id = g_next_id.GetNext();
initial.commit09911bf2008-07-26 23:55:2954 WriteSyncHeader(this, header);
55}
56
[email protected]40c4627d2011-09-09 21:10:3157SyncMessage::~SyncMessage() {
58}
59
initial.commit09911bf2008-07-26 23:55:2960MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() {
[email protected]40c4627d2011-09-09 21:10:3161 DCHECK(deserializer_.get());
62 return deserializer_.release();
initial.commit09911bf2008-07-26 23:55:2963}
64
[email protected]d65cab7a2008-08-12 01:25:4165void SyncMessage::EnableMessagePumping() {
66 DCHECK(!pump_messages_event_);
[email protected]76a6d452012-02-03 21:48:4367 set_pump_messages_event(dummy_event.Pointer());
[email protected]d65cab7a2008-08-12 01:25:4168}
69
initial.commit09911bf2008-07-26 23:55:2970bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) {
71 if (!msg.is_reply())
72 return false;
73
74 return GetMessageId(msg) == request_id;
75}
76
[email protected]ce208f872012-03-07 20:42:5677PickleIterator SyncMessage::GetDataIterator(const Message* msg) {
78 PickleIterator iter(*msg);
79 if (!iter.SkipBytes(kSyncMessageHeaderSize))
80 return PickleIterator();
81 else
82 return iter;
initial.commit09911bf2008-07-26 23:55:2983}
84
85int SyncMessage::GetMessageId(const Message& msg) {
86 if (!msg.is_sync() && !msg.is_reply())
87 return 0;
88
89 SyncHeader header;
90 if (!ReadSyncHeader(msg, &header))
91 return 0;
92
93 return header.message_id;
94}
95
96Message* SyncMessage::GenerateReply(const Message* msg) {
97 DCHECK(msg->is_sync());
98
[email protected]d3216442009-03-05 21:07:2799 Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID,
100 msg->priority());
initial.commit09911bf2008-07-26 23:55:29101 reply->set_reply();
102
103 SyncHeader header;
104
105 // use the same message id, but this time reply bit is set
106 header.message_id = GetMessageId(*msg);
107 WriteSyncHeader(reply, header);
108
109 return reply;
110}
111
112bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) {
113 DCHECK(msg.is_sync() || msg.is_reply());
114
[email protected]ce208f872012-03-07 20:42:56115 PickleIterator iter(msg);
initial.commit09911bf2008-07-26 23:55:29116 bool result = msg.ReadInt(&iter, &header->message_id);
117 if (!result) {
118 NOTREACHED();
119 return false;
120 }
121
122 return true;
123}
124
125bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) {
126 DCHECK(msg->is_sync() || msg->is_reply());
127 DCHECK(msg->payload_size() == 0);
initial.commit09911bf2008-07-26 23:55:29128 bool result = msg->WriteInt(header.message_id);
129 if (!result) {
130 NOTREACHED();
131 return false;
132 }
133
134 // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
135 DCHECK(kSyncMessageHeaderSize == msg->payload_size());
136
137 return true;
138}
139
140
141bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) {
142 return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg));
143}
144
145} // namespace IPC