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_message.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <limits.h>
8*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
9*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
10*635a8641SAndroid Build Coastguard Worker
11*635a8641SAndroid Build Coastguard Worker #include "base/atomic_sequence_num.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
13*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
14*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_message_attachment.h"
15*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_message_attachment_set.h"
16*635a8641SAndroid Build Coastguard Worker
17*635a8641SAndroid Build Coastguard Worker #if defined(OS_POSIX)
18*635a8641SAndroid Build Coastguard Worker #include "base/file_descriptor_posix.h"
19*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_platform_file_attachment_posix.h"
20*635a8641SAndroid Build Coastguard Worker #endif
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker namespace {
23*635a8641SAndroid Build Coastguard Worker
24*635a8641SAndroid Build Coastguard Worker base::AtomicSequenceNumber g_ref_num;
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Worker // Create a reference number for identifying IPC messages in traces. The return
27*635a8641SAndroid Build Coastguard Worker // values has the reference number stored in the upper 24 bits, leaving the low
28*635a8641SAndroid Build Coastguard Worker // 8 bits set to 0 for use as flags.
GetRefNumUpper24()29*635a8641SAndroid Build Coastguard Worker inline uint32_t GetRefNumUpper24() {
30*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceLog* trace_log =
31*635a8641SAndroid Build Coastguard Worker base::trace_event::TraceLog::GetInstance();
32*635a8641SAndroid Build Coastguard Worker uint32_t pid = trace_log ? trace_log->process_id() : 0;
33*635a8641SAndroid Build Coastguard Worker uint32_t count = g_ref_num.GetNext();
34*635a8641SAndroid Build Coastguard Worker // The 24 bit hash is composed of 14 bits of the count and 10 bits of the
35*635a8641SAndroid Build Coastguard Worker // Process ID. With the current trace event buffer cap, the 14-bit count did
36*635a8641SAndroid Build Coastguard Worker // not appear to wrap during a trace. Note that it is not a big deal if
37*635a8641SAndroid Build Coastguard Worker // collisions occur, as this is only used for debugging and trace analysis.
38*635a8641SAndroid Build Coastguard Worker return ((pid << 14) | (count & 0x3fff)) << 8;
39*635a8641SAndroid Build Coastguard Worker }
40*635a8641SAndroid Build Coastguard Worker
41*635a8641SAndroid Build Coastguard Worker } // namespace
42*635a8641SAndroid Build Coastguard Worker
43*635a8641SAndroid Build Coastguard Worker namespace IPC {
44*635a8641SAndroid Build Coastguard Worker
45*635a8641SAndroid Build Coastguard Worker //------------------------------------------------------------------------------
46*635a8641SAndroid Build Coastguard Worker
47*635a8641SAndroid Build Coastguard Worker Message::~Message() = default;
48*635a8641SAndroid Build Coastguard Worker
Message()49*635a8641SAndroid Build Coastguard Worker Message::Message() : base::Pickle(sizeof(Header)) {
50*635a8641SAndroid Build Coastguard Worker header()->routing = header()->type = 0;
51*635a8641SAndroid Build Coastguard Worker header()->flags = GetRefNumUpper24();
52*635a8641SAndroid Build Coastguard Worker #if defined(OS_POSIX) || defined(OS_FUCHSIA)
53*635a8641SAndroid Build Coastguard Worker header()->num_fds = 0;
54*635a8641SAndroid Build Coastguard Worker header()->pad = 0;
55*635a8641SAndroid Build Coastguard Worker #endif
56*635a8641SAndroid Build Coastguard Worker Init();
57*635a8641SAndroid Build Coastguard Worker }
58*635a8641SAndroid Build Coastguard Worker
Message(int32_t routing_id,uint32_t type,PriorityValue priority)59*635a8641SAndroid Build Coastguard Worker Message::Message(int32_t routing_id, uint32_t type, PriorityValue priority)
60*635a8641SAndroid Build Coastguard Worker : base::Pickle(sizeof(Header)) {
61*635a8641SAndroid Build Coastguard Worker header()->routing = routing_id;
62*635a8641SAndroid Build Coastguard Worker header()->type = type;
63*635a8641SAndroid Build Coastguard Worker DCHECK((priority & 0xffffff00) == 0);
64*635a8641SAndroid Build Coastguard Worker header()->flags = priority | GetRefNumUpper24();
65*635a8641SAndroid Build Coastguard Worker #if defined(OS_POSIX) || defined(OS_FUCHSIA)
66*635a8641SAndroid Build Coastguard Worker header()->num_fds = 0;
67*635a8641SAndroid Build Coastguard Worker header()->pad = 0;
68*635a8641SAndroid Build Coastguard Worker #endif
69*635a8641SAndroid Build Coastguard Worker Init();
70*635a8641SAndroid Build Coastguard Worker }
71*635a8641SAndroid Build Coastguard Worker
Message(const char * data,int data_len)72*635a8641SAndroid Build Coastguard Worker Message::Message(const char* data, int data_len)
73*635a8641SAndroid Build Coastguard Worker : base::Pickle(data, data_len) {
74*635a8641SAndroid Build Coastguard Worker Init();
75*635a8641SAndroid Build Coastguard Worker }
76*635a8641SAndroid Build Coastguard Worker
Message(const Message & other)77*635a8641SAndroid Build Coastguard Worker Message::Message(const Message& other) : base::Pickle(other) {
78*635a8641SAndroid Build Coastguard Worker Init();
79*635a8641SAndroid Build Coastguard Worker attachment_set_ = other.attachment_set_;
80*635a8641SAndroid Build Coastguard Worker }
81*635a8641SAndroid Build Coastguard Worker
Init()82*635a8641SAndroid Build Coastguard Worker void Message::Init() {
83*635a8641SAndroid Build Coastguard Worker dispatch_error_ = false;
84*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
85*635a8641SAndroid Build Coastguard Worker received_time_ = 0;
86*635a8641SAndroid Build Coastguard Worker dont_log_ = false;
87*635a8641SAndroid Build Coastguard Worker log_data_ = NULL;
88*635a8641SAndroid Build Coastguard Worker #endif
89*635a8641SAndroid Build Coastguard Worker }
90*635a8641SAndroid Build Coastguard Worker
operator =(const Message & other)91*635a8641SAndroid Build Coastguard Worker Message& Message::operator=(const Message& other) {
92*635a8641SAndroid Build Coastguard Worker *static_cast<base::Pickle*>(this) = other;
93*635a8641SAndroid Build Coastguard Worker attachment_set_ = other.attachment_set_;
94*635a8641SAndroid Build Coastguard Worker return *this;
95*635a8641SAndroid Build Coastguard Worker }
96*635a8641SAndroid Build Coastguard Worker
SetHeaderValues(int32_t routing,uint32_t type,uint32_t flags)97*635a8641SAndroid Build Coastguard Worker void Message::SetHeaderValues(int32_t routing, uint32_t type, uint32_t flags) {
98*635a8641SAndroid Build Coastguard Worker // This should only be called when the message is already empty.
99*635a8641SAndroid Build Coastguard Worker DCHECK(payload_size() == 0);
100*635a8641SAndroid Build Coastguard Worker
101*635a8641SAndroid Build Coastguard Worker header()->routing = routing;
102*635a8641SAndroid Build Coastguard Worker header()->type = type;
103*635a8641SAndroid Build Coastguard Worker header()->flags = flags;
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker
EnsureMessageAttachmentSet()106*635a8641SAndroid Build Coastguard Worker void Message::EnsureMessageAttachmentSet() {
107*635a8641SAndroid Build Coastguard Worker if (attachment_set_.get() == NULL)
108*635a8641SAndroid Build Coastguard Worker attachment_set_ = new MessageAttachmentSet;
109*635a8641SAndroid Build Coastguard Worker }
110*635a8641SAndroid Build Coastguard Worker
111*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
set_sent_time(int64_t time)112*635a8641SAndroid Build Coastguard Worker void Message::set_sent_time(int64_t time) {
113*635a8641SAndroid Build Coastguard Worker DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
114*635a8641SAndroid Build Coastguard Worker header()->flags |= HAS_SENT_TIME_BIT;
115*635a8641SAndroid Build Coastguard Worker WriteInt64(time);
116*635a8641SAndroid Build Coastguard Worker }
117*635a8641SAndroid Build Coastguard Worker
sent_time() const118*635a8641SAndroid Build Coastguard Worker int64_t Message::sent_time() const {
119*635a8641SAndroid Build Coastguard Worker if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
120*635a8641SAndroid Build Coastguard Worker return 0;
121*635a8641SAndroid Build Coastguard Worker
122*635a8641SAndroid Build Coastguard Worker const char* data = end_of_payload();
123*635a8641SAndroid Build Coastguard Worker data -= sizeof(int64_t);
124*635a8641SAndroid Build Coastguard Worker return *(reinterpret_cast<const int64_t*>(data));
125*635a8641SAndroid Build Coastguard Worker }
126*635a8641SAndroid Build Coastguard Worker
set_received_time(int64_t time) const127*635a8641SAndroid Build Coastguard Worker void Message::set_received_time(int64_t time) const {
128*635a8641SAndroid Build Coastguard Worker received_time_ = time;
129*635a8641SAndroid Build Coastguard Worker }
130*635a8641SAndroid Build Coastguard Worker #endif // BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
131*635a8641SAndroid Build Coastguard Worker
NextMessageInfo()132*635a8641SAndroid Build Coastguard Worker Message::NextMessageInfo::NextMessageInfo()
133*635a8641SAndroid Build Coastguard Worker : message_size(0), message_found(false), pickle_end(nullptr),
134*635a8641SAndroid Build Coastguard Worker message_end(nullptr) {}
135*635a8641SAndroid Build Coastguard Worker Message::NextMessageInfo::~NextMessageInfo() = default;
136*635a8641SAndroid Build Coastguard Worker
137*635a8641SAndroid Build Coastguard Worker // static
FindNext(const char * range_start,const char * range_end,NextMessageInfo * info)138*635a8641SAndroid Build Coastguard Worker void Message::FindNext(const char* range_start,
139*635a8641SAndroid Build Coastguard Worker const char* range_end,
140*635a8641SAndroid Build Coastguard Worker NextMessageInfo* info) {
141*635a8641SAndroid Build Coastguard Worker DCHECK(info);
142*635a8641SAndroid Build Coastguard Worker info->message_found = false;
143*635a8641SAndroid Build Coastguard Worker info->message_size = 0;
144*635a8641SAndroid Build Coastguard Worker
145*635a8641SAndroid Build Coastguard Worker size_t pickle_size = 0;
146*635a8641SAndroid Build Coastguard Worker if (!base::Pickle::PeekNext(sizeof(Header),
147*635a8641SAndroid Build Coastguard Worker range_start, range_end, &pickle_size))
148*635a8641SAndroid Build Coastguard Worker return;
149*635a8641SAndroid Build Coastguard Worker
150*635a8641SAndroid Build Coastguard Worker bool have_entire_pickle =
151*635a8641SAndroid Build Coastguard Worker static_cast<size_t>(range_end - range_start) >= pickle_size;
152*635a8641SAndroid Build Coastguard Worker
153*635a8641SAndroid Build Coastguard Worker info->message_size = pickle_size;
154*635a8641SAndroid Build Coastguard Worker
155*635a8641SAndroid Build Coastguard Worker if (!have_entire_pickle)
156*635a8641SAndroid Build Coastguard Worker return;
157*635a8641SAndroid Build Coastguard Worker
158*635a8641SAndroid Build Coastguard Worker const char* pickle_end = range_start + pickle_size;
159*635a8641SAndroid Build Coastguard Worker
160*635a8641SAndroid Build Coastguard Worker info->message_end = pickle_end;
161*635a8641SAndroid Build Coastguard Worker
162*635a8641SAndroid Build Coastguard Worker info->pickle_end = pickle_end;
163*635a8641SAndroid Build Coastguard Worker info->message_found = true;
164*635a8641SAndroid Build Coastguard Worker }
165*635a8641SAndroid Build Coastguard Worker
WriteAttachment(scoped_refptr<base::Pickle::Attachment> attachment)166*635a8641SAndroid Build Coastguard Worker bool Message::WriteAttachment(
167*635a8641SAndroid Build Coastguard Worker scoped_refptr<base::Pickle::Attachment> attachment) {
168*635a8641SAndroid Build Coastguard Worker size_t index;
169*635a8641SAndroid Build Coastguard Worker bool success = attachment_set()->AddAttachment(
170*635a8641SAndroid Build Coastguard Worker base::WrapRefCounted(static_cast<MessageAttachment*>(attachment.get())),
171*635a8641SAndroid Build Coastguard Worker &index);
172*635a8641SAndroid Build Coastguard Worker DCHECK(success);
173*635a8641SAndroid Build Coastguard Worker
174*635a8641SAndroid Build Coastguard Worker // Write the index of the descriptor so that we don't have to
175*635a8641SAndroid Build Coastguard Worker // keep the current descriptor as extra decoding state when deserialising.
176*635a8641SAndroid Build Coastguard Worker WriteInt(static_cast<int>(index));
177*635a8641SAndroid Build Coastguard Worker
178*635a8641SAndroid Build Coastguard Worker return success;
179*635a8641SAndroid Build Coastguard Worker }
180*635a8641SAndroid Build Coastguard Worker
ReadAttachment(base::PickleIterator * iter,scoped_refptr<base::Pickle::Attachment> * attachment) const181*635a8641SAndroid Build Coastguard Worker bool Message::ReadAttachment(
182*635a8641SAndroid Build Coastguard Worker base::PickleIterator* iter,
183*635a8641SAndroid Build Coastguard Worker scoped_refptr<base::Pickle::Attachment>* attachment) const {
184*635a8641SAndroid Build Coastguard Worker int index;
185*635a8641SAndroid Build Coastguard Worker if (!iter->ReadInt(&index))
186*635a8641SAndroid Build Coastguard Worker return false;
187*635a8641SAndroid Build Coastguard Worker
188*635a8641SAndroid Build Coastguard Worker MessageAttachmentSet* attachment_set = attachment_set_.get();
189*635a8641SAndroid Build Coastguard Worker if (!attachment_set)
190*635a8641SAndroid Build Coastguard Worker return false;
191*635a8641SAndroid Build Coastguard Worker
192*635a8641SAndroid Build Coastguard Worker *attachment = attachment_set->GetAttachmentAt(index);
193*635a8641SAndroid Build Coastguard Worker
194*635a8641SAndroid Build Coastguard Worker return nullptr != attachment->get();
195*635a8641SAndroid Build Coastguard Worker }
196*635a8641SAndroid Build Coastguard Worker
HasAttachments() const197*635a8641SAndroid Build Coastguard Worker bool Message::HasAttachments() const {
198*635a8641SAndroid Build Coastguard Worker return attachment_set_.get() && !attachment_set_->empty();
199*635a8641SAndroid Build Coastguard Worker }
200*635a8641SAndroid Build Coastguard Worker
201*635a8641SAndroid Build Coastguard Worker } // namespace IPC
202