14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifndef MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#define MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include <stddef.h>
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <stdint.h>
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <vector>
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/macros.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/memory/aligned_memory.h"
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/system/dispatcher.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/system/memory.h"
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "mojo/system/system_impl_export.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace mojo {
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace system {
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class Channel;
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)class TransportData;
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This class is used to represent data in transit. It is thread-unsafe.
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |MessageInTransit| buffers:
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// A |MessageInTransit| can be serialized by writing the main buffer and then,
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// if it has one, the transport data buffer. Both buffers are
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |kMessageAlignment|-byte aligned and a multiple of |kMessageAlignment| bytes
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// in size.
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// The main buffer consists of the header (of type |Header|, which is an
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// internal detail of this class) followed immediately by the message data
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// (accessed by |bytes()| and of size |num_bytes()|, and also
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// |kMessageAlignment|-byte aligned), and then any padding needed to make the
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// main buffer a multiple of |kMessageAlignment| bytes in size.
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// See |TransportData| for a description of the (serialized) transport data
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// buffer.
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  typedef uint16_t Type;
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Messages that are forwarded to |MessagePipeEndpoint|s.
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static const Type kTypeMessagePipeEndpoint = 0;
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Messages that are forwarded to |MessagePipe|s.
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static const Type kTypeMessagePipe = 1;
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Messages that are consumed by the |Channel|.
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static const Type kTypeChannel = 2;
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Messages that are consumed by the |RawChannel| (implementation).
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const Type kTypeRawChannel = 3;
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  typedef uint16_t Subtype;
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Subtypes for type |kTypeMessagePipeEndpoint|:
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static const Subtype kSubtypeMessagePipeEndpointData = 0;
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Subtypes for type |kTypeMessagePipe|:
590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Nothing currently.
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Subtypes for type |kTypeChannel|:
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static const Subtype kSubtypeChannelRunMessagePipeEndpoint = 0;
620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  static const Subtype kSubtypeChannelRemoveMessagePipeEndpoint = 1;
630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  static const Subtype kSubtypeChannelRemoveMessagePipeEndpointAck = 2;
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Subtypes for type |kTypeRawChannel|:
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static const Subtype kSubtypeRawChannelPosixExtraPlatformHandles = 0;
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  typedef uint32_t EndpointId;
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Never a valid endpoint ID.
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static const EndpointId kInvalidEndpointId = 0;
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Messages (the header and data) must always be aligned to a multiple of this
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // quantity (which must be a power of 2).
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static const size_t kMessageAlignment = 8;
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Forward-declare |Header| so that |View| can use it:
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  struct Header;
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This represents a view of serialized message data in a raw buffer.
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  class MOJO_SYSTEM_IMPL_EXPORT View {
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   public:
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Constructs a view from the given buffer of the given size. (The size must
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // must remain alive/unmodified through the lifetime of this object.
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // |buffer| should be |kMessageAlignment|-byte aligned.
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    View(size_t message_size, const void* buffer);
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Checks that the given |View| appears to be for a valid message, within
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // predetermined limits (e.g., |num_bytes()| and |main_buffer_size()|, that
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // |transport_data_buffer()|/|transport_data_buffer_size()| is for valid
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // transport data -- see |TransportData::ValidateBuffer()|).
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    //
94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // It returns true (and leaves |error_message| alone) if this object appears
95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // to be a valid message (according to the above) and false, pointing
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    // |*error_message| to a suitable error message, if not.
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool IsValid(size_t serialized_platform_handle_size,
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 const char** error_message) const;
99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // API parallel to that for |MessageInTransit| itself (mostly getters for
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // header data).
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const void* main_buffer() const { return buffer_; }
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    size_t main_buffer_size() const {
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes);
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const void* transport_data_buffer() const {
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return (total_size() > main_buffer_size())
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 ? static_cast<const char*>(buffer_) + main_buffer_size()
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 : nullptr;
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    size_t transport_data_buffer_size() const {
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return total_size() - main_buffer_size();
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    size_t total_size() const { return header()->total_size; }
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    uint32_t num_bytes() const { return header()->num_bytes; }
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const void* bytes() const {
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return static_cast<const char*>(buffer_) + sizeof(Header);
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Type type() const { return header()->type; }
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Subtype subtype() const { return header()->subtype; }
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EndpointId source_id() const { return header()->source_id; }
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EndpointId destination_id() const { return header()->destination_id; }
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   private:
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const Header* header() const { return static_cast<const Header*>(buffer_); }
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const void* const buffer_;
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Though this struct is trivial, disallow copy and assign, since it doesn't
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // own its data. (If you're copying/assigning this, you're probably doing
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // something wrong.)
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(View);
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // |bytes| is optional; if null, the message data will be zero-initialized.
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MessageInTransit(Type type,
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   Subtype subtype,
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   uint32_t num_bytes,
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   const void* bytes);
1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |bytes| should be valid (and non-null), unless |num_bytes| is zero.
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MessageInTransit(Type type,
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   Subtype subtype,
1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   uint32_t num_bytes,
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                   UserPointer<const void> bytes);
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Constructs a |MessageInTransit| from a |View|.
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit MessageInTransit(const View& message_view);
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ~MessageInTransit();
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Gets the size of the next message from |buffer|, which has |buffer_size|
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // bytes currently available, returning true and setting |*next_message_size|
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // on success. |buffer| should be aligned on a |kMessageAlignment| boundary
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (and on success, |*next_message_size| will be a multiple of
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // |kMessageAlignment|).
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // TODO(vtl): In |RawChannelPosix|, the alignment requirements are currently
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // satisified on a faith-based basis.
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  static bool GetNextMessageSize(const void* buffer,
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 size_t buffer_size,
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 size_t* next_message_size);
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Makes this message "own" the given set of dispatchers. The dispatchers must
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // not be referenced from anywhere else (in particular, not from the handle
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // table), i.e., each dispatcher must have a reference count of 1. This
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // message must not already have dispatchers.
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void SetDispatchers(scoped_ptr<DispatcherVector> dispatchers);
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Sets the |TransportData| for this message. This should only be done when
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // there are no dispatchers and no existing |TransportData|.
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void SetTransportData(scoped_ptr<TransportData> transport_data);
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Serializes any dispatchers to the secondary buffer. This message must not
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // already have a secondary buffer (so this must only be called once). The
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // caller must ensure (e.g., by holding on to a reference) that |channel|
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // stays alive through the call.
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SerializeAndCloseDispatchers(Channel* channel);
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Gets the main buffer and its size (in number of bytes), respectively.
178010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const void* main_buffer() const { return main_buffer_.get(); }
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t main_buffer_size() const { return main_buffer_size_; }
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Gets the transport data buffer (if any).
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const TransportData* transport_data() const { return transport_data_.get(); }
1830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  TransportData* transport_data() { return transport_data_.get(); }
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Gets the total size of the message (see comment in |Header|, below).
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t total_size() const { return header()->total_size; }
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Gets the size of the message data.
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  uint32_t num_bytes() const { return header()->num_bytes; }
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Gets the message data (of size |num_bytes()| bytes).
192010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const void* bytes() const { return main_buffer_.get() + sizeof(Header); }
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void* bytes() { return main_buffer_.get() + sizeof(Header); }
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Type type() const { return header()->type; }
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Subtype subtype() const { return header()->subtype; }
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EndpointId source_id() const { return header()->source_id; }
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EndpointId destination_id() const { return header()->destination_id; }
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void set_source_id(EndpointId source_id) { header()->source_id = source_id; }
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void set_destination_id(EndpointId destination_id) {
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    header()->destination_id = destination_id;
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Gets the dispatchers attached to this message; this may return null if
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // there are none. Note that the caller may mutate the set of dispatchers
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // (e.g., take ownership of all the dispatchers, leaving the vector empty).
208010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DispatcherVector* dispatchers() { return dispatchers_.get(); }
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Returns true if this message has dispatchers attached.
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  bool has_dispatchers() const {
212c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return dispatchers_ && !dispatchers_->empty();
213c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
214c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Rounds |n| up to a multiple of |kMessageAlignment|.
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static inline size_t RoundUpMessageAlignment(size_t n) {
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return (n + kMessageAlignment - 1) & ~(kMessageAlignment - 1);
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
221010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // To allow us to make compile-assertions about |Header| in the .cc file.
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  struct PrivateStructForCompileAsserts;
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Header for the data (main buffer). Must be a multiple of
2255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // |kMessageAlignment| bytes in size. Must be POD.
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  struct Header {
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Total size of the message, including the header, the message data
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // ("bytes") including padding (to make it a multiple of |kMessageAlignment|
229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // bytes), and serialized handle information. Note that this may not be the
230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // correct value if dispatchers are attached but
231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // |SerializeAndCloseDispatchers()| has not been called.
232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    uint32_t total_size;
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Type type;                  // 2 bytes.
2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Subtype subtype;            // 2 bytes.
2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    EndpointId source_id;       // 4 bytes.
236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    EndpointId destination_id;  // 4 bytes.
237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Size of actual message data.
238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    uint32_t num_bytes;
239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    uint32_t unused;
240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const Header* header() const {
243010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return reinterpret_cast<const Header*>(main_buffer_.get());
244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
245010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); }
246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void ConstructorHelper(Type type, Subtype subtype, uint32_t num_bytes);
248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void UpdateTotalSize();
249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const size_t main_buffer_size_;
251010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_;  // Never null.
252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
253010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<TransportData> transport_data_;  // May be null.
254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
255a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Any dispatchers that may be attached to this message. These dispatchers
256a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // should be "owned" by this message, i.e., have a ref count of exactly 1. (We
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // allow a dispatcher entry to be null, in case it couldn't be duplicated for
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // some reason.)
259010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<DispatcherVector> dispatchers_;
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MessageInTransit);
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace system
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace mojo
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif  // MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
268