blob: f66b4fe882c60abfdf1038a8b47cef01786449f6 [file] [log] [blame]
jbates@chromium.org0fc87362012-03-08 05:42:56 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09002// 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_message.h"
6
erikchenc8dc3f52015-09-12 04:08:53 +09007#include <limits.h>
avi42ebda42015-12-22 11:39:04 +09008#include <stddef.h>
9#include <stdint.h>
erikchenc8dc3f52015-09-12 04:08:53 +090010
andrew@tullo.ch1134b242014-02-26 00:30:15 +090011#include "base/atomic_sequence_num.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090012#include "base/logging.h"
13#include "build/build_config.h"
morrita7d1bfcc2015-01-31 14:45:42 +090014#include "ipc/ipc_message_attachment.h"
morrita33a35902015-01-15 06:17:06 +090015#include "ipc/ipc_message_attachment_set.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090016
17#if defined(OS_POSIX)
morritaab207252014-09-25 05:11:45 +090018#include "base/file_descriptor_posix.h"
morrita7d1bfcc2015-01-31 14:45:42 +090019#include "ipc/ipc_platform_file_attachment_posix.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090020#endif
21
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090022namespace {
23
andrew@tullo.ch1134b242014-02-26 00:30:15 +090024base::StaticAtomicSequenceNumber g_ref_num;
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090025
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.
tfarina1cbfa082015-09-05 03:47:57 +090029inline uint32_t GetRefNumUpper24() {
ssid98735502015-02-10 06:25:39 +090030 base::trace_event::TraceLog* trace_log =
31 base::trace_event::TraceLog::GetInstance();
tfarina1cbfa082015-09-05 03:47:57 +090032 uint32_t pid = trace_log ? trace_log->process_id() : 0;
33 uint32_t count = g_ref_num.GetNext();
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090034 // 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.
dsinclair@chromium.org682119c2013-08-14 09:37:47 +090038 return ((pid << 14) | (count & 0x3fff)) << 8;
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090039}
40
41} // namespace
42
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090043namespace IPC {
44
45//------------------------------------------------------------------------------
46
47Message::~Message() {
48}
49
brettwf3146202015-06-03 13:29:25 +090050Message::Message() : base::Pickle(sizeof(Header)) {
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090051 header()->routing = header()->type = 0;
52 header()->flags = GetRefNumUpper24();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090053#if defined(OS_POSIX)
54 header()->num_fds = 0;
apatrick@google.comb2bde432009-12-05 09:00:58 +090055 header()->pad = 0;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090056#endif
jam@chromium.org822f1fb2014-05-16 08:06:07 +090057 Init();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090058}
59
tfarina1cbfa082015-09-05 03:47:57 +090060Message::Message(int32_t routing_id, uint32_t type, PriorityValue priority)
brettwf3146202015-06-03 13:29:25 +090061 : base::Pickle(sizeof(Header)) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090062 header()->routing = routing_id;
63 header()->type = type;
bbudge@chromium.orgab4c6bc2013-11-05 07:28:12 +090064 DCHECK((priority & 0xffffff00) == 0);
65 header()->flags = priority | GetRefNumUpper24();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090066#if defined(OS_POSIX)
67 header()->num_fds = 0;
apatrick@google.comb2bde432009-12-05 09:00:58 +090068 header()->pad = 0;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090069#endif
jam@chromium.org822f1fb2014-05-16 08:06:07 +090070 Init();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090071}
72
brettwf3146202015-06-03 13:29:25 +090073Message::Message(const char* data, int data_len)
74 : base::Pickle(data, data_len) {
jam@chromium.org822f1fb2014-05-16 08:06:07 +090075 Init();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090076}
77
brettwf3146202015-06-03 13:29:25 +090078Message::Message(const Message& other) : base::Pickle(other) {
jam@chromium.org822f1fb2014-05-16 08:06:07 +090079 Init();
morrita33a35902015-01-15 06:17:06 +090080 attachment_set_ = other.attachment_set_;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090081}
82
jam@chromium.org822f1fb2014-05-16 08:06:07 +090083void Message::Init() {
84 dispatch_error_ = false;
davidsz3bf38eb2017-05-12 18:19:23 +090085#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090086 received_time_ = 0;
87 dont_log_ = false;
88 log_data_ = NULL;
89#endif
90}
91
92Message& Message::operator=(const Message& other) {
brettwf3146202015-06-03 13:29:25 +090093 *static_cast<base::Pickle*>(this) = other;
morrita33a35902015-01-15 06:17:06 +090094 attachment_set_ = other.attachment_set_;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090095 return *this;
96}
97
tfarina1cbfa082015-09-05 03:47:57 +090098void Message::SetHeaderValues(int32_t routing, uint32_t type, uint32_t flags) {
brettw@chromium.orgf48910a2012-06-29 09:05:04 +090099 // This should only be called when the message is already empty.
100 DCHECK(payload_size() == 0);
101
102 header()->routing = routing;
103 header()->type = type;
104 header()->flags = flags;
105}
106
morrita33a35902015-01-15 06:17:06 +0900107void Message::EnsureMessageAttachmentSet() {
108 if (attachment_set_.get() == NULL)
109 attachment_set_ = new MessageAttachmentSet;
110}
111
davidsz3bf38eb2017-05-12 18:19:23 +0900112#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
tfarina1cbfa082015-09-05 03:47:57 +0900113void Message::set_sent_time(int64_t time) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900114 DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
115 header()->flags |= HAS_SENT_TIME_BIT;
116 WriteInt64(time);
117}
118
tfarina1cbfa082015-09-05 03:47:57 +0900119int64_t Message::sent_time() const {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900120 if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
121 return 0;
122
123 const char* data = end_of_payload();
tfarina1cbfa082015-09-05 03:47:57 +0900124 data -= sizeof(int64_t);
125 return *(reinterpret_cast<const int64_t*>(data));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900126}
127
tfarina1cbfa082015-09-05 03:47:57 +0900128void Message::set_received_time(int64_t time) const {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900129 received_time_ = time;
130}
davidsz3bf38eb2017-05-12 18:19:23 +0900131#endif // BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900132
erikchenc8dc3f52015-09-12 04:08:53 +0900133Message::NextMessageInfo::NextMessageInfo()
dskibaaa08dcb2015-10-01 02:24:30 +0900134 : message_size(0), message_found(false), pickle_end(nullptr),
135 message_end(nullptr) {}
erikchenc8dc3f52015-09-12 04:08:53 +0900136Message::NextMessageInfo::~NextMessageInfo() {}
137
138// static
139void Message::FindNext(const char* range_start,
140 const char* range_end,
141 NextMessageInfo* info) {
142 DCHECK(info);
dskibaaa08dcb2015-10-01 02:24:30 +0900143 info->message_found = false;
144 info->message_size = 0;
145
146 size_t pickle_size = 0;
147 if (!base::Pickle::PeekNext(sizeof(Header),
148 range_start, range_end, &pickle_size))
erikchenc8dc3f52015-09-12 04:08:53 +0900149 return;
dskibaaa08dcb2015-10-01 02:24:30 +0900150
151 bool have_entire_pickle =
152 static_cast<size_t>(range_end - range_start) >= pickle_size;
erikchenc8dc3f52015-09-12 04:08:53 +0900153
dskibaaa08dcb2015-10-01 02:24:30 +0900154 info->message_size = pickle_size;
155
156 if (!have_entire_pickle)
157 return;
158
159 const char* pickle_end = range_start + pickle_size;
160
erikchenc8dc3f52015-09-12 04:08:53 +0900161 info->message_end = pickle_end;
erikchenc8dc3f52015-09-12 04:08:53 +0900162
dskibaaa08dcb2015-10-01 02:24:30 +0900163 info->pickle_end = pickle_end;
erikchenc8dc3f52015-09-12 04:08:53 +0900164 info->message_found = true;
165}
166
rockot6dbfea52016-02-04 05:20:16 +0900167bool Message::WriteAttachment(
168 scoped_refptr<base::Pickle::Attachment> attachment) {
erikchenc8fa4212015-10-10 11:43:49 +0900169 size_t index;
rockot6dbfea52016-02-04 05:20:16 +0900170 bool success = attachment_set()->AddAttachment(
171 make_scoped_refptr(static_cast<MessageAttachment*>(attachment.get())),
sammc14583362016-11-23 12:17:35 +0900172 &index);
erikchenc8fa4212015-10-10 11:43:49 +0900173 DCHECK(success);
174
jam7f5c5742016-05-12 06:05:05 +0900175 // NOTE: If you add more data to the pickle, make sure to update
176 // PickleSizer::AddAttachment.
177
erikchenc8fa4212015-10-10 11:43:49 +0900178 // Write the index of the descriptor so that we don't have to
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900179 // keep the current descriptor as extra decoding state when deserialising.
erikchenc8fa4212015-10-10 11:43:49 +0900180 WriteInt(static_cast<int>(index));
181
erikchenc8fa4212015-10-10 11:43:49 +0900182 return success;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900183}
184
morrita7d1bfcc2015-01-31 14:45:42 +0900185bool Message::ReadAttachment(
brettwf3146202015-06-03 13:29:25 +0900186 base::PickleIterator* iter,
rockot6dbfea52016-02-04 05:20:16 +0900187 scoped_refptr<base::Pickle::Attachment>* attachment) const {
erikchenc8fa4212015-10-10 11:43:49 +0900188 int index;
189 if (!iter->ReadInt(&index))
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900190 return false;
191
morrita33a35902015-01-15 06:17:06 +0900192 MessageAttachmentSet* attachment_set = attachment_set_.get();
193 if (!attachment_set)
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900194 return false;
195
sammc14583362016-11-23 12:17:35 +0900196 *attachment = attachment_set->GetAttachmentAt(index);
erikchenc8fa4212015-10-10 11:43:49 +0900197
morrita7d1bfcc2015-01-31 14:45:42 +0900198 return nullptr != attachment->get();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900199}
200
morrita7d1bfcc2015-01-31 14:45:42 +0900201bool Message::HasAttachments() const {
morrita33a35902015-01-15 06:17:06 +0900202 return attachment_set_.get() && !attachment_set_->empty();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900203}
204
thakis@chromium.orgbf9558b2010-01-06 08:20:30 +0900205} // namespace IPC