1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_sync_message.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
8*635a8641SAndroid Build Coastguard Worker
9*635a8641SAndroid Build Coastguard Worker #include "base/atomic_sequence_num.h"
10*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
11*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
12*635a8641SAndroid Build Coastguard Worker
13*635a8641SAndroid Build Coastguard Worker namespace {
14*635a8641SAndroid Build Coastguard Worker
15*635a8641SAndroid Build Coastguard Worker base::AtomicSequenceNumber g_next_id;
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Worker } // namespace
18*635a8641SAndroid Build Coastguard Worker
19*635a8641SAndroid Build Coastguard Worker namespace IPC {
20*635a8641SAndroid Build Coastguard Worker
21*635a8641SAndroid Build Coastguard Worker #define kSyncMessageHeaderSize 4
22*635a8641SAndroid Build Coastguard Worker
SyncMessage(int32_t routing_id,uint32_t type,PriorityValue priority,MessageReplyDeserializer * deserializer)23*635a8641SAndroid Build Coastguard Worker SyncMessage::SyncMessage(int32_t routing_id,
24*635a8641SAndroid Build Coastguard Worker uint32_t type,
25*635a8641SAndroid Build Coastguard Worker PriorityValue priority,
26*635a8641SAndroid Build Coastguard Worker MessageReplyDeserializer* deserializer)
27*635a8641SAndroid Build Coastguard Worker : Message(routing_id, type, priority),
28*635a8641SAndroid Build Coastguard Worker deserializer_(deserializer) {
29*635a8641SAndroid Build Coastguard Worker set_sync();
30*635a8641SAndroid Build Coastguard Worker set_unblock(true);
31*635a8641SAndroid Build Coastguard Worker
32*635a8641SAndroid Build Coastguard Worker // Add synchronous message data before the message payload.
33*635a8641SAndroid Build Coastguard Worker SyncHeader header;
34*635a8641SAndroid Build Coastguard Worker header.message_id = g_next_id.GetNext();
35*635a8641SAndroid Build Coastguard Worker WriteSyncHeader(this, header);
36*635a8641SAndroid Build Coastguard Worker }
37*635a8641SAndroid Build Coastguard Worker
38*635a8641SAndroid Build Coastguard Worker SyncMessage::~SyncMessage() = default;
39*635a8641SAndroid Build Coastguard Worker
GetReplyDeserializer()40*635a8641SAndroid Build Coastguard Worker MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() {
41*635a8641SAndroid Build Coastguard Worker DCHECK(deserializer_.get());
42*635a8641SAndroid Build Coastguard Worker return deserializer_.release();
43*635a8641SAndroid Build Coastguard Worker }
44*635a8641SAndroid Build Coastguard Worker
IsMessageReplyTo(const Message & msg,int request_id)45*635a8641SAndroid Build Coastguard Worker bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) {
46*635a8641SAndroid Build Coastguard Worker if (!msg.is_reply())
47*635a8641SAndroid Build Coastguard Worker return false;
48*635a8641SAndroid Build Coastguard Worker
49*635a8641SAndroid Build Coastguard Worker return GetMessageId(msg) == request_id;
50*635a8641SAndroid Build Coastguard Worker }
51*635a8641SAndroid Build Coastguard Worker
GetDataIterator(const Message * msg)52*635a8641SAndroid Build Coastguard Worker base::PickleIterator SyncMessage::GetDataIterator(const Message* msg) {
53*635a8641SAndroid Build Coastguard Worker base::PickleIterator iter(*msg);
54*635a8641SAndroid Build Coastguard Worker if (!iter.SkipBytes(kSyncMessageHeaderSize))
55*635a8641SAndroid Build Coastguard Worker return base::PickleIterator();
56*635a8641SAndroid Build Coastguard Worker else
57*635a8641SAndroid Build Coastguard Worker return iter;
58*635a8641SAndroid Build Coastguard Worker }
59*635a8641SAndroid Build Coastguard Worker
GetMessageId(const Message & msg)60*635a8641SAndroid Build Coastguard Worker int SyncMessage::GetMessageId(const Message& msg) {
61*635a8641SAndroid Build Coastguard Worker if (!msg.is_sync() && !msg.is_reply())
62*635a8641SAndroid Build Coastguard Worker return 0;
63*635a8641SAndroid Build Coastguard Worker
64*635a8641SAndroid Build Coastguard Worker SyncHeader header;
65*635a8641SAndroid Build Coastguard Worker if (!ReadSyncHeader(msg, &header))
66*635a8641SAndroid Build Coastguard Worker return 0;
67*635a8641SAndroid Build Coastguard Worker
68*635a8641SAndroid Build Coastguard Worker return header.message_id;
69*635a8641SAndroid Build Coastguard Worker }
70*635a8641SAndroid Build Coastguard Worker
GenerateReply(const Message * msg)71*635a8641SAndroid Build Coastguard Worker Message* SyncMessage::GenerateReply(const Message* msg) {
72*635a8641SAndroid Build Coastguard Worker DCHECK(msg->is_sync());
73*635a8641SAndroid Build Coastguard Worker
74*635a8641SAndroid Build Coastguard Worker Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID,
75*635a8641SAndroid Build Coastguard Worker msg->priority());
76*635a8641SAndroid Build Coastguard Worker reply->set_reply();
77*635a8641SAndroid Build Coastguard Worker
78*635a8641SAndroid Build Coastguard Worker SyncHeader header;
79*635a8641SAndroid Build Coastguard Worker
80*635a8641SAndroid Build Coastguard Worker // use the same message id, but this time reply bit is set
81*635a8641SAndroid Build Coastguard Worker header.message_id = GetMessageId(*msg);
82*635a8641SAndroid Build Coastguard Worker WriteSyncHeader(reply, header);
83*635a8641SAndroid Build Coastguard Worker
84*635a8641SAndroid Build Coastguard Worker return reply;
85*635a8641SAndroid Build Coastguard Worker }
86*635a8641SAndroid Build Coastguard Worker
ReadSyncHeader(const Message & msg,SyncHeader * header)87*635a8641SAndroid Build Coastguard Worker bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) {
88*635a8641SAndroid Build Coastguard Worker DCHECK(msg.is_sync() || msg.is_reply());
89*635a8641SAndroid Build Coastguard Worker
90*635a8641SAndroid Build Coastguard Worker base::PickleIterator iter(msg);
91*635a8641SAndroid Build Coastguard Worker bool result = iter.ReadInt(&header->message_id);
92*635a8641SAndroid Build Coastguard Worker if (!result) {
93*635a8641SAndroid Build Coastguard Worker NOTREACHED();
94*635a8641SAndroid Build Coastguard Worker return false;
95*635a8641SAndroid Build Coastguard Worker }
96*635a8641SAndroid Build Coastguard Worker
97*635a8641SAndroid Build Coastguard Worker return true;
98*635a8641SAndroid Build Coastguard Worker }
99*635a8641SAndroid Build Coastguard Worker
WriteSyncHeader(Message * msg,const SyncHeader & header)100*635a8641SAndroid Build Coastguard Worker bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) {
101*635a8641SAndroid Build Coastguard Worker DCHECK(msg->is_sync() || msg->is_reply());
102*635a8641SAndroid Build Coastguard Worker DCHECK(msg->payload_size() == 0);
103*635a8641SAndroid Build Coastguard Worker msg->WriteInt(header.message_id);
104*635a8641SAndroid Build Coastguard Worker
105*635a8641SAndroid Build Coastguard Worker // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
106*635a8641SAndroid Build Coastguard Worker DCHECK(kSyncMessageHeaderSize == msg->payload_size());
107*635a8641SAndroid Build Coastguard Worker
108*635a8641SAndroid Build Coastguard Worker return true;
109*635a8641SAndroid Build Coastguard Worker }
110*635a8641SAndroid Build Coastguard Worker
111*635a8641SAndroid Build Coastguard Worker
SerializeOutputParameters(const Message & msg)112*635a8641SAndroid Build Coastguard Worker bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) {
113*635a8641SAndroid Build Coastguard Worker return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg));
114*635a8641SAndroid Build Coastguard Worker }
115*635a8641SAndroid Build Coastguard Worker
116*635a8641SAndroid Build Coastguard Worker } // namespace IPC
117