xref: /aosp_15_r20/external/libchrome/ipc/ipc_message.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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