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