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