blob: 87c7633b53f88cf85e644f91e508ab094e7c05b9 [file] [log] [blame]
[email protected]ce208f872012-03-07 20:42:561// 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]946d1b22009-07-22 23:57:215#include "ipc/ipc_message.h"
initial.commit09911bf2008-07-26 23:55:296
erikchen29e0f2f2015-09-11 19:08:537#include <limits.h>
8
[email protected]dc4fa482014-02-25 15:30:159#include "base/atomic_sequence_num.h"
initial.commit09911bf2008-07-26 23:55:2910#include "base/logging.h"
[email protected]526776c2009-02-07 00:39:2611#include "build/build_config.h"
erikchen87397e02015-10-10 01:10:2412#include "ipc/attachment_broker.h"
morrita1aa788c2015-01-31 05:45:4213#include "ipc/ipc_message_attachment.h"
morrita4b5c28e22015-01-14 21:17:0614#include "ipc/ipc_message_attachment_set.h"
erikchen87351da2015-09-15 19:11:0915#include "ipc/placeholder_brokerable_attachment.h"
initial.commit09911bf2008-07-26 23:55:2916
[email protected]7135bb042009-02-12 04:05:2817#if defined(OS_POSIX)
morrita96693852014-09-24 20:11:4518#include "base/file_descriptor_posix.h"
morrita1aa788c2015-01-31 05:45:4219#include "ipc/ipc_platform_file_attachment_posix.h"
[email protected]7135bb042009-02-12 04:05:2820#endif
21
[email protected]2a2e3d62012-09-04 23:08:0922namespace {
23
[email protected]dc4fa482014-02-25 15:30:1524base::StaticAtomicSequenceNumber g_ref_num;
[email protected]2a2e3d62012-09-04 23:08:0925
26// Create a reference number for identifying IPC messages in traces. The return
27// values has the reference number stored in the upper 24 bits, leaving the low
28// 8 bits set to 0 for use as flags.
tfarina10a5c062015-09-04 18:47:5729inline uint32_t GetRefNumUpper24() {
ssid759dd8c2015-02-09 21:25:3930 base::trace_event::TraceLog* trace_log =
31 base::trace_event::TraceLog::GetInstance();
tfarina10a5c062015-09-04 18:47:5732 uint32_t pid = trace_log ? trace_log->process_id() : 0;
33 uint32_t count = g_ref_num.GetNext();
[email protected]2a2e3d62012-09-04 23:08:0934 // The 24 bit hash is composed of 14 bits of the count and 10 bits of the
35 // Process ID. With the current trace event buffer cap, the 14-bit count did
36 // not appear to wrap during a trace. Note that it is not a big deal if
37 // collisions occur, as this is only used for debugging and trace analysis.
[email protected]40cb13052013-08-14 00:37:4738 return ((pid << 14) | (count & 0x3fff)) << 8;
[email protected]2a2e3d62012-09-04 23:08:0939}
40
41} // namespace
42
initial.commit09911bf2008-07-26 23:55:2943namespace IPC {
44
45//------------------------------------------------------------------------------
46
47Message::~Message() {
48}
49
brettwbd4d7112015-06-03 04:29:2550Message::Message() : base::Pickle(sizeof(Header)) {
[email protected]2a2e3d62012-09-04 23:08:0951 header()->routing = header()->type = 0;
52 header()->flags = GetRefNumUpper24();
erikchenc32bea672015-10-19 22:23:3253#if USE_ATTACHMENT_BROKER
erikchencd52c882015-09-29 16:50:0554 header()->num_brokered_attachments = 0;
55#endif
[email protected]526776c2009-02-07 00:39:2656#if defined(OS_POSIX)
57 header()->num_fds = 0;
[email protected]15b97af032009-12-05 00:00:5858 header()->pad = 0;
[email protected]526776c2009-02-07 00:39:2659#endif
[email protected]ef2f6ba2014-05-15 23:06:0760 Init();
initial.commit09911bf2008-07-26 23:55:2961}
62
tfarina10a5c062015-09-04 18:47:5763Message::Message(int32_t routing_id, uint32_t type, PriorityValue priority)
brettwbd4d7112015-06-03 04:29:2564 : base::Pickle(sizeof(Header)) {
initial.commit09911bf2008-07-26 23:55:2965 header()->routing = routing_id;
66 header()->type = type;
[email protected]753bb252013-11-04 22:28:1267 DCHECK((priority & 0xffffff00) == 0);
68 header()->flags = priority | GetRefNumUpper24();
erikchenc32bea672015-10-19 22:23:3269#if USE_ATTACHMENT_BROKER
erikchencd52c882015-09-29 16:50:0570 header()->num_brokered_attachments = 0;
71#endif
[email protected]526776c2009-02-07 00:39:2672#if defined(OS_POSIX)
73 header()->num_fds = 0;
[email protected]15b97af032009-12-05 00:00:5874 header()->pad = 0;
[email protected]526776c2009-02-07 00:39:2675#endif
[email protected]ef2f6ba2014-05-15 23:06:0776 Init();
initial.commit09911bf2008-07-26 23:55:2977}
78
brettwbd4d7112015-06-03 04:29:2579Message::Message(const char* data, int data_len)
80 : base::Pickle(data, data_len) {
[email protected]ef2f6ba2014-05-15 23:06:0781 Init();
initial.commit09911bf2008-07-26 23:55:2982}
83
brettwbd4d7112015-06-03 04:29:2584Message::Message(const Message& other) : base::Pickle(other) {
[email protected]ef2f6ba2014-05-15 23:06:0785 Init();
morrita4b5c28e22015-01-14 21:17:0686 attachment_set_ = other.attachment_set_;
initial.commit09911bf2008-07-26 23:55:2987}
88
[email protected]ef2f6ba2014-05-15 23:06:0789void Message::Init() {
90 dispatch_error_ = false;
erikchen3c175a32015-07-28 23:16:4891 sender_pid_ = base::kNullProcessId;
initial.commit09911bf2008-07-26 23:55:2992#ifdef IPC_MESSAGE_LOG_ENABLED
93 received_time_ = 0;
94 dont_log_ = false;
95 log_data_ = NULL;
96#endif
97}
98
99Message& Message::operator=(const Message& other) {
brettwbd4d7112015-06-03 04:29:25100 *static_cast<base::Pickle*>(this) = other;
morrita4b5c28e22015-01-14 21:17:06101 attachment_set_ = other.attachment_set_;
initial.commit09911bf2008-07-26 23:55:29102 return *this;
103}
104
tfarina10a5c062015-09-04 18:47:57105void Message::SetHeaderValues(int32_t routing, uint32_t type, uint32_t flags) {
[email protected]34d48612012-06-29 00:05:04106 // This should only be called when the message is already empty.
107 DCHECK(payload_size() == 0);
108
109 header()->routing = routing;
110 header()->type = type;
111 header()->flags = flags;
112}
113
morrita4b5c28e22015-01-14 21:17:06114void Message::EnsureMessageAttachmentSet() {
115 if (attachment_set_.get() == NULL)
116 attachment_set_ = new MessageAttachmentSet;
117}
118
initial.commit09911bf2008-07-26 23:55:29119#ifdef IPC_MESSAGE_LOG_ENABLED
tfarina10a5c062015-09-04 18:47:57120void Message::set_sent_time(int64_t time) {
initial.commit09911bf2008-07-26 23:55:29121 DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
122 header()->flags |= HAS_SENT_TIME_BIT;
123 WriteInt64(time);
124}
125
tfarina10a5c062015-09-04 18:47:57126int64_t Message::sent_time() const {
initial.commit09911bf2008-07-26 23:55:29127 if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
128 return 0;
129
130 const char* data = end_of_payload();
tfarina10a5c062015-09-04 18:47:57131 data -= sizeof(int64_t);
132 return *(reinterpret_cast<const int64_t*>(data));
initial.commit09911bf2008-07-26 23:55:29133}
134
tfarina10a5c062015-09-04 18:47:57135void Message::set_received_time(int64_t time) const {
initial.commit09911bf2008-07-26 23:55:29136 received_time_ = time;
137}
138#endif
139
erikchen29e0f2f2015-09-11 19:08:53140Message::NextMessageInfo::NextMessageInfo()
dskiba6f3790a2015-09-30 17:24:30141 : message_size(0), message_found(false), pickle_end(nullptr),
142 message_end(nullptr) {}
erikchen29e0f2f2015-09-11 19:08:53143Message::NextMessageInfo::~NextMessageInfo() {}
144
erikchen3b325062015-09-22 21:59:10145Message::SerializedAttachmentIds
146Message::SerializedIdsOfBrokerableAttachments() {
147 DCHECK(HasBrokerableAttachments());
erikchen3722a322015-10-07 20:51:55148 std::vector<BrokerableAttachment*> attachments =
149 attachment_set_->GetBrokerableAttachments();
erikchen3b325062015-09-22 21:59:10150 CHECK_LE(attachments.size(), std::numeric_limits<size_t>::max() /
151 BrokerableAttachment::kNonceSize);
152 size_t size = attachments.size() * BrokerableAttachment::kNonceSize;
153 char* buffer = static_cast<char*>(malloc(size));
154 for (size_t i = 0; i < attachments.size(); ++i) {
155 const BrokerableAttachment* attachment = attachments[i];
156 char* start_range = buffer + i * BrokerableAttachment::kNonceSize;
157 BrokerableAttachment::AttachmentId id = attachment->GetIdentifier();
158 id.SerializeToBuffer(start_range, BrokerableAttachment::kNonceSize);
159 }
160 SerializedAttachmentIds ids;
161 ids.buffer = buffer;
162 ids.size = size;
163 return ids;
164}
165
erikchen29e0f2f2015-09-11 19:08:53166// static
167void Message::FindNext(const char* range_start,
168 const char* range_end,
169 NextMessageInfo* info) {
170 DCHECK(info);
dskiba6f3790a2015-09-30 17:24:30171 info->message_found = false;
172 info->message_size = 0;
173
174 size_t pickle_size = 0;
175 if (!base::Pickle::PeekNext(sizeof(Header),
176 range_start, range_end, &pickle_size))
erikchen29e0f2f2015-09-11 19:08:53177 return;
dskiba6f3790a2015-09-30 17:24:30178
179 bool have_entire_pickle =
180 static_cast<size_t>(range_end - range_start) >= pickle_size;
erikchen29e0f2f2015-09-11 19:08:53181
erikchen87397e02015-10-10 01:10:24182#if USE_ATTACHMENT_BROKER && defined(OS_MACOSX) && !defined(OS_IOS)
dskiba6f3790a2015-09-30 17:24:30183 // TODO(dskiba): determine message_size when entire pickle is not available
184
185 if (!have_entire_pickle)
186 return;
187
188 const char* pickle_end = range_start + pickle_size;
189
erikchen29e0f2f2015-09-11 19:08:53190 // The data is not copied.
dskiba6f3790a2015-09-30 17:24:30191 Message message(range_start, static_cast<int>(pickle_size));
192 size_t num_attachments = message.header()->num_brokered_attachments;
erikchen29e0f2f2015-09-11 19:08:53193
194 // Check for possible overflows.
195 size_t max_size_t = std::numeric_limits<size_t>::max();
196 if (num_attachments >= max_size_t / BrokerableAttachment::kNonceSize)
197 return;
198
199 size_t attachment_length = num_attachments * BrokerableAttachment::kNonceSize;
dskiba6f3790a2015-09-30 17:24:30200 if (pickle_size > max_size_t - attachment_length)
erikchen29e0f2f2015-09-11 19:08:53201 return;
202
203 // Check whether the range includes the attachments.
204 size_t buffer_length = static_cast<size_t>(range_end - range_start);
dskiba6f3790a2015-09-30 17:24:30205 if (buffer_length < attachment_length + pickle_size)
erikchen29e0f2f2015-09-11 19:08:53206 return;
207
erikchen87397e02015-10-10 01:10:24208 for (size_t i = 0; i < num_attachments; ++i) {
erikchen29e0f2f2015-09-11 19:08:53209 const char* attachment_start =
210 pickle_end + i * BrokerableAttachment::kNonceSize;
211 BrokerableAttachment::AttachmentId id(attachment_start,
212 BrokerableAttachment::kNonceSize);
213 info->attachment_ids.push_back(id);
214 }
215 info->message_end =
216 pickle_end + num_attachments * BrokerableAttachment::kNonceSize;
dskiba6f3790a2015-09-30 17:24:30217 info->message_size = info->message_end - range_start;
erikchen29e0f2f2015-09-11 19:08:53218#else
dskiba6f3790a2015-09-30 17:24:30219 info->message_size = pickle_size;
220
221 if (!have_entire_pickle)
222 return;
223
224 const char* pickle_end = range_start + pickle_size;
225
erikchen29e0f2f2015-09-11 19:08:53226 info->message_end = pickle_end;
227#endif // USE_ATTACHMENT_BROKER
228
dskiba6f3790a2015-09-30 17:24:30229 info->pickle_end = pickle_end;
erikchen29e0f2f2015-09-11 19:08:53230 info->message_found = true;
231}
232
erikchen87351da2015-09-15 19:11:09233bool Message::AddPlaceholderBrokerableAttachmentWithId(
234 BrokerableAttachment::AttachmentId id) {
235 scoped_refptr<PlaceholderBrokerableAttachment> attachment(
236 new PlaceholderBrokerableAttachment(id));
237 return attachment_set()->AddAttachment(attachment);
238}
239
morrita1aa788c2015-01-31 05:45:42240bool Message::WriteAttachment(scoped_refptr<MessageAttachment> attachment) {
erikchenae6d3212015-10-10 02:43:49241 bool brokerable;
242 size_t index;
243 bool success =
244 attachment_set()->AddAttachment(attachment, &index, &brokerable);
245 DCHECK(success);
246
247 // Write the type of descriptor.
248 WriteBool(brokerable);
249
250 // Write the index of the descriptor so that we don't have to
[email protected]7135bb042009-02-12 04:05:28251 // keep the current descriptor as extra decoding state when deserialising.
erikchenae6d3212015-10-10 02:43:49252 WriteInt(static_cast<int>(index));
253
254#if USE_ATTACHMENT_BROKER && defined(OS_MACOSX) && !defined(OS_IOS)
255 if (brokerable)
256 header()->num_brokered_attachments++;
257#endif
258
259 return success;
[email protected]7135bb042009-02-12 04:05:28260}
261
morrita1aa788c2015-01-31 05:45:42262bool Message::ReadAttachment(
brettwbd4d7112015-06-03 04:29:25263 base::PickleIterator* iter,
morrita1aa788c2015-01-31 05:45:42264 scoped_refptr<MessageAttachment>* attachment) const {
erikchenae6d3212015-10-10 02:43:49265 bool brokerable;
266 if (!iter->ReadBool(&brokerable))
267 return false;
268
269 int index;
270 if (!iter->ReadInt(&index))
[email protected]7135bb042009-02-12 04:05:28271 return false;
272
morrita4b5c28e22015-01-14 21:17:06273 MessageAttachmentSet* attachment_set = attachment_set_.get();
274 if (!attachment_set)
[email protected]7135bb042009-02-12 04:05:28275 return false;
276
erikchenae6d3212015-10-10 02:43:49277 *attachment = brokerable
278 ? attachment_set->GetBrokerableAttachmentAt(index)
279 : attachment_set->GetNonBrokerableAttachmentAt(index);
280
morrita1aa788c2015-01-31 05:45:42281 return nullptr != attachment->get();
[email protected]7135bb042009-02-12 04:05:28282}
283
morrita1aa788c2015-01-31 05:45:42284bool Message::HasAttachments() const {
morrita4b5c28e22015-01-14 21:17:06285 return attachment_set_.get() && !attachment_set_->empty();
[email protected]7135bb042009-02-12 04:05:28286}
287
morrita81b17e02015-02-06 00:58:30288bool Message::HasMojoHandles() const {
erikcheneece6c32015-07-07 22:13:11289 return attachment_set_.get() && attachment_set_->num_mojo_handles() > 0;
290}
291
292bool Message::HasBrokerableAttachments() const {
293 return attachment_set_.get() &&
294 attachment_set_->num_brokerable_attachments() > 0;
morrita81b17e02015-02-06 00:58:30295}
296
[email protected]d284a5f2010-01-05 23:20:30297} // namespace IPC