Home | History | Annotate | Download | only in ipc
      1 // Copyright (c) 2012 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 IPC_IPC_MESSAGE_H_
      6 #define IPC_IPC_MESSAGE_H_
      7 
      8 #include <stddef.h>
      9 #include <stdint.h>
     10 
     11 #include <string>
     12 
     13 #include "base/gtest_prod_util.h"
     14 #include "base/memory/ref_counted.h"
     15 #include "base/pickle.h"
     16 #include "base/trace_event/trace_event.h"
     17 #include "build/build_config.h"
     18 #include "ipc/attachment_broker.h"
     19 #include "ipc/brokerable_attachment.h"
     20 #include "ipc/ipc_export.h"
     21 
     22 #if !defined(NDEBUG)
     23 #define IPC_MESSAGE_LOG_ENABLED
     24 #endif
     25 
     26 namespace IPC {
     27 
     28 namespace internal {
     29 class ChannelReader;
     30 }  // namespace internal
     31 
     32 //------------------------------------------------------------------------------
     33 
     34 struct LogData;
     35 class MessageAttachment;
     36 class MessageAttachmentSet;
     37 
     38 class IPC_EXPORT Message : public base::Pickle {
     39  public:
     40   enum PriorityValue {
     41     PRIORITY_LOW = 1,
     42     PRIORITY_NORMAL,
     43     PRIORITY_HIGH
     44   };
     45 
     46   // Bit values used in the flags field.
     47   // Upper 24 bits of flags store a reference number, so this enum is limited to
     48   // 8 bits.
     49   enum {
     50     PRIORITY_MASK     = 0x03,  // Low 2 bits of store the priority value.
     51     SYNC_BIT          = 0x04,
     52     REPLY_BIT         = 0x08,
     53     REPLY_ERROR_BIT   = 0x10,
     54     UNBLOCK_BIT       = 0x20,
     55     PUMPING_MSGS_BIT  = 0x40,
     56     HAS_SENT_TIME_BIT = 0x80,
     57   };
     58 
     59   ~Message() override;
     60 
     61   Message();
     62 
     63   // Initialize a message with a user-defined type, priority value, and
     64   // destination WebView ID.
     65   Message(int32_t routing_id, uint32_t type, PriorityValue priority);
     66 
     67   // Initializes a message from a const block of data.  The data is not copied;
     68   // instead the data is merely referenced by this message.  Only const methods
     69   // should be used on the message when initialized this way.
     70   Message(const char* data, int data_len);
     71 
     72   Message(const Message& other);
     73   Message& operator=(const Message& other);
     74 
     75   PriorityValue priority() const {
     76     return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
     77   }
     78 
     79   // True if this is a synchronous message.
     80   void set_sync() {
     81     header()->flags |= SYNC_BIT;
     82   }
     83   bool is_sync() const {
     84     return (header()->flags & SYNC_BIT) != 0;
     85   }
     86 
     87   // Set this on a reply to a synchronous message.
     88   void set_reply() {
     89     header()->flags |= REPLY_BIT;
     90   }
     91 
     92   bool is_reply() const {
     93     return (header()->flags & REPLY_BIT) != 0;
     94   }
     95 
     96   // Set this on a reply to a synchronous message to indicate that no receiver
     97   // was found.
     98   void set_reply_error() {
     99     header()->flags |= REPLY_ERROR_BIT;
    100   }
    101 
    102   bool is_reply_error() const {
    103     return (header()->flags & REPLY_ERROR_BIT) != 0;
    104   }
    105 
    106   // Normally when a receiver gets a message and they're blocked on a
    107   // synchronous message Send, they buffer a message.  Setting this flag causes
    108   // the receiver to be unblocked and the message to be dispatched immediately.
    109   void set_unblock(bool unblock) {
    110     if (unblock) {
    111       header()->flags |= UNBLOCK_BIT;
    112     } else {
    113       header()->flags &= ~UNBLOCK_BIT;
    114     }
    115   }
    116 
    117   bool should_unblock() const {
    118     return (header()->flags & UNBLOCK_BIT) != 0;
    119   }
    120 
    121   // Tells the receiver that the caller is pumping messages while waiting
    122   // for the result.
    123   bool is_caller_pumping_messages() const {
    124     return (header()->flags & PUMPING_MSGS_BIT) != 0;
    125   }
    126 
    127   void set_dispatch_error() const {
    128     dispatch_error_ = true;
    129   }
    130 
    131   bool dispatch_error() const {
    132     return dispatch_error_;
    133   }
    134 
    135   uint32_t type() const {
    136     return header()->type;
    137   }
    138 
    139   int32_t routing_id() const {
    140     return header()->routing;
    141   }
    142 
    143   void set_routing_id(int32_t new_id) {
    144     header()->routing = new_id;
    145   }
    146 
    147   uint32_t flags() const {
    148     return header()->flags;
    149   }
    150 
    151   // Sets all the given header values. The message should be empty at this
    152   // call.
    153   void SetHeaderValues(int32_t routing, uint32_t type, uint32_t flags);
    154 
    155   template<class T, class S, class P>
    156   static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,
    157                        void (T::*func)()) {
    158     (obj->*func)();
    159     return true;
    160   }
    161 
    162   template<class T, class S, class P>
    163   static bool Dispatch(const Message* msg, T* obj, S* sender, P* parameter,
    164                        void (T::*func)(P*)) {
    165     (obj->*func)(parameter);
    166     return true;
    167   }
    168 
    169   // Used for async messages with no parameters.
    170   static void Log(std::string* name, const Message* msg, std::string* l) {
    171   }
    172 
    173   // The static method FindNext() returns several pieces of information, which
    174   // are aggregated into an instance of this struct.
    175   struct IPC_EXPORT NextMessageInfo {
    176     NextMessageInfo();
    177     ~NextMessageInfo();
    178 
    179     // Total message size. Always valid if |message_found| is true.
    180     // If |message_found| is false but we could determine message size
    181     // from the header, this field is non-zero. Otherwise it's zero.
    182     size_t message_size;
    183     // Whether an entire message was found in the given memory range.
    184     bool message_found;
    185     // Only filled in if |message_found| is true.
    186     // The start address is passed into FindNext() by the caller, so isn't
    187     // repeated in this struct. The end address of the pickle should be used to
    188     // construct a base::Pickle.
    189     const char* pickle_end;
    190     // Only filled in if |message_found| is true.
    191     // The end address of the message should be used to determine the start
    192     // address of the next message.
    193     const char* message_end;
    194     // If the message has brokerable attachments, this vector will contain the
    195     // ids of the brokerable attachments. The caller of FindNext() is
    196     // responsible for adding the attachments to the message.
    197     std::vector<BrokerableAttachment::AttachmentId> attachment_ids;
    198   };
    199 
    200   struct SerializedAttachmentIds {
    201     void* buffer;
    202     size_t size;
    203   };
    204   // Creates a buffer that contains a serialization of the ids of the brokerable
    205   // attachments of the message. This buffer is intended to be sent over the IPC
    206   // channel immediately after the pickled message. The caller takes ownership
    207   // of the buffer.
    208   // This method should only be called if the message has brokerable
    209   // attachments.
    210   SerializedAttachmentIds SerializedIdsOfBrokerableAttachments();
    211 
    212   // |info| is an output parameter and must not be nullptr.
    213   static void FindNext(const char* range_start,
    214                        const char* range_end,
    215                        NextMessageInfo* info);
    216 
    217   // Adds a placeholder brokerable attachment that must be replaced before the
    218   // message can be dispatched.
    219   bool AddPlaceholderBrokerableAttachmentWithId(
    220       BrokerableAttachment::AttachmentId id);
    221 
    222   // WriteAttachment appends |attachment| to the end of the set. It returns
    223   // false iff the set is full.
    224   bool WriteAttachment(
    225       scoped_refptr<base::Pickle::Attachment> attachment) override;
    226   // ReadAttachment parses an attachment given the parsing state |iter| and
    227   // writes it to |*attachment|. It returns true on success.
    228   bool ReadAttachment(
    229       base::PickleIterator* iter,
    230       scoped_refptr<base::Pickle::Attachment>* attachment) const override;
    231   // Returns true if there are any attachment in this message.
    232   bool HasAttachments() const override;
    233   // Returns true if there are any MojoHandleAttachments in this message.
    234   bool HasMojoHandles() const;
    235   // Whether the message has any brokerable attachments.
    236   bool HasBrokerableAttachments() const;
    237 
    238   void set_sender_pid(base::ProcessId id) { sender_pid_ = id; }
    239   base::ProcessId get_sender_pid() const { return sender_pid_; }
    240 
    241 #ifdef IPC_MESSAGE_LOG_ENABLED
    242   // Adds the outgoing time from Time::Now() at the end of the message and sets
    243   // a bit to indicate that it's been added.
    244   void set_sent_time(int64_t time);
    245   int64_t sent_time() const;
    246 
    247   void set_received_time(int64_t time) const;
    248   int64_t received_time() const { return received_time_; }
    249   void set_output_params(const std::string& op) const { output_params_ = op; }
    250   const std::string& output_params() const { return output_params_; }
    251   // The following four functions are needed so we can log sync messages with
    252   // delayed replies.  We stick the log data from the sent message into the
    253   // reply message, so that when it's sent and we have the output parameters
    254   // we can log it.  As such, we set a flag on the sent message to not log it.
    255   void set_sync_log_data(LogData* data) const { log_data_ = data; }
    256   LogData* sync_log_data() const { return log_data_; }
    257   void set_dont_log() const { dont_log_ = true; }
    258   bool dont_log() const { return dont_log_; }
    259 #endif
    260 
    261  protected:
    262   friend class Channel;
    263   friend class ChannelMojo;
    264   friend class ChannelNacl;
    265   friend class ChannelPosix;
    266   friend class ChannelWin;
    267   friend class internal::ChannelReader;
    268   friend class MessageReplyDeserializer;
    269   friend class SyncMessage;
    270 
    271 #pragma pack(push, 4)
    272   struct Header : base::Pickle::Header {
    273     int32_t routing;  // ID of the view that this message is destined for
    274     uint32_t type;    // specifies the user-defined message type
    275     uint32_t flags;   // specifies control flags for the message
    276 #if USE_ATTACHMENT_BROKER
    277     // The number of brokered attachments included with this message. The
    278     // ids of the brokered attachment ids are sent immediately after the pickled
    279     // message, before the next pickled message is sent.
    280     uint32_t num_brokered_attachments;
    281 #endif
    282 #if defined(OS_POSIX)
    283     uint16_t num_fds; // the number of descriptors included with this message
    284     uint16_t pad;     // explicitly initialize this to appease valgrind
    285 #endif
    286   };
    287 #pragma pack(pop)
    288 
    289   Header* header() {
    290     return headerT<Header>();
    291   }
    292   const Header* header() const {
    293     return headerT<Header>();
    294   }
    295 
    296   void Init();
    297 
    298   // Used internally to support IPC::Listener::OnBadMessageReceived.
    299   mutable bool dispatch_error_;
    300 
    301   // The set of file descriptors associated with this message.
    302   scoped_refptr<MessageAttachmentSet> attachment_set_;
    303 
    304   // Ensure that a MessageAttachmentSet is allocated
    305   void EnsureMessageAttachmentSet();
    306 
    307   MessageAttachmentSet* attachment_set() {
    308     EnsureMessageAttachmentSet();
    309     return attachment_set_.get();
    310   }
    311   const MessageAttachmentSet* attachment_set() const {
    312     return attachment_set_.get();
    313   }
    314 
    315   // The process id of the sender of the message. This member is populated with
    316   // a valid value for every message dispatched to listeners.
    317   base::ProcessId sender_pid_;
    318 
    319 #ifdef IPC_MESSAGE_LOG_ENABLED
    320   // Used for logging.
    321   mutable int64_t received_time_;
    322   mutable std::string output_params_;
    323   mutable LogData* log_data_;
    324   mutable bool dont_log_;
    325 #endif
    326 
    327   FRIEND_TEST_ALL_PREFIXES(IPCMessageTest, FindNext);
    328   FRIEND_TEST_ALL_PREFIXES(IPCMessageTest, FindNextOverflow);
    329 };
    330 
    331 //------------------------------------------------------------------------------
    332 
    333 }  // namespace IPC
    334 
    335 enum SpecialRoutingIDs {
    336   // indicates that we don't have a routing ID yet.
    337   MSG_ROUTING_NONE = -2,
    338 
    339   // indicates a general message not sent to a particular tab.
    340   MSG_ROUTING_CONTROL = INT32_MAX,
    341 };
    342 
    343 #define IPC_REPLY_ID 0xFFFFFFF0  // Special message id for replies
    344 #define IPC_LOGGING_ID 0xFFFFFFF1  // Special message id for logging
    345 
    346 #endif  // IPC_IPC_MESSAGE_H_
    347