[sqlite] Annotate Chromium-specific exposed functions with SQLITE_API.
[chromium-blink-merge.git] / ipc / ipc_message.cc
blob6b55d277a8441a7c528cf021514faab40bc119d8
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ipc/ipc_message.h"
7 #include "base/atomic_sequence_num.h"
8 #include "base/logging.h"
9 #include "build/build_config.h"
10 #include "ipc/ipc_message_attachment.h"
11 #include "ipc/ipc_message_attachment_set.h"
12 #include "ipc/placeholder_brokerable_attachment.h"
14 #if defined(OS_POSIX)
15 #include "base/file_descriptor_posix.h"
16 #include "ipc/ipc_platform_file_attachment_posix.h"
17 #endif
19 namespace {
21 base::StaticAtomicSequenceNumber g_ref_num;
23 // Create a reference number for identifying IPC messages in traces. The return
24 // values has the reference number stored in the upper 24 bits, leaving the low
25 // 8 bits set to 0 for use as flags.
26 inline uint32 GetRefNumUpper24() {
27 base::trace_event::TraceLog* trace_log =
28 base::trace_event::TraceLog::GetInstance();
29 uint32 pid = trace_log ? trace_log->process_id() : 0;
30 uint32 count = g_ref_num.GetNext();
31 // The 24 bit hash is composed of 14 bits of the count and 10 bits of the
32 // Process ID. With the current trace event buffer cap, the 14-bit count did
33 // not appear to wrap during a trace. Note that it is not a big deal if
34 // collisions occur, as this is only used for debugging and trace analysis.
35 return ((pid << 14) | (count & 0x3fff)) << 8;
38 } // namespace
40 namespace IPC {
42 //------------------------------------------------------------------------------
44 Message::~Message() {
47 Message::Message() : base::Pickle(sizeof(Header)) {
48 header()->routing = header()->type = 0;
49 header()->flags = GetRefNumUpper24();
50 #if USE_ATTACHMENT_BROKER
51 header()->num_brokered_attachments = 0;
52 #endif
53 #if defined(OS_POSIX)
54 header()->num_fds = 0;
55 header()->pad = 0;
56 #endif
57 Init();
60 Message::Message(int32 routing_id, uint32 type, PriorityValue priority)
61 : base::Pickle(sizeof(Header)) {
62 header()->routing = routing_id;
63 header()->type = type;
64 DCHECK((priority & 0xffffff00) == 0);
65 header()->flags = priority | GetRefNumUpper24();
66 #if USE_ATTACHMENT_BROKER
67 header()->num_brokered_attachments = 0;
68 #endif
69 #if defined(OS_POSIX)
70 header()->num_fds = 0;
71 header()->pad = 0;
72 #endif
73 Init();
76 Message::Message(const char* data, int data_len)
77 : base::Pickle(data, data_len) {
78 Init();
81 Message::Message(const Message& other) : base::Pickle(other) {
82 Init();
83 attachment_set_ = other.attachment_set_;
86 void Message::Init() {
87 dispatch_error_ = false;
88 sender_pid_ = base::kNullProcessId;
89 #ifdef IPC_MESSAGE_LOG_ENABLED
90 received_time_ = 0;
91 dont_log_ = false;
92 log_data_ = NULL;
93 #endif
96 Message& Message::operator=(const Message& other) {
97 *static_cast<base::Pickle*>(this) = other;
98 attachment_set_ = other.attachment_set_;
99 return *this;
102 void Message::SetHeaderValues(int32 routing, uint32 type, uint32 flags) {
103 // This should only be called when the message is already empty.
104 DCHECK(payload_size() == 0);
106 header()->routing = routing;
107 header()->type = type;
108 header()->flags = flags;
111 void Message::EnsureMessageAttachmentSet() {
112 if (attachment_set_.get() == NULL)
113 attachment_set_ = new MessageAttachmentSet;
116 #ifdef IPC_MESSAGE_LOG_ENABLED
117 void Message::set_sent_time(int64 time) {
118 DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
119 header()->flags |= HAS_SENT_TIME_BIT;
120 WriteInt64(time);
123 int64 Message::sent_time() const {
124 if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
125 return 0;
127 const char* data = end_of_payload();
128 data -= sizeof(int64);
129 return *(reinterpret_cast<const int64*>(data));
132 void Message::set_received_time(int64 time) const {
133 received_time_ = time;
135 #endif
137 Message::NextMessageInfo::NextMessageInfo()
138 : message_found(false), pickle_end(nullptr), message_end(nullptr) {}
139 Message::NextMessageInfo::~NextMessageInfo() {}
141 // static
142 Message::NextMessageInfo Message::FindNext(const char* range_start,
143 const char* range_end) {
144 NextMessageInfo info;
145 const char* pickle_end =
146 base::Pickle::FindNext(sizeof(Header), range_start, range_end);
147 if (pickle_end == nullptr)
148 return info;
149 info.pickle_end = pickle_end;
151 #if USE_ATTACHMENT_BROKER
152 // The data is not copied.
153 size_t pickle_len = static_cast<size_t>(pickle_end - range_start);
154 Message message(range_start, static_cast<int>(pickle_len));
155 int num_attachments = message.header()->num_brokered_attachments;
157 // Each brokered attachment adds kNonceSize bytes of data to the message. We
158 // want to avoid overflows in our computations, so we limit the number of
159 // brokerable attachments to 100.
160 if (num_attachments > 100)
161 return info;
163 // Check whether the range includes the attachments.
164 size_t attachment_length = num_attachments * BrokerableAttachment::kNonceSize;
165 size_t buffer_length = static_cast<size_t>(range_end - range_start);
166 if (buffer_length < attachment_length + pickle_len)
167 return info;
169 for (int i = 0; i < num_attachments; ++i) {
170 const char* attachment_start =
171 pickle_end + i * (BrokerableAttachment::kNonceSize);
172 BrokerableAttachment::AttachmentId id(attachment_start,
173 BrokerableAttachment::kNonceSize);
174 info.attachment_ids.push_back(id);
176 info.message_end =
177 pickle_end + num_attachments * BrokerableAttachment::kNonceSize;
178 #else
179 info.message_end = pickle_end;
180 #endif // USE_ATTACHMENT_BROKER
182 info.message_found = true;
183 return info;
186 Message::SerializedAttachmentIds
187 Message::SerializedIdsOfBrokerableAttachments() {
188 DCHECK(HasBrokerableAttachments());
189 std::vector<const BrokerableAttachment*> attachments =
190 attachment_set_->PeekBrokerableAttachments();
191 size_t size = attachments.size() * BrokerableAttachment::kNonceSize;
192 char* buffer = static_cast<char*>(malloc(size));
193 for (size_t i = 0; i < attachments.size(); ++i) {
194 const BrokerableAttachment* attachment = attachments[i];
195 char* start_range = buffer + i * BrokerableAttachment::kNonceSize;
196 BrokerableAttachment::AttachmentId id = attachment->GetIdentifier();
197 id.SerializeToBuffer(start_range, BrokerableAttachment::kNonceSize);
199 SerializedAttachmentIds ids;
200 ids.buffer = buffer;
201 ids.size = size;
202 return ids;
205 bool Message::AddPlaceholderBrokerableAttachmentWithId(
206 BrokerableAttachment::AttachmentId id) {
207 scoped_refptr<PlaceholderBrokerableAttachment> attachment(
208 new PlaceholderBrokerableAttachment(id));
209 return attachment_set()->AddAttachment(attachment);
212 bool Message::WriteAttachment(scoped_refptr<MessageAttachment> attachment) {
213 // We write the index of the descriptor so that we don't have to
214 // keep the current descriptor as extra decoding state when deserialising.
215 WriteInt(attachment_set()->size());
217 #if USE_ATTACHMENT_BROKER
218 if (attachment->GetType() == MessageAttachment::TYPE_BROKERABLE_ATTACHMENT)
219 header()->num_brokered_attachments += 1;
220 #endif
222 return attachment_set()->AddAttachment(attachment);
225 bool Message::ReadAttachment(
226 base::PickleIterator* iter,
227 scoped_refptr<MessageAttachment>* attachment) const {
228 int descriptor_index;
229 if (!iter->ReadInt(&descriptor_index))
230 return false;
232 MessageAttachmentSet* attachment_set = attachment_set_.get();
233 if (!attachment_set)
234 return false;
236 *attachment = attachment_set->GetAttachmentAt(descriptor_index);
237 return nullptr != attachment->get();
240 bool Message::HasAttachments() const {
241 return attachment_set_.get() && !attachment_set_->empty();
244 bool Message::HasMojoHandles() const {
245 return attachment_set_.get() && attachment_set_->num_mojo_handles() > 0;
248 bool Message::HasBrokerableAttachments() const {
249 return attachment_set_.get() &&
250 attachment_set_->num_brokerable_attachments() > 0;
253 } // namespace IPC