Home | History | Annotate | Download | only in system
      1 // Copyright 2013 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.
      4 
      5 #ifndef MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
      6 #define MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
      7 
      8 #include <stddef.h>
      9 #include <stdint.h>
     10 
     11 #include <vector>
     12 
     13 #include "base/macros.h"
     14 #include "base/memory/aligned_memory.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "mojo/system/dispatcher.h"
     17 #include "mojo/system/system_impl_export.h"
     18 
     19 namespace mojo {
     20 namespace system {
     21 
     22 class Channel;
     23 class TransportData;
     24 
     25 // This class is used to represent data in transit. It is thread-unsafe.
     26 //
     27 // |MessageInTransit| buffers:
     28 //
     29 // A |MessageInTransit| can be serialized by writing the main buffer and then,
     30 // if it has one, the transport data buffer. Both buffers are
     31 // |kMessageAlignment|-byte aligned and a multiple of |kMessageAlignment| bytes
     32 // in size.
     33 //
     34 // The main buffer consists of the header (of type |Header|, which is an
     35 // internal detail of this class) followed immediately by the message data
     36 // (accessed by |bytes()| and of size |num_bytes()|, and also
     37 // |kMessageAlignment|-byte aligned), and then any padding needed to make the
     38 // main buffer a multiple of |kMessageAlignment| bytes in size.
     39 //
     40 // See |TransportData| for a description of the (serialized) transport data
     41 // buffer.
     42 class MOJO_SYSTEM_IMPL_EXPORT MessageInTransit {
     43  public:
     44   typedef uint16_t Type;
     45   // Messages that are forwarded to |MessagePipeEndpoint|s.
     46   static const Type kTypeMessagePipeEndpoint = 0;
     47   // Messages that are forwarded to |MessagePipe|s.
     48   static const Type kTypeMessagePipe = 1;
     49   // Messages that are consumed by the |Channel|.
     50   static const Type kTypeChannel = 2;
     51   // Messages that are consumed by the |RawChannel| (implementation).
     52   static const Type kTypeRawChannel = 3;
     53 
     54   typedef uint16_t Subtype;
     55   // Subtypes for type |kTypeMessagePipeEndpoint|:
     56   static const Subtype kSubtypeMessagePipeEndpointData = 0;
     57   // Subtypes for type |kTypeMessagePipe|:
     58   // Nothing currently.
     59   // Subtypes for type |kTypeChannel|:
     60   static const Subtype kSubtypeChannelRunMessagePipeEndpoint = 0;
     61   static const Subtype kSubtypeChannelRemoveMessagePipeEndpoint = 1;
     62   static const Subtype kSubtypeChannelRemoveMessagePipeEndpointAck = 2;
     63   // Subtypes for type |kTypeRawChannel|:
     64   static const Subtype kSubtypeRawChannelPosixExtraPlatformHandles = 0;
     65 
     66   typedef uint32_t EndpointId;
     67   // Never a valid endpoint ID.
     68   static const EndpointId kInvalidEndpointId = 0;
     69 
     70   // Messages (the header and data) must always be aligned to a multiple of this
     71   // quantity (which must be a power of 2).
     72   static const size_t kMessageAlignment = 8;
     73 
     74   // Forward-declare |Header| so that |View| can use it:
     75  private:
     76   struct Header;
     77  public:
     78   // This represents a view of serialized message data in a raw buffer.
     79   class MOJO_SYSTEM_IMPL_EXPORT View {
     80    public:
     81     // Constructs a view from the given buffer of the given size. (The size must
     82     // be as provided by |MessageInTransit::GetNextMessageSize()|.) The buffer
     83     // must remain alive/unmodified through the lifetime of this object.
     84     // |buffer| should be |kMessageAlignment|-byte aligned.
     85     View(size_t message_size, const void* buffer);
     86 
     87     // Checks that the given |View| appears to be for a valid message, within
     88     // predetermined limits (e.g., |num_bytes()| and |main_buffer_size()|, that
     89     // |transport_data_buffer()|/|transport_data_buffer_size()| is for valid
     90     // transport data -- see |TransportData::ValidateBuffer()|).
     91     //
     92     // It returns true (and leaves |error_message| alone) if this object appears
     93     // to be a valid message (according to the above) and false, pointing
     94     // |*error_message| to a suitable error message, if not.
     95     bool IsValid(size_t serialized_platform_handle_size,
     96                  const char** error_message) const;
     97 
     98     // API parallel to that for |MessageInTransit| itself (mostly getters for
     99     // header data).
    100     const void* main_buffer() const { return buffer_; }
    101     size_t main_buffer_size() const {
    102       return RoundUpMessageAlignment(sizeof(Header) + header()->num_bytes);
    103     }
    104     const void* transport_data_buffer() const {
    105       return (total_size() > main_buffer_size()) ?
    106           static_cast<const char*>(buffer_) + main_buffer_size() : NULL;
    107     }
    108     size_t transport_data_buffer_size() const {
    109       return total_size() - main_buffer_size();
    110     }
    111     size_t total_size() const { return header()->total_size; }
    112     uint32_t num_bytes() const { return header()->num_bytes; }
    113     const void* bytes() const {
    114       return static_cast<const char*>(buffer_) + sizeof(Header);
    115     }
    116     Type type() const { return header()->type; }
    117     Subtype subtype() const { return header()->subtype; }
    118     EndpointId source_id() const { return header()->source_id; }
    119     EndpointId destination_id() const { return header()->destination_id; }
    120 
    121    private:
    122     const Header* header() const { return static_cast<const Header*>(buffer_); }
    123 
    124     const void* const buffer_;
    125 
    126     // Though this struct is trivial, disallow copy and assign, since it doesn't
    127     // own its data. (If you're copying/assigning this, you're probably doing
    128     // something wrong.)
    129     DISALLOW_COPY_AND_ASSIGN(View);
    130   };
    131 
    132   // |bytes| is optional; if null, the message data will be zero-initialized.
    133   MessageInTransit(Type type,
    134                    Subtype subtype,
    135                    uint32_t num_bytes,
    136                    const void* bytes);
    137   // Constructs a |MessageInTransit| from a |View|.
    138   explicit MessageInTransit(const View& message_view);
    139 
    140   ~MessageInTransit();
    141 
    142   // Gets the size of the next message from |buffer|, which has |buffer_size|
    143   // bytes currently available, returning true and setting |*next_message_size|
    144   // on success. |buffer| should be aligned on a |kMessageAlignment| boundary
    145   // (and on success, |*next_message_size| will be a multiple of
    146   // |kMessageAlignment|).
    147   // TODO(vtl): In |RawChannelPosix|, the alignment requirements are currently
    148   // satisified on a faith-based basis.
    149   static bool GetNextMessageSize(const void* buffer,
    150                                  size_t buffer_size,
    151                                  size_t* next_message_size);
    152 
    153   // Makes this message "own" the given set of dispatchers. The dispatchers must
    154   // not be referenced from anywhere else (in particular, not from the handle
    155   // table), i.e., each dispatcher must have a reference count of 1. This
    156   // message must not already have dispatchers.
    157   void SetDispatchers(scoped_ptr<DispatcherVector> dispatchers);
    158 
    159   // Sets the |TransportData| for this message. This should only be done when
    160   // there are no dispatchers and no existing |TransportData|.
    161   void SetTransportData(scoped_ptr<TransportData> transport_data);
    162 
    163   // Serializes any dispatchers to the secondary buffer. This message must not
    164   // already have a secondary buffer (so this must only be called once). The
    165   // caller must ensure (e.g., by holding on to a reference) that |channel|
    166   // stays alive through the call.
    167   void SerializeAndCloseDispatchers(Channel* channel);
    168 
    169   // Gets the main buffer and its size (in number of bytes), respectively.
    170   const void* main_buffer() const { return main_buffer_.get(); }
    171   size_t main_buffer_size() const { return main_buffer_size_; }
    172 
    173   // Gets the transport data buffer (if any).
    174   const TransportData* transport_data() const { return transport_data_.get(); }
    175   TransportData* transport_data() { return transport_data_.get(); }
    176 
    177   // Gets the total size of the message (see comment in |Header|, below).
    178   size_t total_size() const { return header()->total_size; }
    179 
    180   // Gets the size of the message data.
    181   uint32_t num_bytes() const { return header()->num_bytes; }
    182 
    183   // Gets the message data (of size |num_bytes()| bytes).
    184   const void* bytes() const { return main_buffer_.get() + sizeof(Header); }
    185   void* bytes() { return main_buffer_.get() + sizeof(Header); }
    186 
    187   Type type() const { return header()->type; }
    188   Subtype subtype() const { return header()->subtype; }
    189   EndpointId source_id() const { return header()->source_id; }
    190   EndpointId destination_id() const { return header()->destination_id; }
    191 
    192   void set_source_id(EndpointId source_id) { header()->source_id = source_id; }
    193   void set_destination_id(EndpointId destination_id) {
    194     header()->destination_id = destination_id;
    195   }
    196 
    197   // Gets the dispatchers attached to this message; this may return null if
    198   // there are none. Note that the caller may mutate the set of dispatchers
    199   // (e.g., take ownership of all the dispatchers, leaving the vector empty).
    200   DispatcherVector* dispatchers() { return dispatchers_.get(); }
    201 
    202   // Returns true if this message has dispatchers attached.
    203   bool has_dispatchers() const {
    204     return dispatchers_ && !dispatchers_->empty();
    205   }
    206 
    207   // Rounds |n| up to a multiple of |kMessageAlignment|.
    208   static inline size_t RoundUpMessageAlignment(size_t n) {
    209     return (n + kMessageAlignment - 1) & ~(kMessageAlignment - 1);
    210   }
    211 
    212  private:
    213   // To allow us to make compile-assertions about |Header| in the .cc file.
    214   struct PrivateStructForCompileAsserts;
    215 
    216   // Header for the data (main buffer). Must be a multiple of
    217   // |kMessageAlignment| bytes in size. Must be POD.
    218   struct Header {
    219     // Total size of the message, including the header, the message data
    220     // ("bytes") including padding (to make it a multiple of |kMessageAlignment|
    221     // bytes), and serialized handle information. Note that this may not be the
    222     // correct value if dispatchers are attached but
    223     // |SerializeAndCloseDispatchers()| has not been called.
    224     uint32_t total_size;
    225     Type type;  // 2 bytes.
    226     Subtype subtype;  // 2 bytes.
    227     EndpointId source_id;  // 4 bytes.
    228     EndpointId destination_id;  // 4 bytes.
    229     // Size of actual message data.
    230     uint32_t num_bytes;
    231     uint32_t unused;
    232   };
    233 
    234   const Header* header() const {
    235     return reinterpret_cast<const Header*>(main_buffer_.get());
    236   }
    237   Header* header() { return reinterpret_cast<Header*>(main_buffer_.get()); }
    238 
    239   void UpdateTotalSize();
    240 
    241   const size_t main_buffer_size_;
    242   const scoped_ptr<char, base::AlignedFreeDeleter> main_buffer_;  // Never null.
    243 
    244   scoped_ptr<TransportData> transport_data_;  // May be null.
    245 
    246   // Any dispatchers that may be attached to this message. These dispatchers
    247   // should be "owned" by this message, i.e., have a ref count of exactly 1. (We
    248   // allow a dispatcher entry to be null, in case it couldn't be duplicated for
    249   // some reason.)
    250   scoped_ptr<DispatcherVector> dispatchers_;
    251 
    252   DISALLOW_COPY_AND_ASSIGN(MessageInTransit);
    253 };
    254 
    255 }  // namespace system
    256 }  // namespace mojo
    257 
    258 #endif  // MOJO_SYSTEM_MESSAGE_IN_TRANSIT_H_
    259