ipc_message.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/atomicops.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/file_descriptor_set_posix.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::subtle::Atomic32 g_ref_num = 0;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Create a reference number for identifying IPC messages in traces. The return
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// values has the reference number stored in the upper 24 bits, leaving the low
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 8 bits set to 0 for use as flags.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline uint32 GetRefNumUpper24() {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::debug::TraceLog* trace_log = base::debug::TraceLog::GetInstance();
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 pid = trace_log ? trace_log->process_id() : 0;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 count = base::subtle::NoBarrier_AtomicIncrement(&g_ref_num, 1);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The 24 bit hash is composed of 14 bits of the count and 10 bits of the
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Process ID. With the current trace event buffer cap, the 14-bit count did
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not appear to wrap during a trace. Note that it is not a big deal if
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // collisions occur, as this is only used for debugging and trace analysis.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((pid << 14) | (count & 0x3fff)) << 8;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IPC {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::~Message() {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::Message()
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Pickle(sizeof(Header)) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->routing = header()->type = 0;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->flags = GetRefNumUpper24();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->num_fds = 0;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->pad = 0;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitLoggingVariables();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::Message(int32 routing_id, uint32 type, PriorityValue priority)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Pickle(sizeof(Header)) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->routing = routing_id;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->type = type;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((priority & 0xffffff00) == 0);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->flags = priority | GetRefNumUpper24();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->num_fds = 0;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->pad = 0;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitLoggingVariables();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::Message(const char* data, int data_len) : Pickle(data, data_len) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitLoggingVariables();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::Message(const Message& other) : Pickle(other) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InitLoggingVariables();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_descriptor_set_ = other.file_descriptor_set_;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::InitLoggingVariables() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef IPC_MESSAGE_LOG_ENABLED
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  received_time_ = 0;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dont_log_ = false;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  log_data_ = NULL;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message& Message::operator=(const Message& other) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *static_cast<Pickle*>(this) = other;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_descriptor_set_ = other.file_descriptor_set_;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *this;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::SetHeaderValues(int32 routing, uint32 type, uint32 flags) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This should only be called when the message is already empty.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(payload_size() == 0);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->routing = routing;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->type = type;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->flags = flags;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef IPC_MESSAGE_LOG_ENABLED
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::set_sent_time(int64 time) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((header()->flags & HAS_SENT_TIME_BIT) == 0);
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header()->flags |= HAS_SENT_TIME_BIT;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteInt64(time);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 Message::sent_time() const {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((header()->flags & HAS_SENT_TIME_BIT) == 0)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* data = end_of_payload();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data -= sizeof(int64);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return *(reinterpret_cast<const int64*>(data));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::set_received_time(int64 time) const {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  received_time_ = time;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::WriteFileDescriptor(const base::FileDescriptor& descriptor) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We write the index of the descriptor so that we don't have to
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keep the current descriptor as extra decoding state when deserialising.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WriteInt(file_descriptor_set()->size());
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (descriptor.auto_close) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return file_descriptor_set()->AddAndAutoClose(descriptor.fd);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return file_descriptor_set()->Add(descriptor.fd);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::ReadFileDescriptor(PickleIterator* iter,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 base::FileDescriptor* descriptor) const {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int descriptor_index;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReadInt(iter, &descriptor_index))
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileDescriptorSet* file_descriptor_set = file_descriptor_set_.get();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!file_descriptor_set)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  descriptor->fd = file_descriptor_set->GetDescriptorAt(descriptor_index);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  descriptor->auto_close = true;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return descriptor->fd >= 0;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::HasFileDescriptors() const {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return file_descriptor_set_.get() && !file_descriptor_set_->empty();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::EnsureFileDescriptorSet() {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (file_descriptor_set_.get() == NULL)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_descriptor_set_ = new FileDescriptorSet;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace IPC
163