| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ipc/ipc_message.h" | 5 #include "ipc/ipc_message.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| 11 #include "base/atomic_sequence_num.h" | 11 #include "base/atomic_sequence_num.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 14 #include "ipc/attachment_broker.h" | |
| 15 #include "ipc/ipc_message_attachment.h" | 14 #include "ipc/ipc_message_attachment.h" |
| 16 #include "ipc/ipc_message_attachment_set.h" | 15 #include "ipc/ipc_message_attachment_set.h" |
| 17 #include "ipc/placeholder_brokerable_attachment.h" | |
| 18 | 16 |
| 19 #if defined(OS_POSIX) | 17 #if defined(OS_POSIX) |
| 20 #include "base/file_descriptor_posix.h" | 18 #include "base/file_descriptor_posix.h" |
| 21 #include "ipc/ipc_platform_file_attachment_posix.h" | 19 #include "ipc/ipc_platform_file_attachment_posix.h" |
| 22 #endif | 20 #endif |
| 23 | 21 |
| 24 namespace { | 22 namespace { |
| 25 | 23 |
| 26 base::StaticAtomicSequenceNumber g_ref_num; | 24 base::StaticAtomicSequenceNumber g_ref_num; |
| 27 | 25 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 45 namespace IPC { | 43 namespace IPC { |
| 46 | 44 |
| 47 //------------------------------------------------------------------------------ | 45 //------------------------------------------------------------------------------ |
| 48 | 46 |
| 49 Message::~Message() { | 47 Message::~Message() { |
| 50 } | 48 } |
| 51 | 49 |
| 52 Message::Message() : base::Pickle(sizeof(Header)) { | 50 Message::Message() : base::Pickle(sizeof(Header)) { |
| 53 header()->routing = header()->type = 0; | 51 header()->routing = header()->type = 0; |
| 54 header()->flags = GetRefNumUpper24(); | 52 header()->flags = GetRefNumUpper24(); |
| 55 #if USE_ATTACHMENT_BROKER | |
| 56 header()->num_brokered_attachments = 0; | |
| 57 #endif | |
| 58 #if defined(OS_POSIX) | 53 #if defined(OS_POSIX) |
| 59 header()->num_fds = 0; | 54 header()->num_fds = 0; |
| 60 header()->pad = 0; | 55 header()->pad = 0; |
| 61 #endif | 56 #endif |
| 62 Init(); | 57 Init(); |
| 63 } | 58 } |
| 64 | 59 |
| 65 Message::Message(int32_t routing_id, uint32_t type, PriorityValue priority) | 60 Message::Message(int32_t routing_id, uint32_t type, PriorityValue priority) |
| 66 : base::Pickle(sizeof(Header)) { | 61 : base::Pickle(sizeof(Header)) { |
| 67 header()->routing = routing_id; | 62 header()->routing = routing_id; |
| 68 header()->type = type; | 63 header()->type = type; |
| 69 DCHECK((priority & 0xffffff00) == 0); | 64 DCHECK((priority & 0xffffff00) == 0); |
| 70 header()->flags = priority | GetRefNumUpper24(); | 65 header()->flags = priority | GetRefNumUpper24(); |
| 71 #if USE_ATTACHMENT_BROKER | |
| 72 header()->num_brokered_attachments = 0; | |
| 73 #endif | |
| 74 #if defined(OS_POSIX) | 66 #if defined(OS_POSIX) |
| 75 header()->num_fds = 0; | 67 header()->num_fds = 0; |
| 76 header()->pad = 0; | 68 header()->pad = 0; |
| 77 #endif | 69 #endif |
| 78 Init(); | 70 Init(); |
| 79 } | 71 } |
| 80 | 72 |
| 81 Message::Message(const char* data, int data_len) | 73 Message::Message(const char* data, int data_len) |
| 82 : base::Pickle(data, data_len) { | 74 : base::Pickle(data, data_len) { |
| 83 Init(); | 75 Init(); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 void Message::set_received_time(int64_t time) const { | 131 void Message::set_received_time(int64_t time) const { |
| 140 received_time_ = time; | 132 received_time_ = time; |
| 141 } | 133 } |
| 142 #endif | 134 #endif |
| 143 | 135 |
| 144 Message::NextMessageInfo::NextMessageInfo() | 136 Message::NextMessageInfo::NextMessageInfo() |
| 145 : message_size(0), message_found(false), pickle_end(nullptr), | 137 : message_size(0), message_found(false), pickle_end(nullptr), |
| 146 message_end(nullptr) {} | 138 message_end(nullptr) {} |
| 147 Message::NextMessageInfo::~NextMessageInfo() {} | 139 Message::NextMessageInfo::~NextMessageInfo() {} |
| 148 | 140 |
| 149 Message::SerializedAttachmentIds | |
| 150 Message::SerializedIdsOfBrokerableAttachments() { | |
| 151 DCHECK(HasBrokerableAttachments()); | |
| 152 std::vector<scoped_refptr<IPC::BrokerableAttachment>> attachments( | |
| 153 attachment_set_->GetBrokerableAttachments()); | |
| 154 CHECK_LE(attachments.size(), std::numeric_limits<size_t>::max() / | |
| 155 BrokerableAttachment::kNonceSize); | |
| 156 size_t size = attachments.size() * BrokerableAttachment::kNonceSize; | |
| 157 char* buffer = static_cast<char*>(malloc(size)); | |
| 158 for (size_t i = 0; i < attachments.size(); ++i) { | |
| 159 char* start_range = buffer + i * BrokerableAttachment::kNonceSize; | |
| 160 BrokerableAttachment::AttachmentId id = attachments[i]->GetIdentifier(); | |
| 161 id.SerializeToBuffer(start_range, BrokerableAttachment::kNonceSize); | |
| 162 } | |
| 163 SerializedAttachmentIds ids; | |
| 164 ids.buffer = buffer; | |
| 165 ids.size = size; | |
| 166 return ids; | |
| 167 } | |
| 168 | |
| 169 // static | 141 // static |
| 170 void Message::FindNext(const char* range_start, | 142 void Message::FindNext(const char* range_start, |
| 171 const char* range_end, | 143 const char* range_end, |
| 172 NextMessageInfo* info) { | 144 NextMessageInfo* info) { |
| 173 DCHECK(info); | 145 DCHECK(info); |
| 174 info->message_found = false; | 146 info->message_found = false; |
| 175 info->message_size = 0; | 147 info->message_size = 0; |
| 176 | 148 |
| 177 size_t pickle_size = 0; | 149 size_t pickle_size = 0; |
| 178 if (!base::Pickle::PeekNext(sizeof(Header), | 150 if (!base::Pickle::PeekNext(sizeof(Header), |
| 179 range_start, range_end, &pickle_size)) | 151 range_start, range_end, &pickle_size)) |
| 180 return; | 152 return; |
| 181 | 153 |
| 182 bool have_entire_pickle = | 154 bool have_entire_pickle = |
| 183 static_cast<size_t>(range_end - range_start) >= pickle_size; | 155 static_cast<size_t>(range_end - range_start) >= pickle_size; |
| 184 | 156 |
| 185 #if USE_ATTACHMENT_BROKER | |
| 186 // TODO(dskiba): determine message_size when entire pickle is not available | |
| 187 | |
| 188 if (!have_entire_pickle) | |
| 189 return; | |
| 190 | |
| 191 const char* pickle_end = range_start + pickle_size; | |
| 192 | |
| 193 // The data is not copied. | |
| 194 Message message(range_start, static_cast<int>(pickle_size)); | |
| 195 size_t num_attachments = message.header()->num_brokered_attachments; | |
| 196 | |
| 197 // Check for possible overflows. | |
| 198 size_t max_size_t = std::numeric_limits<size_t>::max(); | |
| 199 if (num_attachments >= max_size_t / BrokerableAttachment::kNonceSize) | |
| 200 return; | |
| 201 | |
| 202 size_t attachment_length = num_attachments * BrokerableAttachment::kNonceSize; | |
| 203 if (pickle_size > max_size_t - attachment_length) | |
| 204 return; | |
| 205 | |
| 206 // Check whether the range includes the attachments. | |
| 207 size_t buffer_length = static_cast<size_t>(range_end - range_start); | |
| 208 if (buffer_length < attachment_length + pickle_size) | |
| 209 return; | |
| 210 | |
| 211 for (size_t i = 0; i < num_attachments; ++i) { | |
| 212 const char* attachment_start = | |
| 213 pickle_end + i * BrokerableAttachment::kNonceSize; | |
| 214 BrokerableAttachment::AttachmentId id(attachment_start, | |
| 215 BrokerableAttachment::kNonceSize); | |
| 216 info->attachment_ids.push_back(id); | |
| 217 } | |
| 218 info->message_end = | |
| 219 pickle_end + num_attachments * BrokerableAttachment::kNonceSize; | |
| 220 info->message_size = info->message_end - range_start; | |
| 221 #else | |
| 222 info->message_size = pickle_size; | 157 info->message_size = pickle_size; |
| 223 | 158 |
| 224 if (!have_entire_pickle) | 159 if (!have_entire_pickle) |
| 225 return; | 160 return; |
| 226 | 161 |
| 227 const char* pickle_end = range_start + pickle_size; | 162 const char* pickle_end = range_start + pickle_size; |
| 228 | 163 |
| 229 info->message_end = pickle_end; | 164 info->message_end = pickle_end; |
| 230 #endif // USE_ATTACHMENT_BROKER | |
| 231 | 165 |
| 232 info->pickle_end = pickle_end; | 166 info->pickle_end = pickle_end; |
| 233 info->message_found = true; | 167 info->message_found = true; |
| 234 } | 168 } |
| 235 | 169 |
| 236 bool Message::AddPlaceholderBrokerableAttachmentWithId( | |
| 237 BrokerableAttachment::AttachmentId id) { | |
| 238 scoped_refptr<PlaceholderBrokerableAttachment> attachment( | |
| 239 new PlaceholderBrokerableAttachment(id)); | |
| 240 return attachment_set()->AddAttachment(attachment); | |
| 241 } | |
| 242 | |
| 243 bool Message::WriteAttachment( | 170 bool Message::WriteAttachment( |
| 244 scoped_refptr<base::Pickle::Attachment> attachment) { | 171 scoped_refptr<base::Pickle::Attachment> attachment) { |
| 245 bool brokerable; | 172 bool brokerable; |
| 246 size_t index; | 173 size_t index; |
| 247 bool success = attachment_set()->AddAttachment( | 174 bool success = attachment_set()->AddAttachment( |
| 248 make_scoped_refptr(static_cast<MessageAttachment*>(attachment.get())), | 175 make_scoped_refptr(static_cast<MessageAttachment*>(attachment.get())), |
| 249 &index, &brokerable); | 176 &index, &brokerable); |
| 250 DCHECK(success); | 177 DCHECK(success); |
| 251 | 178 |
| 252 // NOTE: If you add more data to the pickle, make sure to update | 179 // NOTE: If you add more data to the pickle, make sure to update |
| 253 // PickleSizer::AddAttachment. | 180 // PickleSizer::AddAttachment. |
| 254 | 181 |
| 255 // Write the type of descriptor. | 182 // Write the type of descriptor. |
| 256 WriteBool(brokerable); | 183 WriteBool(brokerable); |
| 257 | 184 |
| 258 // Write the index of the descriptor so that we don't have to | 185 // Write the index of the descriptor so that we don't have to |
| 259 // keep the current descriptor as extra decoding state when deserialising. | 186 // keep the current descriptor as extra decoding state when deserialising. |
| 260 WriteInt(static_cast<int>(index)); | 187 WriteInt(static_cast<int>(index)); |
| 261 | 188 |
| 262 #if USE_ATTACHMENT_BROKER | |
| 263 if (brokerable) | |
| 264 header()->num_brokered_attachments++; | |
| 265 #endif | |
| 266 | |
| 267 return success; | 189 return success; |
| 268 } | 190 } |
| 269 | 191 |
| 270 bool Message::ReadAttachment( | 192 bool Message::ReadAttachment( |
| 271 base::PickleIterator* iter, | 193 base::PickleIterator* iter, |
| 272 scoped_refptr<base::Pickle::Attachment>* attachment) const { | 194 scoped_refptr<base::Pickle::Attachment>* attachment) const { |
| 273 bool brokerable; | 195 bool brokerable; |
| 274 if (!iter->ReadBool(&brokerable)) | 196 if (!iter->ReadBool(&brokerable)) |
| 275 return false; | 197 return false; |
| 276 | 198 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 296 bool Message::HasMojoHandles() const { | 218 bool Message::HasMojoHandles() const { |
| 297 return attachment_set_.get() && attachment_set_->num_mojo_handles() > 0; | 219 return attachment_set_.get() && attachment_set_->num_mojo_handles() > 0; |
| 298 } | 220 } |
| 299 | 221 |
| 300 bool Message::HasBrokerableAttachments() const { | 222 bool Message::HasBrokerableAttachments() const { |
| 301 return attachment_set_.get() && | 223 return attachment_set_.get() && |
| 302 attachment_set_->num_brokerable_attachments() > 0; | 224 attachment_set_->num_brokerable_attachments() > 0; |
| 303 } | 225 } |
| 304 | 226 |
| 305 } // namespace IPC | 227 } // namespace IPC |
| OLD | NEW |