blob: 1ac4d6e3026a35e7817b068a95ba446e72d15b4f [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
andrew@tullo.ch1134b242014-02-26 00:30:15 +09007#include "base/atomic_sequence_num.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09008#include "base/logging.h"
9#include "build/build_config.h"
10
11#if defined(OS_POSIX)
12#include "ipc/file_descriptor_set_posix.h"
13#endif
14
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090015namespace {
16
andrew@tullo.ch1134b242014-02-26 00:30:15 +090017base::StaticAtomicSequenceNumber g_ref_num;
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090018
19// Create a reference number for identifying IPC messages in traces. The return
20// values has the reference number stored in the upper 24 bits, leaving the low
21// 8 bits set to 0 for use as flags.
22inline uint32 GetRefNumUpper24() {
23 base::debug::TraceLog* trace_log = base::debug::TraceLog::GetInstance();
24 int32 pid = trace_log ? trace_log->process_id() : 0;
andrew@tullo.ch1134b242014-02-26 00:30:15 +090025 int32 count = g_ref_num.GetNext();
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090026 // The 24 bit hash is composed of 14 bits of the count and 10 bits of the
27 // Process ID. With the current trace event buffer cap, the 14-bit count did
28 // not appear to wrap during a trace. Note that it is not a big deal if
29 // collisions occur, as this is only used for debugging and trace analysis.
dsinclair@chromium.org682119c2013-08-14 09:37:47 +090030 return ((pid << 14) | (count & 0x3fff)) << 8;
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090031}
32
33} // namespace
34
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090035namespace IPC {
36
37//------------------------------------------------------------------------------
38
39Message::~Message() {
40}
41
42Message::Message()
43 : Pickle(sizeof(Header)) {
jbates@chromium.org4b8271c2012-09-05 08:08:09 +090044 header()->routing = header()->type = 0;
45 header()->flags = GetRefNumUpper24();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090046#if defined(OS_POSIX)
47 header()->num_fds = 0;
apatrick@google.comb2bde432009-12-05 09:00:58 +090048 header()->pad = 0;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090049#endif
jam@chromium.org822f1fb2014-05-16 08:06:07 +090050 Init();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090051}
52
bbudge@chromium.orgab4c6bc2013-11-05 07:28:12 +090053Message::Message(int32 routing_id, uint32 type, PriorityValue priority)
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090054 : Pickle(sizeof(Header)) {
55 header()->routing = routing_id;
56 header()->type = type;
bbudge@chromium.orgab4c6bc2013-11-05 07:28:12 +090057 DCHECK((priority & 0xffffff00) == 0);
58 header()->flags = priority | GetRefNumUpper24();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090059#if defined(OS_POSIX)
60 header()->num_fds = 0;
apatrick@google.comb2bde432009-12-05 09:00:58 +090061 header()->pad = 0;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090062#endif
jam@chromium.org822f1fb2014-05-16 08:06:07 +090063 Init();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090064}
65
bbudge@chromium.orgab4c6bc2013-11-05 07:28:12 +090066Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
jam@chromium.org822f1fb2014-05-16 08:06:07 +090067 Init();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090068}
69
70Message::Message(const Message& other) : Pickle(other) {
jam@chromium.org822f1fb2014-05-16 08:06:07 +090071 Init();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090072#if defined(OS_POSIX)
73 file_descriptor_set_ = other.file_descriptor_set_;
74#endif
75}
76
jam@chromium.org822f1fb2014-05-16 08:06:07 +090077void Message::Init() {
78 dispatch_error_ = false;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090079#ifdef IPC_MESSAGE_LOG_ENABLED
80 received_time_ = 0;
81 dont_log_ = false;
82 log_data_ = NULL;
83#endif
84}
85
86Message& Message::operator=(const Message& other) {
87 *static_cast<Pickle*>(this) = other;
88#if defined(OS_POSIX)
89 file_descriptor_set_ = other.file_descriptor_set_;
90#endif
91 return *this;
92}
93
brettw@chromium.orgf48910a2012-06-29 09:05:04 +090094void Message::SetHeaderValues(int32 routing, uint32 type, uint32 flags) {
95 // This should only be called when the message is already empty.
96 DCHECK(payload_size() == 0);
97
98 header()->routing = routing;
99 header()->type = type;
100 header()->flags = flags;
101}
102
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900103#ifdef IPC_MESSAGE_LOG_ENABLED
104void Message::set_sent_time(int64 time) {
105 DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
106 header()->flags |= HAS_SENT_TIME_BIT;
107 WriteInt64(time);
108}
109
110int64 Message::sent_time() const {
111 if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
112 return 0;
113
114 const char* data = end_of_payload();
115 data -= sizeof(int64);
116 return *(reinterpret_cast<const int64*>(data));
117}
118
119void Message::set_received_time(int64 time) const {
120 received_time_ = time;
121}
122#endif
123
124#if defined(OS_POSIX)
125bool Message::WriteFileDescriptor(const base::FileDescriptor& descriptor) {
126 // We write the index of the descriptor so that we don't have to
127 // keep the current descriptor as extra decoding state when deserialising.
128 WriteInt(file_descriptor_set()->size());
129 if (descriptor.auto_close) {
130 return file_descriptor_set()->AddAndAutoClose(descriptor.fd);
131 } else {
132 return file_descriptor_set()->Add(descriptor.fd);
133 }
134}
135
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900136bool Message::ReadFileDescriptor(PickleIterator* iter,
estade@chromium.org21ae4812009-11-05 04:01:03 +0900137 base::FileDescriptor* descriptor) const {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900138 int descriptor_index;
139 if (!ReadInt(iter, &descriptor_index))
140 return false;
141
142 FileDescriptorSet* file_descriptor_set = file_descriptor_set_.get();
143 if (!file_descriptor_set)
144 return false;
145
146 descriptor->fd = file_descriptor_set->GetDescriptorAt(descriptor_index);
147 descriptor->auto_close = true;
148
149 return descriptor->fd >= 0;
150}
151
brettw@chromium.orgf48910a2012-06-29 09:05:04 +0900152bool Message::HasFileDescriptors() const {
153 return file_descriptor_set_.get() && !file_descriptor_set_->empty();
154}
155
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900156void Message::EnsureFileDescriptorSet() {
157 if (file_descriptor_set_.get() == NULL)
158 file_descriptor_set_ = new FileDescriptorSet;
159}
160
161#endif
162
thakis@chromium.orgbf9558b2010-01-06 08:20:30 +0900163} // namespace IPC