Home | History | Annotate | Download | only in core
      1 // Copyright 2017 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_CORE_USER_MESSAGE_IMPL_H_
      6 #define MOJO_CORE_USER_MESSAGE_IMPL_H_
      7 
      8 #include <memory>
      9 #include <utility>
     10 #include <vector>
     11 
     12 #include "base/macros.h"
     13 #include "base/optional.h"
     14 #include "mojo/core/channel.h"
     15 #include "mojo/core/dispatcher.h"
     16 #include "mojo/core/ports/event.h"
     17 #include "mojo/core/ports/name.h"
     18 #include "mojo/core/ports/port_ref.h"
     19 #include "mojo/core/ports/user_message.h"
     20 #include "mojo/core/system_impl_export.h"
     21 #include "mojo/public/c/system/message_pipe.h"
     22 #include "mojo/public/c/system/types.h"
     23 
     24 namespace mojo {
     25 namespace core {
     26 
     27 // UserMessageImpl is the sole implementation of ports::UserMessage used to
     28 // attach message data to any ports::UserMessageEvent.
     29 //
     30 // A UserMessageImpl may be either serialized or unserialized. Unserialized
     31 // instances are serialized lazily only when necessary, i.e., if and when
     32 // Serialize() is called to obtain a serialized message for wire transfer.
     33 class MOJO_SYSTEM_IMPL_EXPORT UserMessageImpl : public ports::UserMessage {
     34  public:
     35   static const TypeInfo kUserMessageTypeInfo;
     36 
     37   // Determines how ExtractSerializedHandles should behave when it encounters an
     38   // unrecoverable serialized handle.
     39   enum ExtractBadHandlePolicy {
     40     // Continue extracting handles upon encountering a bad handle. The bad
     41     // handle will be extracted with an invalid handle value.
     42     kSkip,
     43 
     44     // Abort the extraction process, leaving any valid serialized handles still
     45     // in the message.
     46     kAbort,
     47   };
     48 
     49   ~UserMessageImpl() override;
     50 
     51   // Creates a new ports::UserMessageEvent with an attached UserMessageImpl.
     52   static std::unique_ptr<ports::UserMessageEvent> CreateEventForNewMessage();
     53 
     54   // Creates a new ports::UserMessageEvent with an attached serialized
     55   // UserMessageImpl. May fail iff one or more |dispatchers| fails to serialize
     56   // (e.g. due to it being in an invalid state.)
     57   //
     58   // Upon success, MOJO_RESULT_OK is returned and the new UserMessageEvent is
     59   // stored in |*out_event|.
     60   static MojoResult CreateEventForNewSerializedMessage(
     61       uint32_t num_bytes,
     62       const Dispatcher::DispatcherInTransit* dispatchers,
     63       uint32_t num_dispatchers,
     64       std::unique_ptr<ports::UserMessageEvent>* out_event);
     65 
     66   // Creates a new UserMessageImpl from an existing serialized message buffer
     67   // which was read from a Channel. Takes ownership of |channel_message|.
     68   // |payload| and |payload_size| represent the range of bytes within
     69   // |channel_message| which should be parsed by this call.
     70   static std::unique_ptr<UserMessageImpl> CreateFromChannelMessage(
     71       ports::UserMessageEvent* message_event,
     72       Channel::MessagePtr channel_message,
     73       void* payload,
     74       size_t payload_size);
     75 
     76   // Extracts the serialized Channel::Message from the UserMessageEvent in
     77   // |event|. |event| must have a serialized UserMessageImpl instance attached.
     78   // |message_event| is serialized into the front of the message payload before
     79   // returning.
     80   static Channel::MessagePtr FinalizeEventMessage(
     81       std::unique_ptr<ports::UserMessageEvent> event);
     82 
     83   bool HasContext() const { return context_ != 0; }
     84 
     85   uintptr_t context() const { return context_; }
     86 
     87   bool IsSerialized() const {
     88     if (HasContext()) {
     89       DCHECK(!channel_message_);
     90       return false;
     91     }
     92 
     93     return !!channel_message_;
     94   }
     95 
     96   bool IsTransmittable() const { return !IsSerialized() || is_committed_; }
     97 
     98   void* user_payload() {
     99     DCHECK(IsSerialized());
    100     return user_payload_;
    101   }
    102 
    103   const void* user_payload() const {
    104     DCHECK(IsSerialized());
    105     return user_payload_;
    106   }
    107 
    108   size_t user_payload_size() const {
    109     DCHECK(IsSerialized());
    110     return user_payload_size_;
    111   }
    112 
    113   size_t user_payload_capacity() const;
    114 
    115   size_t num_handles() const;
    116 
    117   void set_source_node(const ports::NodeName& name) { source_node_ = name; }
    118   const ports::NodeName& source_node() const { return source_node_; }
    119 
    120   MojoResult SetContext(uintptr_t context,
    121                         MojoMessageContextSerializer serializer,
    122                         MojoMessageContextDestructor destructor);
    123   MojoResult AppendData(uint32_t additional_payload_size,
    124                         const MojoHandle* handles,
    125                         uint32_t num_handles);
    126   MojoResult CommitSize();
    127 
    128   // If this message is not already serialized, this serializes it.
    129   MojoResult SerializeIfNecessary();
    130 
    131   // Extracts handles from this (serialized) message.
    132   //
    133   // Returns |MOJO_RESULT_OK|
    134   // if sucessful, |MOJO_RESULT_FAILED_PRECONDITION| if this isn't a serialized
    135   // message, |MOJO_RESULT_NOT_FOUND| if all serialized handles have already
    136   // been extracted, or |MOJO_RESULT_ABORTED| if one or more handles failed
    137   // extraction.
    138   //
    139   // On success, |handles| is populated with |num_handles()| extracted handles,
    140   // whose ownership is thereby transferred to the caller.
    141   MojoResult ExtractSerializedHandles(ExtractBadHandlePolicy bad_handle_policy,
    142                                       MojoHandle* handles);
    143 
    144   // Forces all handle serialization to fail. Serialization can fail in
    145   // production for a few different reasons (e.g. file descriptor exhaustion
    146   // when duping data pipe buffer handles) which may be difficult to control in
    147   // testing environments. This forces the common serialization code path to
    148   // always behave as if the underlying implementation signaled failure,
    149   // allowing tests to exercise those cases.
    150   static void FailHandleSerializationForTesting(bool fail);
    151 
    152  private:
    153   // Creates an unserialized UserMessageImpl with an associated |context| and
    154   // |thunks|. If the message is ever going to be routed to another node (see
    155   // |WillBeRoutedExternally()| below), it will be serialized at that time using
    156   // operations provided by |thunks|.
    157   UserMessageImpl(ports::UserMessageEvent* message_event);
    158 
    159   // Creates a serialized UserMessageImpl backed by an existing Channel::Message
    160   // object. |header| and |user_payload| must be pointers into
    161   // |channel_message|'s own storage, and |user_payload_size| is the number of
    162   // bytes comprising the user message contents at |user_payload|.
    163   UserMessageImpl(ports::UserMessageEvent* message_event,
    164                   Channel::MessagePtr channel_message,
    165                   void* header,
    166                   size_t header_size,
    167                   void* user_payload,
    168                   size_t user_payload_size);
    169 
    170   // UserMessage:
    171   bool WillBeRoutedExternally() override;
    172   size_t GetSizeIfSerialized() const override;
    173 
    174   // The event which owns this serialized message. Not owned.
    175   ports::UserMessageEvent* const message_event_;
    176 
    177   // Unserialized message state.
    178   uintptr_t context_ = 0;
    179   MojoMessageContextSerializer context_serializer_ = nullptr;
    180   MojoMessageContextDestructor context_destructor_ = nullptr;
    181 
    182   // Serialized message contents. May be null if this is not a serialized
    183   // message.
    184   Channel::MessagePtr channel_message_;
    185 
    186   // Indicates whether any handles serialized within |channel_message_| have
    187   // yet to be extracted.
    188   bool has_serialized_handles_ = false;
    189 
    190   // Indicates whether the serialized message's contents (if any) have been
    191   // committed yet.
    192   bool is_committed_ = false;
    193 
    194   // Only valid if |channel_message_| is non-null. |header_| is the address
    195   // of the UserMessageImpl's internal MessageHeader structure within the
    196   // serialized message buffer. |user_payload_| is the address of the first byte
    197   // after any serialized dispatchers, with the payload comprising the remaining
    198   // |user_payload_size_| bytes of the message.
    199   void* header_ = nullptr;
    200   size_t header_size_ = 0;
    201   void* user_payload_ = nullptr;
    202   size_t user_payload_size_ = 0;
    203 
    204   // Handles which have been attached to the serialized message but which have
    205   // not yet been serialized.
    206   std::vector<Dispatcher::DispatcherInTransit> pending_handle_attachments_;
    207 
    208   // The node name from which this message was received, iff it came from
    209   // out-of-process and the source is known.
    210   ports::NodeName source_node_ = ports::kInvalidNodeName;
    211 
    212   DISALLOW_COPY_AND_ASSIGN(UserMessageImpl);
    213 };
    214 
    215 }  // namespace core
    216 }  // namespace mojo
    217 
    218 #endif  // MOJO_CORE_USER_MESSAGE_IMPL_H_
    219