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