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